#!/usr/bin/env php E bin/phpstanEconf/bleedingEdge.neon7conf/config.level0.neonLconf/config.level1.neonVhXconf/config.level10.neonppCconf/config.level2.neon ɤconf/config.level3.neonxx@] conf/config.level4.neonNlm conf/config.level5.neon88 xconf/config.level6.neonZNVconf/config.level7.neonPconf/config.level8.neonkk.oconf/config.level9.neonoor=Bconf/config.levelmax.neon""$`conf/config.neonE"E"@conf/config.stubValidator.neon![jconf/parametersSchema.neonqq/'conf/parsers.neon**˅XPconf/services.neonNconf/turbo.neon preload.php]]resources/RegexGrammar.pp7?yresources/functionMap.php &{ua&resources/functionMap_bleedingEdge.phpc$resources/functionMap_php74delta.php$$resources/functionMap_php80delta.php..41resources/functionMap_php80delta_bleedingEdge.phpė'$resources/functionMap_php81delta.phpT@¤$resources/functionMap_php82delta.php^^"Q$resources/functionMap_php83delta.php@B{$resources/functionMap_php84delta.phprrś$resources/functionMap_php85delta.phpUUƥqѤresources/functionMetadata.php}}VӤsrc/AnalysedCodeException.phpPesrc/Analyser/Analyser.php/Hsrc/Analyser/AnalyserResult.phpF(src/Analyser/AnalyserResultFinalizer.php))Ƥ$src/Analyser/ArgumentsNormalizer.php00>dk&,src/Analyser/ConditionalExpressionHolder.phpFf!src/Analyser/ConstantResolver.phpGGAce(src/Analyser/ConstantResolverFactory.php##̤Ȥ+src/Analyser/DirectInternalScopeFactory.php\\V2src/Analyser/DirectInternalScopeFactoryFactory.php n#src/Analyser/EndStatementResult.phpQQrq,src/Analyser/EnsuredNonNullabilityResult.phpQQϱb6src/Analyser/EnsuredNonNullabilityResultExpression.phpsrc/Analyser/Error.php k'tsrc/Analyser/ExprHandler.phpo1src/Analyser/ExprHandler/ArrayDimFetchHandler.php|Ӥ)src/Analyser/ExprHandler/ArrayHandler.php##6\1src/Analyser/ExprHandler/ArrowFunctionHandler.php!!hlv*src/Analyser/ExprHandler/AssignHandler.phpdd̤,src/Analyser/ExprHandler/AssignOpHandler.php$$KȤ,src/Analyser/ExprHandler/BinaryOpHandler.phpN#N#.src/Analyser/ExprHandler/BitwiseNotHandler.php=A.src/Analyser/ExprHandler/BooleanAndHandler.phph?.src/Analyser/ExprHandler/BooleanNotHandler.php+g-src/Analyser/ExprHandler/BooleanOrHandler.php``a(src/Analyser/ExprHandler/CastHandler.php͈.src/Analyser/ExprHandler/CastStringHandler.php  tCtx3src/Analyser/ExprHandler/ClassConstFetchHandler.php9 9 DzS)src/Analyser/ExprHandler/CloneHandler.phpuuAt+src/Analyser/ExprHandler/ClosureHandler.php``-w,src/Analyser/ExprHandler/CoalesceHandler.php'O.src/Analyser/ExprHandler/ConstFetchHandler.php sh4)src/Analyser/ExprHandler/EmptyHandler.php? ? s1src/Analyser/ExprHandler/ErrorSuppressHandler.php0K(src/Analyser/ExprHandler/EvalHandler.phpaa~(src/Analyser/ExprHandler/ExitHandler.php1>src/Analyser/ExprHandler/FirstClassCallableFuncCallHandler.phppp$A @src/Analyser/ExprHandler/FirstClassCallableMethodCallHandler.phpZ풤9src/Analyser/ExprHandler/FirstClassCallableNewHandler.phpZ{@src/Analyser/ExprHandler/FirstClassCallableStaticCallHandler.php D|,src/Analyser/ExprHandler/FuncCallHandler.phpooy7src/Analyser/ExprHandler/Helper/ClosureTypeResolver.php=C=C[P|>src/Analyser/ExprHandler/Helper/ImplicitToStringCallHelper.phpC>src/Analyser/ExprHandler/Helper/MethodCallReturnTypeHelper.php~~s_:src/Analyser/ExprHandler/Helper/MethodThrowPointHelper.phppp~Ǥ8src/Analyser/ExprHandler/Helper/NonNullabilityHelper.php:̤Asrc/Analyser/ExprHandler/Helper/NullsafeShortCircuitingHelper.phpLL4 =src/Analyser/ExprHandler/Helper/VoidToNullTypeTransformer.php,,E+src/Analyser/ExprHandler/IncludeHandler.php%%$b.src/Analyser/ExprHandler/InstanceofHandler.phpCCs翤6src/Analyser/ExprHandler/InterpolatedStringHandler.php ?qXr)src/Analyser/ExprHandler/IssetHandler.phpYYs< )src/Analyser/ExprHandler/MatchHandler.php [ [aڤ.src/Analyser/ExprHandler/MethodCallHandler.php++A3'src/Analyser/ExprHandler/NewHandler.php9a9ad6src/Analyser/ExprHandler/NullsafeMethodCallHandler.php  Ԥ9src/Analyser/ExprHandler/NullsafePropertyFetchHandler.php y(src/Analyser/ExprHandler/PipeHandler.phpE E j"1+src/Analyser/ExprHandler/PostDecHandler.phpaR+src/Analyser/ExprHandler/PostIncHandler.php3[!*src/Analyser/ExprHandler/PreDecHandler.php e*src/Analyser/ExprHandler/PreIncHandler.php P?)src/Analyser/ExprHandler/PrintHandler.phpV\{1src/Analyser/ExprHandler/PropertyFetchHandler.phpOO-Ʀ*src/Analyser/ExprHandler/ScalarHandler.phpAA@/.src/Analyser/ExprHandler/StaticCallHandler.phpy<y<ɤ7src/Analyser/ExprHandler/StaticPropertyFetchHandler.php3+src/Analyser/ExprHandler/TernaryHandler.phpddŖ)src/Analyser/ExprHandler/ThrowHandler.phpQj .src/Analyser/ExprHandler/UnaryMinusHandler.php|-src/Analyser/ExprHandler/UnaryPlusHandler.php56Ik,src/Analyser/ExprHandler/VariableHandler.php d@src/Analyser/ExprHandler/Virtual/AlwaysRememberedExprHandler.phpo4$2Asrc/Analyser/ExprHandler/Virtual/ExistingArrayDimFetchHandler.phpYY@src/Analyser/ExprHandler/Virtual/FunctionCallableNodeHandler.php?Bsrc/Analyser/ExprHandler/Virtual/GetIterableKeyTypeExprHandler.phpQQiX9٤Dsrc/Analyser/ExprHandler/Virtual/GetIterableValueTypeExprHandler.php[[/3٤Bsrc/Analyser/ExprHandler/Virtual/GetOffsetValueTypeExprHandler.phpjj^XϤEsrc/Analyser/ExprHandler/Virtual/InstantiationCallableNodeHandler.php)۸>src/Analyser/ExprHandler/Virtual/MethodCallableNodeHandler.php=k:src/Analyser/ExprHandler/Virtual/NativeTypeExprHandler.phpjjۦUDsrc/Analyser/ExprHandler/Virtual/OriginalPropertyTypeExprHandler.phpVVդJsrc/Analyser/ExprHandler/Virtual/SetExistingOffsetValueTypeExprHandler.phpǛxBsrc/Analyser/ExprHandler/Virtual/SetOffsetValueTypeExprHandler.phpk[༤Dsrc/Analyser/ExprHandler/Virtual/StaticMethodCallableNodeHandler.php% % `Ƥ4src/Analyser/ExprHandler/Virtual/TypeExprHandler.php䔤;src/Analyser/ExprHandler/Virtual/UnsetOffsetExprHandler.phpGG-src/Analyser/ExprHandler/YieldFromHandler.php1y{)src/Analyser/ExprHandler/YieldHandler.php  C"src/Analyser/ExpressionContext.php!src/Analyser/ExpressionResult.php  $g(src/Analyser/ExpressionResultStorage.phpOq%src/Analyser/ExpressionTypeHolder.php\\M 0src/Analyser/Fiber/BeforeScopeForExprRequest.phpW|\-src/Analyser/Fiber/FiberNodeScopeResolver.phpwwM Ǥ!src/Analyser/Fiber/FiberScope.phpUU/sPѤ'src/Analyser/Fiber/ParkFiberRequest.phpeesrc/Analyser/FileAnalyser.php!3!3>yߤ%src/Analyser/FileAnalyserCallback.php)1)1;i#src/Analyser/FileAnalyserResult.phpaaK src/Analyser/FinalizerResult.phpJJsrc/Analyser/FixedErrorDiff.php<<V#src/Analyser/Ignore/IgnoreLexer.php` ` c*=,src/Analyser/Ignore/IgnoreParseException.phpݤ$src/Analyser/Ignore/IgnoredError.phpgȤ*src/Analyser/Ignore/IgnoredErrorHelper.php,H9src/Analyser/Ignore/IgnoredErrorHelperProcessedResult.phpb!%0src/Analyser/Ignore/IgnoredErrorHelperResult.php))ܲ%src/Analyser/IgnoreErrorExtension.php¤-src/Analyser/IgnoreErrorExtensionProvider.php>>w#src/Analyser/ImpurePoint.phpIo&src/Analyser/IntermediaryNameScope.php%X(+src/Analyser/InternalEndStatementResult.phply5src/Analyser/InternalError.php @'ͼ%src/Analyser/InternalScopeFactory.phprX1,src/Analyser/InternalScopeFactoryFactory.php..=y+src/Analyser/InternalStatementExitPoint.phpA(src/Analyser/InternalStatementResult.phpѻ#src/Analyser/InternalThrowPoint.php lL)src/Analyser/LazyInternalScopeFactory.phpTT&src/Analyser/LocalIgnoresProcessor.phpar,src/Analyser/LocalIgnoresProcessorResult.phpMM:Asrc/Analyser/MutatingScope.phpEE src/Analyser/NameScope.php9pۤ$src/Analyser/NodeCallbackInvoker.php+g"src/Analyser/NodeScopeResolver.phpa_a_Gy!src/Analyser/NoopNodeCallback.phpcy'src/Analyser/NullsafeOperatorHelper.php ^c src/Analyser/OutOfClassScope.phpK%src/Analyser/ProcessClosureResult.php2)(src/Analyser/ResultCache/ResultCache.php=^X/src/Analyser/ResultCache/ResultCacheClearer.php/src/Analyser/ResultCache/ResultCacheManager.php<<l6src/Analyser/ResultCache/ResultCacheManagerFactory.php>\>5src/Analyser/ResultCache/ResultCacheMetaExtension.phppp=5src/Analyser/ResultCache/ResultCacheProcessResult.php==%H)src/Analyser/RicherScopeGetTypeHelper.php s/%src/Analyser/RuleErrorTransformer.phpԧksrc/Analyser/Scope.php11:Msrc/Analyser/ScopeContext.php 36src/Analyser/ScopeFactory.php""$src/Analyser/ShallowNodeCallback.phpT'src/Analyser/SpecifiedTypes.phpԏޤ!src/Analyser/StatementContext.phpuu #src/Analyser/StatementExitPoint.php--hr src/Analyser/StatementResult.php88ʝesrc/Analyser/ThrowPoint.php_ڤ-src/Analyser/Traverser/CloneTypeTraverser.phpHڪ<src/Analyser/Traverser/ConstructorClassTemplateTraverser.php33q77src/Analyser/Traverser/GenericTypeTemplateTraverser.phpNU7src/Analyser/Traverser/TransformStaticTypeTraverser.php@@$\.src/Analyser/Traverser/VoidToNullTraverser.phpQQ^zsrc/Analyser/TypeSpecifier.phph$h$,src/Analyser/TypeSpecifierAwareExtension.php_%src/Analyser/TypeSpecifierContext.phpJ%1%src/Analyser/TypeSpecifierFactory.php b=8+src/Analyser/UndefinedVariableException.php}ʤ*src/Analyser/VirtualAssignNodeCallback.phpGGg$0'src/Broker/AnonymousClassNameHelper.phpHH& src/Broker/BrokerFactory.phpccf%src/Broker/ClassNotFoundException.phpt" (src/Broker/ConstantNotFoundException.php//і9(src/Broker/FunctionNotFoundException.phpNsrc/Cache/Cache.phpff, src/Cache/CacheItem.phpՄ_src/Cache/CacheStorage.php#\src/Cache/FileCacheStorage.phpoo|K src/Cache/MemoryCacheStorage.php*>+src/Classes/ForbiddenClassNameExtension.phpKK8$ɑ src/Collectors/CollectedData.phpYm-src/Collectors/Collector.php  u src/Collectors/Registry.phppP "src/Collectors/RegistryFactory.phpCC"src/Command/AnalyseApplication.phpC=C= Τsrc/Command/AnalyseCommand.phpZZWsrc/Command/AnalyserRunner.php{{src/Command/AnalysisResult.phpyh#src/Command/Bisect/BinarySearch.php>>M'src/Command/Bisect/BinarySearchStep.phpYYn'src/Command/BisectCommand.php1818v'src/Command/ClearResultCacheCommand.phpf f K>.Wsrc/Command/CommandHelper.php}}+tsrc/Command/DiagnoseCommand.phpU%src/Command/DumpParametersCommand.phpmۉ9src/Command/ErrorFormatter/BaselineNeonErrorFormatter.phpZ8src/Command/ErrorFormatter/BaselinePhpErrorFormatter.phprr̤7src/Command/ErrorFormatter/CheckstyleErrorFormatter.phpZ~7src/Command/ErrorFormatter/CiDetectedErrorFormatter.php""x|-src/Command/ErrorFormatter/ErrorFormatter.php3src/Command/ErrorFormatter/GithubErrorFormatter.php3 3 kt3src/Command/ErrorFormatter/GitlabErrorFormatter.php =5|1src/Command/ErrorFormatter/JsonErrorFormatter.phpSSʵ2src/Command/ErrorFormatter/JunitErrorFormatter.php +X0src/Command/ErrorFormatter/RawErrorFormatter.php#2src/Command/ErrorFormatter/TableErrorFormatter.php-&-&;u֮5src/Command/ErrorFormatter/TeamcityErrorFormatter.phpI "src/Command/ErrorsConsoleStyle.php1b]Y src/Command/FixerApplication.phpXX-oϤ%src/Command/FixerProcessException.phpH}"src/Command/FixerWorkerCommand.php!src/Command/FixerWorkerRunner.phpx6x6 Wפ%src/Command/IgnoredRegexValidator.phpee#l+src/Command/IgnoredRegexValidatorResult.php/src/Command/InceptionNotSuccessfulException.php_src/Command/InceptionResult.phpLJ*3src/Command/Output.phptv src/Command/OutputStyle.php;o<%src/Command/Symfony/SymfonyOutput.php!$src/Command/Symfony/SymfonyStyle.php@@Oזsrc/Command/WorkerCommand.phpPTusrc/Command/fixer-phar.pubkey  u䪤%src/Dependency/DependencyResolver.php]]ݹڤsrc/Dependency/ExportedNode.php^^뾮5src/Dependency/ExportedNode/ExportedAttributeNode.php9src/Dependency/ExportedNode/ExportedClassConstantNode.php  ':src/Dependency/ExportedNode/ExportedClassConstantsNode.phpd d P1src/Dependency/ExportedNode/ExportedClassNode.php)Ja4src/Dependency/ExportedNode/ExportedEnumCaseNode.phpxxاx0src/Dependency/ExportedNode/ExportedEnumNode.php_4src/Dependency/ExportedNode/ExportedFunctionNode.phphh$#5src/Dependency/ExportedNode/ExportedInterfaceNode.php xj2src/Dependency/ExportedNode/ExportedMethodNode.php95src/Dependency/ExportedNode/ExportedParameterNode.phphNj2src/Dependency/ExportedNode/ExportedPhpDocNode.phpHä6src/Dependency/ExportedNode/ExportedPropertiesNode.phpu '8src/Dependency/ExportedNode/ExportedPropertyHookNode.php1src/Dependency/ExportedNode/ExportedTraitNode.phpUt:src/Dependency/ExportedNode/ExportedTraitUseAdaptation.php O&e&src/Dependency/ExportedNodeFetcher.phpd'src/Dependency/ExportedNodeResolver.php<<(L&src/Dependency/ExportedNodeVisitor.phpYݤ#src/Dependency/NodeDependencies.php#src/Dependency/RootExportedNode.phpQ|4?src/DependencyInjection/AutowiredAttributeServicesExtension.php^^漤.src/DependencyInjection/AutowiredParameter.phpoU,src/DependencyInjection/AutowiredService.php**7k.src/DependencyInjection/BleedingEdgeToggle.php||'4src/DependencyInjection/ConditionalTagsExtension.phpi(src/DependencyInjection/Configurator.php,,%src/DependencyInjection/Container.php6,src/DependencyInjection/ContainerFactory.php==PZ6src/DependencyInjection/DerivativeContainerFactory.php 4֤;src/DependencyInjection/DuplicateIncludedFilesException.phpuu7src/DependencyInjection/ExpandRelativePathExtension.phpܠ\)src/DependencyInjection/FnsrExtension.php0%V+src/DependencyInjection/GenerateFactory.php!!51x8src/DependencyInjection/InvalidExcludePathsException.phppP/8src/DependencyInjection/InvalidIgnoredErrorException.phpc@src/DependencyInjection/InvalidIgnoredErrorPatternsException.php440(6src/DependencyInjection/InvalidPhpVersionException.phpil)src/DependencyInjection/LoaderFactory.phpf{s.src/DependencyInjection/MemoizingContainer.php8Psrc/DependencyInjection/MissingImplementedInterfaceInServiceWithTagException.php\H3src/DependencyInjection/MissingServiceException.php9熤-src/DependencyInjection/Neon/OptionalPath.php7'src/DependencyInjection/NeonAdapter.php&0src/DependencyInjection/NeonCachedFileReader.phpw&src/DependencyInjection/NeonLoader.php0src/DependencyInjection/Nette/NetteContainer.php  5T*/src/DependencyInjection/NonAutowiredService.php//+*6src/DependencyInjection/ParameterNotFoundException.phpPP D5src/DependencyInjection/ParametersSchemaExtension.php/src/DependencyInjection/ProjectConfigHelper.phpDߤOsrc/DependencyInjection/Reflection/ClassReflectionExtensionRegistryProvider.php  ϛSsrc/DependencyInjection/Reflection/LazyClassReflectionExtensionRegistryProvider.php 8LV/src/DependencyInjection/RegisteredCollector.php%*src/DependencyInjection/RegisteredRule.php*src/DependencyInjection/RulesExtension.php00!W>src/DependencyInjection/StubValidatorRuleServicesExtension.phpJKsrc/DependencyInjection/Type/DynamicReturnTypeExtensionRegistryProvider.phpAmmBsrc/DependencyInjection/Type/DynamicThrowTypeExtensionProvider.phpА3Psrc/DependencyInjection/Type/ExpressionTypeResolverExtensionRegistryProvider.php1Osrc/DependencyInjection/Type/LazyDynamicReturnTypeExtensionRegistryProvider.phpHFsrc/DependencyInjection/Type/LazyDynamicThrowTypeExtensionProvider.phpTsrc/DependencyInjection/Type/LazyExpressionTypeResolverExtensionRegistryProvider.phpTsrc/DependencyInjection/Type/LazyOperatorTypeSpecifyingExtensionRegistryProvider.phpJsrc/DependencyInjection/Type/LazyParameterClosureThisExtensionProvider.phpNN?vJsrc/DependencyInjection/Type/LazyParameterClosureTypeExtensionProvider.php_lFsrc/DependencyInjection/Type/LazyParameterOutTypeExtensionProvider.php2]Ysrc/DependencyInjection/Type/LazyUnaryOperatorTypeSpecifyingExtensionRegistryProvider.php!!*9OPsrc/DependencyInjection/Type/OperatorTypeSpecifyingExtensionRegistryProvider.phpa/iFsrc/DependencyInjection/Type/ParameterClosureThisExtensionProvider.phpΛFsrc/DependencyInjection/Type/ParameterClosureTypeExtensionProvider.php\Bsrc/DependencyInjection/Type/ParameterOutTypeExtensionProvider.php*5;Usrc/DependencyInjection/Type/UnaryOperatorTypeSpecifyingExtensionRegistryProvider.php!![ 9src/DependencyInjection/ValidateExcludePathsExtension.php -v:src/DependencyInjection/ValidateIgnoredErrorsExtension.php)):8src/DependencyInjection/ValidateServiceTagsExtension.php$$k.src/DependencyInjection/ValidatesStubFiles.php"Ϥ"src/Diagnose/DiagnoseExtension.phpg_)src/Diagnose/PHPStanDiagnoseExtension.php''9{&src/File/CouldNotReadFileException.phpXޤ'src/File/CouldNotWriteFileException.phpk&src/File/FileExcluder.php( ( eP src/File/FileExcluderFactory.php$)#src/File/FileExcluderRawFactory.php'9src/File/FileFinder.php>,jsrc/File/FileFinderResult.phpBB:;hsrc/File/FileHelper.php oE ޤsrc/File/FileMonitor.phpx՜src/File/FileMonitorResult.php*src/File/FileReader.php*pn1src/File/FileWriter.phpzȤ$src/File/FuzzyRelativePathHelper.phpnn#src/File/NullRelativePathHelper.php}.src/File/ParentDirectoryRelativePathHelper.php"src/File/PathNotFoundException.phpKC_Esrc/File/RelativePathHelper.phpA@%src/File/SimpleRelativePathHelper.phpޤ3src/File/SystemAgnosticSimpleRelativePathHelper.phpְ$src/Fixable/FileChangedException.phpcT&src/Fixable/MergeConflictException.phpMsrc/Fixable/Patcher.php{{jä&src/Fixable/PhpDoc/CallbackVisitor.phps#src/Fixable/PhpDoc/PhpDocEditor.php1src/Fixable/PhpPrinter.phpMMҖ*src/Internal/DeprecatedAttributeHelper.phpXXۤ!src/Internal/DirectoryCreator.php>*src/Internal/DirectoryCreatorException.php? s"src/Internal/HttpClientFactory.php? Tsrc/Internal/SprintfHelper.phpsrc/NeverException.phpiick,src/Node/AnonymousClassNode.phphsrc/Node/BooleanAndNode.phpSSB\src/Node/BooleanOrNode.phpIIgΤ#src/Node/BreaklessWhileLoopNode.php<<0=?+src/Node/CatchWithUnthrownExceptionNode.phpssrc/Node/ClassConstantsNode.php.٤src/Node/ClassMethod.phpKKnfsrc/Node/ClassMethodsNode.php U src/Node/ClassPropertiesNode.php A AQ, ۤsrc/Node/ClassPropertyNode.phpi$src/Node/ClassStatementsGatherer.php&&{+(src/Node/ClosureReturnStatementsNode.php &פsrc/Node/CollectedDataNode.phpQU(src/Node/Constant/ClassConstantFetch.php++hˤsrc/Node/DeepNodeCloner.php//9.%src/Node/DoWhileLoopConditionNode.phpХsrc/Node/ExecutionEndNode.phpX?x &src/Node/Expr/AlwaysRememberedExpr.phphh@@'src/Node/Expr/ExistingArrayDimFetch.php$$kC'src/Node/Expr/ForeachValueByRefExpr.php=6(src/Node/Expr/GetIterableKeyTypeExpr.php٤*src/Node/Expr/GetIterableValueTypeExpr.phpཷR(src/Node/Expr/GetOffsetValueTypeExpr.php&&ߡV8src/Node/Expr/IntertwinedVariableByReferenceWithExpr.phpJJA src/Node/Expr/NativeTypeExpr.php~k(src/Node/Expr/OriginalForeachKeyExpr.php<<KrΌ*src/Node/Expr/OriginalForeachValueExpr.php@@zėF*src/Node/Expr/OriginalPropertyTypeExpr.php獣4src/Node/Expr/ParameterVariableOriginalValueExpr.phpTTp^ޤ(src/Node/Expr/PossiblyImpureCallExpr.phpn0,src/Node/Expr/PropertyInitializationExpr.php^ e0src/Node/Expr/SetExistingOffsetValueTypeExpr.php*(src/Node/Expr/SetOffsetValueTypeExpr.phpH1esrc/Node/Expr/TypeExpr.phpȔܤ!src/Node/Expr/UnsetOffsetExpr.phphQsrc/Node/FileNode.php}}J"src/Node/FinallyExitPointsNode.phpNNI!src/Node/FunctionCallableNode.php\\!)src/Node/FunctionReturnStatementsNode.php{ { 2n src/Node/InArrowFunctionNode.phpEEoNsrc/Node/InClassMethodNode.php&ǫsrc/Node/InClassNode.php  HP-src/Node/InClosureNode.phpsrc/Node/InForeachNode.php 4qsrc/Node/InFunctionNode.php[3Ӥsrc/Node/InPropertyHookNode.php8^src/Node/InTraitNode.phpJJN&src/Node/InstantiationCallableNode.phpaa vsrc/Node/InvalidateExprNode.phpmQ@src/Node/IssetExpr.php 6]src/Node/LiteralArrayItem.php$$6\Ԭsrc/Node/LiteralArrayNode.phpuФsrc/Node/MatchExpressionArm.php7q#src/Node/MatchExpressionArmBody.phpEҤ(src/Node/MatchExpressionArmCondition.php ^ src/Node/MatchExpressionNode.phposrc/Node/Method/MethodCall.php]]Zxäsrc/Node/MethodCallableNode.php <'src/Node/MethodReturnStatementsNode.phpPP src/Node/NoopExpressionNode.php9䗤 src/Node/Printer/ExprPrinter.phpK)$src/Node/Printer/NodeTypePrinter.phpӢxsrc/Node/Printer/Printer.php}$src/Node/Property/PropertyAssign.php886"src/Node/Property/PropertyRead.php??xY|#src/Node/Property/PropertyWrite.php223Asrc/Node/PropertyAssignNode.php0bf-src/Node/PropertyHookReturnStatementsNode.php ~B&src/Node/PropertyHookStatementNode.php&&/Esrc/Node/ReturnStatement.phpAA'0!src/Node/ReturnStatementsNode.phpD%src/Node/StaticMethodCallableNode.php6%src/Node/UnreachableStatementNode.phpVV=P{,src/Node/VarTagChangedExpressionTypeNode.php"-y}src/Node/VariableAssignNode.php,ޔsrc/Node/VirtualNode.phpV $src/Parallel/ForkParallelChecker.php Dsrc/Parallel/ForkedProcess.phpEE^h!src/Parallel/ParallelAnalyser.php>> asrc/Parallel/Process.php<src/Parallel/ProcessBase.phpp p Ec;src/Parallel/ProcessPool.phpOO d)src/Parallel/ProcessTimedOutException.phpߤsrc/Parallel/Schedule.php@>Ksrc/Parallel/Scheduler.php M0src/Parallel/SpawnedProcess.php0 0 ,;src/Parallel/WorkerRunner.phpH%H%H&h6$src/Parser/AnonymousClassVisitor.phpK$src/Parser/ArrayFilterArgVisitor.phpLLex"src/Parser/ArrayFindArgVisitor.phpO*!src/Parser/ArrayMapArgVisitor.php0s"src/Parser/ArrayWalkArgVisitor.phpFF> ª&src/Parser/ArrowFunctionArgVisitor.php*ҽsrc/Parser/CachedParser.php 0src/Parser/CleaningParser.php`src/Parser/CleaningVisitor.php NJ[> src/Parser/ClosureArgVisitor.php  Ut$src/Parser/ClosureBindArgVisitor.phptt e&src/Parser/ClosureBindToVarVisitor.php&N#src/Parser/CurlSetOptArgVisitor.phpII.(src/Parser/CurlSetOptArrayArgVisitor.phpYYDX^%src/Parser/DeclarePositionVisitor.php..tS/src/Parser/ImmediatelyInvokedClosureVisitor.phpQQ@R src/Parser/ImplodeArgVisitor.phpnnB٤#src/Parser/LastConditionVisitor.php Jsrc/Parser/LexerFactory.phpe$src/Parser/LineAttributesVisitor.php%hb/src/Parser/MagicConstantParamDefaultVisitor.phpgg_N+src/Parser/NewAssignedToPropertyVisitor.php22ۯ%%src/Parser/ParentStmtTypesVisitor.phpwE'src/Parser/Parser.phpk^$src/Parser/ParserErrorsException.php0 src/Parser/PathRoutingParser.php C#Ĥ!src/Parser/PhpParserDecorator.php!g~src/Parser/PhpParserFactory.php6%src/Parser/PipeTransformerVisitor.phpя4src/Parser/RemoveUnusedCodeByPhpVersionIdVisitor.phpM M `,src/Parser/ReversePipeTransformerVisitor.phpzwsrc/Parser/RichParser.php%5%5HmYsrc/Parser/SimpleParser.phpOOǖW)src/Parser/StandaloneThrowExprVisitor.phpuHʤsrc/Parser/StubParser.phpMM*~%src/Parser/TraitCollectingVisitor.phpq䄤"src/Parser/TryCatchTypeVisitor.php-src/Parser/TypeTraverserInstanceofVisitor.php0g$src/Parser/UseAliasVisitor.phpffzb8%src/Php/ComposerPhpVersionFactory.php Q>$src/Php/ComposerPhpVersionParser.phpggM6src/Php/PhpVersion.phpF0F06src/Php/PhpVersionFactory.phpN#$src/Php/PhpVersionFactoryFactory.phpZZ[.src/Php/PhpVersions.phpZZ\F-src/PhpDoc/BcMathNumberStubFilesExtension.phpcc$src/PhpDoc/ConstExprNodeResolver.php))A'src/PhpDoc/DefaultStubFilesProvider.php X#>src/PhpDoc/DirectTypeNodeResolverExtensionRegistryProvider.phpb[.src/PhpDoc/InheritedPhpDocParameterMapping.phpvv}A-src/PhpDoc/JsonValidateStubFilesExtension.phpWW<src/PhpDoc/LazyTypeNodeResolverExtensionRegistryProvider.phpo4src/PhpDoc/NameScopeAlreadyBeingCreatedException.php//(src/PhpDoc/PhpDocInheritanceResolver.php(( !src/PhpDoc/PhpDocNodeResolver.phphhZ#src/PhpDoc/PhpDocStringResolver.php ).0src/PhpDoc/ReflectionClassStubFilesExtension.phpӤ/src/PhpDoc/ReflectionEnumStubFilesExtension.phpi/"src/PhpDoc/ResolvedPhpDocBlock.php?-src/PhpDoc/SocketSelectStubFilesExtension.phpl!src/PhpDoc/StubFilesExtension.phpss7 src/PhpDoc/StubFilesProvider.phpv!src/PhpDoc/StubPhpDocProvider.php33'src/PhpDoc/StubSourceLocatorFactory.php ^ӭsrc/PhpDoc/StubValidator.php  ssrc/PhpDoc/Tag/AssertTag.php$ $ nŧ%src/PhpDoc/Tag/AssertTagParameter.phpbbH src/PhpDoc/Tag/DeprecatedTag.phpBB*Τsrc/PhpDoc/Tag/ExtendsTag.php;;3g src/PhpDoc/Tag/ImplementsTag.php>>ͤsrc/PhpDoc/Tag/MethodTag.php2%src/PhpDoc/Tag/MethodTagParameter.php\src/PhpDoc/Tag/MixinTag.php999&src/PhpDoc/Tag/ParamClosureThisTag.php&src/PhpDoc/Tag/ParamOutTag.php^Qsrc/PhpDoc/Tag/ParamTag.php}}src/PhpDoc/Tag/PropertyTag.phpfml$src/PhpDoc/Tag/RequireExtendsTag.phpBBOƤ'src/PhpDoc/Tag/RequireImplementsTag.phpEE2src/PhpDoc/Tag/ReturnTag.php@ src/PhpDoc/Tag/SealedTypeTag.phpW!src/PhpDoc/Tag/SelfOutTypeTag.php<:src/PhpDoc/Tag/TemplateTag.php  <9src/PhpDoc/Tag/ThrowsTag.php::Ƽ!%src/PhpDoc/Tag/TypeAliasImportTag.php8YCsrc/PhpDoc/Tag/TypeAliasTag.php@&src/PhpDoc/Tag/TypedTag.php̥h^src/PhpDoc/Tag/UsesTag.php88Jsrc/PhpDoc/Tag/VarTag.php@ qsrc/PhpDoc/TypeNodeResolver.phpAA.Ҥ-src/PhpDoc/TypeNodeResolverAwareExtension.phph(src/PhpDoc/TypeNodeResolverExtension.phpT5src/PhpDoc/TypeNodeResolverExtensionAwareRegistry.phpvvM^0src/PhpDoc/TypeNodeResolverExtensionRegistry.php\8src/PhpDoc/TypeNodeResolverExtensionRegistryProvider.php[!src/PhpDoc/TypeStringResolver.php:nsrc/Process/CpuCoreCounter.phpm$src/Process/ForkedProcessPromise.phpRRtzN(src/Process/ProcessCanceledException.phpw@X'src/Process/ProcessCrashedException.php &Фsrc/Process/ProcessHelper.php[ [ 284src/Process/ProcessPromise.phpVW%src/Process/SpawnedProcessPromise.phpD D {H 2src/Reflection/AdditionalConstructorsExtension.php#s:src/Reflection/AllowedSubTypesClassReflectionExtension.php*9src/Reflection/Annotations/AnnotationMethodReflection.php0;src/Reflection/Annotations/AnnotationPropertyReflection.php |Csrc/Reflection/Annotations/AnnotationsMethodParameterReflection.php  0٤Isrc/Reflection/Annotations/AnnotationsMethodsClassReflectionExtension.phpLzLsrc/Reflection/Annotations/AnnotationsPropertiesClassReflectionExtension.phpQsrc/Reflection/Assertions.phpbZ>&src/Reflection/AttributeReflection.php]]63-src/Reflection/AttributeReflectionFactory.php''q<src/Reflection/BetterReflection/BetterReflectionProvider.php:V:VӤHsrc/Reflection/BetterReflection/BetterReflectionSourceLocatorFactory.php8'8'7H@src/Reflection/BetterReflection/Reflector/MemoizingReflector.phpPsrc/Reflection/BetterReflection/SourceLocator/AutoloadFunctionsSourceLocator.php  wvGsrc/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php66w@src/Reflection/BetterReflection/SourceLocator/CachingVisitor.php..\`src/Reflection/BetterReflection/SourceLocator/ComposerJsonAndInstalledJsonSourceLocatorMaker.php((7V=src/Reflection/BetterReflection/SourceLocator/FetchedNode.php Dsrc/Reflection/BetterReflection/SourceLocator/FetchedNodesResult.php--H8Bsrc/Reflection/BetterReflection/SourceLocator/FileNodesFetcher.phpꞷKsrc/Reflection/BetterReflection/SourceLocator/FileReadTrapStreamWrapper.php44Csrc/Reflection/BetterReflection/SourceLocator/LazySourceLocator.php!!YQsrc/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.phpo/o/|n6bXsrc/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorFactory.php|"w[src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorRepository.php  NFOsrc/Reflection/BetterReflection/SourceLocator/OptimizedPsrAutoloaderLocator.php #]Vsrc/Reflection/BetterReflection/SourceLocator/OptimizedPsrAutoloaderLocatorFactory.phprr¶Rsrc/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocator.php)0)0 9JYsrc/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocatorFactory.php%3<\src/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocatorRepository.phpG *@src/Reflection/BetterReflection/SourceLocator/PhpFileCleaner.phpK"K"Ф_Rsrc/Reflection/BetterReflection/SourceLocator/PhpVersionBlacklistSourceLocator.php"YNsrc/Reflection/BetterReflection/SourceLocator/ReflectionClassSourceLocator.php@@;I¤Psrc/Reflection/BetterReflection/SourceLocator/RewriteClassAliasSourceLocator.php*=Msrc/Reflection/BetterReflection/SourceLocator/SkipClassAliasSourceLocator.php|Ksrc/Reflection/BetterReflection/SourceLocator/SkipPolyfillSourceLocator.php8 8 5Esrc/Reflection/BetterReflection/SourceLocator/SymbolFinderInFiles.php,;iySsrc/Reflection/BetterReflection/SourceStubber/PhpStormStubsSourceStubberFactory.phpvʯPsrc/Reflection/BetterReflection/SourceStubber/ReflectionSourceStubberFactory.phpcᥤ\src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.phpTbBXsrc/Reflection/BetterReflection/Type/AdapterReflectionEnumDynamicReturnTypeExtension.phpz z h7src/Reflection/Callables/CallableParametersAcceptor.php. &4src/Reflection/Callables/FunctionCallableVariant.phpqqN.src/Reflection/Callables/SimpleImpurePoint.php :-src/Reflection/Callables/SimpleThrowPoint.php]]ٱ*src/Reflection/ClassConstantReflection.php=,src/Reflection/ClassMemberAccessAnswerer.php  Q(src/Reflection/ClassMemberReflection.php潤"src/Reflection/ClassNameHelper.php@*="src/Reflection/ClassReflection.php55yJvѤ3src/Reflection/ClassReflectionExtensionRegistry.php )src/Reflection/ClassReflectionFactory.phpGG;Ѥ5src/Reflection/Constant/RuntimeConstantReflection.phpE%/]%src/Reflection/ConstantNameHelper.php]]ۤ%src/Reflection/ConstantReflection.phpcc><%src/Reflection/ConstructorsHelper.php> > k@src/Reflection/Deprecation/ClassConstantDeprecationExtension.phpi8src/Reflection/Deprecation/ClassDeprecationExtension.phpaa=>;src/Reflection/Deprecation/ConstantDeprecationExtension.php);*src/Reflection/Deprecation/Deprecation.php66&"V2src/Reflection/Deprecation/DeprecationProvider.phpl5>k;src/Reflection/Deprecation/EnumCaseDeprecationExtension.phpѤ;src/Reflection/Deprecation/FunctionDeprecationExtension.php#`9src/Reflection/Deprecation/MethodDeprecationExtension.php-];src/Reflection/Deprecation/PropertyDeprecationExtension.php/]4src/Reflection/Dummy/ChangedTypeMethodReflection.phpBBOS6src/Reflection/Dummy/ChangedTypePropertyReflection.php++ŢNu5src/Reflection/Dummy/DummyClassConstantReflection.php9 9 ⌄3src/Reflection/Dummy/DummyConstructorReflection.php ҋd.src/Reflection/Dummy/DummyMethodReflection.phpC C io0src/Reflection/Dummy/DummyPropertyReflection.phpO O %src/Reflection/EnumCaseReflection.php -ٓ2src/Reflection/ExtendedCallableFunctionVariant.php $\*src/Reflection/ExtendedFunctionVariant.phpH+src/Reflection/ExtendedMethodReflection.phpv v 0.src/Reflection/ExtendedParameterReflection.phpvv?P1-src/Reflection/ExtendedParametersAcceptor.phpȜ-src/Reflection/ExtendedPropertyReflection.php 1o%src/Reflection/FunctionReflection.phpa a g,src/Reflection/FunctionReflectionFactory.php||gpn"src/Reflection/FunctionVariant.php#c4src/Reflection/GenericParametersAcceptorResolver.phpffL3Q%src/Reflection/InaccessibleMethod.phpvj{ˤ)src/Reflection/InitializerExprContext.phph.src/Reflection/InitializerExprTypeResolver.php"||9,src/Reflection/MethodPrototypeReflection.phpee #src/Reflection/MethodReflection.phpg2src/Reflection/MethodsClassReflectionExtension.php88`Y;9src/Reflection/MissingConstantFromReflectionException.php||'ʤ7src/Reflection/MissingMethodFromReflectionException.phpvvCzb9src/Reflection/MissingPropertyFromReflectionException.php}}D$9src/Reflection/MissingStaticAccessorInstanceException.phpҙ.src/Reflection/Mixin/MixinMethodReflection.phpH=src/Reflection/Mixin/MixinMethodsClassReflectionExtension.php  aФ@src/Reflection/Mixin/MixinPropertiesClassReflectionExtension.phpw w _P$src/Reflection/NamespaceAnswerer.php0;src/Reflection/Native/ExtendedNativeParameterReflection.php 2src/Reflection/Native/NativeFunctionReflection.phpwu0src/Reflection/Native/NativeMethodReflection.phpdd}ä3src/Reflection/Native/NativeParameterReflection.phpEzqOsrc/Reflection/PHPStan/NativeReflectionEnumReturnDynamicReturnTypeExtension.phpˤ&src/Reflection/ParameterReflection.phpkkb%src/Reflection/ParametersAcceptor.phpff0<Ǥ-src/Reflection/ParametersAcceptorSelector.php$%$src/Reflection/PassedByReference.php  ^Τ2src/Reflection/Php/ClosureCallMethodReflection.php\LuEsrc/Reflection/Php/ClosureCallUnresolvedMethodPrototypeReflection.phpBB%src/Reflection/Php/DummyParameter.php^^ :Bsrc/Reflection/Php/EnumAllowedSubTypesClassReflectionExtension.phpOOنt0src/Reflection/Php/EnumCasesMethodReflection.php2-src/Reflection/Php/EnumPropertyReflection.phpO O [u@src/Reflection/Php/EnumUnresolvedPropertyPrototypeReflection.phpRR-src/Reflection/Php/ExitFunctionReflection.php 4¤-src/Reflection/Php/ExtendedDummyParameter.php``ۤ2src/Reflection/Php/PhpClassReflectionExtension.phpBM}:src/Reflection/Php/PhpFunctionFromParserNodeReflection.phpQ.Q.gV^,src/Reflection/Php/PhpFunctionReflection.php##x78src/Reflection/Php/PhpMethodFromParserNodeReflection.php$$*src/Reflection/Php/PhpMethodReflection.phpBBF1src/Reflection/Php/PhpMethodReflectionFactory.phphhެF;src/Reflection/Php/PhpParameterFromParserNodeReflection.php -src/Reflection/Php/PhpParameterReflection.php<6,src/Reflection/Php/PhpPropertyReflection.phpW%W%jDsrc/Reflection/Php/SealedAllowedSubTypesClassReflectionExtension.phpzz/src/Reflection/Php/SimpleXMLElementProperty.phpG G 6src/Reflection/Php/Soap/SoapClientMethodReflection.phpeNGEsrc/Reflection/Php/Soap/SoapClientMethodsClassReflectionExtension.php"F3src/Reflection/Php/UniversalObjectCrateProperty.php Dsrc/Reflection/Php/UniversalObjectCratesClassReflectionExtension.php b1^+src/Reflection/PhpVersionStaticAccessor.phpII:פ5src/Reflection/PropertiesClassReflectionExtension.phpQQ%src/Reflection/PropertyReflection.php3src/Reflection/RealClassClassConstantReflection.phpy]%src/Reflection/ReflectionProvider.phpvSFsrc/Reflection/ReflectionProvider/DirectReflectionProviderProvider.php337wT=src/Reflection/ReflectionProvider/DummyReflectionProvider.phpuuA%Dsrc/Reflection/ReflectionProvider/LazyReflectionProviderProvider.phpQQAsrc/Reflection/ReflectionProvider/MemoizingReflectionProvider.php c¤?src/Reflection/ReflectionProvider/ReflectionProviderFactory.phpv@src/Reflection/ReflectionProvider/ReflectionProviderProvider.php N3src/Reflection/ReflectionProviderStaticAccessor.php- Qsrc/Reflection/RequireExtension/RequireExtendsMethodsClassReflectionExtension.phpjNTsrc/Reflection/RequireExtension/RequireExtendsPropertiesClassReflectionExtension.php?c*src/Reflection/ResolvedFunctionVariant.phpYYC$6src/Reflection/ResolvedFunctionVariantWithCallable.phpQp6src/Reflection/ResolvedFunctionVariantWithOriginal.phpw)w)ä+src/Reflection/ResolvedMethodReflection.phpqqhI-src/Reflection/ResolvedPropertyReflection.phpjj1src/Reflection/SignatureMap/FunctionSignature.php@@XӤ<src/Reflection/SignatureMap/FunctionSignatureMapProvider.php((@src/Reflection/SignatureMap/NativeFunctionReflectionProvider.php##2src/Reflection/SignatureMap/ParameterSignature.phpWW|8src/Reflection/SignatureMap/Php8SignatureMapProvider.phpHPHPN2src/Reflection/SignatureMap/SignatureMapParser.php L"4src/Reflection/SignatureMap/SignatureMapProvider.php;src/Reflection/SignatureMap/SignatureMapProviderFactory.php\O,src/Reflection/TrivialParametersAcceptor.php+ + ɤCsrc/Reflection/Type/CallbackUnresolvedMethodPrototypeReflection.php7"Esrc/Reflection/Type/CallbackUnresolvedPropertyPrototypeReflection.phpEGsrc/Reflection/Type/CalledOnTypeUnresolvedMethodPrototypeReflection.php  yMIsrc/Reflection/Type/CalledOnTypeUnresolvedPropertyPrototypeReflection.phpjj$8src/Reflection/Type/IntersectionTypeMethodReflection.php##Y:src/Reflection/Type/IntersectionTypePropertyReflection.php0WKsrc/Reflection/Type/IntersectionTypeUnresolvedMethodPrototypeReflection.php />Msrc/Reflection/Type/IntersectionTypeUnresolvedPropertyPrototypeReflection.php t1src/Reflection/Type/UnionTypeMethodReflection.phpF3src/Reflection/Type/UnionTypePropertyReflection.phpKKD¬Dsrc/Reflection/Type/UnionTypeUnresolvedMethodPrototypeReflection.php 7Fsrc/Reflection/Type/UnionTypeUnresolvedPropertyPrototypeReflection.phpy y .;src/Reflection/Type/UnresolvedMethodPrototypeReflection.phpN=src/Reflection/Type/UnresolvedPropertyPrototypeReflection.phpNj 2src/Reflection/WrappedExtendedMethodReflection.php[ͩ4src/Reflection/WrappedExtendedPropertyReflection.php  0Q,src/Reflection/WrapperPropertyReflection.phpW(src/Rules/Api/ApiClassConstFetchRule.php Yp%src/Rules/Api/ApiClassExtendsRule.php i(src/Rules/Api/ApiClassImplementsRule.php: : #src/Rules/Api/ApiInstanceofRule.php@@xKWϤ'src/Rules/Api/ApiInstanceofTypeRule.php ٤&src/Rules/Api/ApiInstantiationRule.php R)src/Rules/Api/ApiInterfaceExtendsRule.php7 7 ) Ϥ#src/Rules/Api/ApiMethodCallRule.phpw w jWsrc/Rules/Api/ApiRuleHelper.php jW#src/Rules/Api/ApiStaticCallRule.php !src/Rules/Api/ApiTraitUseRule.phpk%src/Rules/Api/GetTemplateTypeRule.php ˤ5src/Rules/Api/NodeConnectingVisitorAttributesRule.phpc:F(src/Rules/Api/OldPhpParser4ClassRule.php 87src/Rules/Api/PhpStanNamespaceIn3rdPartyPackageRule.php  arF/src/Rules/Api/RuntimeReflectionFunctionRule.phpBBqs:4src/Rules/Api/RuntimeReflectionInstantiationRule.phpa a n*src/Rules/Arrays/AllowedArrayKeysTypes.php /}+src/Rules/Arrays/ArrayDestructuringRule.php o b'src/Rules/Arrays/ArrayUnpackingRule.phpHH[녤$src/Rules/Arrays/DeadForeachRule.php__5src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.phpH2src/Rules/Arrays/InvalidKeyInArrayDimFetchRule.phpz z HRX.src/Rules/Arrays/InvalidKeyInArrayItemRule.phpͮ-*src/Rules/Arrays/IterableInForeachRule.phpDDb[r:src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php5559src/Rules/Arrays/NonexistentOffsetInArrayDimFetchRule.phpCr-src/Rules/Arrays/OffsetAccessAssignOpRule.php /src/Rules/Arrays/OffsetAccessAssignmentRule.php  )"ʤ4src/Rules/Arrays/OffsetAccessValueAssignmentRule.php; ; nL9src/Rules/Arrays/OffsetAccessWithoutDimForReadingRule.php<<c5'.src/Rules/Arrays/UnpackIterableInArrayRule.phpisrc/Rules/AttributesCheck.php nl%src/Rules/Cast/DeprecatedCastRule.php. . Vosrc/Rules/Cast/EchoRule.php|~"src/Rules/Cast/InvalidCastRule.php ׶֤2src/Rules/Cast/InvalidPartOfEncapsedStringRule.phpW^src/Rules/Cast/PrintRule.php[[¯ src/Rules/Cast/UnsetCastRule.phpqRQsrc/Rules/Cast/VoidCastRule.php6'src/Rules/ClassCaseSensitivityCheck.phpyba%src/Rules/ClassForbiddenNameCheck.php _Z5msrc/Rules/ClassNameCheck.php? ? ti`Zsrc/Rules/ClassNameNodePair.phprr*$src/Rules/ClassNameUsageLocation.php22;P<src/Rules/Classes/AccessPrivateConstantThroughStaticRule.phpyܤ)src/Rules/Classes/AllowedSubTypesRule.phpOO)src/Rules/Classes/ClassAttributesRule.phpK K w1src/Rules/Classes/ClassConstantAttributesRule.phpKKo@ʤ'src/Rules/Classes/ClassConstantRule.phpc'c'TNƤ1src/Rules/Classes/ConsistentConstructorHelper.php{{c3src/Rules/Classes/DuplicateClassDeclarationRule.phpJ0src/Rules/Classes/DuplicateDeclarationHelper.phpW.src/Rules/Classes/DuplicateDeclarationRule.phpL,f3src/Rules/Classes/DuplicateTraitDeclarationRule.phpJJ$]o$src/Rules/Classes/EnumSanityRule.phpff5src/Rules/Classes/ExistingClassInClassExtendsRule.php})3src/Rules/Classes/ExistingClassInInstanceOfRule.php [1src/Rules/Classes/ExistingClassInTraitUseRule.phpJJ!0ͤ:src/Rules/Classes/ExistingClassesInClassImplementsRule.php !9src/Rules/Classes/ExistingClassesInEnumImplementsRule.php ڤ;src/Rules/Classes/ExistingClassesInInterfaceExtendsRule.php ݤ.src/Rules/Classes/ImpossibleInstanceOfRule.php77B/src/Rules/Classes/InstantiationCallableRule.phpo7'src/Rules/Classes/InstantiationRule.php//¤3src/Rules/Classes/InvalidPromotedPropertiesRule.php  v+src/Rules/Classes/LocalTypeAliasesCheck.php<<礢_*src/Rules/Classes/LocalTypeAliasesRule.php``anȤ/src/Rules/Classes/LocalTypeTraitAliasesRule.php(8L2src/Rules/Classes/LocalTypeTraitUseAliasesRule.phpzqE$src/Rules/Classes/MethodTagCheck.php11B'#src/Rules/Classes/MethodTagRule.phpKK+(src/Rules/Classes/MethodTagTraitRule.php57+src/Rules/Classes/MethodTagTraitUseRule.phpoKE src/Rules/Classes/MixinCheck.phpqqԤsrc/Rules/Classes/MixinRule.php??$src/Rules/Classes/MixinTraitRule.phpAȽ'src/Rules/Classes/MixinTraitUseRule.phpRo>src/Rules/Classes/NewStaticInAbstractClassStaticMethodRule.php**+#src/Rules/Classes/NewStaticRule.php ֏W0src/Rules/Classes/NonClassAttributeClassRule.php#&src/Rules/Classes/PropertyTagCheck.php))@&,+%src/Rules/Classes/PropertyTagRule.phpQQs;̤*src/Rules/Classes/PropertyTagTraitRule.phpa-src/Rules/Classes/PropertyTagTraitUseRule.phpJ='src/Rules/Classes/ReadOnlyClassRule.php(src/Rules/Classes/RequireExtendsRule.php  ^B+src/Rules/Classes/RequireImplementsRule.php(En-src/Rules/Classes/TraitAttributeClassRule.phpHA5src/Rules/Classes/UnusedConstructorParametersRule.php& & 8src/Rules/Comparison/BooleanAndConstantConditionRule.php @௤8src/Rules/Comparison/BooleanNotConstantConditionRule.php7src/Rules/Comparison/BooleanOrConstantConditionRule.php Y٣4src/Rules/Comparison/ConstantConditionRuleHelper.phpi i 4src/Rules/Comparison/ConstantLooseComparisonRule.phpjjP9src/Rules/Comparison/DoWhileLoopConstantConditionRule.phpΤ4src/Rules/Comparison/ElseIfConstantConditionRule.phpu 0src/Rules/Comparison/IfConstantConditionRule.phpc c dF<src/Rules/Comparison/ImpossibleCheckTypeFunctionCallRule.phpĆФ2src/Rules/Comparison/ImpossibleCheckTypeHelper.phpcIcI*H:src/Rules/Comparison/ImpossibleCheckTypeMethodCallRule.phpYYP-@src/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRule.phpaaJt8src/Rules/Comparison/LogicalXorConstantConditionRule.php))I<,src/Rules/Comparison/MatchExpressionRule.php++ EcGsrc/Rules/Comparison/NumberComparisonOperatorsConstantConditionRule.php''$`Ϥ0src/Rules/Comparison/PossiblyImpureTipHelper.php...ä=src/Rules/Comparison/StrictComparisonOfDifferentTypesRule.phpkp O=src/Rules/Comparison/TernaryOperatorConstantConditionRule.phph h KT4Z7src/Rules/Comparison/UsageOfVoidMatchExpressionRule.phpee¢:src/Rules/Comparison/WhileLoopAlwaysFalseConditionRule.php  v=g9src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.phpI9src/Rules/Constants/AlwaysUsedClassConstantsExtension.phpQLEAsrc/Rules/Constants/AlwaysUsedClassConstantsExtensionProvider.phpDDs0src/Rules/Constants/ClassAsClassConstantRule.php,6L.src/Rules/Constants/ConstantAttributesRule.php*?7$src/Rules/Constants/ConstantRule.phpsrc/Rules/DeadCode/ConstructorWithoutImpurePointsCollector.php\\9J;src/Rules/DeadCode/FunctionWithoutImpurePointsCollector.phpbb9src/Rules/DeadCode/MethodWithoutImpurePointsCollector.phpf ʤsrc/Rules/DeadCode/NoopRule.phpue4src/Rules/DeadCode/PossiblyPureFuncCallCollector.phpn6src/Rules/DeadCode/PossiblyPureMethodCallCollector.php F/src/Rules/DeadCode/PossiblyPureNewCollector.phpee ;%[6src/Rules/DeadCode/PossiblyPureStaticCallCollector.php義/src/Rules/DeadCode/UnreachableStatementRule.phpO0src/Rules/DeadCode/UnusedPrivateConstantRule.php||@.src/Rules/DeadCode/UnusedPrivateMethodRule.phpccS] 0src/Rules/DeadCode/UnusedPrivatePropertyRule.php//0?"src/Rules/Debug/DebugScopeRule.phpoo.Yt&src/Rules/Debug/DumpNativeTypeRule.php:\&src/Rules/Debug/DumpPhpDocTypeRule.phpK됤 src/Rules/Debug/DumpTypeRule.phpRX`"src/Rules/Debug/FileAssertRule.phpY src/Rules/DirectRegistry.php$$i*.src/Rules/EnumCases/EnumCaseAttributesRule.phpDD k/src/Rules/EnumCases/EnumCaseOutsideEnumRule.php$$:#7src/Rules/Exceptions/CatchWithUnthrownExceptionRule.phpK K ^lZ5src/Rules/Exceptions/CaughtExceptionExistenceRule.phpN N Mw5src/Rules/Exceptions/DefaultExceptionTypeResolver.php'Ѥ.src/Rules/Exceptions/ExceptionTypeResolver.php46src/Rules/Exceptions/MethodThrowTypeCovarianceRule.php88vDsrc/Rules/Exceptions/MissingCheckedExceptionInFunctionThrowsRule.phpyyeKBsrc/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRule.phppWQHsrc/Rules/Exceptions/MissingCheckedExceptionInPropertyHookThrowsRule.php5=src/Rules/Exceptions/MissingCheckedExceptionInThrowsCheck.phpZZRh.src/Rules/Exceptions/NoncapturingCatchRule.php:src/Rules/Exceptions/OverwrittenExitPointByFinallyRule.php٤*src/Rules/Exceptions/ThrowExprTypeRule.phpDDfAä,src/Rules/Exceptions/ThrowExpressionRule.phpZZݮEsrc/Rules/Exceptions/ThrowsVoidFunctionWithExplicitThrowPointRule.phpw w .JCsrc/Rules/Exceptions/ThrowsVoidMethodWithExplicitThrowPointRule.php u>Isrc/Rules/Exceptions/ThrowsVoidPropertyHookWithExplicitThrowPointRule.php *x5src/Rules/Exceptions/TooWideFunctionThrowTypeRule.phpVV@^3src/Rules/Exceptions/TooWideMethodThrowTypeRule.php*9src/Rules/Exceptions/TooWidePropertyHookThrowTypeRule.php~~Ƣx.src/Rules/Exceptions/TooWideThrowTypeCheck.php  lAsrc/Rules/FileRuleError.phpnDB"src/Rules/FixableNodeRuleError.php>src/Rules/FoundTypeResult.phpĤ)src/Rules/FunctionCallParametersCheck.phpCwCw3\%src/Rules/FunctionDefinitionCheck.phpffLȧ%src/Rules/FunctionReturnTypeCheck.php~ ~ Yg'src/Rules/Functions/ArrayFilterRule.php4'src/Rules/Functions/ArrayValuesRule.php{{XI3src/Rules/Functions/ArrowFunctionAttributesRule.phpxx<src/Rules/Functions/ArrowFunctionReturnNullsafeByRefRule.phpx~A3src/Rules/Functions/ArrowFunctionReturnTypeRule.php (Z)src/Rules/Functions/CallCallablesRule.phpSܤ4src/Rules/Functions/CallToFunctionParametersRule.php 55@src/Rules/Functions/CallToFunctionStatementWithNoDiscardRule.phpEsrc/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php% % Ϡ25src/Rules/Functions/CallToNonExistentFunctionRule.php f(src/Rules/Functions/CallUserFuncRule.php ,"-src/Rules/Functions/ClosureAttributesRule.php`` Ѥ-src/Rules/Functions/ClosureReturnTypeRule.php++քӤ,src/Rules/Functions/DefineParametersRule.php8src/Rules/Functions/DuplicateFunctionDeclarationRule.phpBafCsrc/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRule.php88^=src/Rules/Functions/ExistingClassesInClosureTypehintsRule.php?-6src/Rules/Functions/ExistingClassesInTypehintsRule.php%src/Rules/Functions/FilterVarRule.phpj\.src/Rules/Functions/FunctionAttributesRule.phpddU|,src/Rules/Functions/FunctionCallableRule.php//5K<src/Rules/Functions/ImplodeParameterCastableToStringRule.php dIsrc/Rules/Functions/IncompatibleArrowFunctionDefaultParameterTypeRule.php KƤCsrc/Rules/Functions/IncompatibleClosureDefaultParameterTypeRule.phpl<src/Rules/Functions/IncompatibleDefaultParameterTypeRule.php\33)src/Rules/Functions/InnerFunctionRule.php+U֤?src/Rules/Functions/InvalidLexicalVariablesInClosureUseRule.php~0src/Rules/Functions/InvalidParameterNameRule.phpLV <src/Rules/Functions/MissingFunctionParameterTypehintRule.phpnn9src/Rules/Functions/MissingFunctionReturnTypehintRule.php Ĥ+src/Rules/Functions/ParamAttributesRule.phpʃ5src/Rules/Functions/ParameterCastableToNumberRule.php{ { #Ф5src/Rules/Functions/ParameterCastableToStringRule.php| | s֊1src/Rules/Functions/PrintfArrayParametersRule.phpo#($src/Rules/Functions/PrintfHelper.phpll%$/src/Rules/Functions/PrintfParameterTypeRule.phpCgP,src/Rules/Functions/PrintfParametersRule.phpe)src/Rules/Functions/PrintfPlaceholder.php A@/src/Rules/Functions/RandomIntParametersRule.php H}/src/Rules/Functions/RedefinedParametersRule.php  C/src/Rules/Functions/ReturnNullsafeByRefRule.php&src/Rules/Functions/ReturnTypeRule.phpOO!R9src/Rules/Functions/SortParameterCastableToStringRule.phpsu"-src/Rules/Functions/UnusedClosureUsesRule.phpOg6src/Rules/Functions/UselessFunctionReturnValueRule.php 9src/Rules/Functions/VariadicParametersDeclarationRule.phpuuoyФ*src/Rules/Generators/YieldFromTypeRule.php!̩-src/Rules/Generators/YieldInGeneratorRule.phpSK&src/Rules/Generators/YieldTypeRule.phph h z))src/Rules/Generics/ClassAncestorsRule.php22,src/Rules/Generics/ClassTemplateTypeRule.php?A֤1src/Rules/Generics/CrossCheckInterfacesHelper.phpR R Έ(src/Rules/Generics/EnumAncestorsRule.php 3+src/Rules/Generics/EnumTemplateTypeRule.phpv4src/Rules/Generics/FunctionSignatureVarianceRule.phpzzɤ/src/Rules/Generics/FunctionTemplateTypeRule.php  m,src/Rules/Generics/GenericAncestorsCheck.php?k -src/Rules/Generics/GenericObjectTypeCheck.php -src/Rules/Generics/InterfaceAncestorsRule.phpܮ0src/Rules/Generics/InterfaceTemplateTypeRule.php}!ˤ2src/Rules/Generics/MethodSignatureVarianceRule.phpv1src/Rules/Generics/MethodTagTemplateTypeCheck.php I0src/Rules/Generics/MethodTagTemplateTypeRule.php75src/Rules/Generics/MethodTagTemplateTypeTraitRule.phpm-src/Rules/Generics/MethodTemplateTypeRule.php+src/Rules/Generics/PropertyVarianceRule.phpiiA柤(src/Rules/Generics/TemplateTypeCheck.php|(|(Dl,src/Rules/Generics/TraitTemplateTypeRule.php v%src/Rules/Generics/UsedTraitsRule.php vO7$src/Rules/Generics/VarianceCheck.phpSS9p!src/Rules/IdentifierRuleError.phpR)src/Rules/Ignore/IgnoreParseErrorRule.php2Gsrc/Rules/InternalTag/RestrictedInternalClassConstantUsageExtension.php Csrc/Rules/InternalTag/RestrictedInternalClassNameUsageExtension.php. . (Bsrc/Rules/InternalTag/RestrictedInternalFunctionUsageExtension.phpC0\@src/Rules/InternalTag/RestrictedInternalMethodUsageExtension.phpQ Q L7 Bsrc/Rules/InternalTag/RestrictedInternalPropertyUsageExtension.php I27src/Rules/InternalTag/RestrictedInternalUsageHelper.phpzsrc/Rules/IssetCheck.phpA4A4ӅT.src/Rules/Keywords/ContinueBreakInLoopRule.phpaajԤ-src/Rules/Keywords/DeclareStrictTypesRule.phpO,src/Rules/Keywords/RequireFileExistsRule.phpM.ͤsrc/Rules/LazyRegistry.phpt_2src/Rules/LineRuleError.php}R0src/Rules/MetadataRuleError.php:src/Rules/Methods/AbstractMethodInNonAbstractClassRule.phpT寤/src/Rules/Methods/AbstractPrivateMethodRule.php%%O/src/Rules/Methods/AlwaysUsedMethodExtension.phpZZI7src/Rules/Methods/AlwaysUsedMethodExtensionProvider.php((*K%src/Rules/Methods/CallMethodsRule.phpq8src/Rules/Methods/CallPrivateMethodThroughStaticRule.php<<֪Ȥ+src/Rules/Methods/CallStaticMethodsRule.php55j̧Fsrc/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.phpdd<src/Rules/Methods/CallToMethodStatementWithNoDiscardRule.php/<Asrc/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php\ \ _Bsrc/Rules/Methods/CallToStaticMethodStatementWithNoDiscardRule.php̅*Gsrc/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php ʘ:src/Rules/Methods/ConsistentConstructorDeclarationRule.phpPޤ/src/Rules/Methods/ConsistentConstructorRule.phpee`c,/src/Rules/Methods/ConstructorReturnTypeRule.php-(=src/Rules/Methods/DirectAlwaysUsedMethodExtensionProvider.php>R4src/Rules/Methods/ExistingClassesInTypehintsRule.php>#&(src/Rules/PhpDoc/RequireExtendsCheck.php--i46src/Rules/PhpDoc/RequireExtendsDefinitionClassRule.php_6src/Rules/PhpDoc/RequireExtendsDefinitionTraitRule.php[<濤9src/Rules/PhpDoc/RequireImplementsDefinitionClassRule.php99N9src/Rules/PhpDoc/RequireImplementsDefinitionTraitRule.phpKVɤ.src/Rules/PhpDoc/SealedDefinitionClassRule.php Uߤ.src/Rules/PhpDoc/SealedDefinitionTraitRule.phpee@ܤ+src/Rules/PhpDoc/UnresolvableTypeHelper.phpnnO4src/Rules/PhpDoc/VarTagChangedExpressionTypeRule.phpz/ )src/Rules/PhpDoc/VarTagTypeRuleHelper.php%*%*)x2src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php55ņ *src/Rules/Playground/FunctionNeverRule.phpQQG( 4(src/Rules/Playground/MethodNeverRule.phpssK(src/Rules/Playground/NeverRuleHelper.php  &src/Rules/Playground/NoPhpCodeRule.phpTTѠä-src/Rules/Playground/NotAnalysedTraitRule.phppMy*src/Rules/Playground/PhpdocCommentRule.php!la-src/Rules/Playground/PromoteParameterRule.phpff즡1src/Rules/Playground/StaticVarWithoutTypeRule.phpssG!%?src/Rules/Properties/AccessPrivatePropertyThroughStaticRule.phphhz.src/Rules/Properties/AccessPropertiesCheck.phpP,P,t*5src/Rules/Properties/AccessPropertiesInAssignRule.phpS(-src/Rules/Properties/AccessPropertiesRule.phpE-4src/Rules/Properties/AccessStaticPropertiesCheck.php((騤;src/Rules/Properties/AccessStaticPropertiesInAssignRule.phpmD3src/Rules/Properties/AccessStaticPropertiesRule.php22*Bsrc/Rules/Properties/DefaultValueTypesAssignedToPropertiesRule.php~Csrc/Rules/Properties/DirectReadWritePropertiesExtensionProvider.phpmmy8src/Rules/Properties/ExistingClassesInPropertiesRule.phpx&6Csrc/Rules/Properties/ExistingClassesInPropertyHookTypehintsRule.php LS0src/Rules/Properties/FoundPropertyReflection.php:src/Rules/Properties/GetNonVirtualPropertyHookReadRule.php22(oQ8src/Rules/Properties/InvalidCallablePropertyTypeRule.phpX/w!Asrc/Rules/Properties/LazyReadWritePropertiesExtensionProvider.php4ޤ4src/Rules/Properties/MissingPropertyTypehintRule.php -Bsrc/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRule.php  :src/Rules/Properties/MissingReadOnlyPropertyAssignRule.phpv v ol2src/Rules/Properties/NullsafePropertyFetchRule.phpuuPz/src/Rules/Properties/OverridingPropertyRule.phpEE5{*2src/Rules/Properties/PropertiesInInterfaceRule.php, , W.src/Rules/Properties/PropertyAssignRefRule.phpvvQb;/src/Rules/Properties/PropertyAttributesRule.phpPPz+src/Rules/Properties/PropertyDescriptor.phpbj3src/Rules/Properties/PropertyHookAttributesRule.phpaқ,src/Rules/Properties/PropertyInClassRule.php(11src/Rules/Properties/PropertyReflectionFinder.phpRRF"#>src/Rules/Properties/ReadOnlyByPhpDocPropertyAssignRefRule.php"jѤ;src/Rules/Properties/ReadOnlyByPhpDocPropertyAssignRule.php<6O5src/Rules/Properties/ReadOnlyByPhpDocPropertyRule.php6src/Rules/Properties/ReadOnlyPropertyAssignRefRule.phpCC;!U93src/Rules/Properties/ReadOnlyPropertyAssignRule.phpW-src/Rules/Properties/ReadOnlyPropertyRule.php_`Τ5src/Rules/Properties/ReadWritePropertiesExtension.phpzjj=src/Rules/Properties/ReadWritePropertiesExtensionProvider.php--7src/Rules/Properties/ReadingWriteOnlyPropertiesRule.phpj j \5rP<src/Rules/Properties/SetNonVirtualPropertyHookAssignRule.php n5src/Rules/Properties/SetPropertyHookParameterRule.phpR146src/Rules/Properties/TypesAssignedToPropertiesRule.php' Z2src/Rules/Properties/UninitializedPropertyRule.phpxb8src/Rules/Properties/WritingToReadOnlyPropertiesRule.phpK K $/5&src/Rules/Pure/FunctionPurityCheck.php]J#src/Rules/Pure/PureFunctionRule.php++De!src/Rules/Pure/PureMethodRule.phpYY81src/Rules/Regexp/RegularExpressionPatternRule.phpZ1src/Rules/Regexp/RegularExpressionQuotingRule.php+ksrc/Rules/Registry.php&&j Csrc/Rules/RestrictedUsage/RestrictedClassConstantUsageExtension.phpI'>src/Rules/RestrictedUsage/RestrictedClassConstantUsageRule.php__T?src/Rules/RestrictedUsage/RestrictedClassNameUsageExtension.php.;Asrc/Rules/RestrictedUsage/RestrictedFunctionCallableUsageRule.phpZ>src/Rules/RestrictedUsage/RestrictedFunctionUsageExtension.phpP9src/Rules/RestrictedUsage/RestrictedFunctionUsageRule.phpOj?src/Rules/RestrictedUsage/RestrictedMethodCallableUsageRule.php  S H<src/Rules/RestrictedUsage/RestrictedMethodUsageExtension.phpU`zq7src/Rules/RestrictedUsage/RestrictedMethodUsageRule.php P>src/Rules/RestrictedUsage/RestrictedPropertyUsageExtension.phpoG9src/Rules/RestrictedUsage/RestrictedPropertyUsageRule.php TEsrc/Rules/RestrictedUsage/RestrictedStaticMethodCallableUsageRule.php``@]=src/Rules/RestrictedUsage/RestrictedStaticMethodUsageRule.php  V?src/Rules/RestrictedUsage/RestrictedStaticPropertyUsageRule.phpYYW?N-src/Rules/RestrictedUsage/RestrictedUsage.php==j <Gsrc/Rules/RestrictedUsage/RestrictedUsageOfDeprecatedStringCastRule.php0 0 %Lsrc/Rules/RestrictedUsage/RewrittenDeclaringClassClassConstantReflection.php poEsrc/Rules/RestrictedUsage/RewrittenDeclaringClassMethodReflection.php~ƤGsrc/Rules/RestrictedUsage/RewrittenDeclaringClassPropertyReflection.php]]G(Ysrc/Rules/Rule.phpaa/Jsrc/Rules/RuleError.php src/Rules/RuleErrorBuilder.php|ŠѤ#src/Rules/RuleErrors/RuleError1.phpDD0%src/Rules/RuleErrors/RuleError101.php'%src/Rules/RuleErrors/RuleError103.phpNS%src/Rules/RuleErrors/RuleError105.phpB%src/Rules/RuleErrors/RuleError107.phpjB%src/Rules/RuleErrors/RuleError109.php0%$src/Rules/RuleErrors/RuleError11.phphh3}:d%src/Rules/RuleErrors/RuleError111.phpy:J%src/Rules/RuleErrors/RuleError113.php##%src/Rules/RuleErrors/RuleError115.phpu*%src/Rules/RuleErrors/RuleError117.phpBBŌä%src/Rules/RuleErrors/RuleError119.php]%src/Rules/RuleErrors/RuleError121.phpwט%src/Rules/RuleErrors/RuleError123.phpFFO.%src/Rules/RuleErrors/RuleError125.php%src/Rules/RuleErrors/RuleError127.phpeeվa%src/Rules/RuleErrors/RuleError129.phplt$src/Rules/RuleErrors/RuleError13.php$%src/Rules/RuleErrors/RuleError131.phprL%src/Rules/RuleErrors/RuleError133.phpA|%src/Rules/RuleErrors/RuleError135.phph2%src/Rules/RuleErrors/RuleError137.phpEٜ%src/Rules/RuleErrors/RuleError139.phpC4J%src/Rules/RuleErrors/RuleError141.php!%src/Rules/RuleErrors/RuleError143.php11B%src/Rules/RuleErrors/RuleError145.php{/r%src/Rules/RuleErrors/RuleError147.php55C|:%src/Rules/RuleErrors/RuleError149.phpmv$src/Rules/RuleErrors/RuleError15.php%src/Rules/RuleErrors/RuleError151.phpTT=L%src/Rules/RuleErrors/RuleError153.php66%src/Rules/RuleErrors/RuleError155.phpX_%src/Rules/RuleErrors/RuleError157.phpUUAӤ%src/Rules/RuleErrors/RuleError159.php@|Ĥ%src/Rules/RuleErrors/RuleError161.phps%src/Rules/RuleErrors/RuleError163.phphh-f%src/Rules/RuleErrors/RuleError165.phphOQڤ%src/Rules/RuleErrors/RuleError167.php9M%src/Rules/RuleErrors/RuleError169.phpiiG`$src/Rules/RuleErrors/RuleError17.php~ eQ%src/Rules/RuleErrors/RuleError171.phpĤ%src/Rules/RuleErrors/RuleError173.phpi%src/Rules/RuleErrors/RuleError175.phpW%%src/Rules/RuleErrors/RuleError177.phpx@j%src/Rules/RuleErrors/RuleError179.php,ä%src/Rules/RuleErrors/RuleError181.phpeV%src/Rules/RuleErrors/RuleError183.php<<%src/Rules/RuleErrors/RuleError185.php*)գ%src/Rules/RuleErrors/RuleError187.phpbo%src/Rules/RuleErrors/RuleError189.php==A;¤$src/Rules/RuleErrors/RuleError19.phpEֵN%src/Rules/RuleErrors/RuleError191.php2x%%src/Rules/RuleErrors/RuleError193.php//,C$%src/Rules/RuleErrors/RuleError195.php%src/Rules/RuleErrors/RuleError197.phpNNdx%src/Rules/RuleErrors/RuleError235.php::y,Ӥ%src/Rules/RuleErrors/RuleError237.php4#3%src/Rules/RuleErrors/RuleError239.phpYY%src/Rules/RuleErrors/RuleError241.php?:u%src/Rules/RuleErrors/RuleError243.php]]l%src/Rules/RuleErrors/RuleError245.php{@e%src/Rules/RuleErrors/RuleError247.php||ƨ%src/Rules/RuleErrors/RuleError249.php^^C$src/Rules/RuleErrors/RuleError25.php%src/Rules/RuleErrors/RuleError251.phpXƤ%src/Rules/RuleErrors/RuleError253.php}}"Ԥ%src/Rules/RuleErrors/RuleError255.phpP$src/Rules/RuleErrors/RuleError27.phpa$src/Rules/RuleErrors/RuleError29.php5#src/Rules/RuleErrors/RuleError3.phpE$src/Rules/RuleErrors/RuleError31.php<<J8!$src/Rules/RuleErrors/RuleError33.php--.l6q$src/Rules/RuleErrors/RuleError35.php|$src/Rules/RuleErrors/RuleError37.phpLLmo$src/Rules/RuleErrors/RuleError39.php$src/Rules/RuleErrors/RuleError41.phpt $src/Rules/RuleErrors/RuleError43.phpPP2K$src/Rules/RuleErrors/RuleError45.phpxӎW$src/Rules/RuleErrors/RuleError47.phpoo-s)¤$src/Rules/RuleErrors/RuleError49.php0#src/Rules/RuleErrors/RuleError5.phpccヤ$src/Rules/RuleErrors/RuleError51.phpssfJ$src/Rules/RuleErrors/RuleError53.phpHWw$src/Rules/RuleErrors/RuleError55.php~$src/Rules/RuleErrors/RuleError57.phpttr0$src/Rules/RuleErrors/RuleError59.phpp$src/Rules/RuleErrors/RuleError61.php$src/Rules/RuleErrors/RuleError63.php$$mn$src/Rules/RuleErrors/RuleError65.phpnޭΤ$src/Rules/RuleErrors/RuleError67.phpFP\$src/Rules/RuleErrors/RuleError69.phpWD#src/Rules/RuleErrors/RuleError7.phpG$src/Rules/RuleErrors/RuleError71.php55Y" $src/Rules/RuleErrors/RuleError73.php?S$src/Rules/RuleErrors/RuleError75.phpsrc/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php7!;src/Rules/TooWideTypehints/TooWideParameterOutTypeCheck.phpg g z`6src/Rules/TooWideTypehints/TooWidePropertyTypeRule.php ]r/src/Rules/TooWideTypehints/TooWideTypeCheck.phpCC*_2src/Rules/Traits/ConflictingTraitConstantsRule.php''P*src/Rules/Traits/ConstantsInTraitsRule.phpQQ!{/)src/Rules/Traits/NotAnalysedTraitRule.phps(src/Rules/Traits/TraitAttributesRule.phpO7).src/Rules/Traits/TraitDeclarationCollector.php+-X&src/Rules/Traits/TraitUseCollector.phpQFG+src/Rules/Types/InvalidTypesInUnionRule.php Ƥ+src/Rules/UnusedFunctionParametersCheck.php99ݔߤ8src/Rules/Variables/AssignToByRefExprFromForeachRule.php}}!,src/Rules/Variables/CompactVariablesRule.php ]+src/Rules/Variables/DefinedVariableRule.php  ʙ|!src/Rules/Variables/EmptyRule.php{{`71src/Rules/Variables/InvalidVariableAssignRule.phppc!src/Rules/Variables/IssetRule.php  Ĭ(src/Rules/Variables/NullCoalesceRule.phpuV4src/Rules/Variables/ParameterOutAssignedTypeRule.php [8src/Rules/Variables/ParameterOutExecutionEndTypeRule.phpVɥ1src/Rules/Variables/ThisInGlobalStatementRule.php,,E>n1src/Rules/Variables/ThisInStaticStatementRule.phpqD#!src/Rules/Variables/UnsetRule.php\+src/Rules/Variables/VariableCloningRule.php?z+src/Rules/Whitespace/FileWhitespaceRule.php 湡 src/ShouldNotHappenException.phpsrc/Testing/CompositeRule.phpOGsrc/Testing/DelayedRule.php22`b&src/Testing/ErrorFormatterTestCase.php>>%src/Testing/LevelsTestCase.phpII1KH,src/Testing/NonexistentAnalysedClassRule.php\ܤ,src/Testing/NonexistentAnalysedTraitRule.phpFsrc/Testing/PHPStanTestCase.php[[rԤ$src/Testing/PHPStanTestCaseTrait.php ^1դ,src/Testing/PHPUnit/ContainerInitializer.phpAtAsrc/Testing/PHPUnit/InitContainerBeforeDataProviderSubscriber.phpve9src/Testing/PHPUnit/InitContainerBeforeTestSubscriber.php\Y/src/Testing/PHPUnit/PHPStanPHPUnitExtension.phpkGsrc/Testing/RuleTestCase.php--pǖsrc/Testing/TestCase.neon˸,src/Testing/TestCaseSourceLocatorFactory.php-nf%src/Testing/TypeInferenceTestCase.phpJJ_src/Testing/functions.phpߟ,src/TrinaryLogic.php)Ɇ#src/Turbo/TurboExtensionEnabler.php isrc/Type/AcceptsResult.phpg&-src/Type/Accessory/AccessoryArrayListType.php116=1src/Type/Accessory/AccessoryLiteralStringType.php##-b3src/Type/Accessory/AccessoryLowercaseStringType.php$$I2src/Type/Accessory/AccessoryNonEmptyStringType.php%%]'w2src/Type/Accessory/AccessoryNonFalsyStringType.php%% ^1src/Type/Accessory/AccessoryNumericStringType.php|%|%M$src/Type/Accessory/AccessoryType.phpG G |ɰ3src/Type/Accessory/AccessoryUppercaseStringType.php$$~O$src/Type/Accessory/HasMethodType.php""q:$src/Type/Accessory/HasOffsetType.php006)src/Type/Accessory/HasOffsetValueType.php;;?Rܢ&src/Type/Accessory/HasPropertyType.phpTTle](src/Type/Accessory/NonEmptyArrayType.php00~B)src/Type/Accessory/OversizedArrayType.php++8xsrc/Type/ArrayType.phpqqi src/Type/BenevolentUnionType.phpyy_src/Type/BitwiseFlagHelper.php""THsrc/Type/BooleanType.php>src/Type/CallableType.php ` `nsrc/Type/CallableTypeHelper.phpĝN1src/Type/CircularTypeAliasDefinitionException.phpűä'src/Type/CircularTypeAliasErrorType.php[}$src/Type/ClassConstantAccessType.php" " vs(src/Type/ClassNameToObjectTypeResult.php33LCsrc/Type/ClassStringType.php$ $ /src/Type/ClosureType.phpnn铬Lsrc/Type/ClosureTypeFactory.phpmAˤsrc/Type/CompoundType.php22~Bsrc/Type/ConditionalType.php))ϋժ(src/Type/ConditionalTypeForParameter.php))׎l'src/Type/Constant/ConstantArrayType.phpCC;f(0src/Type/Constant/ConstantArrayTypeAndMethod.php6.src/Type/Constant/ConstantArrayTypeBuilder.php==T)src/Type/Constant/ConstantBooleanType.phpB(=Y'src/Type/Constant/ConstantFloatType.php )src/Type/Constant/ConstantIntegerType.php q-}2src/Type/Constant/ConstantScalarToBooleanTrait.php Mm(src/Type/Constant/ConstantStringType.php7Q7Q +src/Type/Constant/OversizedArrayBuilder.php99src/Type/ConstantScalarType.phpDD &src/Type/ConstantTypeHelper.php@訤,src/Type/DirectTypeAliasResolverProvider.php)L/src/Type/DynamicFunctionReturnTypeExtension.php||O.src/Type/DynamicFunctionThrowTypeExtension.phpjjl-src/Type/DynamicMethodReturnTypeExtension.phpNc,src/Type/DynamicMethodThrowTypeExtension.phpeeق/src/Type/DynamicReturnTypeExtensionRegistry.phpnn "13src/Type/DynamicStaticMethodReturnTypeExtension.phpK2src/Type/DynamicStaticMethodThrowTypeExtension.php{˒$src/Type/Enum/EnumCaseObjectType.phpKsrc/Type/ErrorType.phpRVWsrc/Type/ExponentiateHelper.php̤,src/Type/ExpressionTypeResolverExtension.phpHHLҤ4src/Type/ExpressionTypeResolverExtensionRegistry.php,,8src/Type/FileTypeMapper.php00msrc/Type/FloatType.php^^u2src/Type/FunctionParameterClosureThisExtension.php~2src/Type/FunctionParameterClosureTypeExtension.php\.src/Type/FunctionParameterOutTypeExtension.php5,src/Type/FunctionTypeSpecifyingExtension.php( F src/Type/GeneralizePrecision.php""r͕+src/Type/Generic/GenericClassStringType.php%%=Lؤ&src/Type/Generic/GenericObjectType.php;;6&src/Type/Generic/GenericStaticType.php##,+&src/Type/Generic/TemplateArrayType.php~Ф0src/Type/Generic/TemplateBenevolentUnionType.phpGGlm(src/Type/Generic/TemplateBooleanType.phpVԤ.src/Type/Generic/TemplateConstantArrayType.php--5-0src/Type/Generic/TemplateConstantIntegerType.php>>Aں/src/Type/Generic/TemplateConstantStringType.php99L|&src/Type/Generic/TemplateFloatType.php}wZ.src/Type/Generic/TemplateGenericObjectType.php%(src/Type/Generic/TemplateIntegerType.php`-src/Type/Generic/TemplateIntersectionType.php )src/Type/Generic/TemplateIterableType.php++^&src/Type/Generic/TemplateKeyOfType.php@&src/Type/Generic/TemplateMixedType.php//fߴ%src/Type/Generic/TemplateNullType.phpe,src/Type/Generic/TemplateObjectShapeType.phpGG'src/Type/Generic/TemplateObjectType.php  83src/Type/Generic/TemplateObjectWithoutClassType.php uh,src/Type/Generic/TemplateStrictMixedType.php<8'src/Type/Generic/TemplateStringType.php˜!src/Type/Generic/TemplateType.php22]1src/Type/Generic/TemplateTypeArgumentStrategy.phpk 5(src/Type/Generic/TemplateTypeFactory.phpjjz'src/Type/Generic/TemplateTypeHelper.phppʁ$src/Type/Generic/TemplateTypeMap.php92src/Type/Generic/TemplateTypeParameterStrategy.phpk*src/Type/Generic/TemplateTypeReference.phpb0ʤ&src/Type/Generic/TemplateTypeScope.phpȓؤ)src/Type/Generic/TemplateTypeStrategy.php::7^)&src/Type/Generic/TemplateTypeTrait.php22U)src/Type/Generic/TemplateTypeVariance.php%%a`,src/Type/Generic/TemplateTypeVarianceMap.phph&src/Type/Generic/TemplateUnionType.php,,y)src/Type/Generic/TypeProjectionHelper.phprrdo'src/Type/Helper/GetTemplateTypeType.phpH H nsrc/Type/IntegerRangeType.php__isrc/Type/IntegerType.phpH դsrc/Type/IntersectionType.php  T src/Type/IsSuperTypeOfResult.phpKK}isrc/Type/IterableType.phpT=T=+>5"src/Type/JustNullableTypeTrait.phpXsrc/Type/KeyOfType.phpS S ӱsrc/Type/LateResolvableType.php3H*src/Type/LazyTypeAliasResolverProvider.php"src/Type/LooseComparisonHelper.php {*0src/Type/MethodParameterClosureThisExtension.phpm0src/Type/MethodParameterClosureTypeExtension.phpqqLk,src/Type/MethodParameterOutTypeExtension.php*src/Type/MethodTypeSpecifyingExtension.phpDDHg/src/Type/MixedType.phpsrc/Type/NeverType.php@@%뤤src/Type/NewObjectType.phpc c "src/Type/NonAcceptingNeverType.php'src/Type/NonexistentParentClassType.php$$#bxsrc/Type/NullType.php**%*src/Type/ObjectShapePropertyReflection.php avsrc/Type/ObjectShapeType.phpMMr_1#src/Type/ObjectType.phpWr#src/Type/ObjectWithoutClassType.phpBksrc/Type/OffsetAccessType.php J뒤,src/Type/OperatorTypeSpecifyingExtension.php4b4src/Type/OperatorTypeSpecifyingExtensionRegistry.phpUsrc/Type/PHPStan/ClassNameUsageLocationCreateIdentifierDynamicReturnTypeExtension.phptte攤(src/Type/ParserNodeTypeToPHPStanType.php6src/Type/Php/AbsFunctionDynamicReturnTypeExtension.php**G9src/Type/Php/ArgumentBasedFunctionReturnTypeExtension.php  >src/Type/Php/ArrayChangeKeyCaseFunctionReturnTypeExtension.phpYYIϲ6src/Type/Php/ArrayChunkFunctionReturnTypeExtension.php\\HMդ7src/Type/Php/ArrayColumnFunctionReturnTypeExtension.phpd"src/Type/Php/ArrayColumnHelper.php۩}8src/Type/Php/ArrayCombineFunctionReturnTypeExtension.php&7src/Type/Php/ArrayCombineFunctionThrowTypeExtension.phpד%#src/Type/Php/ArrayCombineHelper.phpc]6o;src/Type/Php/ArrayCountValuesDynamicReturnTypeExtension.phpۤ7src/Type/Php/ArrayCurrentDynamicReturnTypeExtension.php>>%5src/Type/Php/ArrayFillFunctionReturnTypeExtension.phpA A e9src/Type/Php/ArrayFillKeysFunctionReturnTypeExtension.php__F?7src/Type/Php/ArrayFilterFunctionReturnTypeExtension.php;;~4src/Type/Php/ArrayFilterFunctionReturnTypeHelper.php00(բ5src/Type/Php/ArrayFindFunctionReturnTypeExtension.phpԿ8src/Type/Php/ArrayFindKeyFunctionReturnTypeExtension.phpss@9src/Type/Php/ArrayFirstLastDynamicReturnTypeExtension.php,,;P5src/Type/Php/ArrayFlipFunctionReturnTypeExtension.php88k=src/Type/Php/ArrayIntersectKeyFunctionReturnTypeExtension.php7?3src/Type/Php/ArrayKeyDynamicReturnTypeExtension.php(U>src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php%%ڵ<src/Type/Php/ArrayKeysFunctionDynamicReturnTypeExtension.phpQH.y4src/Type/Php/ArrayMapFunctionReturnTypeExtension.phpuuo 1=src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.phphM>4src/Type/Php/ArrayNextDynamicReturnTypeExtension.php>%3src/Type/Php/ArrayPadDynamicReturnTypeExtension.php  X@src/Type/Php/ArrayPointerFunctionsDynamicReturnTypeExtension.php""4src/Type/Php/ArrayPopFunctionReturnTypeExtension.php  ͏5src/Type/Php/ArrayRandFunctionReturnTypeExtension.phpVVsrc/Type/Php/ArraySearchFunctionDynamicReturnTypeExtension.phpb;src/Type/Php/ArraySearchFunctionTypeSpecifyingExtension.php _6src/Type/Php/ArrayShiftFunctionReturnTypeExtension.phpܤ6src/Type/Php/ArraySliceFunctionReturnTypeExtension.php٤7src/Type/Php/ArraySpliceFunctionReturnTypeExtension.phpK0%;src/Type/Php/ArraySumFunctionDynamicReturnTypeExtension.phpq>src/Type/Php/ArrayValuesFunctionDynamicReturnTypeExtension.phpll֥6src/Type/Php/AssertFunctionTypeSpecifyingExtension.php8M)src/Type/Php/AssertThrowTypeExtension.phpppo?src/Type/Php/BackedEnumFromMethodDynamicReturnTypeExtension.php .?src/Type/Php/Base64DecodeDynamicFunctionReturnTypeExtension.php""MT<src/Type/Php/BcMathNumberOperatorTypeSpecifyingExtension.php  C&6src/Type/Php/BcMathStringOrNullReturnTypeExtension.php''=t;src/Type/Php/ClassExistsFunctionTypeSpecifyingExtension.php{ { k;src/Type/Php/ClassImplementsFunctionReturnTypeExtension.php6src/Type/Php/ClosureBindDynamicReturnTypeExtension.php/8src/Type/Php/ClosureBindToDynamicReturnTypeExtension.php:_>src/Type/Php/ClosureFromCallableDynamicReturnTypeExtension.phpL֤<src/Type/Php/ClosureGetCurrentDynamicReturnTypeExtension.phpTx3src/Type/Php/CompactFunctionReturnTypeExtension.php ,㿤4src/Type/Php/ConstantFunctionReturnTypeExtension.phpOOCsrc/Type/Php/ConstantHelper.phpܶ=src/Type/Php/CountCharsFunctionDynamicReturnTypeExtension.phpӤ1src/Type/Php/CountFunctionReturnTypeExtension.phpzz V5src/Type/Php/CountFunctionTypeSpecifyingExtension.phptѤ:src/Type/Php/CtypeDigitFunctionTypeSpecifyingExtension.php >src/Type/Php/CurlGetinfoFunctionDynamicReturnTypeExtension.phpX#X#*2^6src/Type/Php/DateFormatFunctionReturnTypeExtension.phpK]4src/Type/Php/DateFormatMethodReturnTypeExtension.php__?0src/Type/Php/DateFunctionReturnTypeExtension.php¥*z-src/Type/Php/DateFunctionReturnTypeHelper.php  7:src/Type/Php/DateIntervalConstructorThrowTypeExtension.phpvCsrc/Type/Php/DateIntervalCreateFromDateStringThrowTypeExtension.phpwwx7src/Type/Php/DateIntervalDynamicReturnTypeExtension.phpr=src/Type/Php/DateIntervalFormatDynamicReturnTypeExtension.phpF>V>src/Type/Php/DateIntervalFormatFunctionReturnTypeExtension.php{B3src/Type/Php/DateIntervalFormatReturnTypeHelper.php  .U9src/Type/Php/DatePeriodConstructorReturnTypeExtension.php q6src/Type/Php/DateTimeConstructorThrowTypeExtension.php??S-9src/Type/Php/DateTimeCreateDynamicReturnTypeExtension.phprrھ>v3src/Type/Php/DateTimeDynamicReturnTypeExtension.phppp1!07src/Type/Php/DateTimeModifyMethodThrowTypeExtension.phpaӷ2src/Type/Php/DateTimeModifyReturnTypeExtension.php 4src/Type/Php/DateTimeSubMethodThrowTypeExtension.php55C:src/Type/Php/DateTimeZoneConstructorThrowTypeExtension.php̉6src/Type/Php/DefineConstantTypeSpecifyingExtension.phpRR>C7src/Type/Php/DefinedConstantTypeSpecifyingExtension.phpj:src/Type/Php/DioStatDynamicFunctionReturnTypeExtension.php|dCsrc/Type/Php/DomDocumentCreateElementDynamicReturnTypeExtension.phpCCBsrc/Type/Php/DomDocumentCreateElementDynamicThrowTypeExtension.php¤5src/Type/Php/DsMapDynamicMethodThrowTypeExtension.php0src/Type/Php/DsMapDynamicReturnTypeExtension.php{{o:src/Type/Php/ExplodeFunctionDynamicReturnTypeExtension.php 5_/src/Type/Php/FilterFunctionReturnTypeHelper.php1M1MQ6src/Type/Php/FilterInputDynamicReturnTypeExtension.phpzz6)9src/Type/Php/FilterVarArrayDynamicReturnTypeExtension.phpj j ߙ4src/Type/Php/FilterVarDynamicReturnTypeExtension.phpM+/,src/Type/Php/FilterVarThrowTypeExtension.phpC C e*.>src/Type/Php/FunctionExistsFunctionTypeSpecifyingExtension.phpXXx:9src/Type/Php/GetCalledClassDynamicReturnTypeExtension.php{(3src/Type/Php/GetClassDynamicReturnTypeExtension.phpϖ:8src/Type/Php/GetDebugTypeFunctionReturnTypeExtension.php--1פ:src/Type/Php/GetDefinedVarsFunctionReturnTypeExtension.phpQQ$^Asrc/Type/Php/GetParentClassDynamicFunctionReturnTypeExtension.php ?src/Type/Php/GettimeofdayDynamicFunctionReturnTypeExtension.phpI3src/Type/Php/GettypeFunctionReturnTypeExtension.phpb b RY83src/Type/Php/GmpOperatorTypeSpecifyingExtension.php8src/Type/Php/GmpUnaryOperatorTypeSpecifyingExtension.php۠Y1src/Type/Php/HashFunctionsReturnTypeExtension.php??>:src/Type/Php/HighlightStringDynamicReturnTypeExtension.phpAAdB2src/Type/Php/HrtimeFunctionReturnTypeExtension.phpFFu91src/Type/Php/IdateFunctionReturnTypeExtension.php  9.src/Type/Php/IdateFunctionReturnTypeHelper.php nA3src/Type/Php/ImplodeFunctionReturnTypeExtension.php~~PĤ7src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php..¤*src/Type/Php/IniGetReturnTypeExtension.php2)src/Type/Php/IntdivThrowTypeExtension.phpI3src/Type/Php/IsAFunctionTypeSpecifyingExtension.php J%N0src/Type/Php/IsAFunctionTypeSpecifyingHelper.phpO7src/Type/Php/IsArrayFunctionTypeSpecifyingExtension.phpKKJ!:src/Type/Php/IsCallableFunctionTypeSpecifyingExtension.php }Gh:src/Type/Php/IsIterableFunctionTypeSpecifyingExtension.phpMM<src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php  UCv;src/Type/Php/IteratorToArrayFunctionReturnTypeExtension.phpߢ;src/Type/Php/JsonThrowOnErrorDynamicReturnTypeExtension.php稔ۤ'src/Type/Php/JsonThrowTypeExtension.php;;b1src/Type/Php/LtrimFunctionReturnTypeExtension.php Ż7=src/Type/Php/MbConvertEncodingFunctionReturnTypeExtension.php==>bS/src/Type/Php/MbFunctionsReturnTypeExtension.php  =4src/Type/Php/MbFunctionsReturnTypeExtensionTrait.php=4src/Type/Php/MbStrlenFunctionReturnTypeExtension.php۶З@src/Type/Php/MbSubstituteCharacterDynamicReturnTypeExtension.phpTi4src/Type/Php/MethodExistsTypeSpecifyingExtension.php =5src/Type/Php/MicrotimeFunctionReturnTypeExtension.php>2src/Type/Php/MinMaxFunctionReturnTypeExtension.php-ۤ;src/Type/Php/NonEmptyStringFunctionsReturnTypeExtension.php: : ؤ?src/Type/Php/NumberFormatFunctionDynamicReturnTypeExtension.php]]6˔-src/Type/Php/OpenSslCipherMethodsProvider.php<8src/Type/Php/OpenSslEncryptParameterOutTypeExtension.phpv v `Y:src/Type/Php/OpensslCipherFunctionsReturnTypeExtension.php[\.src/Type/Php/PDOConnectReturnTypeExtension.php N2src/Type/Php/ParseStrParameterOutTypeExtension.php'';src/Type/Php/ParseUrlFunctionDynamicReturnTypeExtension.phpA;src/Type/Php/PathinfoFunctionDynamicReturnTypeExtension.php? ? sn8src/Type/Php/PdoStatementFetchAllReturnTypeExtension.phpxx.3F/src/Type/Php/PowFunctionReturnTypeExtension.php6src/Type/Php/PregFilterFunctionReturnTypeExtension.phpL 3src/Type/Php/PregMatchParameterOutTypeExtension.php埤1src/Type/Php/PregMatchTypeSpecifyingExtension.php IYX8src/Type/Php/PregReplaceCallbackClosureTypeExtension.php7I4src/Type/Php/PregSplitDynamicReturnTypeExtension.php .qɤ6src/Type/Php/PropertyExistsTypeSpecifyingExtension.php< < K^5src/Type/Php/RandomIntFunctionReturnTypeExtension.php  z1src/Type/Php/RangeFunctionReturnTypeExtension.phpCC6}8E=src/Type/Php/ReflectionClassConstructorThrowTypeExtension.phpjjq9pCsrc/Type/Php/ReflectionClassIsSubclassOfTypeSpecifyingExtension.php6@src/Type/Php/ReflectionFunctionConstructorThrowTypeExtension.phpdꜤAsrc/Type/Php/ReflectionGetAttributesMethodReturnTypeExtension.php E*T>src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php P@src/Type/Php/ReflectionPropertyConstructorThrowTypeExtension.php" " F'src/Type/Php/RegexArrayShapeMatcher.php<@<@zcƤ;src/Type/Php/ReplaceFunctionsDynamicReturnTypeExtension.php$1src/Type/Php/RoundFunctionReturnTypeExtension.php8 8 {m7src/Type/Php/SetTypeFunctionTypeSpecifyingExtension.phpQQ1?src/Type/Php/SimpleXMLElementAsXMLMethodReturnTypeExtension.php~~wAsrc/Type/Php/SimpleXMLElementClassPropertyReflectionExtension.php,DD>src/Type/Php/SimpleXMLElementConstructorThrowTypeExtension.phpt>%?src/Type/Php/SimpleXMLElementXpathMethodReturnTypeExtension.phpc:src/Type/Php/SprintfFunctionDynamicReturnTypeExtension.php004w9src/Type/Php/SscanfFunctionDynamicReturnTypeExtension.php ±Ҥ/src/Type/Php/StatDynamicReturnTypeExtension.phpnC4src/Type/Php/StrCaseFunctionsReturnTypeExtension.phpıЌ5src/Type/Php/StrContainingTypeSpecifyingExtension.php  ByAsrc/Type/Php/StrIncrementDecrementFunctionReturnTypeExtension.php  oC2src/Type/Php/StrPadFunctionReturnTypeExtension.phpm m sR5src/Type/Php/StrRepeatFunctionReturnTypeExtension.php/X⭤4src/Type/Php/StrSplitFunctionReturnTypeExtension.phpϤ2src/Type/Php/StrTokFunctionReturnTypeExtension.php?src/Type/Php/StrWordCountFunctionDynamicReturnTypeExtension.phpodL2src/Type/Php/StrlenFunctionReturnTypeExtension.php 2src/Type/Php/StrrevFunctionReturnTypeExtension.phpQ Q  5src/Type/Php/StrtotimeFunctionReturnTypeExtension.php D8src/Type/Php/StrvalFamilyFunctionReturnTypeExtension.php  S}1src/Type/Php/SubstrDynamicReturnTypeExtension.phpBB-src/Type/Php/ThrowableReturnTypeExtension.php3 3 7src/Type/Php/TriggerErrorDynamicReturnTypeExtension.php,ȕ7src/Type/Php/TrimFunctionDynamicReturnTypeExtension.php daBsrc/Type/Php/TypeSpecifyingFunctionsDynamicReturnTypeExtension.phpLgAsrc/Type/Php/VersionCompareFunctionDynamicReturnTypeExtension.phpu U@src/Type/Php/VersionCompareFunctionDynamicThrowTypeExtension.php Ho1src/Type/Php/XMLReaderOpenReturnTypeExtension.phpѤsrc/Type/RecursionGuard.phpvG#src/Type/Regex/RegexAlternation.php=ܯ%src/Type/Regex/RegexAstWalkResult.php &&src/Type/Regex/RegexCapturingGroup.php11V;%(src/Type/Regex/RegexExpressionHelper.phpG!src/Type/Regex/RegexGroupList.phpvv)0:#src/Type/Regex/RegexGroupParser.php]].v'src/Type/Regex/RegexGroupWalkResult.php З珤)src/Type/Regex/RegexNonCapturingGroup.php*Asrc/Type/ResourceType.php  miq&src/Type/SimultaneousTypeTraverser.php> 6src/Type/StaticMethodParameterClosureThisExtension.php&eŤ6src/Type/StaticMethodParameterClosureTypeExtension.php"@ 2src/Type/StaticMethodParameterOutTypeExtension.phpv0src/Type/StaticMethodTypeSpecifyingExtension.phpdd7src/Type/StaticType.php!v!v~Bsrc/Type/StaticTypeFactory.php: : @src/Type/StrictMixedType.php55 dh8src/Type/StringAlwaysAcceptingObjectWithToStringType.php 7src/Type/StringNeverAcceptingObjectWithToStringType.phpSf7src/Type/StringType.php""Ivsrc/Type/SubtractableType.php]])Tsrc/Type/ThisType.php$ $ ]"src/Type/Traits/ArrayTypeTrait.php1 6src/Type/Traits/ConstantNumericComparisonTypeTrait.php }on+src/Type/Traits/ConstantScalarTypeTrait.php33p*src/Type/Traits/FalseyBooleanTypeTrait.php @l+src/Type/Traits/LateResolvableTypeTrait.php;J;Jդ,<'src/Type/Traits/MaybeArrayTypeTrait.php Bϔ*src/Type/Traits/MaybeCallableTypeTrait.phpDf]q*src/Type/Traits/MaybeIterableTypeTrait.php@@<((src/Type/Traits/MaybeObjectTypeTrait.phphQ2src/Type/Traits/MaybeOffsetAccessibleTypeTrait.phpN(src/Type/Traits/MaybeStringTypeTrait.phpJ$D%src/Type/Traits/NonArrayTypeTrait.php w5(src/Type/Traits/NonCallableTypeTrait.php|[c-src/Type/Traits/NonGeneralizableTypeTrait.phpKKD8'src/Type/Traits/NonGenericTypeTrait.phpÜP](src/Type/Traits/NonIterableTypeTrait.phpg"&src/Type/Traits/NonObjectTypeTrait.php5\s0src/Type/Traits/NonOffsetAccessibleTypeTrait.php' ?*src/Type/Traits/NonRemoveableTypeTrait.php}֗#src/Type/Traits/ObjectTypeTrait.php((uU*src/Type/Traits/SubstractableTypeTrait.php,*src/Type/Traits/TruthyBooleanTypeTrait.php-src/Type/Traits/UndecidedBooleanTypeTrait.phpG3src/Type/TypeResult.phpcmsrc/Type/TypeTraverser.php**:g\"src/Type/TypeTraverserCallable.php  x9src/Type/TypeUtils.php!!Owsrc/Type/TypeWithClassName.phpfάsrc/Type/TypehintHelper.php__ʤ1src/Type/UnaryOperatorTypeSpecifyingExtension.phpꆤ9src/Type/UnaryOperatorTypeSpecifyingExtensionRegistry.php38src/Type/UnionType.phpGG[^wsrc/Type/UnionTypeHelper.php$src/Type/UsefulTypeAliasResolver.php!Tsrc/Type/ValueOfType.php  xsrc/Type/VerbosityLevel.phpi!i!dsrc/Type/VoidType.phpjsrc/autoloadFunctions.phpǝQsrc/debugScope.php src/dumpType.php66Rstubs/ArrayObject.stubj+ͤstubs/Countable.stuboo Ustubs/Exception.stub9 9 ostubs/ImagickPixel.stubpp+stubs/Memcached.stub⊃stubs/PDOStatement.stub ޤstubs/Redis.stub{{i%stubs/ReflectionAttribute.stub  qstubs/ReflectionClass.stubbb80D"stubs/ReflectionClassConstant.stubDxd)stubs/ReflectionClassWithLazyObjects.stubyy0;stubs/ReflectionEnum.stub(stubs/ReflectionEnumWithLazyObjects.stubr̉%stubs/ReflectionFunctionAbstract.stubʾstubs/ReflectionMethod.stubästubs/ReflectionParameter.stub  xstubs/ReflectionProperty.stub  Ctstubs/SplObjectStorage.stub+qstubs/WeakReference.stub```stubs/arrayFunctions.stub,, ystubs/bcmath.stubmmܤstubs/core.stubP0P0(獤stubs/ctype.stubDDstubs/date.stubuu!]^stubs/dom.stub ¦stubs/ext-ds.stub99 ڤstubs/file.stub__;>stubs/ibm_db2.stubcҤstubs/iterable.stubs$s$hästubs/json_validate.stubvRstubs/mysqli.stubXX FVstubs/runtime/Attribute84.php99Qۊstubs/runtime/Attribute85.phpW!stubs/runtime/Enum/BackedEnum.php  M%stubs/runtime/Enum/ReflectionEnum.phpmG/stubs/runtime/Enum/ReflectionEnumBackedCase.php;7y-stubs/runtime/Enum/ReflectionEnumUnitCase.phpstubs/runtime/Enum/UnitEnum.php%stubs/runtime/ReflectionAttribute.phpkʤ,stubs/runtime/ReflectionIntersectionType.php;%stubs/runtime/ReflectionUnionType.phpD=stubs/socket_select.stubf/stubs/socket_select_php8.stub٤stubs/spl.stub// stubs/stream_socket_client.stub60stubs/stream_socket_server.stub[Q, stubs/typeCheckingFunctions.stub}} Rstubs/zip.stub44#vendor/attributes.phptvendor/autoload.phpm vendor/clue/ndjson-react/LICENSE::DiG(vendor/clue/ndjson-react/src/Decoder.php@((vendor/clue/ndjson-react/src/Encoder.php9mߤvendor/composer/ClassLoader.php??2@u%vendor/composer/InstalledVersions.phpCC06vendor/composer/pcre/src/MatchAllWithOffsetsResult.phpoc(vendor/composer/pcre/src/MatchResult.php˞i4vendor/composer/pcre/src/MatchStrictGroupsResult.phpA3vendor/composer/pcre/src/MatchWithOffsetsResult.phpvh<vendor/composer/pcre/src/PHPStan/InvalidRegexPatternRule.php55t3vendor/composer/pcre/src/PHPStan/PregMatchFlags.php__=l Gvendor/composer/pcre/src/PHPStan/PregMatchParameterOutTypeExtension.php;;AEvendor/composer/pcre/src/PHPStan/PregMatchTypeSpecifyingExtension.php ꭌLvendor/composer/pcre/src/PHPStan/PregReplaceCallbackClosureTypeExtension.php ?vendor/composer/pcre/src/PHPStan/UnsafeStrictGroupsCallRule.php\ \ 8 *vendor/composer/pcre/src/PcreException.php\臤!vendor/composer/pcre/src/Preg.php%E%E-n"vendor/composer/pcre/src/Regex.phpM8*vendor/composer/pcre/src/ReplaceResult.php $59vendor/composer/pcre/src/UnexpectedNullMatchException.phpG̡vendor/composer/semver/LICENSEBh)vendor/composer/semver/src/Comparator.phpb b щ/vendor/composer/semver/src/CompilingMatcher.php% % /vendor/composer/semver/src/Constraint/Bound.phpC C +4_4vendor/composer/semver/src/Constraint/Constraint.phps0s0x¤=vendor/composer/semver/src/Constraint/ConstraintInterface.php5<vendor/composer/semver/src/Constraint/MatchAllConstraint.phpbj?=vendor/composer/semver/src/Constraint/MatchNoneConstraint.phpᒄ9vendor/composer/semver/src/Constraint/MultiConstraint.php;#;#{Ϯ'vendor/composer/semver/src/Interval.php&(vendor/composer/semver/src/Intervals.phpNN.9%vendor/composer/semver/src/Semver.phpc c E,vendor/composer/semver/src/VersionParser.phpBUBU̹&vendor/composer/xdebug-handler/LICENSE))#;^0vendor/composer/xdebug-handler/src/PhpConfig.php78.vendor/composer/xdebug-handler/src/Process.phpb b >o-vendor/composer/xdebug-handler/src/Status.phpHHa"S4vendor/composer/xdebug-handler/src/XdebugHandler.phpTT"vendor/evenement/evenement/LICENSE  {I=/vendor/evenement/evenement/src/EventEmitter.phprr 8vendor/evenement/evenement/src/EventEmitterInterface.phpR@Ӥ4vendor/evenement/evenement/src/EventEmitterTrait.phpXXN h.vendor/fidry/cpu-core-counter/bin/diagnose.phpaPФ-vendor/fidry/cpu-core-counter/bin/execute.phpkk+vendor/fidry/cpu-core-counter/bin/trace.phpBBfG4vendor/fidry/cpu-core-counter/src/CpuCoreCounter.php!!1/vendor/fidry/cpu-core-counter/src/Diagnoser.phpvvt?vendor/fidry/cpu-core-counter/src/Executor/ProcOpenExecutor.phpܤ>vendor/fidry/cpu-core-counter/src/Executor/ProcessExecutor.phpYϤCvendor/fidry/cpu-core-counter/src/Finder/CmiCmdletLogicalFinder.php5zDvendor/fidry/cpu-core-counter/src/Finder/CmiCmdletPhysicalFinder.php$$-:vendor/fidry/cpu-core-counter/src/Finder/CpuCoreFinder.php  ':vendor/fidry/cpu-core-counter/src/Finder/CpuInfoFinder.php  .3[?vendor/fidry/cpu-core-counter/src/Finder/DummyCpuCoreFinder.phpkk>vendor/fidry/cpu-core-counter/src/Finder/EnvVariableFinder.php||p;vendor/fidry/cpu-core-counter/src/Finder/FinderRegistry.php&Ci<vendor/fidry/cpu-core-counter/src/Finder/HwLogicalFinder.phptti=vendor/fidry/cpu-core-counter/src/Finder/HwPhysicalFinder.phpxx.?vendor/fidry/cpu-core-counter/src/Finder/LscpuLogicalFinder.phpIIafU@vendor/fidry/cpu-core-counter/src/Finder/LscpuPhysicalFinder.php \S8vendor/fidry/cpu-core-counter/src/Finder/NProcFinder.php?t_1=vendor/fidry/cpu-core-counter/src/Finder/NProcessorFinder.phpc>7>vendor/fidry/cpu-core-counter/src/Finder/NullCpuCoreFinder.php8Cvendor/fidry/cpu-core-counter/src/Finder/OnlyInPowerShellFinder.php;Avendor/fidry/cpu-core-counter/src/Finder/OnlyOnOSFamilyFinder.php"5@vendor/fidry/cpu-core-counter/src/Finder/ProcOpenBasedFinder.php} } wYfAvendor/fidry/cpu-core-counter/src/Finder/SkipOnOSFamilyFinder.php9pIvendor/fidry/cpu-core-counter/src/Finder/WindowsRegistryLogicalFinder.phpoo ¤>vendor/fidry/cpu-core-counter/src/Finder/WmicLogicalFinder.phpZ?vendor/fidry/cpu-core-counter/src/Finder/WmicPhysicalFinder.phpÈR>vendor/fidry/cpu-core-counter/src/Finder/_NProcessorFinder.phpOrQ=vendor/fidry/cpu-core-counter/src/NumberOfCpuCoreNotFound.php##ɥI;vendor/fidry/cpu-core-counter/src/ParallelisationResult.php9L vendor/guzzlehttp/guzzle/LICENSEՇ*vendor/guzzlehttp/guzzle/package-lock.jsonUUPw/vendor/guzzlehttp/guzzle/src/BodySummarizer.phpkki8vendor/guzzlehttp/guzzle/src/BodySummarizerInterface.phpck_'vendor/guzzlehttp/guzzle/src/Client.php0G0G[0vendor/guzzlehttp/guzzle/src/ClientInterface.php |,vendor/guzzlehttp/guzzle/src/ClientTrait.php##1vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php0#0#:vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php@ @ #U5vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php A8vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.phpRҟ1vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php77|?vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.phpy:vendor/guzzlehttp/guzzle/src/Exception/ClientException.phpCt;vendor/guzzlehttp/guzzle/src/Exception/ConnectException.phpL@(~:vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.phpCNCvendor/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php@;vendor/guzzlehttp/guzzle/src/Exception/RequestException.phpꬤ:vendor/guzzlehttp/guzzle/src/Exception/ServerException.phpmDvendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.phpxx(*<vendor/guzzlehttp/guzzle/src/Exception/TransferException.php-4vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php{j{jh-P=vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.phpX4vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.phpZZ+E9vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php!!0{*V3vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.phps s Kc'r8vendor/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php@@ 4vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php`9b.vendor/guzzlehttp/guzzle/src/Handler/Proxy.phpTT4m96vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.phpFRFR-vendor/guzzlehttp/guzzle/src/HandlerStack.php!!$1vendor/guzzlehttp/guzzle/src/MessageFormatter.phpQG:vendor/guzzlehttp/guzzle/src/MessageFormatterInterface.phpiiktԤ+vendor/guzzlehttp/guzzle/src/Middleware.php))( ˤ%vendor/guzzlehttp/guzzle/src/Pool.php"6vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.phpL L sEB3vendor/guzzlehttp/guzzle/src/RedirectMiddleware.phpCC{u/vendor/guzzlehttp/guzzle/src/RequestOptions.php**xʾ0vendor/guzzlehttp/guzzle/src/RetryMiddleware.php Ev.vendor/guzzlehttp/guzzle/src/TransferStats.php E&vendor/guzzlehttp/guzzle/src/Utils.php33*vendor/guzzlehttp/guzzle/src/functions.php77*2vendor/guzzlehttp/guzzle/src/functions_include.php[!"vendor/guzzlehttp/promises/LICENSEz*/5vendor/guzzlehttp/promises/src/AggregateException.php8vendor/guzzlehttp/promises/src/CancellationException.phphP,vendor/guzzlehttp/promises/src/Coroutine.php))z)vendor/guzzlehttp/promises/src/Create.php/b'vendor/guzzlehttp/promises/src/Each.php \$.vendor/guzzlehttp/promises/src/EachPromise.phpmmJ}3vendor/guzzlehttp/promises/src/FulfilledPromise.phpz>20%vendor/guzzlehttp/promises/src/Is.phpXU@*vendor/guzzlehttp/promises/src/Promise.php8"8"eO3vendor/guzzlehttp/promises/src/PromiseInterface.php U14vendor/guzzlehttp/promises/src/PromisorInterface.php  _P2vendor/guzzlehttp/promises/src/RejectedPromise.phpKJu5vendor/guzzlehttp/promises/src/RejectionException.phpWŤ,vendor/guzzlehttp/promises/src/TaskQueue.phpbI95vendor/guzzlehttp/promises/src/TaskQueueInterface.phpǤ(vendor/guzzlehttp/promises/src/Utils.php;KGvendor/guzzlehttp/psr7/LICENSEzz^pL+vendor/guzzlehttp/psr7/src/AppendStream.phpI{+vendor/guzzlehttp/psr7/src/BufferStream.php 9,vendor/guzzlehttp/psr7/src/CachingStream.php#g-vendor/guzzlehttp/psr7/src/DroppingStream.php->vendor/guzzlehttp/psr7/src/Exception/MalformedUriException.phpw'vendor/guzzlehttp/psr7/src/FnStream.php}x@%vendor/guzzlehttp/psr7/src/Header.phpll0ͤ*vendor/guzzlehttp/psr7/src/HttpFactory.php xF,vendor/guzzlehttp/psr7/src/InflateStream.phpפ-vendor/guzzlehttp/psr7/src/LazyOpenStream.php__m[*vendor/guzzlehttp/psr7/src/LimitStream.phpooCbś&vendor/guzzlehttp/psr7/src/Message.php~+vendor/guzzlehttp/psr7/src/MessageTrait.php̾'vendor/guzzlehttp/psr7/src/MimeType.phpŀ疤.vendor/guzzlehttp/psr7/src/MultipartStream.phpҤ+vendor/guzzlehttp/psr7/src/NoSeekStream.php007)vendor/guzzlehttp/psr7/src/PumpStream.phpzI8O$vendor/guzzlehttp/psr7/src/Query.php  @z&vendor/guzzlehttp/psr7/src/Request.php00,].C'vendor/guzzlehttp/psr7/src/Response.phpEE=~:&vendor/guzzlehttp/psr7/src/Rfc7230.php ,vendor/guzzlehttp/psr7/src/ServerRequest.phpw$w$m%vendor/guzzlehttp/psr7/src/Stream.phpp\|3vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php  j,vendor/guzzlehttp/psr7/src/StreamWrapper.phpzz^d+vendor/guzzlehttp/psr7/src/UploadedFile.phplL"vendor/guzzlehttp/psr7/src/Uri.php3S3S|j ,vendor/guzzlehttp/psr7/src/UriComparator.php-@٤,vendor/guzzlehttp/psr7/src/UriNormalizer.phpE E -_*vendor/guzzlehttp/psr7/src/UriResolver.php a$vendor/guzzlehttp/psr7/src/Utils.php<<Wwqvendor/hoa/compiler/Bin/Pp.php8.vendor/hoa/compiler/Documentation/En/Index.xyld/.vendor/hoa/compiler/Documentation/Fr/Index.xylttE+vendor/hoa/compiler/Exception/Exception.phpUS=vendor/hoa/compiler/Exception/FinalStateHasNotBeenReached.phpbsϤ.vendor/hoa/compiler/Exception/IllegalToken.php EW 'vendor/hoa/compiler/Exception/Lexer.php&vendor/hoa/compiler/Exception/Rule.php5<@1vendor/hoa/compiler/Exception/UnexpectedToken.php/3vendor/hoa/compiler/Exception/UnrecognizedToken.php wؤvendor/hoa/compiler/Ll1.phpjjT (9!vendor/hoa/compiler/Llk/Lexer.phpLBvendor/hoa/compiler/Llk/Llk.phpX.X.ACKvendor/hoa/compiler/Llk/Llk.pp Gr"vendor/hoa/compiler/Llk/Parser.phpPP`)vendor/hoa/compiler/Llk/Rule/Analyzer.php33'vendor/hoa/compiler/Llk/Rule/Choice.phpeeOᙤ.vendor/hoa/compiler/Llk/Rule/Concatenation.phpzz_oP&vendor/hoa/compiler/Llk/Rule/Ekzit.phpooV|&vendor/hoa/compiler/Llk/Rule/Entry.phphh+ͤ+vendor/hoa/compiler/Llk/Rule/Invocation.phpKK+vendor/hoa/compiler/Llk/Rule/Repetition.php %vendor/hoa/compiler/Llk/Rule/Rule.php!&vendor/hoa/compiler/Llk/Rule/Token.php==i/5vendor/hoa/compiler/Llk/Sampler/BoundedExhaustive.php&&y,,vendor/hoa/compiler/Llk/Sampler/Coverage.php F FVl-vendor/hoa/compiler/Llk/Sampler/Exception.phpk+vendor/hoa/compiler/Llk/Sampler/Sampler.phpu"+vendor/hoa/compiler/Llk/Sampler/Uniform.php"":O$vendor/hoa/compiler/Llk/TreeNode.php||vendor/hoa/compiler/PATCHES.txt__u?6vendor/hoa/compiler/Test/Integration/Documentation.php HR:vendor/hoa/compiler/Test/Integration/Llk/Documentation.phpVV :vendor/hoa/compiler/Test/Integration/Llk/Rule/Analyzer.phpa$a$P6vendor/hoa/compiler/Test/Integration/Llk/Soundness.php>&5vendor/hoa/compiler/Test/Unit/Exception/Exception.phpvvԤGvendor/hoa/compiler/Test/Unit/Exception/FinalStateHasNotBeenReached.phpu738vendor/hoa/compiler/Test/Unit/Exception/IllegalToken.php4 4 `I1vendor/hoa/compiler/Test/Unit/Exception/Lexer.phpss _0vendor/hoa/compiler/Test/Unit/Exception/Rule.phpooݗ3;vendor/hoa/compiler/Test/Unit/Exception/UnexpectedToken.php@ @ V[)=vendor/hoa/compiler/Test/Unit/Exception/UnrecognizedToken.phpH H O|+vendor/hoa/compiler/Test/Unit/Llk/Lexer.php##7]T)vendor/hoa/compiler/Test/Unit/Llk/Llk.php11>1vendor/hoa/compiler/Test/Unit/Llk/Rule/Choice.phpnnA48vendor/hoa/compiler/Test/Unit/Llk/Rule/Concatenation.php0ͤ0vendor/hoa/compiler/Test/Unit/Llk/Rule/Ekzit.php0vendor/hoa/compiler/Test/Unit/Llk/Rule/Entry.phpj85vendor/hoa/compiler/Test/Unit/Llk/Rule/Invocation.phpUfT:5vendor/hoa/compiler/Test/Unit/Llk/Rule/Repetition.phpuu s/vendor/hoa/compiler/Test/Unit/Llk/Rule/Rule.php#W00vendor/hoa/compiler/Test/Unit/Llk/Rule/Token.phpj*7vendor/hoa/compiler/Test/Unit/Llk/Sampler/Exception.phpf5.vendor/hoa/compiler/Test/Unit/Llk/TreeNode.php%%Z$vendor/hoa/compiler/Visitor/Dump.php; ; og%vendor/hoa/consistency/Autoloader.phpII:ӂ&vendor/hoa/consistency/Consistency.php $vendor/hoa/consistency/Exception.phpmX"vendor/hoa/consistency/PATCHES.txtoV?"vendor/hoa/consistency/Prelude.phpY`i/vendor/hoa/consistency/Test/Unit/Autoloader.php '0vendor/hoa/consistency/Test/Unit/Consistency.phpB.vendor/hoa/consistency/Test/Unit/Exception.phpNN_9.vendor/hoa/consistency/Test/Unit/Xcallable.phpq"q"ϖ$vendor/hoa/consistency/Xcallable.phpZ Z ,vendor/hoa/event/Bucket.phpD D 4u*vendor/hoa/event/Event.php"'vendor/hoa/event/Exception.php=vendor/hoa/event/Listenable.phpGOvendor/hoa/event/Listener.phpS Tvendor/hoa/event/Listens.php vendor/hoa/event/Source.php__%vendor/hoa/event/Test/Unit/Bucket.php H$vendor/hoa/event/Test/Unit/Event.php^z(vendor/hoa/event/Test/Unit/Exception.php<<(.)vendor/hoa/event/Test/Unit/Listenable.php11Z'vendor/hoa/event/Test/Unit/Listener.phpq<&vendor/hoa/event/Test/Unit/Listens.phpѥk%vendor/hoa/event/Test/Unit/Source.php>3Qvendor/hoa/exception/Error.phpB B /Fwܤ"vendor/hoa/exception/Exception.phpM M Ǘvendor/hoa/exception/Group.phpRR[jvendor/hoa/exception/Idle.phpp vendor/hoa/exception/PATCHES.txt`on(vendor/hoa/exception/Test/Unit/Error.php L3M,vendor/hoa/exception/Test/Unit/Exception.php! ! cebӤ(vendor/hoa/exception/Test/Unit/Group.php33+'vendor/hoa/exception/Test/Unit/Idle.phpvendor/hoa/file/Directory.phpd,¤'vendor/hoa/file/Exception/Exception.phpsi.vendor/hoa/file/Exception/FileDoesNotExist.phpKivendor/hoa/file/File.php%%EYvendor/hoa/file/Finder.phpDD%vendor/hoa/file/Generic.php33ߺvendor/hoa/file/Link/Link.phpDD RRvendor/hoa/file/Link/Read.phpEE-e"vendor/hoa/file/Link/ReadWrite.php""+դvendor/hoa/file/Link/Write.phpx~vendor/hoa/file/PATCHES.txt)vendor/hoa/file/Read.php66vvendor/hoa/file/ReadWrite.php""۱Xevendor/hoa/file/SplFileInfo.php  RK"vendor/hoa/file/Temporary/Read.phpbb 'vendor/hoa/file/Temporary/ReadWrite.php""A'vendor/hoa/file/Temporary/Temporary.php( ϴ#vendor/hoa/file/Temporary/Write.phpTJ%vendor/hoa/file/Watcher.phpvendor/hoa/file/Write.php?!vendor/hoa/iterator/Aggregate.phpvvˤvendor/hoa/iterator/Append.php^^{Fvendor/hoa/iterator/Buffer.php&vendor/hoa/iterator/CallbackFilter.php~~L)vendor/hoa/iterator/CallbackGenerator.php 6H9vendor/hoa/iterator/Counter.php6՟%vendor/hoa/iterator/Demultiplexer.php: +!vendor/hoa/iterator/Directory.php~!vendor/hoa/iterator/Exception.php>T"vendor/hoa/iterator/FileSystem.php vendor/hoa/iterator/Filter.phpggiһvendor/hoa/iterator/Glob.phpVVǻ vendor/hoa/iterator/Infinite.phpff* vendor/hoa/iterator/Iterator.php(vendor/hoa/iterator/IteratorIterator.phpvviÃ#vendor/hoa/iterator/Limit.phpZZ!x#!vendor/hoa/iterator/Lookahead.phpooN"vendor/hoa/iterator/Lookbehind.php44*4vendor/hoa/iterator/Map.phpVVwvendor/hoa/iterator/Mock.phpXX|! vendor/hoa/iterator/Multiple.php   vendor/hoa/iterator/NoRewind.phpff7Z/}vendor/hoa/iterator/Outer.phpff񽲤vendor/hoa/iterator/PATCHES.txt20vendor/hoa/iterator/Recursive/CallbackFilter.php+vendor/hoa/iterator/Recursive/Directory.php6FY(vendor/hoa/iterator/Recursive/Filter.php҅*vendor/hoa/iterator/Recursive/Iterator.phps%vendor/hoa/iterator/Recursive/Map.php||PX:&vendor/hoa/iterator/Recursive/Mock.phpoow+vendor/hoa/iterator/Recursive/Recursive.php\3vendor/hoa/iterator/Recursive/RegularExpression.phplֲ)vendor/hoa/iterator/RegularExpression.php!!@  vendor/hoa/iterator/Repeater.php55q vendor/hoa/iterator/Seekable.phpqqפ#vendor/hoa/iterator/SplFileInfo.phpaaIi‹(vendor/hoa/iterator/Test/Unit/Append.php ի 2(vendor/hoa/iterator/Test/Unit/Buffer.php''b0vendor/hoa/iterator/Test/Unit/CallbackFilter.phpYYqv93vendor/hoa/iterator/Test/Unit/CallbackGenerator.php~Ϥ)vendor/hoa/iterator/Test/Unit/Counter.php &'F/vendor/hoa/iterator/Test/Unit/Demultiplexer.php S9+vendor/hoa/iterator/Test/Unit/Directory.php ,vendor/hoa/iterator/Test/Unit/FileSystem.php  9d(vendor/hoa/iterator/Test/Unit/Filter.php' ' 0ޤ*vendor/hoa/iterator/Test/Unit/Infinite.phpM6 2vendor/hoa/iterator/Test/Unit/IteratorIterator.phpZ'vendor/hoa/iterator/Test/Unit/Limit.php d\+vendor/hoa/iterator/Test/Unit/Lookahead.php88[d,vendor/hoa/iterator/Test/Unit/Lookbehind.phpCCjNӤ%vendor/hoa/iterator/Test/Unit/Map.php  &vendor/hoa/iterator/Test/Unit/Mock.phpP P Jّ*vendor/hoa/iterator/Test/Unit/Multiple.php )))*vendor/hoa/iterator/Test/Unit/NoRewind.phpK K r(3vendor/hoa/iterator/Test/Unit/RegularExpression.php *vendor/hoa/iterator/Test/Unit/Repeater.php  0-vendor/hoa/iterator/Test/Unit/SplFileInfo.php--avendor/hoa/math/Arithmetic.pp ٤vendor/hoa/math/Bin/Calc.php0%?-vendor/hoa/math/Combinatorics/Arrangement.phpsY7>vendor/hoa/math/Combinatorics/Combination/CartesianProduct.php%9vendor/hoa/math/Combinatorics/Combination/Combination.php ?03vendor/hoa/math/Combinatorics/Combination/Gamma.php>> *vendor/hoa/math/Combinatorics/Counting.phpsY7+vendor/hoa/math/Combinatorics/FiniteSet.phpsY7-vendor/hoa/math/Combinatorics/Permutation.phpsY7vendor/hoa/math/Context.php  U4vendor/hoa/math/Exception/AlreadyDefinedConstant.php='vendor/hoa/math/Exception/Exception.phpG0-vendor/hoa/math/Exception/UnknownConstant.phpq-vendor/hoa/math/Exception/UnknownFunction.php䒤-vendor/hoa/math/Exception/UnknownVariable.php*"vendor/hoa/math/Sampler/Random.php Ŗ#vendor/hoa/math/Sampler/Sampler.php'vendor/hoa/math/Test/Unit/Arithmetic.pp .RHvendor/hoa/math/Test/Unit/Combinatorics/Combination/CartesianProduct.phpi i :0Cvendor/hoa/math/Test/Unit/Combinatorics/Combination/Combination.php  4=vendor/hoa/math/Test/Unit/Combinatorics/Combination/Gamma.phpy y %vendor/hoa/math/Test/Unit/Context.phpF#vendor/hoa/math/Test/Unit/Issue.php4 4 5 Y,vendor/hoa/math/Test/Unit/Sampler/Random.php||? 0vendor/hoa/math/Test/Unit/Visitor/Arithmetic.php99Avendor/hoa/math/Util.phpYYc] &vendor/hoa/math/Visitor/Arithmetic.php&&[`̤#vendor/hoa/protocol/Bin/Resolve.phpuhӐ!vendor/hoa/protocol/Exception.php6\$vendor/hoa/protocol/Node/Library.php rD!vendor/hoa/protocol/Node/Node.php&&N\vendor/hoa/protocol/PATCHES.txtP vendor/hoa/protocol/Protocol.php*+vendor/hoa/protocol/Test/Unit/Exception.phpEEҤ.vendor/hoa/protocol/Test/Unit/Node/Library.php6`HX+vendor/hoa/protocol/Test/Unit/Node/Node.php*vendor/hoa/protocol/Test/Unit/Protocol.phpv)vendor/hoa/protocol/Test/Unit/Wrapper.phpNNrWvendor/hoa/protocol/Wrapper.phpFFTavendor/hoa/regex/Exception.php vendor/hoa/regex/Grammar.pp  AL&vendor/hoa/regex/Visitor/Isotropic.php$$;Gvendor/hoa/stream/Bucket.php{{ vendor/hoa/stream/Composite.php ¯~vendor/hoa/stream/Context.php__gfvendor/hoa/stream/Exception.phpe3"vendor/hoa/stream/Filter/Basic.phpx&vendor/hoa/stream/Filter/Exception.php#vendor/hoa/stream/Filter/Filter.php[)vendor/hoa/stream/Filter/LateComputed.phpcc(ك(vendor/hoa/stream/IStream/Bufferable.php Yq vendor/hoa/stream/IStream/In.phpnnT &vendor/hoa/stream/IStream/Lockable.phph h !vendor/hoa/stream/IStream/Out.php ǟΤ&vendor/hoa/stream/IStream/Pathable.phpssI7'vendor/hoa/stream/IStream/Pointable.php  gq&vendor/hoa/stream/IStream/Statable.php i$vendor/hoa/stream/IStream/Stream.phpg(vendor/hoa/stream/IStream/Structural.phpq~'vendor/hoa/stream/IStream/Touchable.php-6vendor/hoa/stream/PATCHES.txtaQvendor/hoa/stream/Stream.phpAA8k*vendor/hoa/stream/Test/Fixtures/index.html贤4vendor/hoa/stream/Test/Integration/Filter/Filter.phpT4:vendor/hoa/stream/Test/Integration/Filter/LateComputed.php b-vendor/hoa/stream/Test/Integration/Stream.phpjjp@&vendor/hoa/stream/Test/Unit/Bucket.php)vendor/hoa/stream/Test/Unit/Composite.php Sw'vendor/hoa/stream/Test/Unit/Context.php#P)vendor/hoa/stream/Test/Unit/Exception.php\\ vR,vendor/hoa/stream/Test/Unit/Filter/Basic.php/Y1[0vendor/hoa/stream/Test/Unit/Filter/Exception.phpiirb -vendor/hoa/stream/Test/Unit/Filter/Filter.phps2vendor/hoa/stream/Test/Unit/IStream/Bufferable.php q;*vendor/hoa/stream/Test/Unit/IStream/In.php>6c0vendor/hoa/stream/Test/Unit/IStream/Lockable.php- - j+vendor/hoa/stream/Test/Unit/IStream/Out.phpY0vendor/hoa/stream/Test/Unit/IStream/Pathable.phpa0r1vendor/hoa/stream/Test/Unit/IStream/Pointable.php }Q0vendor/hoa/stream/Test/Unit/IStream/Statable.php7 7 0F.vendor/hoa/stream/Test/Unit/IStream/Stream.phphh 2vendor/hoa/stream/Test/Unit/IStream/Structural.phpS1vendor/hoa/stream/Test/Unit/IStream/Touchable.php2 2 e&vendor/hoa/stream/Test/Unit/Stream.phpFFd(1vendor/hoa/stream/Test/Unit/Wrapper/Exception.phpqq 5vendor/hoa/stream/Test/Unit/Wrapper/IWrapper/File.phpןk9vendor/hoa/stream/Test/Unit/Wrapper/IWrapper/IWrapper.php  A&7vendor/hoa/stream/Test/Unit/Wrapper/IWrapper/Stream.php/vendor/hoa/stream/Test/Unit/Wrapper/Wrapper.phpi篤'vendor/hoa/stream/Wrapper/Exception.phpXe+vendor/hoa/stream/Wrapper/IWrapper/File.php݉=/vendor/hoa/stream/Wrapper/IWrapper/IWrapper.phpV-vendor/hoa/stream/Wrapper/IWrapper/Stream.php0(0(_S%vendor/hoa/stream/Wrapper/Wrapper.phpXH#vendor/hoa/ustring/Bin/Fromcode.php !vendor/hoa/ustring/Bin/Tocode.php DȤ-vendor/hoa/ustring/Documentation/En/Index.xylhhv-vendor/hoa/ustring/Documentation/Fr/Index.xylEnEnFp vendor/hoa/ustring/Exception.phpPRvendor/hoa/ustring/Search.php&vendor/hoa/ustring/Test/Unit/Issue.php88Ft'vendor/hoa/ustring/Test/Unit/Search.phpşx(vendor/hoa/ustring/Test/Unit/Ustring.php7Q7Qevendor/hoa/ustring/Ustring.phpee? vendor/hoa/visitor/Element.phpeb(vendor/hoa/visitor/Test/Unit/Element.phpI>&vendor/hoa/visitor/Test/Unit/Visit.phpFg;vendor/hoa/visitor/Visit.php5 vendor/hoa/zformat/Exception.phpNf vendor/hoa/zformat/Parameter.phpFF hڤ&vendor/hoa/zformat/Parameterizable.phpKn.vendor/jetbrains/phpstorm-stubs/Core/Core.stubqqȏ0vendor/jetbrains/phpstorm-stubs/Core/Core_c.stubG0vendor/jetbrains/phpstorm-stubs/Core/Core_d.stub$$P*vendor/jetbrains/phpstorm-stubs/Ev/Ev.stubƤ,vendor/jetbrains/phpstorm-stubs/FFI/FFI.stubUkUk /vendor/jetbrains/phpstorm-stubs/Inspections.xmlwl'vendor/jetbrains/phpstorm-stubs/LICENSEW,W,M̤:vendor/jetbrains/phpstorm-stubs/LuaSandbox/LuaSandbox.stubEE+vendor/jetbrains/phpstorm-stubs/PATCHES.txtEEZΤ,vendor/jetbrains/phpstorm-stubs/PDO/PDO.stub؃؃Y4vendor/jetbrains/phpstorm-stubs/Parle/ErrorInfo.stubAA0vendor/jetbrains/phpstorm-stubs/Parle/Lexer.stub**; 9vendor/jetbrains/phpstorm-stubs/Parle/LexerException.stubww^Ut1vendor/jetbrains/phpstorm-stubs/Parle/Parser.stub,,:vendor/jetbrains/phpstorm-stubs/Parle/ParserException.stubxxL1vendor/jetbrains/phpstorm-stubs/Parle/RLexer.stub w2vendor/jetbrains/phpstorm-stubs/Parle/RParser.stubɥФ0vendor/jetbrains/phpstorm-stubs/Parle/Stack.stubAA.>o_0vendor/jetbrains/phpstorm-stubs/Parle/Token.stubN.vendor/jetbrains/phpstorm-stubs/Phar/Phar.stub//D74vendor/jetbrains/phpstorm-stubs/PhpStormStubsMap.phpw w @vendor/jetbrains/phpstorm-stubs/Reflection/PropertyHookType.stub33F:vendor/jetbrains/phpstorm-stubs/Reflection/Reflection.stubCCvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionAttribute.stubז?vendor/jetbrains/phpstorm-stubs/Reflection/ReflectionClass.stubWaWab(Gvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionClassConstant.stub@@wyCBvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionConstant.stub..>vendor/jetbrains/phpstorm-stubs/Reflection/ReflectionEnum.stubNHvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionEnumBackedCase.stubPPgFvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionEnumUnitCase.stubE;Cvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionException.stub#5Cvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionExtension.stub22~?vendor/jetbrains/phpstorm-stubs/Reflection/ReflectionFiber.stub*aBvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionFunction.stubbJvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionFunctionAbstract.stubh(h(#Cvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionGenerator.stubL L +KJvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionIntersectionType.stub6c8@vendor/jetbrains/phpstorm-stubs/Reflection/ReflectionMethod.stub**$#Cvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionNamedType.stubpp'@vendor/jetbrains/phpstorm-stubs/Reflection/ReflectionObject.stub0Cvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionParameter.stub''EOBvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionProperty.stub11r^Cvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionReference.stub؆5>vendor/jetbrains/phpstorm-stubs/Reflection/ReflectionType.stubRCvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionUnionType.stub  ˜Gvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionZendExtension.stub b{`9vendor/jetbrains/phpstorm-stubs/Reflection/Reflector.stubT,vendor/jetbrains/phpstorm-stubs/SPL/SPL.stubVV /vendor/jetbrains/phpstorm-stubs/SPL/SPL_c1.stubBB{B.vendor/jetbrains/phpstorm-stubs/SPL/SPL_f.stubiiы2vendor/jetbrains/phpstorm-stubs/SQLite/SQLite.stub##<#2vendor/jetbrains/phpstorm-stubs/SaxonC/SaxonC.stubll# 8vendor/jetbrains/phpstorm-stubs/SimpleXML/SimpleXML.stubLL4vendor/jetbrains/phpstorm-stubs/SplType/SplType.stub o9vendor/jetbrains/phpstorm-stubs/Zend OPcache/OPcache.stub  ~Z8vendor/jetbrains/phpstorm-stubs/ZendCache/ZendCache.stub  ab>vendor/jetbrains/phpstorm-stubs/ZendDebugger/ZendDebugger.stubw!8vendor/jetbrains/phpstorm-stubs/ZendUtils/ZendUtils.stub88܌4vendor/jetbrains/phpstorm-stubs/aerospike/Bytes.stub  ʍ8vendor/jetbrains/phpstorm-stubs/aerospike/aerospike.stub*4*4{Ƥ.vendor/jetbrains/phpstorm-stubs/amqp/amqp.stubffuŦ2vendor/jetbrains/phpstorm-stubs/apache/apache.stub--L.vendor/jetbrains/phpstorm-stubs/apcu/apcu.stub[n[nF,vendor/jetbrains/phpstorm-stubs/ast/ast.stub [ [nΤ2vendor/jetbrains/phpstorm-stubs/bcmath/bcmath.stub44yӤ8vendor/jetbrains/phpstorm-stubs/blackfire/blackfire.stubHHZ42vendor/jetbrains/phpstorm-stubs/brotli/brotli.stubp<5ʤ,vendor/jetbrains/phpstorm-stubs/bz2/bz2.stubP6vendor/jetbrains/phpstorm-stubs/calendar/calendar.stub&&?8vendor/jetbrains/phpstorm-stubs/cassandra/cassandra.stubc c t2:vendor/jetbrains/phpstorm-stubs/com_dotnet/com_dotnet.stubf/f/b8vendor/jetbrains/phpstorm-stubs/couchbase/couchbase.stubEJY;vendor/jetbrains/phpstorm-stubs/couchbase_v2/couchbase.stubdz :vendor/jetbrains/phpstorm-stubs/couchbase_v2/toplevel.stubWWa->2vendor/jetbrains/phpstorm-stubs/crypto/crypto.stub1?1?ګפ0vendor/jetbrains/phpstorm-stubs/ctype/ctype.stubRRP2vendor/jetbrains/phpstorm-stubs/cubrid/cubrid.stubxx:#8vendor/jetbrains/phpstorm-stubs/curl/CURLStringFile.stub@b.vendor/jetbrains/phpstorm-stubs/curl/curl.stubtt"c 0vendor/jetbrains/phpstorm-stubs/curl/curl_d.stubRR>2.vendor/jetbrains/phpstorm-stubs/date/date.stub!0vendor/jetbrains/phpstorm-stubs/date/date_c.stub0vendor/jetbrains/phpstorm-stubs/date/date_d.stubvv5 3vendor/jetbrains/phpstorm-stubs/dba/Connection.stubGGo@3,vendor/jetbrains/phpstorm-stubs/dba/dba.stubS0S019vendor/jetbrains/phpstorm-stubs/ddtrace/ddtrace.stub.stubcT34vendor/jetbrains/phpstorm-stubs/decimal/decimal.stub<<<<zy,vendor/jetbrains/phpstorm-stubs/dio/dio.stub%%'&.vendor/jetbrains/phpstorm-stubs/dio/dio_d.stubC,vendor/jetbrains/phpstorm-stubs/dom/dom.stubw.vendor/jetbrains/phpstorm-stubs/dom/dom_c.stubdd@.vendor/jetbrains/phpstorm-stubs/dom/dom_n.stubLL>Ӥ*vendor/jetbrains/phpstorm-stubs/ds/ds.stubڥڥf-vendor/jetbrains/phpstorm-stubs/ds_v2/ds.stub"<"<R{,vendor/jetbrains/phpstorm-stubs/eio/eio.stubyy20s=<vendor/jetbrains/phpstorm-stubs/elastic_apm/elastic_apm.stub~~4vendor/jetbrains/phpstorm-stubs/enchant/enchant.stub))R0vendor/jetbrains/phpstorm-stubs/event/event.stubzI7vendor/jetbrains/phpstorm-stubs/excimer/ExcimerLog.stubvvLɒ<vendor/jetbrains/phpstorm-stubs/excimer/ExcimerLogEntry.stubXXŧڤ<vendor/jetbrains/phpstorm-stubs/excimer/ExcimerProfiler.stub Z9vendor/jetbrains/phpstorm-stubs/excimer/ExcimerTimer.stub )4vendor/jetbrains/phpstorm-stubs/excimer/globals.stubSo.vendor/jetbrains/phpstorm-stubs/exif/exif.stubC2vendor/jetbrains/phpstorm-stubs/expect/expect.stub I.Ȥ.vendor/jetbrains/phpstorm-stubs/fann/fann.stubhha*2vendor/jetbrains/phpstorm-stubs/ffmpeg/ffmpeg.stubg%6vendor/jetbrains/phpstorm-stubs/fileinfo/fileinfo.stubt"t"J2vendor/jetbrains/phpstorm-stubs/filter/filter.stub<<1Z4vendor/jetbrains/phpstorm-stubs/filter/filter_c.stuba,vendor/jetbrains/phpstorm-stubs/fpm/fpm.stubB:vendor/jetbrains/phpstorm-stubs/frankenphp/frankenphp.stub  !H3vendor/jetbrains/phpstorm-stubs/ftp/Connection.stubGG!,vendor/jetbrains/phpstorm-stubs/ftp/ftp.stubiiڀH.vendor/jetbrains/phpstorm-stubs/gd/GdFont.stub33`I=*vendor/jetbrains/phpstorm-stubs/gd/gd.stub KR4vendor/jetbrains/phpstorm-stubs/gearman/gearman.stubU0vendor/jetbrains/phpstorm-stubs/geoip/geoip.stub$$6.vendor/jetbrains/phpstorm-stubs/geos/geos.stubAAꕤ4vendor/jetbrains/phpstorm-stubs/gettext/gettext.stub\\f4vendor/jetbrains/phpstorm-stubs/gmagick/gmagick.stubjjY\ ,vendor/jetbrains/phpstorm-stubs/gmp/gmp.stubvvq80vendor/jetbrains/phpstorm-stubs/gnupg/gnupg.stub`I`Ip.vendor/jetbrains/phpstorm-stubs/grpc/grpc.stubYYO.vendor/jetbrains/phpstorm-stubs/hash/hash.stubEE~b.vendor/jetbrains/phpstorm-stubs/http/http.stub/vendor/jetbrains/phpstorm-stubs/http/http3.stub4vendor/jetbrains/phpstorm-stubs/ibm_db2/ibm_db2.stubK60vendor/jetbrains/phpstorm-stubs/iconv/iconv.stub55Ec&6vendor/jetbrains/phpstorm-stubs/igbinary/igbinary.stubo/4vendor/jetbrains/phpstorm-stubs/imagick/imagick.stub 4vendor/jetbrains/phpstorm-stubs/imap/Connection.stubHHF?.vendor/jetbrains/phpstorm-stubs/imap/imap.stub;;Е4vendor/jetbrains/phpstorm-stubs/inotify/inotify.stubNNn8vendor/jetbrains/phpstorm-stubs/interbase/interbase.stub2vendor/jetbrains/phpstorm-stubs/intl/IntlChar.stubO/O/.<̤Bvendor/jetbrains/phpstorm-stubs/intl/IntlDatePatternGenerator.stub$J;vendor/jetbrains/phpstorm-stubs/intl/IntlListFormatter.stub??ua.vendor/jetbrains/phpstorm-stubs/intl/intl.stub8y.vendor/jetbrains/phpstorm-stubs/json/json.stub66Vz;6vendor/jetbrains/phpstorm-stubs/jsonpath/jsonpath.stub006m.vendor/jetbrains/phpstorm-stubs/judy/judy.stubF"F"q34vendor/jetbrains/phpstorm-stubs/ldap/Connection.stubHH0vendor/jetbrains/phpstorm-stubs/ldap/Result.stubDDvZ5vendor/jetbrains/phpstorm-stubs/ldap/ResultEntry.stubIIPx_.vendor/jetbrains/phpstorm-stubs/ldap/ldap.stub=qA4vendor/jetbrains/phpstorm-stubs/leveldb/LevelDB.stub;6vendor/jetbrains/phpstorm-stubs/libevent/libevent.stub"Y"Y08vendor/jetbrains/phpstorm-stubs/libsodium/libsodium.stube<e<`-:vendor/jetbrains/phpstorm-stubs/libsodium/libsodium_d.stub@@+Ƥ:vendor/jetbrains/phpstorm-stubs/libsodium/libsodium_f.stubړ+<vendor/jetbrains/phpstorm-stubs/libvirt-php/libvirt-php.stub99:`2vendor/jetbrains/phpstorm-stubs/libxml/libxml.stubW%W%&fפ8vendor/jetbrains/phpstorm-stubs/litespeed/litespeed.stubG,vendor/jetbrains/phpstorm-stubs/lua/lua.stub< < €,vendor/jetbrains/phpstorm-stubs/lzf/lzf.stubƤ8vendor/jetbrains/phpstorm-stubs/mailparse/mailparse.stub)8vendor/jetbrains/phpstorm-stubs/mapscript/mapscript.stub{|K8vendor/jetbrains/phpstorm-stubs/maxminddb/maxminddb.stubn+06vendor/jetbrains/phpstorm-stubs/mbstring/mbstring.stubxxxu2vendor/jetbrains/phpstorm-stubs/mcrypt/mcrypt.stub__iXV6vendor/jetbrains/phpstorm-stubs/memcache/memcache.stub 4qӤ8vendor/jetbrains/phpstorm-stubs/memcached/memcached.stub4vendor/jetbrains/phpstorm-stubs/meminfo/meminfo.stubrbɤ?vendor/jetbrains/phpstorm-stubs/meta/attributes/ArrayShape.stubXXp?vendor/jetbrains/phpstorm-stubs/meta/attributes/Deprecated.stubCvendor/jetbrains/phpstorm-stubs/meta/attributes/ExpectedValues.stub:qŤ>vendor/jetbrains/phpstorm-stubs/meta/attributes/Immutable.stuba'=vendor/jetbrains/phpstorm-stubs/meta/attributes/Language.stubMJ=vendor/jetbrains/phpstorm-stubs/meta/attributes/NoReturn.stub4@vendor/jetbrains/phpstorm-stubs/meta/attributes/ObjectShape.stubk p9vendor/jetbrains/phpstorm-stubs/meta/attributes/Pure.stubTvendor/jetbrains/phpstorm-stubs/meta/attributes/internal/LanguageLevelTypeAware.stuboo%[vendor/jetbrains/phpstorm-stubs/meta/attributes/internal/PhpStormStubsElementAvailable.stube3Pvendor/jetbrains/phpstorm-stubs/meta/attributes/internal/ReturnTypeContract.stubhh< xKvendor/jetbrains/phpstorm-stubs/meta/attributes/internal/TentativeType.stub().vendor/jetbrains/phpstorm-stubs/ming/ming.stubr"r"2: 0vendor/jetbrains/phpstorm-stubs/mongo/mongo.stub:8vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Binary.stub  t\ĤAvendor/jetbrains/phpstorm-stubs/mongodb/BSON/BinaryInterface.stubz;vendor/jetbrains/phpstorm-stubs/mongodb/BSON/DBPointer.stubHI<vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Decimal128.stubDD66Evendor/jetbrains/phpstorm-stubs/mongodb/BSON/Decimal128Interface.stub@@K֤:vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Document.stub#7vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Int64.stubhY:vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Iterator.stub <vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Javascript.stub*2Evendor/jetbrains/phpstorm-stubs/mongodb/BSON/JavascriptInterface.stublm8vendor/jetbrains/phpstorm-stubs/mongodb/BSON/MaxKey.stub^Avendor/jetbrains/phpstorm-stubs/mongodb/BSON/MaxKeyInterface.stub#8vendor/jetbrains/phpstorm-stubs/mongodb/BSON/MinKey.stubbOAvendor/jetbrains/phpstorm-stubs/mongodb/BSON/MinKeyInterface.stubGu:vendor/jetbrains/phpstorm-stubs/mongodb/BSON/ObjectId.stubAĤCvendor/jetbrains/phpstorm-stubs/mongodb/BSON/ObjectIdInterface.stubx7!=vendor/jetbrains/phpstorm-stubs/mongodb/BSON/PackedArray.stub @=vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Persistable.stub!t7vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Regex.stubc,<@vendor/jetbrains/phpstorm-stubs/mongodb/BSON/RegexInterface.stub}}E>vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Serializable.stub@}8vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Symbol.stub/ ;vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Timestamp.stubO{Dvendor/jetbrains/phpstorm-stubs/mongodb/BSON/TimestampInterface.stubG٤6vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Type.stub'J-=vendor/jetbrains/phpstorm-stubs/mongodb/BSON/UTCDateTime.stub3Fvendor/jetbrains/phpstorm-stubs/mongodb/BSON/UTCDateTimeInterface.stubS ;vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Undefined.stubK,@vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Unserializable.stub<vendor/jetbrains/phpstorm-stubs/mongodb/BSON/VectorType.stub7x6vendor/jetbrains/phpstorm-stubs/mongodb/BulkWrite.stub #ZBvendor/jetbrains/phpstorm-stubs/mongodb/BulkWriteCommand.stub.stub nHvendor/jetbrains/phpstorm-stubs/mongodb/BulkWriteCommandResult.stub.stubgD=vendor/jetbrains/phpstorm-stubs/mongodb/ClientEncryption.stubHH7#4vendor/jetbrains/phpstorm-stubs/mongodb/Command.stub޾d3vendor/jetbrains/phpstorm-stubs/mongodb/Cursor.stub w<vendor/jetbrains/phpstorm-stubs/mongodb/CursorInterface.stub- Nvendor/jetbrains/phpstorm-stubs/mongodb/Exception/AuthenticationException.stub55KUvendor/jetbrains/phpstorm-stubs/mongodb/Exception/BulkWriteCommandException.stub.stub& & -4Ivendor/jetbrains/phpstorm-stubs/mongodb/Exception/BulkWriteException.stubeeP~yGvendor/jetbrains/phpstorm-stubs/mongodb/Exception/CommandException.stubzzXJvendor/jetbrains/phpstorm-stubs/mongodb/Exception/ConnectionException.stubGGAlQvendor/jetbrains/phpstorm-stubs/mongodb/Exception/ConnectionTimeoutException.stubdd -;Jvendor/jetbrains/phpstorm-stubs/mongodb/Exception/EncryptionException.stub,, 5@vendor/jetbrains/phpstorm-stubs/mongodb/Exception/Exception.stub::MPvendor/jetbrains/phpstorm-stubs/mongodb/Exception/ExecutionTimeoutException.stubHHAOvendor/jetbrains/phpstorm-stubs/mongodb/Exception/InvalidArgumentException.stubSS5k:Evendor/jetbrains/phpstorm-stubs/mongodb/Exception/LogicException.stubZŤGvendor/jetbrains/phpstorm-stubs/mongodb/Exception/RuntimeException.stubFFEFvendor/jetbrains/phpstorm-stubs/mongodb/Exception/ServerException.stub`Ovendor/jetbrains/phpstorm-stubs/mongodb/Exception/UnexpectedValueException.stubjjMmLvendor/jetbrains/phpstorm-stubs/mongodb/Exception/WriteConcernException.stubyy4vendor/jetbrains/phpstorm-stubs/mongodb/Manager.stubY.Y.DJvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/CommandFailedEvent.stubqq%]Kvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/CommandStartedEvent.stub  1f9Ivendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/CommandSubscriber.stubjm#Mvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/CommandSucceededEvent.stub︤Evendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/LogSubscriber.stubn̅Fvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/SDAMSubscriber.stub ƐJvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/ServerChangedEvent.stub,,,Ivendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/ServerClosedEvent.stubLLfbRvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/ServerHeartbeatFailedEvent.stub’bSvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/ServerHeartbeatStartedEvent.stubKK_@֤Uvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/ServerHeartbeatSucceededEvent.stubnJvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/ServerOpeningEvent.stubPPg=IGBvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/Subscriber.stubLvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/TopologyChangedEvent.stublʤKvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/TopologyClosedEvent.stub,OLvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/TopologyOpeningEvent.stubAvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/functions.stubuuƽg2vendor/jetbrains/phpstorm-stubs/mongodb/Query.stubԶǤ8vendor/jetbrains/phpstorm-stubs/mongodb/ReadConcern.stubEE^׶\;vendor/jetbrains/phpstorm-stubs/mongodb/ReadPreference.stub, , n$3vendor/jetbrains/phpstorm-stubs/mongodb/Server.stubD+D+&q6vendor/jetbrains/phpstorm-stubs/mongodb/ServerApi.stuby>vendor/jetbrains/phpstorm-stubs/mongodb/ServerDescription.stub.4vendor/jetbrains/phpstorm-stubs/mongodb/Session.stubTTڸ7@vendor/jetbrains/phpstorm-stubs/mongodb/TopologyDescription.stub,9vendor/jetbrains/phpstorm-stubs/mongodb/WriteConcern.stub@ @ DŤ>vendor/jetbrains/phpstorm-stubs/mongodb/WriteConcernError.stub7vendor/jetbrains/phpstorm-stubs/mongodb/WriteError.stub{{ B8vendor/jetbrains/phpstorm-stubs/mongodb/WriteResult.stub 4vendor/jetbrains/phpstorm-stubs/mongodb/mongodb.stubFF.@vendor/jetbrains/phpstorm-stubs/mosquitto-php/mosquitto-php.stubq5q5H^6vendor/jetbrains/phpstorm-stubs/mqseries/mqseries.stub1%4vendor/jetbrains/phpstorm-stubs/msgpack/msgpack.stubXX2d\0vendor/jetbrains/phpstorm-stubs/mssql/mssql.stub6M6MW˟0vendor/jetbrains/phpstorm-stubs/mysql/mysql.stub@vendor/jetbrains/phpstorm-stubs/mysql_xdevapi/mysql_xdevapi.stubgC2vendor/jetbrains/phpstorm-stubs/mysqli/mysqli.stubFFuK4vendor/jetbrains/phpstorm-stubs/ncurses/ncurses.stub*֩6vendor/jetbrains/phpstorm-stubs/newrelic/newrelic.stub70vendor/jetbrains/phpstorm-stubs/oauth/oauth.stubb b bp.vendor/jetbrains/phpstorm-stubs/oci8/oci8.stuboo5֤0vendor/jetbrains/phpstorm-stubs/oci8/oci8v3.stubE9E94vendor/jetbrains/phpstorm-stubs/odbc/Connection.stub,,|0vendor/jetbrains/phpstorm-stubs/odbc/Result.stub((99.vendor/jetbrains/phpstorm-stubs/odbc/odbc.stubll=/4vendor/jetbrains/phpstorm-stubs/openssl/openssl.stubfä@vendor/jetbrains/phpstorm-stubs/opentelemetry/opentelemetry.stubPP,vendor/jetbrains/phpstorm-stubs/pam/pam.stubs]76vendor/jetbrains/phpstorm-stubs/parallel/parallel.stub4z>vendor/jetbrains/phpstorm-stubs/parallel/parallel/Channel.stub((&Dvendor/jetbrains/phpstorm-stubs/parallel/parallel/Channel/Error.stubKK%Kvendor/jetbrains/phpstorm-stubs/parallel/parallel/Channel/Error/Closed.stubeez Nvendor/jetbrains/phpstorm-stubs/parallel/parallel/Channel/Error/Existence.stubhhyäQvendor/jetbrains/phpstorm-stubs/parallel/parallel/Channel/Error/IllegalValue.stubkk<vendor/jetbrains/phpstorm-stubs/parallel/parallel/Error.stub::{=vendor/jetbrains/phpstorm-stubs/parallel/parallel/Events.stub ܤCvendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Error.stubJJžMvendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Error/Existence.stubffRbKvendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Error/Timeout.stubddJ6Cvendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Event.stub̀8Ivendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Event/Error.stubPPRHvendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Event/Type.stub..ϞZ>Cvendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Input.stub00>Ivendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Input/Error.stubPP?Svendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Input/Error/Existence.stubrr7oVvendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Input/Error/IllegalValue.stubuui=vendor/jetbrains/phpstorm-stubs/parallel/parallel/Future.stub``.?DäCvendor/jetbrains/phpstorm-stubs/parallel/parallel/Future/Error.stubJJbMvendor/jetbrains/phpstorm-stubs/parallel/parallel/Future/Error/Cancelled.stub__Kvendor/jetbrains/phpstorm-stubs/parallel/parallel/Future/Error/Foreign.stub]]}Jvendor/jetbrains/phpstorm-stubs/parallel/parallel/Future/Error/Killed.stub\\< >vendor/jetbrains/phpstorm-stubs/parallel/parallel/Runtime.stub0ˤDvendor/jetbrains/phpstorm-stubs/parallel/parallel/Runtime/Error.stubKKNvendor/jetbrains/phpstorm-stubs/parallel/parallel/Runtime/Error/Bootstrap.stubhhU>^;vendor/jetbrains/phpstorm-stubs/parallel/parallel/Sync.stubҧ Avendor/jetbrains/phpstorm-stubs/parallel/parallel/Sync/Error.stubHHbNvendor/jetbrains/phpstorm-stubs/parallel/parallel/Sync/Error/IllegalValue.stubee> w0vendor/jetbrains/phpstorm-stubs/pcntl/pcntl.stubXX~2vendor/jetbrains/phpstorm-stubs/pcntl/pcntl_c.stubzEh.vendor/jetbrains/phpstorm-stubs/pcov/pcov.stub\X.vendor/jetbrains/phpstorm-stubs/pcre/pcre.stubPPF2vendor/jetbrains/phpstorm-stubs/pdflib/PDFlib.stub/T/T5% K0vendor/jetbrains/phpstorm-stubs/pgsql/pgsql.stubtt?K2vendor/jetbrains/phpstorm-stubs/pgsql/pgsql_c.stub޲2vendor/jetbrains/phpstorm-stubs/phpdbg/phpdbg.stubggAȾO0vendor/jetbrains/phpstorm-stubs/posix/posix.stubcncn*vendor/jetbrains/phpstorm-stubs/pq/pq.stub++2vendor/jetbrains/phpstorm-stubs/pspell/pspell.stubq.q.0\4vendor/jetbrains/phpstorm-stubs/pspell/pspell_c.stubR 6vendor/jetbrains/phpstorm-stubs/pthreads/pthreads.stubHH>9+vendor/jetbrains/phpstorm-stubs/qodana.yaml 'JX;2vendor/jetbrains/phpstorm-stubs/radius/radius.stubGG4g2vendor/jetbrains/phpstorm-stubs/random/random.stubR;,vendor/jetbrains/phpstorm-stubs/rar/rar.stub__EQ`4vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka.stubqq;Ҥ9vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Conf.stubͺ=vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Consumer.stubTYBvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/ConsumerTopic.stub>>vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Exception.stubAAD/QBvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/KafkaConsumer.stub~ ~ Gvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/KafkaConsumerTopic.stubC٤Hvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/KafkaErrorException.stubQ<vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Message.stubz[=vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Metadata.stubώDvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Metadata/Broker.stubIQuRHvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Metadata/Collection.stubLGvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Metadata/Partition.stubCvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Metadata/Topic.stubc=vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Producer.stub99߲Bvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/ProducerTopic.stubaa:vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Queue.stubhh:vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Topic.stub{{t{=>vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/TopicConf.stub  xCvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/TopicPartition.stub!!9<6vendor/jetbrains/phpstorm-stubs/rdkafka/constants.stub## 6vendor/jetbrains/phpstorm-stubs/rdkafka/functions.stub6vendor/jetbrains/phpstorm-stubs/readline/readline.stubFF򓘤2vendor/jetbrains/phpstorm-stubs/recode/recode.stubO0vendor/jetbrains/phpstorm-stubs/redis/Redis.stub#S#S,5vendor/jetbrains/phpstorm-stubs/redis/RedisArray.stubtwtw7vendor/jetbrains/phpstorm-stubs/redis/RedisCluster.stub00$u8vendor/jetbrains/phpstorm-stubs/redis/RedisSentinel.stubX2/vendor/jetbrains/phpstorm-stubs/regex/ereg.stubz z =cP8vendor/jetbrains/phpstorm-stubs/relay/AdaptiveCache.stub\ \ uĤ2vendor/jetbrains/phpstorm-stubs/relay/Cluster.stub||'0vendor/jetbrains/phpstorm-stubs/relay/Event.stub,7A1vendor/jetbrains/phpstorm-stubs/relay/Events.stub)4vendor/jetbrains/phpstorm-stubs/relay/Exception.stubccr!2vendor/jetbrains/phpstorm-stubs/relay/KeyType.stubۼ0vendor/jetbrains/phpstorm-stubs/relay/Relay.stub%3vendor/jetbrains/phpstorm-stubs/relay/Sentinel.stub *L0vendor/jetbrains/phpstorm-stubs/relay/Table.stubooN/~4vendor/jetbrains/phpstorm-stubs/rpminfo/rpminfo.stub--,vendor/jetbrains/phpstorm-stubs/rrd/rrd.stub00Τ+vendor/jetbrains/phpstorm-stubs/runTests.shHX;vendor/jetbrains/phpstorm-stubs/session/SessionHandler.stub[([(mf4vendor/jetbrains/phpstorm-stubs/session/session.stubGG0vendor/jetbrains/phpstorm-stubs/shmop/shmop.stub2ɤ6vendor/jetbrains/phpstorm-stubs/simdjson/simdjson.stub//P^Jvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient.stub!Xvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Configuration.stubxxռvSvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Consumer.stubWWTvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Exception.stubddYv^vendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/KafkaErrorException.stubi',Rvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Message.stubkSvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Metadata.stub99!aZvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Metadata/Broker.stub99uo`^vendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Metadata/Collection.stub  ]vendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Metadata/Partition.stubgYvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Metadata/Topic.stubSS\Svendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Producer.stubИPvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Topic.stub Yvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/TopicPartition.stub&&>~Bvendor/jetbrains/phpstorm-stubs/simple_kafka_client/functions.stubBQ9vendor/jetbrains/phpstorm-stubs/snappy/snappy/snappy.stub .vendor/jetbrains/phpstorm-stubs/snmp/snmp.stubo4.vendor/jetbrains/phpstorm-stubs/soap/soap.stub!B0vendor/jetbrains/phpstorm-stubs/soap/soap_n.stubld4vendor/jetbrains/phpstorm-stubs/sockets/sockets.stubuuuԤ2vendor/jetbrains/phpstorm-stubs/sodium/sodium.stubg٤@vendor/jetbrains/phpstorm-stubs/solr/Documents/SolrDocument.stub 0 0q Evendor/jetbrains/phpstorm-stubs/solr/Documents/SolrDocumentField.stub \Evendor/jetbrains/phpstorm-stubs/solr/Documents/SolrInputDocument.stub_/_/LߤHvendor/jetbrains/phpstorm-stubs/solr/Exceptions/SolrClientException.stubssGPBvendor/jetbrains/phpstorm-stubs/solr/Exceptions/SolrException.stub&Qvendor/jetbrains/phpstorm-stubs/solr/Exceptions/SolrIllegalArgumentException.stub)4Rvendor/jetbrains/phpstorm-stubs/solr/Exceptions/SolrIllegalOperationException.stub-N%[vendor/jetbrains/phpstorm-stubs/solr/Exceptions/SolrMissingMandatoryParameterException.stubnHvendor/jetbrains/phpstorm-stubs/solr/Exceptions/SolrServerException.stubyyC$Fvendor/jetbrains/phpstorm-stubs/solr/Queries/SolrCollapseFunction.stubΤAvendor/jetbrains/phpstorm-stubs/solr/Queries/SolrDisMaxQuery.stub--ݿFvendor/jetbrains/phpstorm-stubs/solr/Queries/SolrModifiableParams.stubkk%<vendor/jetbrains/phpstorm-stubs/solr/Queries/SolrParams.stubty;vendor/jetbrains/phpstorm-stubs/solr/Queries/SolrQuery.stub}?}?]IGvendor/jetbrains/phpstorm-stubs/solr/Responses/SolrGenericResponse.stub++Dvendor/jetbrains/phpstorm-stubs/solr/Responses/SolrPingResponse.stubޡޤEvendor/jetbrains/phpstorm-stubs/solr/Responses/SolrQueryResponse.stubɤ@vendor/jetbrains/phpstorm-stubs/solr/Responses/SolrResponse.stub/I%Fvendor/jetbrains/phpstorm-stubs/solr/Responses/SolrUpdateResponse.stub%%>H٤4vendor/jetbrains/phpstorm-stubs/solr/SolrClient.stubMM~D*]:vendor/jetbrains/phpstorm-stubs/solr/Utils/SolrObject.stub  t 9vendor/jetbrains/phpstorm-stubs/solr/Utils/SolrUtils.stub O3vendor/jetbrains/phpstorm-stubs/solr/constants.stubDD c3vendor/jetbrains/phpstorm-stubs/solr/functions.stubAA4vendor/jetbrains/phpstorm-stubs/sqlite3/sqlite3.stubhh ä2vendor/jetbrains/phpstorm-stubs/sqlsrv/sqlsrv.stub~~i.vendor/jetbrains/phpstorm-stubs/ssh2/ssh2.stubdde>vendor/jetbrains/phpstorm-stubs/standard/_standard_manual.stub))ػD4vendor/jetbrains/phpstorm-stubs/standard/_types.stubHH1|3vendor/jetbrains/phpstorm-stubs/standard/basic.stub--;Q6vendor/jetbrains/phpstorm-stubs/standard/password.stubiio8vendor/jetbrains/phpstorm-stubs/standard/standard_0.stub\\W¤8vendor/jetbrains/phpstorm-stubs/standard/standard_1.stubGG9vendor/jetbrains/phpstorm-stubs/standard/standard_10.stubrr"Hݤ8vendor/jetbrains/phpstorm-stubs/standard/standard_2.stubL8vendor/jetbrains/phpstorm-stubs/standard/standard_3.stubzz/C8vendor/jetbrains/phpstorm-stubs/standard/standard_4.stub8vendor/jetbrains/phpstorm-stubs/standard/standard_5.stub,,=ڤ8vendor/jetbrains/phpstorm-stubs/standard/standard_6.stubr8vendor/jetbrains/phpstorm-stubs/standard/standard_7.stubll͒{8vendor/jetbrains/phpstorm-stubs/standard/standard_8.stubnN8vendor/jetbrains/phpstorm-stubs/standard/standard_9.stubввo'>vendor/jetbrains/phpstorm-stubs/standard/standard_defines.stubDD˺0vendor/jetbrains/phpstorm-stubs/stats/stats.stub"H"He0vendor/jetbrains/phpstorm-stubs/stomp/stomp.stubA"A"!K4vendor/jetbrains/phpstorm-stubs/suhosin/suhosin.stubQ?vendor/jetbrains/phpstorm-stubs/superglobals/_superglobals.stub--88,vendor/jetbrains/phpstorm-stubs/svm/SVM.stubqͤ1vendor/jetbrains/phpstorm-stubs/svm/SVMModel.stub p,vendor/jetbrains/phpstorm-stubs/svn/svn.stubll R9vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Atomic.stubeKͤ>vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Atomic/Long.stub9vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Client.stub  ѤCvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Client/Exception.stubhh;Fvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Connection/Iterator.stubfoƤ<vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine.stub@$ʼDvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Channel.stubOhCvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Client.stubpծDvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Context.stubKvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Curl/Exception.stubpp{_ԤHvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Http/Client.stub)) g&Rvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Http/Client/Exception.stubwwHvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Http/Server.stuby*Ivendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Http2/Client.stubooG>Svendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Http2/Client/Exception.stubxxP Evendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Iterator.stub4;Bvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/MySQL.stub==6w8Lvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/MySQL/Exception.stubqqQïLvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/MySQL/Statement.stub5Bvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Redis.stub n n2mFvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Scheduler.stub9Cvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Socket.stubaaMMvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Socket/Exception.stubrr-| Cvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/System.stub SAۤ8vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Error.stubRRT8vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Event.stubw<vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Exception.stubZZ@vendor/jetbrains/phpstorm-stubs/swoole/Swoole/ExitException.stub  _?vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Http/Request.stub],@vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Http/Response.stubc>vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Http/Server.stub``Y@vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Http2/Request.stubH1Avendor/jetbrains/phpstorm-stubs/swoole/Swoole/Http2/Response.stubi7vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Lock.stub.n:vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Process.stub8<ڋ?vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Process/Pool.stubL4!?vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Redis/Server.stub ?:vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Runtime.stub9vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Server.stubq&q&EĤ?vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Server/Event.stub4@vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Server/Packet.stub+Evendor/jetbrains/phpstorm-stubs/swoole/Swoole/Server/PipeMessage.stubvD>vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Server/Port.stub_{Dvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Server/StatusInfo.stub.>vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Server/Task.stubeZvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Thread/Lock.stubstm=vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Thread/Map.stub-j?vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Thread/Queue.stubBBp 8vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Timer.stub{{UAvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Timer/Iterator.stubg8'Gvendor/jetbrains/phpstorm-stubs/swoole/Swoole/WebSocket/CloseFrame.stub%Bvendor/jetbrains/phpstorm-stubs/swoole/Swoole/WebSocket/Frame.stubDCvendor/jetbrains/phpstorm-stubs/swoole/Swoole/WebSocket/Server.stub!Af3vendor/jetbrains/phpstorm-stubs/swoole/aliases.stubX X ᕤ5vendor/jetbrains/phpstorm-stubs/swoole/constants.stubAA@y5vendor/jetbrains/phpstorm-stubs/swoole/functions.stubn(n( ;5vendor/jetbrains/phpstorm-stubs/sybase/sybase_ct.stub77#!.vendor/jetbrains/phpstorm-stubs/sync/sync.stub77h3R64vendor/jetbrains/phpstorm-stubs/sysvmsg/sysvmsg.stub&&82~4vendor/jetbrains/phpstorm-stubs/sysvsem/sysvsem.stub zX4vendor/jetbrains/phpstorm-stubs/sysvshm/sysvshm.stub}}5o\.vendor/jetbrains/phpstorm-stubs/tidy/tidy.stubaao 7vendor/jetbrains/phpstorm-stubs/tokenizer/PhpToken.stub&8vendor/jetbrains/phpstorm-stubs/tokenizer/tokenizer.stubw9.vendor/jetbrains/phpstorm-stubs/uopz/uopz.stub&&-#Bvendor/jetbrains/phpstorm-stubs/uploadprogress/uploadprogress.stub  r݋,vendor/jetbrains/phpstorm-stubs/uri/uri.stub|*0vendor/jetbrains/phpstorm-stubs/uuid/uuid_c.stub }j*vendor/jetbrains/phpstorm-stubs/uv/UV.stub  h<4vendor/jetbrains/phpstorm-stubs/uv/uv_functions.stubffG).vendor/jetbrains/phpstorm-stubs/v8js/v8js.stubA!.vendor/jetbrains/phpstorm-stubs/wddx/wddx.stub [L>vendor/jetbrains/phpstorm-stubs/win32service/win32service.stubEcEcRۤ8vendor/jetbrains/phpstorm-stubs/winbinder/winbinder.stubxx:6vendor/jetbrains/phpstorm-stubs/wincache/wincache.stubaa잤2vendor/jetbrains/phpstorm-stubs/xcache/xcache.stub^)2vendor/jetbrains/phpstorm-stubs/xdebug/xdebug.stub33^Ȥ0vendor/jetbrains/phpstorm-stubs/xdiff/xdiff.stub7(7( פ2vendor/jetbrains/phpstorm-stubs/xhprof/xhprof.stubg"դ8vendor/jetbrains/phpstorm-stubs/xlswriter/xlswriter.stub+>+>',vendor/jetbrains/phpstorm-stubs/xml/xml.stubYY_x8vendor/jetbrains/phpstorm-stubs/xmlreader/xmlreader.stubsDsD+{ˤ2vendor/jetbrains/phpstorm-stubs/xmlrpc/xmlrpc.stub8vendor/jetbrains/phpstorm-stubs/xmlwriter/xmlwriter.stubc,vendor/jetbrains/phpstorm-stubs/xsl/xsl.stub<<t(0vendor/jetbrains/phpstorm-stubs/xxtea/xxtea.stub$nڤ,vendor/jetbrains/phpstorm-stubs/yaf/yaf.stub``ת6vendor/jetbrains/phpstorm-stubs/yaf/yaf_namespace.stubt[t[ Ĥ.vendor/jetbrains/phpstorm-stubs/yaml/yaml.stubhh{Ȥ,vendor/jetbrains/phpstorm-stubs/yar/yar.stub$$^Q.vendor/jetbrains/phpstorm-stubs/zend/zend.stubXXB 0vendor/jetbrains/phpstorm-stubs/zend/zend_d.stub-|j0vendor/jetbrains/phpstorm-stubs/zend/zend_f.stub..6x,vendor/jetbrains/phpstorm-stubs/zip/zip.stub `.vendor/jetbrains/phpstorm-stubs/zlib/zlib.stubLL㳚,vendor/jetbrains/phpstorm-stubs/zmq/zmq.stub1s1sE8vendor/jetbrains/phpstorm-stubs/zookeeper/zookeeper.stub ' ' .vendor/jetbrains/phpstorm-stubs/zstd/zstd.stubuu^s5vendor/nette/bootstrap/src/Bootstrap/Configurator.php++G~GFvendor/nette/bootstrap/src/Bootstrap/Extensions/ConstantsExtension.php))E@vendor/nette/bootstrap/src/Bootstrap/Extensions/PhpExtension.phpMM!j+vendor/nette/bootstrap/src/Configurator.php4kҤvendor/nette/di/PATCHES.txt]`Ȏ6vendor/nette/di/src/Bridges/DITracy/ContainerPanel.phpc c Hvendor/nette/di/src/Bridges/DITracy/templates/ContainerPanel.panel.phtml]띦Fvendor/nette/di/src/Bridges/DITracy/templates/ContainerPanel.tab.phtml>F-,vendor/nette/di/src/DI/Attributes/Inject.php  ঃH%vendor/nette/di/src/DI/Autowiring.phpDD#vendor/nette/di/src/DI/Compiler.php%%?%Z?,vendor/nette/di/src/DI/CompilerExtension.php{{Ť)vendor/nette/di/src/DI/Config/Adapter.phpӤ6vendor/nette/di/src/DI/Config/Adapters/NeonAdapter.phpK5vendor/nette/di/src/DI/Config/Adapters/PhpAdapter.php_)vendor/nette/di/src/DI/Config/Helpers.php##琸(vendor/nette/di/src/DI/Config/Loader.php  3ʍ$vendor/nette/di/src/DI/Container.php,,fw+vendor/nette/di/src/DI/ContainerBuilder.php++*vendor/nette/di/src/DI/ContainerLoader.php//U29vendor/nette/di/src/DI/Definitions/AccessorDefinition.php]i1vendor/nette/di/src/DI/Definitions/Definition.php 8vendor/nette/di/src/DI/Definitions/FactoryDefinition.php"#"#x9vendor/nette/di/src/DI/Definitions/ImportedDefinition.phpN8vendor/nette/di/src/DI/Definitions/LocatorDefinition.php]]00vendor/nette/di/src/DI/Definitions/Reference.php)28vendor/nette/di/src/DI/Definitions/ServiceDefinition.phpYYss0vendor/nette/di/src/DI/Definitions/Statement.php{Vr,vendor/nette/di/src/DI/DependencyChecker.php8+vendor/nette/di/src/DI/DynamicParameter.phpooB8vendor/nette/di/src/DI/Extensions/ConstantsExtension.phpvLp1vendor/nette/di/src/DI/Extensions/DIExtension.php. . &8vendor/nette/di/src/DI/Extensions/DecoratorExtension.phpZ Z 7g6vendor/nette/di/src/DI/Extensions/DefinitionSchema.php::8 9vendor/nette/di/src/DI/Extensions/ExtensionsExtension.php  c365vendor/nette/di/src/DI/Extensions/InjectExtension.phpŤ9vendor/nette/di/src/DI/Extensions/ParametersExtension.phprry2vendor/nette/di/src/DI/Extensions/PhpExtension.php# 5vendor/nette/di/src/DI/Extensions/SearchExtension.phpW7vendor/nette/di/src/DI/Extensions/ServicesExtension.phpXM"vendor/nette/di/src/DI/Helpers.php##6ϒ)'vendor/nette/di/src/DI/PhpGenerator.php`#vendor/nette/di/src/DI/Resolver.php6b6bvLr%vendor/nette/di/src/DI/exceptions.php55A}%vendor/nette/di/src/compatibility.php(vendor/nette/finder/src/Utils/Finder.phpI*I*Vvendor/nette/neon/bin/neon-lintDD0<&vendor/nette/neon/src/Neon/Decoder.php/C&vendor/nette/neon/src/Neon/Encoder.php\ \ [ϣ%vendor/nette/neon/src/Neon/Entity.phpH5(vendor/nette/neon/src/Neon/Exception.php77Nդ$vendor/nette/neon/src/Neon/Lexer.php kF W#vendor/nette/neon/src/Neon/Neon.php''5*#vendor/nette/neon/src/Neon/Node.phpO1vendor/nette/neon/src/Neon/Node/ArrayItemNode.php¤-vendor/nette/neon/src/Neon/Node/ArrayNode.php}}f2vendor/nette/neon/src/Neon/Node/BlockArrayNode.phpe 3vendor/nette/neon/src/Neon/Node/EntityChainNode.phpJݧ.vendor/nette/neon/src/Neon/Node/EntityNode.phpRR#t3vendor/nette/neon/src/Neon/Node/InlineArrayNode.php^^p r/vendor/nette/neon/src/Neon/Node/LiteralNode.php  'G.vendor/nette/neon/src/Neon/Node/StringNode.php  >Oߤ%vendor/nette/neon/src/Neon/Parser.php!!SQ$vendor/nette/neon/src/Neon/Token.php}}nKڤ*vendor/nette/neon/src/Neon/TokenStream.php  4(vendor/nette/neon/src/Neon/Traverser.phphh¤"vendor/nette/php-generator/ncs.php'',9vendor/nette/php-generator/src/PhpGenerator/Attribute.php]]C鴤9vendor/nette/php-generator/src/PhpGenerator/ClassType.php::z(U7vendor/nette/php-generator/src/PhpGenerator/Closure.phpY2A8vendor/nette/php-generator/src/PhpGenerator/Constant.phpsD6vendor/nette/php-generator/src/PhpGenerator/Dumper.php""o8vendor/nette/php-generator/src/PhpGenerator/EnumCase.php9vendor/nette/php-generator/src/PhpGenerator/Extractor.php==7vendor/nette/php-generator/src/PhpGenerator/Factory.phpo3o3j>vendor/nette/php-generator/src/PhpGenerator/GlobalFunction.phpV5{7vendor/nette/php-generator/src/PhpGenerator/Helpers.phpRR6Z7vendor/nette/php-generator/src/PhpGenerator/Literal.phpi6vendor/nette/php-generator/src/PhpGenerator/Method.php @59vendor/nette/php-generator/src/PhpGenerator/Parameter.php  rQ7vendor/nette/php-generator/src/PhpGenerator/PhpFile.phpVD:vendor/nette/php-generator/src/PhpGenerator/PhpLiteral.phpt7<vendor/nette/php-generator/src/PhpGenerator/PhpNamespace.php''6o7vendor/nette/php-generator/src/PhpGenerator/Printer.php44\#@Avendor/nette/php-generator/src/PhpGenerator/PromotedParameter.php?ˤ8vendor/nette/php-generator/src/PhpGenerator/Property.php *:vendor/nette/php-generator/src/PhpGenerator/PsrPrinter.php#8vendor/nette/php-generator/src/PhpGenerator/TraitUse.phpf٤Evendor/nette/php-generator/src/PhpGenerator/Traits/AttributeAware.phpEfCvendor/nette/php-generator/src/PhpGenerator/Traits/CommentAware.phpMCvendor/nette/php-generator/src/PhpGenerator/Traits/FunctionLike.phpP@vendor/nette/php-generator/src/PhpGenerator/Traits/NameAware.phpt< Fvendor/nette/php-generator/src/PhpGenerator/Traits/VisibilityAware.php33-e4vendor/nette/php-generator/src/PhpGenerator/Type.phpJJ999vendor/nette/robot-loader/src/RobotLoader/RobotLoader.phpb@b@ B*vendor/nette/schema/src/Schema/Context.phpvҤ3vendor/nette/schema/src/Schema/DynamicParameter.phpeI1vendor/nette/schema/src/Schema/Elements/AnyOf.phpLL9٤0vendor/nette/schema/src/Schema/Elements/Base.phpO95vendor/nette/schema/src/Schema/Elements/Structure.php`v0vendor/nette/schema/src/Schema/Elements/Type.phpMH)vendor/nette/schema/src/Schema/Expect.php ||*vendor/nette/schema/src/Schema/Helpers.phpds9*vendor/nette/schema/src/Schema/Message.php 7,vendor/nette/schema/src/Schema/Processor.php )vendor/nette/schema/src/Schema/Schema.phpyy6vendor/nette/schema/src/Schema/ValidationException.php ۤ)vendor/nette/utils/src/HtmlStringable.phpjjNp74vendor/nette/utils/src/Iterators/CachingIterator.php Ӥ+vendor/nette/utils/src/Iterators/Mapper.phpL&vendor/nette/utils/src/SmartObject.phpLH&vendor/nette/utils/src/StaticClass.php?tؒ%vendor/nette/utils/src/Translator.php,*vendor/nette/utils/src/Utils/ArrayHash.php *vendor/nette/utils/src/Utils/ArrayList.php  f]{'vendor/nette/utils/src/Utils/Arrays.php11M)vendor/nette/utils/src/Utils/Callback.phpVia.)vendor/nette/utils/src/Utils/DateTime.phpVV}s+vendor/nette/utils/src/Utils/FileSystem.phpB!B!rF'vendor/nette/utils/src/Utils/Floats.phpZ Z ɋ(vendor/nette/utils/src/Utils/Helpers.php| | aeҥ%vendor/nette/utils/src/Utils/Html.php_Z_Zv^&vendor/nette/utils/src/Utils/Image.phpxbxbIä%vendor/nette/utils/src/Utils/Json.php-.vendor/nette/utils/src/Utils/ObjectHelpers.php((!d,vendor/nette/utils/src/Utils/ObjectMixin.php+aR*vendor/nette/utils/src/Utils/Paginator.php^D'vendor/nette/utils/src/Utils/Random.php-:+vendor/nette/utils/src/Utils/Reflection.php66v(vendor/nette/utils/src/Utils/Strings.phpxRxRi[%vendor/nette/utils/src/Utils/Type.phpw+vendor/nette/utils/src/Utils/Validators.php//.ˤ+vendor/nette/utils/src/Utils/exceptions.phpK#(vendor/nette/utils/src/compatibility.php6r8%vendor/nette/utils/src/exceptions.php_Xvendor/nikic/php-parser/LICENSE*1vendor/nikic/php-parser/lib/PhpParser/Builder.phpGX <vendor/nikic/php-parser/lib/PhpParser/Builder/ClassConst.php.XȤ8vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.php**6u=vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php=w:vendor/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php0hפ7vendor/nikic/php-parser/lib/PhpParser/Builder/Enum_.php <٤>vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php((ܤ;vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.phpbbR Ф<vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php3 3 s8vendor/nikic/php-parser/lib/PhpParser/Builder/Method.phprrXd<vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.phpLL"Yդ7vendor/nikic/php-parser/lib/PhpParser/Builder/Param.phppp0ˍ:vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php  9=:vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php0Dvendor/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.phpP8vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php } ;6vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php'ݘ8vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php**Ʒ8vendor/nikic/php-parser/lib/PhpParser/BuilderHelpers.php%%K1vendor/nikic/php-parser/lib/PhpParser/Comment.php  S5vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.phphhyFvendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.phpqqR<vendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php&&靤/vendor/nikic/php-parser/lib/PhpParser/Error.phpQQ^6vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php88kAvendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.phpqq-8?vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.phpttD;vendor/nikic/php-parser/lib/PhpParser/Internal/DiffElem.phpŤ9vendor/nikic/php-parser/lib/PhpParser/Internal/Differ.php m Lvendor/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.phpA A }*@vendor/nikic/php-parser/lib/PhpParser/Internal/TokenPolyfill.php$${af>vendor/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php##G^K5vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php /vendor/nikic/php-parser/lib/PhpParser/Lexer.phpG9vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php  8_vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AsymmetricVisibilityTokenEmulator.php Ovendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.phpԿx=Ovendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.phpՋSvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.phpMvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php99DIPvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.phpEFSvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php((Rvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/PipeOperatorEmulator.phpPP_ޤSvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/PropertyTokenEmulator.php#[vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyFunctionTokenEmulator.php0Svendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.phpkkLXMvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.phpdd!Kvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php33{Nvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/VoidCastEmulator.php% % r3vendor/nikic/php-parser/lib/PhpParser/Modifiers.php ,5vendor/nikic/php-parser/lib/PhpParser/NameContext.php&&h.vendor/nikic/php-parser/lib/PhpParser/Node.php!!$O42vendor/nikic/php-parser/lib/PhpParser/Node/Arg.phpHH8vendor/nikic/php-parser/lib/PhpParser/Node/ArrayItem.php&&HI68vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php\\gj#=vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.phprgӤ9vendor/nikic/php-parser/lib/PhpParser/Node/ClosureUse.php>:vendor/nikic/php-parser/lib/PhpParser/Node/ComplexType.phpCC y5vendor/nikic/php-parser/lib/PhpParser/Node/Const_.php##g_:vendor/nikic/php-parser/lib/PhpParser/Node/DeclareItem.php((w?3vendor/nikic/php-parser/lib/PhpParser/Node/Expr.php:Avendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php??eKy=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php66j!A:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.phpNNiAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php  W:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.phpbжɤ<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.phpGrЯGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.phpkFvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.phpfGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.phpĤEvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.phpۅCvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php3T@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.phpܗBvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php@"E@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.phpI@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.phpNAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php~@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php)Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php3ꨤGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.phpOؤ=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php@@Oy<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.phpLLtԤGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php>>1OtQFvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php<<|3:jGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php>>*_Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php??Nr?Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php==JEvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php;;bCvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php664l@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php00ǁBvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php55W"Dvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php889݃Kvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.phpGGNFvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php>>iGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php@@$[Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php==pGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php@@\F%Bvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php44W@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php00W@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php00[T\ҤEvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php;;e>Ivendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.phpDDn4nAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pipe.php33kʤAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php22X@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php11.qFvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php==lĤGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php??H,>פDvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php885 EKvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.phpGG+BFvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php>>>m>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php->vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.phpW<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.phpCۤ8vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php==8?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.phpxv>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.phpggk?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.phpQ:=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.phpccӁq@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php9 @vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.phpmm fU?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.phpC8>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Void_.php(.Cvendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php^q :vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php%;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php. . @!ߤ>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php:: >vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.phpKڟڤ:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.phpfj9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php'ƤAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.phpغ9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.phpr!J?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.phpee6Τ:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.phpX7Τ9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.phpX_|:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.phpIo>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php08vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.phpnn,XFvendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php55MڤIvendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.phpy@`;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php.PpU;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php?:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php`:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php+[CAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.phpE$=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php$$1=>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php))JAGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.phpJ;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.phpU:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.phpF`"*>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.phpH#=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.phpKv<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.phpPԤ=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php=ߤ:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.phpWWH;vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.phpuj9vendor/nikic/php-parser/lib/PhpParser/Node/Identifier.php::dEvendor/nikic/php-parser/lib/PhpParser/Node/InterpolatedStringPart.phpzz+?vendor/nikic/php-parser/lib/PhpParser/Node/IntersectionType.phpw¤7vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.phpύ3vendor/nikic/php-parser/lib/PhpParser/Node/Name.php!!PBvendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php=]<vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.phpzG;vendor/nikic/php-parser/lib/PhpParser/Node/NullableType.php;H4vendor/nikic/php-parser/lib/PhpParser/Node/Param.php-ࣤ;vendor/nikic/php-parser/lib/PhpParser/Node/PropertyHook.php /'DD;vendor/nikic/php-parser/lib/PhpParser/Node/PropertyItem.phpxx\5vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.phpssuQ=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php88lg >vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php]]HwHvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php/z<vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Float_.php@:vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Int_.php 3Hvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/InterpolatedString.php~u޼=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php22?9Q@vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php``"))Gvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.phpBB2Dvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php;;7LEvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php>> Jvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.phpKK5Evendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php>>ɤGvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.phpDDDXKvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.phpNN aIvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Property.phpJJQg@Gvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.phpBB8{ih=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.phpm8vendor/nikic/php-parser/lib/PhpParser/Node/StaticVar.php11wE3vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.phpEt19vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Block.phpˈtq:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php>9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.phpnn-t:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.phpUUۂ9>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php//S=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php qA?vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.phpƯ;:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php V\m:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php*$=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php%e%Bvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.phpQQ]<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php7׃7vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php<<vg9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.phpL;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.phpCC t9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php B<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.phpM9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.phpGG%i>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php'<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php0eƤ8vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.phpXl<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.phpj%X=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php ;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.phpS~9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.phpz(K<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.phpCC訴@vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php  A7vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.phpHa>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php >vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.phpKK9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.phpuΤ>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php87vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php.. 辤<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php} } WDvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.phpWWL;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php%=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php66P;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php2;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php11PQ<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php}aFvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php%% 2Lvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php}gWQvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php&&ӋB:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.phpNN-<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.phpHHjOd:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php2":vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php99*E8vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.phpGN:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php??!8vendor/nikic/php-parser/lib/PhpParser/Node/UnionType.php>96vendor/nikic/php-parser/lib/PhpParser/Node/UseItem.php9@vendor/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php  <Bvendor/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.phpH}6vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.phpbbKD4vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php((Vd4vendor/nikic/php-parser/lib/PhpParser/NodeFinder.php_ _ %TƤ7vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php ( (v@vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.phpkki5vendor/nikic/php-parser/lib/PhpParser/NodeVisitor.phpbb5zDvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php!FNvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CommentAnnotatingVisitor.phpz z (Dvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.phpk #)Ivendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.phpe'ˤBvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php''!BKvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php L\Mvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.phpGGO=vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.phpBx+%0vendor/nikic/php-parser/lib/PhpParser/Parser.php,5vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.phpyyGZ5vendor/nikic/php-parser/lib/PhpParser/Parser/Php8.php?8vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php 7vendor/nikic/php-parser/lib/PhpParser/ParserFactory.php  f׼4vendor/nikic/php-parser/lib/PhpParser/PhpVersion.phpc7vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter.phpdM@vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php?vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.phph h </vendor/nikic/php-parser/lib/PhpParser/Token.phps>vendor/nikic/php-parser/lib/PhpParser/compatibility_tokens.php  vL!vendor/ondram/ci-detector/ecs.phpvvL /vendor/ondram/ci-detector/src/Ci/AbstractCi.phpCC;f-vendor/ondram/ci-detector/src/Ci/AppVeyor.phpRR{<%1vendor/ondram/ci-detector/src/Ci/AwsCodeBuild.php.. m3vendor/ondram/ci-detector/src/Ci/AzurePipelines.php+vendor/ondram/ci-detector/src/Ci/Bamboo.phpv7vendor/ondram/ci-detector/src/Ci/BitbucketPipelines.phpQQ*vendor/ondram/ci-detector/src/Ci/Buddy.php>&0vendor/ondram/ci-detector/src/Ci/CiInterface.phpS S $l+vendor/ondram/ci-detector/src/Ci/Circle.php䂲-vendor/ondram/ci-detector/src/Ci/Codeship.phprr4<2vendor/ondram/ci-detector/src/Ci/Continuousphp.phpZKV*vendor/ondram/ci-detector/src/Ci/Drone.php>c#2vendor/ondram/ci-detector/src/Ci/GitHubActions.phpaa< ~+vendor/ondram/ci-detector/src/Ci/GitLab.phpeͻ,vendor/ondram/ci-detector/src/Ci/Jenkins.php--A.vendor/ondram/ci-detector/src/Ci/SourceHut.phpOOP 4-vendor/ondram/ci-detector/src/Ci/TeamCity.php  NY+vendor/ondram/ci-detector/src/Ci/Travis.phpnќ,vendor/ondram/ci-detector/src/Ci/Wercker.php>F Ť,vendor/ondram/ci-detector/src/CiDetector.php yE5vendor/ondram/ci-detector/src/CiDetectorInterface.phptt%vendor/ondram/ci-detector/src/Env.phpQ‰Bvendor/ondram/ci-detector/src/Exception/CiNotDetectedException.php5dR.vendor/ondram/ci-detector/src/TrinaryLogic.php!!0 }-vendor/ondrejmirtes/better-reflection/LICENSE66Ww>vendor/ondrejmirtes/better-reflection/src/BetterReflection.phpccP:ǤXvendor/ondrejmirtes/better-reflection/src/Identifier/Exception/InvalidIdentifierName.phpddL׺Cvendor/ondrejmirtes/better-reflection/src/Identifier/Identifier.php))EGvendor/ondrejmirtes/better-reflection/src/Identifier/IdentifierType.php Mvendor/ondrejmirtes/better-reflection/src/NodeCompiler/CompileNodeToValue.php99OKlHvendor/ondrejmirtes/better-reflection/src/NodeCompiler/CompiledValue.php_Jvendor/ondrejmirtes/better-reflection/src/NodeCompiler/CompilerContext.phpVV%8IXvendor/ondrejmirtes/better-reflection/src/NodeCompiler/Exception/UnableToCompileNode.php xL|Yvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/Exception/NotImplemented.phpIReuvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/Exception/NotImplementedBecauseItTriggersAutoloading.phphh^!cXvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/FakeReflectionAttribute.phpFTvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionAttribute.php~ ~ _@s[vendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionAttributeFactory.php66Pvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionClass.php]]dǤXvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionClassConstant.phpu!Ovendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionEnum.phpTT/Yvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionEnumBackedCase.phpWvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionEnumUnitCase.phpYY3Svendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionFunction.php # #t^[vendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionIntersectionType.php3ϤQvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionMethod.phpz-z-.Tvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionNamedType.phpy y ZIQvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionObject.phpOOEQTvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionParameter.php""Svendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionProperty.php00טԗOvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionType.phpf f 1>fTvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionUnionType.phpeVTvendor/ondrejmirtes/better-reflection/src/Reflection/Annotation/AnnotationHelper.php(( t\vendor/ondrejmirtes/better-reflection/src/Reflection/Attribute/ReflectionAttributeHelper.phpt t &YO!Tvendor/ondrejmirtes/better-reflection/src/Reflection/Deprecated/DeprecatedHelper.php`וTvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/CircularReference.phpll‰*Tvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/ClassDoesNotExist.phpEVvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/CodeLocationMissing.phpޤWvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/FunctionDoesNotExist.phpzzlʤ_vendor/ondrejmirtes/better-reflection/src/Reflection/Exception/InvalidArrowFunctionBodyNode.php++v,Vvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/InvalidConstantNode.php8d6Zvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/InvalidDefaultValueType.phpudBZvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/MethodPrototypeNotFound.php27VSvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/NoObjectProvided.phprSKvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/NoParent.phpߤNvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/NotAnObject.phpg?[vendor/ondrejmirtes/better-reflection/src/Reflection/Exception/ObjectNotInstanceOfClass.phpwwFWvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/PropertyDoesNotExist.php\\D1Vvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/PropertyIsNotStatic.phpZZRHvendor/ondrejmirtes/better-reflection/src/Reflection/ExprCacheHelper.php  S Cvendor/ondrejmirtes/better-reflection/src/Reflection/Reflection.phpjLvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionAttribute.phpIͤHvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionClass.phpCPvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionClassConstant.phpe1e1Kvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionConstant.phpK/K/qmGvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionEnum.php8[Kvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionEnumCase.phptt>ŤKvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionFunction.phpmH#Svendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionFunctionAbstract.phpLLѺ/Svendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionIntersectionType.phptt!}Ivendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionMethod.phpJJ}ܤLvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionNamedType.phpbΤIvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionObject.php556xꜤLvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionParameter.phpDD~qKvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionProperty.phpXsXsjvSvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionPropertyHookType.phpmm(Gvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionType.phpT T m$Lvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionUnionType.php.Bavendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionAttributeStringCast.php/evendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionClassConstantStringCast.php22~ ?]vendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionClassStringCast.php5"5"`vendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionConstantStringCast.phpf`vendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionEnumCaseStringCast.php !`vendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionFunctionStringCast.php BsK^vendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionMethodStringCast.phpKK eavendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionParameterStringCast.phpbb(2`vendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionPropertyStringCast.php5Ѥ^vendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionStringCastHelper.php^]t_\vendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionTypeStringCast.php  KVvendor/ondrejmirtes/better-reflection/src/Reflection/Support/AlreadyVisitedClasses.phpaa Hvendor/ondrejmirtes/better-reflection/src/Reflector/DefaultReflector.php|[\Tvendor/ondrejmirtes/better-reflection/src/Reflector/Exception/IdentifierNotFound.php  UUAvendor/ondrejmirtes/better-reflection/src/Reflector/Reflector.php  . d[vendor/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Exception/ParseToAstFailure.php\!Uvendor/ondrejmirtes/better-reflection/src/SourceLocator/Ast/FindReflectionsInTree.php~~~Gvendor/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Locator.php {iVvendor/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Parser/MemoizingParser.php___j^vendor/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Strategy/AstConversionStrategy.phpϜYvendor/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Strategy/NodeToReflection.php ivendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/EvaledAnonymousClassCannotBeLocated.php22u{bvendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/EvaledClosureCannotBeLocated.php##FVvendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/InvalidDirectory.php4Uvendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/InvalidFileInfo.php))[jBYvendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/InvalidFileLocation.php\vendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/NoAnonymousClassOnLine.php~~^=Uvendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/NoClosureOnLine.phpooi@Vvendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/NotInternalClass.phpzׯcvendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/TwoAnonymousClassesOnSameLine.phpc[vendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/TwoClosuresOnSameLine.phpqqz Gvendor/ondrejmirtes/better-reflection/src/SourceLocator/FileChecker.php+DVvendor/ondrejmirtes/better-reflection/src/SourceLocator/Located/AliasLocatedSource.php++Zvendor/ondrejmirtes/better-reflection/src/SourceLocator/Located/AnonymousLocatedSource.php&&>4Wvendor/ondrejmirtes/better-reflection/src/SourceLocator/Located/EvaledLocatedSource.php ۵Yvendor/ondrejmirtes/better-reflection/src/SourceLocator/Located/InternalLocatedSource.php  7Qvendor/ondrejmirtes/better-reflection/src/SourceLocator/Located/LocatedSource.php` ` =`vendor/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/AggregateSourceStubber.php%[mvendor/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/Exception/CouldNotFindPhpStormStubs.php//6fvendor/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/PhpStormStubs/CachingVisitor.php oҤdvendor/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/PhpStormStubsSourceStubber.php{{;[avendor/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/ReflectionSourceStubber.phpyy:)gWvendor/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/SourceStubber.php~~mwRvendor/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/StubData.phpIIuVvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/AbstractSourceLocator.php  2TWvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/AggregateSourceLocator.php Hbvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/AnonymousClassObjectSourceLocator.php=1iVvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/AutoloadSourceLocator.php//9pvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/AutoloadSourceLocator/FileReadTrapStreamWrapper.php}}m$ڤUvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/ClosureSourceLocator.phpJevendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/Exception.phpZ\mvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/FailedToParseJson.phpC!#Fsvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/InvalidProjectDirectory.phpm`=]ovendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/MissingComposerJson.php-EEpvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/MissingInstalledJson.phpP:lvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/MakeLocatorForComposerJson.phpt]|vendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/MakeLocatorForComposerJsonAndInstalledJson.phpWMmvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/MakeLocatorForInstalledJson.phpcڍavendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/Exception/Exception.phplvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/Exception/InvalidPrefixMapping.phpppYvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/Psr0Mapping.phpI!Yvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/Psr4Mapping.php <'bvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/PsrAutoloaderMapping.phpttkbQ^vendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/PsrAutoloaderLocator.php 7`ФVvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/ComposerSourceLocator.phpgӤYvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/DirectoriesSourceLocator.phpqXvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/EvaledCodeSourceLocator.phpQQZvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/FileIteratorSourceLocator.php ]ݤWvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/MemoizingSourceLocator.php z]Yvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/PhpInternalSourceLocator.php   kXvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/SingleFileSourceLocator.php LNvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/SourceLocator.php))Tvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/StringSourceLocator.php77Lvendor/ondrejmirtes/better-reflection/src/Util/CalculateReflectionColumn.phpBHvendor/ondrejmirtes/better-reflection/src/Util/ClassExistenceChecker.phpRLFvendor/ondrejmirtes/better-reflection/src/Util/ConstantNodeChecker.phpPvendor/ondrejmirtes/better-reflection/src/Util/Exception/InvalidNodePosition.phpUUWo|Kvendor/ondrejmirtes/better-reflection/src/Util/Exception/NoNodePosition.php(=vendor/ondrejmirtes/better-reflection/src/Util/FileHelper.php  ģ[Gvendor/ondrejmirtes/better-reflection/src/Util/FindReflectionOnLine.php\\:Dvendor/ondrejmirtes/better-reflection/src/Util/GetLastDocComment.phpUy:vendor/ondrejmirtes/better-reflection/src/Util/Memoize.php3Q8vendor/ondrejmirtes/composer-attribute-collector/LICENSEQvendor/ondrejmirtes/composer-attribute-collector/src/AttributeGroupsReflector.php<vendor/ondrejmirtes/php-merge/src/PhpMerge/internal/Line.php cǤ"vendor/phpstan/php-8-stubs/LICENSEQQw+vendor/phpstan/php-8-stubs/Php8StubsMap.php))>(vendor/phpstan/php-8-stubs/stubs/LICENSE VAvendor/phpstan/php-8-stubs/stubs/Zend/AllowDynamicProperties.stub]%=vendor/phpstan/php-8-stubs/stubs/Zend/ArgumentCountError.stub77f-:vendor/phpstan/php-8-stubs/stubs/Zend/ArithmeticError.stub00ڏ6vendor/phpstan/php-8-stubs/stubs/Zend/ArrayAccess.stub55&+4vendor/phpstan/php-8-stubs/stubs/Zend/Attribute.stubO O 3F5vendor/phpstan/php-8-stubs/stubs/Zend/BackedEnum.stubH+Cvendor/phpstan/php-8-stubs/stubs/Zend/ClosedGeneratorException.stub==kQ2vendor/phpstan/php-8-stubs/stubs/Zend/Closure.stubOO\7vendor/phpstan/php-8-stubs/stubs/Zend/CompileError.stub--4vendor/phpstan/php-8-stubs/stubs/Zend/Countable.stub}}ҿBvendor/phpstan/php-8-stubs/stubs/Zend/DelayedTargetValidation.stubN{5vendor/phpstan/php-8-stubs/stubs/Zend/Deprecated.stub8Ĥ>vendor/phpstan/php-8-stubs/stubs/Zend/DivisionByZeroError.stub>>8դ0vendor/phpstan/php-8-stubs/stubs/Zend/Error.stube9vendor/phpstan/php-8-stubs/stubs/Zend/ErrorException.stub   m4vendor/phpstan/php-8-stubs/stubs/Zend/Exception.stubdd?[i0vendor/phpstan/php-8-stubs/stubs/Zend/Fiber.stub  m5vendor/phpstan/php-8-stubs/stubs/Zend/FiberError.stubppU34vendor/phpstan/php-8-stubs/stubs/Zend/Generator.stub::;vendor/phpstan/php-8-stubs/stubs/Zend/InternalIterator.stub }3vendor/phpstan/php-8-stubs/stubs/Zend/Iterator.stub]燤<vendor/phpstan/php-8-stubs/stubs/Zend/IteratorAggregate.stub-E4vendor/phpstan/php-8-stubs/stubs/Zend/NoDiscard.stubYj3vendor/phpstan/php-8-stubs/stubs/Zend/Override.stub~}Ϥ5vendor/phpstan/php-8-stubs/stubs/Zend/ParseError.stub22!Dvendor/phpstan/php-8-stubs/stubs/Zend/RequestParseBodyException.stubOOZ4_?vendor/phpstan/php-8-stubs/stubs/Zend/ReturnTypeWillChange.stubkkY=vendor/phpstan/php-8-stubs/stubs/Zend/SensitiveParameter.stubQBvendor/phpstan/php-8-stubs/stubs/Zend/SensitiveParameterValue.stubCzO7vendor/phpstan/php-8-stubs/stubs/Zend/Serializable.stubi5vendor/phpstan/php-8-stubs/stubs/Zend/Stringable.stubJJ}ވ4vendor/phpstan/php-8-stubs/stubs/Zend/Throwable.stuboo׍x6vendor/phpstan/php-8-stubs/stubs/Zend/Traversable.stubCCł4vendor/phpstan/php-8-stubs/stubs/Zend/TypeError.stub**֤>vendor/phpstan/php-8-stubs/stubs/Zend/UnhandledMatchError.stub44-A3vendor/phpstan/php-8-stubs/stubs/Zend/UnitEnum.stubyywGuפ5vendor/phpstan/php-8-stubs/stubs/Zend/ValueError.stub++&Ȳ2vendor/phpstan/php-8-stubs/stubs/Zend/WeakMap.stubDD-8vendor/phpstan/php-8-stubs/stubs/Zend/WeakReference.stubqq6vendor/phpstan/php-8-stubs/stubs/Zend/class_alias.stub[[Ĥ7vendor/phpstan/php-8-stubs/stubs/Zend/class_exists.stubMM*CF0vendor/phpstan/php-8-stubs/stubs/Zend/clone.stubrr(i:vendor/phpstan/php-8-stubs/stubs/Zend/debug_backtrace.stubjjq@vendor/phpstan/php-8-stubs/stubs/Zend/debug_print_backtrace.stubRRL1vendor/phpstan/php-8-stubs/stubs/Zend/define.stubn2vendor/phpstan/php-8-stubs/stubs/Zend/defined.stub99n*b.vendor/phpstan/php-8-stubs/stubs/Zend/die.stub[[$ 6vendor/phpstan/php-8-stubs/stubs/Zend/enum_exists.stub\\ԩ :vendor/phpstan/php-8-stubs/stubs/Zend/error_reporting.stubCCATp/vendor/phpstan/php-8-stubs/stubs/Zend/exit.stubIIF&;vendor/phpstan/php-8-stubs/stubs/Zend/extension_loaded.stub>>2[놤7vendor/phpstan/php-8-stubs/stubs/Zend/func_get_arg.stub778vendor/phpstan/php-8-stubs/stubs/Zend/func_get_args.stub++68vendor/phpstan/php-8-stubs/stubs/Zend/func_num_args.stub))OPh:vendor/phpstan/php-8-stubs/stubs/Zend/function_exists.stub<<$m<vendor/phpstan/php-8-stubs/stubs/Zend/gc_collect_cycles.stub--W5vendor/phpstan/php-8-stubs/stubs/Zend/gc_disable.stub''4vendor/phpstan/php-8-stubs/stubs/Zend/gc_enable.stub&&V/5vendor/phpstan/php-8-stubs/stubs/Zend/gc_enabled.stub''r}8vendor/phpstan/php-8-stubs/stubs/Zend/gc_mem_caches.stub00c4vendor/phpstan/php-8-stubs/stubs/Zend/gc_status.stub''9H;vendor/phpstan/php-8-stubs/stubs/Zend/get_called_class.stub//歉4vendor/phpstan/php-8-stubs/stubs/Zend/get_class.stub@@Ap<vendor/phpstan/php-8-stubs/stubs/Zend/get_class_methods.stubMMcn99vendor/phpstan/php-8-stubs/stubs/Zend/get_class_vars.stub99uD[?vendor/phpstan/php-8-stubs/stubs/Zend/get_declared_classes.stub22p} ȤBvendor/phpstan/php-8-stubs/stubs/Zend/get_declared_interfaces.stub55X,D>vendor/phpstan/php-8-stubs/stubs/Zend/get_declared_traits.stub11Z@vendor/phpstan/php-8-stubs/stubs/Zend/get_defined_constants.stubKK@vendor/phpstan/php-8-stubs/stubs/Zend/get_defined_functions.stubPPOb;vendor/phpstan/php-8-stubs/stubs/Zend/get_defined_vars.stub..+9<vendor/phpstan/php-8-stubs/stubs/Zend/get_error_handler.stubDDlr@vendor/phpstan/php-8-stubs/stubs/Zend/get_exception_handler.stubHH Ф>vendor/phpstan/php-8-stubs/stubs/Zend/get_extension_funcs.stubHH=vendor/phpstan/php-8-stubs/stubs/Zend/get_included_files.stub00RG^@vendor/phpstan/php-8-stubs/stubs/Zend/get_loaded_extensions.stubPP0̤Bvendor/phpstan/php-8-stubs/stubs/Zend/get_mangled_object_vars.stubCC:vendor/phpstan/php-8-stubs/stubs/Zend/get_object_vars.stub;;2zc;vendor/phpstan/php-8-stubs/stubs/Zend/get_parent_class.stub]]=vendor/phpstan/php-8-stubs/stubs/Zend/get_required_files.stubQQ :vendor/phpstan/php-8-stubs/stubs/Zend/get_resource_id.stubUU\ ߤ<vendor/phpstan/php-8-stubs/stubs/Zend/get_resource_type.stubZZ(ˤ8vendor/phpstan/php-8-stubs/stubs/Zend/get_resources.stub??P2鮤;vendor/phpstan/php-8-stubs/stubs/Zend/interface_exists.stubUUy/vendor/phpstan/php-8-stubs/stubs/Zend/is_a.stubߤ9vendor/phpstan/php-8-stubs/stubs/Zend/is_subclass_of.stub18vendor/phpstan/php-8-stubs/stubs/Zend/method_exists.stubww_ڟ:vendor/phpstan/php-8-stubs/stubs/Zend/property_exists.stub{{y@vendor/phpstan/php-8-stubs/stubs/Zend/restore_error_handler.stub$P%)Dvendor/phpstan/php-8-stubs/stubs/Zend/restore_exception_handler.stubҤ<vendor/phpstan/php-8-stubs/stubs/Zend/set_error_handler.stub~~SQ@vendor/phpstan/php-8-stubs/stubs/Zend/set_exception_handler.stubgg#\%3vendor/phpstan/php-8-stubs/stubs/Zend/stdClass.stubJJ" _5vendor/phpstan/php-8-stubs/stubs/Zend/strcasecmp.stubFFX1vendor/phpstan/php-8-stubs/stubs/Zend/strcmp.stubBB01vendor/phpstan/php-8-stubs/stubs/Zend/strlen.stub00<6vendor/phpstan/php-8-stubs/stubs/Zend/strncasecmp.stubTT*b 2vendor/phpstan/php-8-stubs/stubs/Zend/strncmp.stubPP)7vendor/phpstan/php-8-stubs/stubs/Zend/trait_exists.stubMMϐ88vendor/phpstan/php-8-stubs/stubs/Zend/trigger_error.stub;c5vendor/phpstan/php-8-stubs/stubs/Zend/user_error.stubvendor/phpstan/php-8-stubs/stubs/ext/bcmath/BcMath/Number.stub>6vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcadd.stubtt˯7vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcceil.stubTT7vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bccomp.stubPPt 6vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcdiv.stubRR 9vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcdivmod.stubc788vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcfloor.stubUU6vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcmod.stubRR5P6vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcmul.stubRRf=6vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcpow.stubUUzä9vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcpowmod.stubii"?58vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcround.stub8vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcscale.stub55<7vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcsqrt.stubDD=M6vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcsub.stubRRrjD5vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzclose.stubff\m8vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzcompress.stubdd?Qmu:vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzdecompress.stub``V5vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzerrno.stub-+5vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzerror.stub6vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzerrstr.stubWǤ5vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzflush.stubff4vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzopen.stubDӤ4vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzread.stub]] ѤC5vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzwrite.stub1]Dvendor/phpstan/php-8-stubs/stubs/ext/calendar/cal_days_in_month.stubss V>vendor/phpstan/php-8-stubs/stubs/ext/calendar/cal_from_jd.stubGG +~;vendor/phpstan/php-8-stubs/stubs/ext/calendar/cal_info.stub88<vendor/phpstan/php-8-stubs/stubs/ext/calendar/cal_to_jd.stubSSoY>vendor/phpstan/php-8-stubs/stubs/ext/calendar/easter_date.stubXXM>vendor/phpstan/php-8-stubs/stubs/ext/calendar/easter_days.stubXXTX2=vendor/phpstan/php-8-stubs/stubs/ext/calendar/frenchtojd.stubEE@vendor/phpstan/php-8-stubs/stubs/ext/calendar/gregoriantojd.stubHH%g^>vendor/phpstan/php-8-stubs/stubs/ext/calendar/jddayofweek.stubXXb>vendor/phpstan/php-8-stubs/stubs/ext/calendar/jdmonthname.stubDDt=vendor/phpstan/php-8-stubs/stubs/ext/calendar/jdtofrench.stub88dV@vendor/phpstan/php-8-stubs/stubs/ext/calendar/jdtogregorian.stub;; =vendor/phpstan/php-8-stubs/stubs/ext/calendar/jdtojewish.stub^^zA=vendor/phpstan/php-8-stubs/stubs/ext/calendar/jdtojulian.stub88ݝ;vendor/phpstan/php-8-stubs/stubs/ext/calendar/jdtounix.stub33)&=vendor/phpstan/php-8-stubs/stubs/ext/calendar/jewishtojd.stubEE=vendor/phpstan/php-8-stubs/stubs/ext/calendar/juliantojd.stubEE;vendor/phpstan/php-8-stubs/stubs/ext/calendar/unixtojd.stub@@bvEvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/COMPersistHelper.stub찤8vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com.stubKϯDvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com_create_guid.stub44\B#Cvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com_event_sink.stub{{B0ԅBvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com_exception.stub??PfJvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com_get_active_object.stub\\)ˤEvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com_load_typelib.stub[[gEvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com_message_pump.stubJJGvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com_print_typeinfo.stub?oHvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com_safearray_proxy.stubCCj;vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/dotnet.stub`*<vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant.stub4b@p@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_abs.stub88<դ@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_add.stubEE'Z5@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_and.stubEE{wqAvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_cast.stubII*@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_cat.stubEEj@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_cmp.stubxx?Pvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_date_from_timestamp.stubJJzNvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_date_to_timestamp.stubGG뾤@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_div.stubEE@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_eqv.stubEE=@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_fix.stub88FEvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_get_type.stub==NDAvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_idiv.stubFFh@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_imp.stubEE26W@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_int.stub88(?^@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_mod.stubEEY@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_mul.stubEE5[@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_neg.stub88ox@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_not.stub88F?vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_or.stubDDS@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_pow.stubEEWgBvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_round.stubJJ.@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_set.stubii Evendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_set_type.stubIIkjo@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_sub.stubEEAg3@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_xor.stubEE؏+;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_alnum.stubUU=4c7;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_alpha.stub33;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_cntrl.stub33Ҥ;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_digit.stub33簤;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_graph.stub33_r;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_lower.stub33̤;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_print.stub33Ë&;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_punct.stub33!^;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_space.stub336 ;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_upper.stub33mM<vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_xdigit.stub44u7vendor/phpstan/php-8-stubs/stubs/ext/curl/CURLFile.stubn7B=vendor/phpstan/php-8-stubs/stubs/ext/curl/CURLStringFile.stub'V9vendor/phpstan/php-8-stubs/stubs/ext/curl/CurlHandle.stubDD>vendor/phpstan/php-8-stubs/stubs/ext/curl/CurlMultiHandle.stub''`f`>vendor/phpstan/php-8-stubs/stubs/ext/curl/CurlShareHandle.stub''4\4Hvendor/phpstan/php-8-stubs/stubs/ext/curl/CurlSharePersistentHandle.stub(.9vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_close.stubz?vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_copy_handle.stubMM 9vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_errno.stub999vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_error.stub<<>ti:vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_escape.stub8vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_exec.stubGGa?vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_file_create.stub~~1$j;vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_getinfo.stubRR38vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_init.stubFFB4Dvendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_add_handle.stubdd8QA:?vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_close.stubKKD$)?vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_errno.stubJJ h>vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_exec.stub{{ IJEvendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_get_handles.stubcc5BDvendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_getcontent.stubHH8Cvendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_info_read.stub2W>vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_init.stub885ƤGvendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_remove_handle.stubggm@vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_select.stubaa`x@vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_setopt.stubgg}ˤBvendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_strerror.stubBB9vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_pause.stubvv i;9vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_reset.stubAAuL:vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_setopt.stubVVb@vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_setopt_array.stubQQxgL?vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_share_close.stubd~?vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_share_errno.stubJJu>vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_share_init.stub88ZHɤIvendor/phpstan/php-8-stubs/stubs/ext/curl/curl_share_init_persistent.stub9@vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_share_setopt.stubggBvendor/phpstan/php-8-stubs/stubs/ext/curl/curl_share_strerror.stubBBm2<vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_strerror.stub<<óq<vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_unescape.stubUU:vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_upkeep.stubj;vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_version.stub00sXU8vendor/phpstan/php-8-stubs/stubs/ext/date/DateError.stubYY<vendor/phpstan/php-8-stubs/stubs/ext/date/DateException.stubaaf;vendor/phpstan/php-8-stubs/stubs/ext/date/DateInterval.stub$$ԤLvendor/phpstan/php-8-stubs/stubs/ext/date/DateInvalidOperationException.stubuu+`Kvendor/phpstan/php-8-stubs/stubs/ext/date/DateInvalidTimeZoneException.stubtt~MSvendor/phpstan/php-8-stubs/stubs/ext/date/DateMalformedIntervalStringException.stub||oȗQvendor/phpstan/php-8-stubs/stubs/ext/date/DateMalformedPeriodStringException.stubzz& TKvendor/phpstan/php-8-stubs/stubs/ext/date/DateMalformedStringException.stubtttkw>vendor/phpstan/php-8-stubs/stubs/ext/date/DateObjectError.stubccG\9vendor/phpstan/php-8-stubs/stubs/ext/date/DatePeriod.stubUG=vendor/phpstan/php-8-stubs/stubs/ext/date/DateRangeError.stubbb(u7vendor/phpstan/php-8-stubs/stubs/ext/date/DateTime.stub\@2@vendor/phpstan/php-8-stubs/stubs/ext/date/DateTimeImmutable.stubH@vendor/phpstan/php-8-stubs/stubs/ext/date/DateTimeInterface.stubfQ;vendor/phpstan/php-8-stubs/stubs/ext/date/DateTimeZone.stub{8vendor/phpstan/php-8-stubs/stubs/ext/date/checkdate.stubEE&3vendor/phpstan/php-8-stubs/stubs/ext/date/date.stubIIY7vendor/phpstan/php-8-stubs/stubs/ext/date/date_add.stubTT57f:vendor/phpstan/php-8-stubs/stubs/ext/date/date_create.stubll/Fvendor/phpstan/php-8-stubs/stubs/ext/date/date_create_from_format.stub4Dvendor/phpstan/php-8-stubs/stubs/ext/date/date_create_immutable.stubPvendor/phpstan/php-8-stubs/stubs/ext/date/date_create_immutable_from_format.stubh<vendor/phpstan/php-8-stubs/stubs/ext/date/date_date_set.stubaai&Hvendor/phpstan/php-8-stubs/stubs/ext/date/date_default_timezone_get.stub88 H6Hvendor/phpstan/php-8-stubs/stubs/ext/date/date_default_timezone_set.stubHH`e8vendor/phpstan/php-8-stubs/stubs/ext/date/date_diff.stubS~:vendor/phpstan/php-8-stubs/stubs/ext/date/date_format.stubTTq(%ӤCvendor/phpstan/php-8-stubs/stubs/ext/date/date_get_last_errors.stub88ovendor/phpstan/php-8-stubs/stubs/ext/date/date_offset_get.stubEEZ)9vendor/phpstan/php-8-stubs/stubs/ext/date/date_parse.stub88hEvendor/phpstan/php-8-stubs/stubs/ext/date/date_parse_from_format.stubTTA7vendor/phpstan/php-8-stubs/stubs/ext/date/date_sub.stubTTq}<vendor/phpstan/php-8-stubs/stubs/ext/date/date_sun_info.stub\\I@;vendor/phpstan/php-8-stubs/stubs/ext/date/date_sunrise.stub##T:vendor/phpstan/php-8-stubs/stubs/ext/date/date_sunset.stub!!g򛭤<vendor/phpstan/php-8-stubs/stubs/ext/date/date_time_set.stubr@Avendor/phpstan/php-8-stubs/stubs/ext/date/date_timestamp_get.stubHH/a=Avendor/phpstan/php-8-stubs/stubs/ext/date/date_timestamp_set.stubUU%=@vendor/phpstan/php-8-stubs/stubs/ext/date/date_timezone_get.stubWW |@vendor/phpstan/php-8-stubs/stubs/ext/date/date_timezone_set.stub]](6vendor/phpstan/php-8-stubs/stubs/ext/date/getdate.stub;;6<5vendor/phpstan/php-8-stubs/stubs/ext/date/gmdate.stubKKe7vendor/phpstan/php-8-stubs/stubs/ext/date/gmmktime.stub˜9vendor/phpstan/php-8-stubs/stubs/ext/date/gmstrftime.stub--&4vendor/phpstan/php-8-stubs/stubs/ext/date/idate.stubMM188vendor/phpstan/php-8-stubs/stubs/ext/date/localtime.stubXX&55vendor/phpstan/php-8-stubs/stubs/ext/date/mktime.stubqd7vendor/phpstan/php-8-stubs/stubs/ext/date/strftime.stub))L98vendor/phpstan/php-8-stubs/stubs/ext/date/strtotime.stubyyIѤ3vendor/phpstan/php-8-stubs/stubs/ext/date/time.stub eJvendor/phpstan/php-8-stubs/stubs/ext/date/timezone_abbreviations_list.stub99?Hvendor/phpstan/php-8-stubs/stubs/ext/date/timezone_identifiers_list.stubzz]Dvendor/phpstan/php-8-stubs/stubs/ext/date/timezone_location_get.stubNNaFvendor/phpstan/php-8-stubs/stubs/ext/date/timezone_name_from_abbr.stubnn@vendor/phpstan/php-8-stubs/stubs/ext/date/timezone_name_get.stubEEJBvendor/phpstan/php-8-stubs/stubs/ext/date/timezone_offset_get.stubbb <vendor/phpstan/php-8-stubs/stubs/ext/date/timezone_open.stubII.Gvendor/phpstan/php-8-stubs/stubs/ext/date/timezone_transitions_get.stub~~Cvendor/phpstan/php-8-stubs/stubs/ext/date/timezone_version_get.stub33a1nj<vendor/phpstan/php-8-stubs/stubs/ext/dba/Dba/Connection.stubvvh+7vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_close.stubٻ8vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_delete.stubKKmj,8vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_exists.stubKKl7vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_fetch.stubIؤ:vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_firstkey.stub:vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_handlers.stubAAbl8vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_insert.stubxx9#$;vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_key_split.stubGGP6vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_list.stub&&9vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_nextkey.stubT̤6vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_open.stubkkf:vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_optimize.stubR7vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_popen.stub% ޤ9vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_replace.stub{{B6vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_sync.stub[5vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMAttr.stub=vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMCdataSection.stubll >vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMCharacterData.stub$$!2:vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMChildNode.stubIIheL8vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMComment.stubuup=19vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMDocument.stub㖑Avendor/phpstan/php-8-stubs/stubs/ext/dom/DOMDocumentFragment.stub77 Τ=vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMDocumentType.stubTToW=8vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMElement.stubs7vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMEntity.stub,,v@vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMEntityReference.stuboo*:vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMException.stub77wH?vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMImplementation.stub.. Z>vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMNameSpaceNode.stubPHۤ=vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMNamedNodeMap.stub5vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMNode.stub q'9vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMNodeList.stubCCGQ9vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMNotation.stub..c;vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMParentNode.stubAAFvendor/phpstan/php-8-stubs/stubs/ext/dom/DOMProcessingInstruction.stubBȤ5vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMText.stub8葰6vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMXPath.stubIBvendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/AdjacentPosition.stubKK(d6vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Attr.stub55Bˤ>vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/CDATASection.stubQQfƤ?vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/CharacterData.stub ;vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/ChildNode.stub Ť9vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Comment.stubUU,:vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Document.stub lߕBvendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/DocumentFragment.stub~~t~]">vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/DocumentType.stub>>ط¤Avendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/DtdNamedNodeMap.stub  9vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Element.stubGG8vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Entity.stubKKbXǤAvendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/EntityReference.stubTTn݁@vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/HTMLCollection.stub`֤>vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/HTMLDocument.stub==vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/HTMLElement.stubSSd7z@vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Implementation.stub>vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/NamedNodeMap.stubc?vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/NamespaceInfo.stub!D6vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Node.stub .0:vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/NodeList.stubɘ:vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Notation.stubMMo<vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/ParentNode.stubyycqGvendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/ProcessingInstruction.stubcc}ʤ6vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Text.stub11ztf;vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/TokenList.stub>>ޢ=vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/XMLDocument.stub/p7vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/XPath.stubAA> ?vendor/phpstan/php-8-stubs/stubs/ext/fileinfo/finfo_buffer.stub6 rH>vendor/phpstan/php-8-stubs/stubs/ext/fileinfo/finfo_close.stubBB=vendor/phpstan/php-8-stubs/stubs/ext/fileinfo/finfo_file.stubvz=vendor/phpstan/php-8-stubs/stubs/ext/fileinfo/finfo_open.stub<*Bvendor/phpstan/php-8-stubs/stubs/ext/fileinfo/finfo_set_flags.stub  +6%Dvendor/phpstan/php-8-stubs/stubs/ext/fileinfo/mime_content_type.stubkk}.Gvendor/phpstan/php-8-stubs/stubs/ext/filter/Filter/FilterException.stubXXi2.Mvendor/phpstan/php-8-stubs/stubs/ext/filter/Filter/FilterFailedException.stubkk_?vendor/phpstan/php-8-stubs/stubs/ext/filter/filter_has_var.stubnnu`:vendor/phpstan/php-8-stubs/stubs/ext/filter/filter_id.stub77=vendor/phpstan/php-8-stubs/stubs/ext/filter/filter_input.stub{{`@8Cvendor/phpstan/php-8-stubs/stubs/ext/filter/filter_input_array.stubKx<vendor/phpstan/php-8-stubs/stubs/ext/filter/filter_list.stub))!߈;vendor/phpstan/php-8-stubs/stubs/ext/filter/filter_var.stubjjcAvendor/phpstan/php-8-stubs/stubs/ext/filter/filter_var_array.stub+{K<vendor/phpstan/php-8-stubs/stubs/ext/ftp/FTP/Connection.stubvv;p7vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_alloc.stub*8vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_append.stub//w6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_cdup.stub"7vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_chdir.stub0e7vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_chmod.stuboG7vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_close.stubƅV9vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_connect.stub`q8vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_delete.stub_96vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_exec.stubXB`6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_fget.stubmm~F6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_fput.stubmm3y5vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_get.stubKKŧ<vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_get_option.stubWU!7vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_login.stubB"6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_mdtm.stub@ԅ7vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_mkdir.stubԵ16vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_mlsd.stub٬Ԥ=vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_nb_continue.stubc Ǥ9vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_nb_fget.stubqqBE9vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_nb_fput.stubqq8vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_nb_get.stubUU8vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_nb_put.stub[[dC#T7vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_nlist.stub  ]6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_pasv.stuba~5vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_put.stubKK&ۤ5vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_pwd.stubvEF6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_quit.stub_5vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_raw.stub.Z9vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_rawlist.stub@@_8vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_rename.stub^❤7vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_rmdir.stub<vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_set_option.stubÿo6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_site.stub6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_size.stub'E=vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_ssl_connect.stub**kv9vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_systype.stubn3vendor/phpstan/php-8-stubs/stubs/ext/gd/GdFont.stubbb+<4vendor/phpstan/php-8-stubs/stubs/ext/gd/GdImage.stubAA_n ¤4vendor/phpstan/php-8-stubs/stubs/ext/gd/gd_info.stub%%>8vendor/phpstan/php-8-stubs/stubs/ext/gd/imageaffine.stubee Dvendor/phpstan/php-8-stubs/stubs/ext/gd/imageaffinematrixconcat.stubYY`| Avendor/phpstan/php-8-stubs/stubs/ext/gd/imageaffinematrixget.stubnn"?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagealphablending.stub(.r;vendor/phpstan/php-8-stubs/stubs/ext/gd/imageantialias.stub U5vendor/phpstan/php-8-stubs/stubs/ext/gd/imagearc.stubMM-6vendor/phpstan/php-8-stubs/stubs/ext/gd/imageavif.stubJ(a5vendor/phpstan/php-8-stubs/stubs/ext/gd/imagebmp.stubx+6vendor/phpstan/php-8-stubs/stubs/ext/gd/imagechar.stub)Y8vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecharup.stub =?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorallocate.stubddպDvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorallocatealpha.stubuuX9vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorat.stubMMF&>vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorclosest.stub]]xpCvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorclosestalpha.stubnnPAvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorclosesthwb.stub``-خAvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolordeallocate.stubi\o<vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorexact.stub[[Avendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorexactalpha.stubll<vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolormatch.stub!M>vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorresolve.stub]]#ޤCvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorresolvealpha.stubnn1hV:vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorset.stub\y.@vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorsforindex.stubLLp=vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorstotal.stub;;FpBvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolortransparent.stubTTϤ=vendor/phpstan/php-8-stubs/stubs/ext/gd/imageconvolution.stubjj$ݤ6vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecopy.stubYY(hP;vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecopymerge.stubwwA71?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecopymergegray.stub/U#?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecopyresampled.stubxn=vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecopyresized.stub8vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreate.stubII$@vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromavif.stubK?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefrombmp.stub\\DE>vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromgd.stubHH7r?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromgd2.stubII.Cvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromgd2part.stubvvH?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromgif.stubIIik7@vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromjpeg.stub]]x?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefrompng.stubccBvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromstring.stubHHc?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromtga.stubcc6>&@vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromwbmp.stubQQ @vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromwebp.stubeeY ?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromxbm.stubPPW?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromxpm.stub\\:qAvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatetruecolor.stubRRޤ6vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecrop.stubQQ :vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecropauto.stub-<vendor/phpstan/php-8-stubs/stubs/ext/gd/imagedashedline.stub5i9vendor/phpstan/php-8-stubs/stubs/ext/gd/imagedestroy.stub;09vendor/phpstan/php-8-stubs/stubs/ext/gd/imageellipse.stubX6vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefill.stub;vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefilledarc.stubqq C?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefilledellipse.stub2?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefilledpolygon.stub{{)EAvendor/phpstan/php-8-stubs/stubs/ext/gd/imagefilledrectangle.stub䝚Ԥ>vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefilltoborder.stub8vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefilter.stub~~|&6vendor/phpstan/php-8-stubs/stubs/ext/gd/imageflip.stubs<vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefontheight.stubPjKK;vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefontwidth.stubd~Ҥ8vendor/phpstan/php-8-stubs/stubs/ext/gd/imageftbbox.stuby(8vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefttext.stub"*X>vendor/phpstan/php-8-stubs/stubs/ext/gd/imagegammacorrect.stubڋ$4vendor/phpstan/php-8-stubs/stubs/ext/gd/imagegd.stubII9v5vendor/phpstan/php-8-stubs/stubs/ext/gd/imagegd2.stubfa9vendor/phpstan/php-8-stubs/stubs/ext/gd/imagegetclip.stub99KgBvendor/phpstan/php-8-stubs/stubs/ext/gd/imagegetinterpolation.stub@@W"u5vendor/phpstan/php-8-stubs/stubs/ext/gd/imagegif.stubkk <vendor/phpstan/php-8-stubs/stubs/ext/gd/imagegrabscreen.stub66cO<vendor/phpstan/php-8-stubs/stubs/ext/gd/imagegrabwindow.stubmmp;vendor/phpstan/php-8-stubs/stubs/ext/gd/imageinterlace.stubPP;=vendor/phpstan/php-8-stubs/stubs/ext/gd/imageistruecolor.stub<< @f6vendor/phpstan/php-8-stubs/stubs/ext/gd/imagejpeg.stubQf=vendor/phpstan/php-8-stubs/stubs/ext/gd/imagelayereffect.stubS(#6vendor/phpstan/php-8-stubs/stubs/ext/gd/imageline.stubv/ਤ:vendor/phpstan/php-8-stubs/stubs/ext/gd/imageloadfont.stub"t禤=vendor/phpstan/php-8-stubs/stubs/ext/gd/imageopenpolygon.stubyyޅL=vendor/phpstan/php-8-stubs/stubs/ext/gd/imagepalettecopy.stubII\4Dvendor/phpstan/php-8-stubs/stubs/ext/gd/imagepalettetotruecolor.stubCCI5vendor/phpstan/php-8-stubs/stubs/ext/gd/imagepng.stubXGC 9vendor/phpstan/php-8-stubs/stubs/ext/gd/imagepolygon.stubuuC;vendor/phpstan/php-8-stubs/stubs/ext/gd/imagerectangle.stubڂY<vendor/phpstan/php-8-stubs/stubs/ext/gd/imageresolution.stub@@8vendor/phpstan/php-8-stubs/stubs/ext/gd/imagerotate.stubUUNv;vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesavealpha.stubS37vendor/phpstan/php-8-stubs/stubs/ext/gd/imagescale.stub~~F2|>:vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesetbrush.stubXH9vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesetclip.stub3;Bvendor/phpstan/php-8-stubs/stubs/ext/gd/imagesetinterpolation.stubcc$m:vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesetpixel.stub:vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesetstyle.stubGG]>vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesetthickness.stubXˀ9vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesettile.stub+Z8vendor/phpstan/php-8-stubs/stubs/ext/gd/imagestring.stub@":vendor/phpstan/php-8-stubs/stubs/ext/gd/imagestringup.stub뇪~4vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesx.stub22(QhŤ4vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesy.stub22iJ䫤Dvendor/phpstan/php-8-stubs/stubs/ext/gd/imagetruecolortopalette.stubbb9vendor/phpstan/php-8-stubs/stubs/ext/gd/imagettfbbox.stubؤ9vendor/phpstan/php-8-stubs/stubs/ext/gd/imagettftext.stubW17vendor/phpstan/php-8-stubs/stubs/ext/gd/imagetypes.stub&&o J6vendor/phpstan/php-8-stubs/stubs/ext/gd/imagewbmp.stubU?6vendor/phpstan/php-8-stubs/stubs/ext/gd/imagewebp.stub%b5vendor/phpstan/php-8-stubs/stubs/ext/gd/imagexbm.stubmm/n3vendor/phpstan/php-8-stubs/stubs/ext/gettext/_.stubEEhﳀIvendor/phpstan/php-8-stubs/stubs/ext/gettext/bind_textdomain_codeset.stubCCEމ@vendor/phpstan/php-8-stubs/stubs/ext/gettext/bindtextdomain.stubh;vendor/phpstan/php-8-stubs/stubs/ext/gettext/dcgettext.stubVVr-T<vendor/phpstan/php-8-stubs/stubs/ext/gettext/dcngettext.stub:vendor/phpstan/php-8-stubs/stubs/ext/gettext/dgettext.stubFF;;vendor/phpstan/php-8-stubs/stubs/ext/gettext/dngettext.stubO9vendor/phpstan/php-8-stubs/stubs/ext/gettext/gettext.stub55R9ג:vendor/phpstan/php-8-stubs/stubs/ext/gettext/ngettext.stubhhٵ<vendor/phpstan/php-8-stubs/stubs/ext/gettext/textdomain.stubǕ1vendor/phpstan/php-8-stubs/stubs/ext/gmp/GMP.stub<<(5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_abs.stub88ܕp5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_add.stubPP<5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_and.stubPPcmΒ:vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_binomial.stubCC 8vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_clrbit.stub<<-ؤ5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_cmp.stubOOЃ5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_com.stub88SԴ5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_div.stub>}7vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_div_q.stubwww8vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_div_qr.stubyy77vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_div_r.stubwwlo9?:vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_divexact.stubUUj8vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_export.stubt6vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_fact.stub99B烤5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_gcd.stubPP68vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_gcdext.stubTTFߤ9vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_hamdist.stubSS0)"8vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_import.stubww[Y6vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_init.stubCC'¿J8vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_intval.stub::Z8vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_invert.stubYY^ 8vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_jacobi.stubRRj;vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_kronecker.stubUU#¤5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_lcm.stubPPZ%:vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_legendre.stubTTN5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_mod.stubPPPZ5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_mul.stubPPFF5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_neg.stub88;vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_nextprime.stub>>4vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_or.stubOON4?vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_perfect_power.stubBBIqΤ@vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_perfect_square.stubCCeE*0:vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_popcount.stub<<=55vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_pow.stubGG6vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_powm.stubnnzR<vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_prob_prime.stubUUY=vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_random_bits.stub55>vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_random_range.stubWW-=vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_random_seed.stubAA86vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_root.stubCCF9vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_rootrem.stubGGǛ7vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_scan0.stubFFHV7vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_scan1.stubFF68vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_setbit.stubPP +6vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_sign.stub88}6vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_sqrt.stub992H9vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_sqrtrem.stub==.8vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_strval.stubMMO-5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_sub.stubPPAi9vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_testbit.stubHHaOX5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_xor.stubPPɐm:vendor/phpstan/php-8-stubs/stubs/ext/hash/HashContext.stub 3vendor/phpstan/php-8-stubs/stubs/ext/hash/hash.stub**N9vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_algos.stub((Fa8vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_copy.stubCCj:vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_equals.stubQQݍ8vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_file.stubT59vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_final.stubTT+i8vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_hkdf.stubxx8vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_hmac.stubeeZ饤>vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_hmac_algos.stub--BU(=vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_hmac_file.stubttm8vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_init.stubP8:vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_pbkdf2.stub__DѤ:vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_update.stubd8?vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_update_file.stub\Avendor/phpstan/php-8-stubs/stubs/ext/hash/hash_update_stream.stub}}WZ4vendor/phpstan/php-8-stubs/stubs/ext/hash/mhash.stub8.s:vendor/phpstan/php-8-stubs/stubs/ext/hash/mhash_count.stub#NCvendor/phpstan/php-8-stubs/stubs/ext/hash/mhash_get_block_size.stubntBvendor/phpstan/php-8-stubs/stubs/ext/hash/mhash_get_hash_name.stub؏*?vendor/phpstan/php-8-stubs/stubs/ext/hash/mhash_keygen_s2k.stub%%\4ä5vendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv.stubddzޱBvendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_get_encoding.stubQQiIAvendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_mime_decode.stubmm:Ivendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_mime_decode_headers.stubuu% ;Avendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_mime_encode.stubrrx Bvendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_set_encoding.stubMM۱<vendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_strlen.stubxx<vendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_strpos.stubyy2h*=vendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_strrpos.stubiia2<vendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_substr.stub{{'6>vendor/phpstan/php-8-stubs/stubs/ext/imap/IMAP/Connection.stubww̑^f8vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_8bit.stub<<W:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_alerts.stub//:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_append.stubUU(^:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_base64.stub>>T':vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_binary.stub>>s8vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_body.stub>vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_bodystruct.stub Z9vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_check.stub?8Bvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_clearflag_full.stubcڤ9vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_close.stub--J]:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_create.stube6Avendor/phpstan/php-8-stubs/stubs/ext/imap/imap_createmailbox.stub#%:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_delete.stubrrǖ{Avendor/phpstan/php-8-stubs/stubs/ext/imap/imap_deletemailbox.stub*ɧ:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_errors.stub//r;vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_expunge.stubΡBvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_fetch_overview.stub+=vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_fetchbody.stub$?vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_fetchheader.stub=vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_fetchmime.stub"Bvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_fetchstructure.stub  `=vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_fetchtext.stub--er6vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_gc.stub!װ=vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_get_quota.stubIIR<Avendor/phpstan/php-8-stubs/stubs/ext/imap/imap_get_quotaroot.stubž:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_getacl.stubk@vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_getmailboxes.stubӤAvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_getsubscribed.stub>vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_headerinfo.stubCC}V@;vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_headers.stuba ;vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_is_open.stubPPz>vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_last_error.stub448vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_list.stubREȤ?vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_listmailbox.stub33hk<vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_listscan.stub!IۤBvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_listsubscribed.stub99?9:8vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_lsub.stub ݤ8vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_mail.stubcp|@vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_mail_compose.stubTT0=vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_mail_copy.stubt=vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_mail_move.stub)ԤBvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_mailboxmsginfo.stub28Fvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_mime_header_decode.stubPPplr9vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_msgno.stub^7.Avendor/phpstan/php-8-stubs/stubs/ext/imap/imap_mutf7_to_utf8.stubEE:ܤ;vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_num_msg.stubb1>vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_num_recent.stubE678vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_open.stubD8vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_ping.stubI@@:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_qprint.stub>>:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_rename.stubX֤Avendor/phpstan/php-8-stubs/stubs/ext/imap/imap_renamemailbox.stub8P:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_reopen.stub  7:oHvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_rfc822_parse_adrlist.stub__cHvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_rfc822_parse_headers.stubppóHvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_rfc822_write_address.stubqqٹ<vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_savebody.stubuuQp8vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_scan.stubOO^BeM?vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_scanmailbox.stub]]?:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_search.stub--R-$?vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_unsubscribe.stub'{J?vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_utf7_decode.stubCCb5?vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_utf7_encode.stub==N 8vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_utf8.stubAA tAvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_utf8_to_mutf7.stub\\h<vendor/phpstan/php-8-stubs/stubs/ext/intl/IntlException.stubTTcNvendor/phpstan/php-8-stubs/stubs/ext/intl/breakiterator/IntlBreakIterator.stubLLWvendor/phpstan/php-8-stubs/stubs/ext/intl/breakiterator/IntlCodePointBreakIterator.stub?Nvendor/phpstan/php-8-stubs/stubs/ext/intl/breakiterator/IntlPartsIterator.stub@@(FWvendor/phpstan/php-8-stubs/stubs/ext/intl/breakiterator/IntlRuleBasedBreakIterator.stubf,Dvendor/phpstan/php-8-stubs/stubs/ext/intl/calendar/IntlCalendar.stubGG`9Mvendor/phpstan/php-8-stubs/stubs/ext/intl/calendar/IntlGregorianCalendar.stub`T@vendor/phpstan/php-8-stubs/stubs/ext/intl/collator/Collator.stubF F x>=vendor/phpstan/php-8-stubs/stubs/ext/intl/collator_asort.stubpp^R?vendor/phpstan/php-8-stubs/stubs/ext/intl/collator_compare.stubee<=R>vendor/phpstan/php-8-stubs/stubs/ext/intl/collator_create.stubOO `Evendor/phpstan/php-8-stubs/stubs/ext/intl/collator_get_attribute.stubYY'C $Fvendor/phpstan/php-8-stubs/stubs/ext/intl/collator_get_error_code.stubJJ.ȤIvendor/phpstan/php-8-stubs/stubs/ext/intl/collator_get_error_message.stubPP]#Bvendor/phpstan/php-8-stubs/stubs/ext/intl/collator_get_locale.stubTT/<Dvendor/phpstan/php-8-stubs/stubs/ext/intl/collator_get_sort_key.stub[[KDvendor/phpstan/php-8-stubs/stubs/ext/intl/collator_get_strength.stubBB4[Evendor/phpstan/php-8-stubs/stubs/ext/intl/collator_set_attribute.stub``Dvendor/phpstan/php-8-stubs/stubs/ext/intl/collator_set_strength.stubІp<vendor/phpstan/php-8-stubs/stubs/ext/intl/collator_sort.stubooǍKvendor/phpstan/php-8-stubs/stubs/ext/intl/collator_sort_with_sort_keys.stubYY$r_Bvendor/phpstan/php-8-stubs/stubs/ext/intl/common/IntlIterator.stubiiXACvendor/phpstan/php-8-stubs/stubs/ext/intl/converter/UConverter.stub(1(1F=vendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_create.stub5񍗤=vendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_format.stub4Dvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_format_object.stub2wCvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_calendar.stubSS{эJvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_calendar_object.stubiiV*+}Cvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_datetype.stubSSyEvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_error_code.stubOO4.Hvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_error_message.stubUUDoAvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_locale.stubtt:LԤBvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_pattern.stubUUSXCvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_timetype.stubSS`PCvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_timezone.stub]]^=Fvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_timezone_id.stubYYkAvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_is_lenient.stubLLGԤ@vendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_localtime.stubwy<vendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_parse.stub7Cvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_set_calendar.stubppW)`Bvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_set_lenient.stub\\n*wBvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_set_pattern.stub^^C-Cvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_set_timezone.stubKKvendor/phpstan/php-8-stubs/stubs/ext/intl/dateformat/IntlDateFormatter.stub!!UĤRvendor/phpstan/php-8-stubs/stubs/ext/intl/dateformat/IntlDatePatternGenerator.stubNNޒ!Hvendor/phpstan/php-8-stubs/stubs/ext/intl/formatter/NumberFormatter.stub__1a?vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_extract.stub恤Cvendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_levenshtein.stubjmZAvendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_str_split.stubff-sq?vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_stripos.stub0^?vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_stristr.stub<>vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_strlen.stubSS 4>vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_strpos.stubВu@vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_strripos.stub!0?vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_strrpos.stubm01>vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_strstr.stub` >vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_substr.stub]-;vendor/phpstan/php-8-stubs/stubs/ext/intl/idn_to_ascii.stub3H:vendor/phpstan/php-8-stubs/stubs/ext/intl/idn_to_utf8.stubJu>vendor/phpstan/php-8-stubs/stubs/ext/intl/intl_error_name.stub<<vz1Bvendor/phpstan/php-8-stubs/stubs/ext/intl/intl_get_error_code.stub<<Q/Evendor/phpstan/php-8-stubs/stubs/ext/intl/intl_get_error_message.stub55C;$>vendor/phpstan/php-8-stubs/stubs/ext/intl/intl_is_failure.stub::{y:vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_add.stubWWy;z<vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_after.stubWWU=vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_before.stubXX3T<vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_clear.stubVʤFvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_create_instance.stubkkX f=vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_equals.stubXXeWGvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_field_difference.stuboo?Evendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_from_date_time.stubooJK:vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get.stubPP@D Ivendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_actual_maximum.stub__'zyIvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_actual_minimum.stub__%B@Lvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_available_locales.stub;;?Kvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_day_of_week_type.stubee2Evendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_error_code.stubOO,%室Hvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_error_message.stubUULvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_first_day_of_week.stubVVPC̤Kvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_greatest_minimum.stubaa1zTvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_keyword_values_for_locale.stubHvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_least_maximum.stub^^RvAvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_locale.stubYY Bvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_maximum.stubXX{Uvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_minimal_days_in_first_week.stub__F@Bvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_minimum.stubXXB(>vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_now.stub--Z2Tvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_repeated_wall_time_option.stubXXSvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_skipped_wall_time_option.stubWWy?vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_time.stubKK]Dvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_time_zone.stubXXC?vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_type.stubFF|Mvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_weekend_transition.stubggwrGvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_in_daylight_time.stubLLGvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_is_equivalent_to.stubbbqrAvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_is_lenient.stubFFsFLq=vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_is_set.stubNNi=Avendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_is_weekend.stub``c);vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_roll.stubrrFe:vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_set.stub3Lvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_set_first_day_of_week.stubtBvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_set_lenient.stub\Uvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_set_minimal_days_in_first_week.stubM=Tvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_set_repeated_wall_time_option.stub^`lSvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_set_skipped_wall_time_option.stubJ?vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_set_time.stubVVsDvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_set_time_zone.stub)) mrCvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_to_date_time.stubSS!=rJvendor/phpstan/php-8-stubs/stubs/ext/intl/intlgregcal_create_instance.stubjO%Ovendor/phpstan/php-8-stubs/stubs/ext/intl/intlgregcal_get_gregorian_change.stub^^dƤGvendor/phpstan/php-8-stubs/stubs/ext/intl/intlgregcal_is_leap_year.stub``Ovendor/phpstan/php-8-stubs/stubs/ext/intl/intlgregcal_set_gregorian_change.stuboo<}Jvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_count_equivalent_ids.stub^^$'Dvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_create_default.stub;;9BHvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_create_enumeration.stub..GߤFvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_create_time_zone.stubPP{ФUvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_create_time_zone_id_enumeration.stub:Ivendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_from_date_time_zone.stubXXtEFvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_canonical_id.stub7Fvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_display_name.stubhWEvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_dst_savings.stubIICತGvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_equivalent_id.stub\\5Dvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_error_code.stubNNUGvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_error_message.stubTTy=vendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_gmt.stub44Avendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_iana_id.stub||`<vendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_id.stubIIAKvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_id_for_windows_id.stubkkR-@vendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_offset.stubqs(ɤDvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_raw_offset.stubHHD@vendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_region.stubHHW_̤Ivendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_tz_data_version.stub??KU^>Avendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_unknown.stub88Dvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_windows_id.stubnn{$ŋDvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_has_same_rules.stubff Gvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_to_date_time_zone.stub[[}KGvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_use_daylight_time.stubLLҤNvendor/phpstan/php-8-stubs/stubs/ext/intl/listformatter/IntlListFormatter.stubVVDmd<vendor/phpstan/php-8-stubs/stubs/ext/intl/locale/Locale.stubHH=Fvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_accept_from_http.stubJJg׽Hvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_add_likely_subtags.stub]]zBvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_canonicalize.stubAA:=vendor/phpstan/php-8-stubs/stubs/ext/intl/locale_compose.stubAA~`ФDvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_filter_matches.stubrrFvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_all_variants.stubDDlAvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_default.stub>>FPJvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_display_language.stubmm׫Fvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_display_name.stubii8դHvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_display_region.stubkk+_Hvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_display_script.stubkkdkIvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_display_variant.stubll2T[Bvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_keywords.stubJJTJvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_primary_language.stubII@~@vendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_region.stub??@vendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_script.stub??FʿFvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_is_right_to_left.stubSS̔<vendor/phpstan/php-8-stubs/stubs/ext/intl/locale_lookup.stubrqFvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_minimize_subtags.stub[[`;vendor/phpstan/php-8-stubs/stubs/ext/intl/locale_parse.stub99pAvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_set_default.stub=d<vendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_create.stubggb<vendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_format.stub]]X/_Dvendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_format_message.stubhhDvendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_get_error_code.stubMMwυGvendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_get_error_message.stubSSVY@vendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_get_locale.stubLL+ Avendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_get_pattern.stubSSu;vendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_parse.stub\\Lvendor/phpstan/php-8-stubs/stubs/ext/intl/resourcebundle_get_error_code.stubPP9eOvendor/phpstan/php-8-stubs/stubs/ext/intl/resourcebundle_get_error_message.stubVV6Evendor/phpstan/php-8-stubs/stubs/ext/intl/resourcebundle_locales.stubHHxʤHvendor/phpstan/php-8-stubs/stubs/ext/intl/spoofchecker/Spoofchecker.stubSSYZ>Dvendor/phpstan/php-8-stubs/stubs/ext/intl/timezone/IntlTimeZone.stubUۤLvendor/phpstan/php-8-stubs/stubs/ext/intl/transliterator/Transliterator.stubH Dvendor/phpstan/php-8-stubs/stubs/ext/intl/transliterator_create.stubw%Ovendor/phpstan/php-8-stubs/stubs/ext/intl/transliterator_create_from_rules.stubw4Lvendor/phpstan/php-8-stubs/stubs/ext/intl/transliterator_create_inverse.stubee~1KLvendor/phpstan/php-8-stubs/stubs/ext/intl/transliterator_get_error_code.stubOvendor/phpstan/php-8-stubs/stubs/ext/intl/transliterator_get_error_message.stubiUFvendor/phpstan/php-8-stubs/stubs/ext/intl/transliterator_list_ids.stub;;@Kvendor/phpstan/php-8-stubs/stubs/ext/intl/transliterator_transliterate.stub!nr=vendor/phpstan/php-8-stubs/stubs/ext/intl/uchar/IntlChar.stubJJ 4l<vendor/phpstan/php-8-stubs/stubs/ext/json/JsonException.stub22P'?vendor/phpstan/php-8-stubs/stubs/ext/json/JsonSerializable.stubaH:vendor/phpstan/php-8-stubs/stubs/ext/json/json_decode.stubrrh):vendor/phpstan/php-8-stubs/stubs/ext/json/json_encode.stubx褤>vendor/phpstan/php-8-stubs/stubs/ext/json/json_last_error.stub++ߏ,ӤBvendor/phpstan/php-8-stubs/stubs/ext/json/json_last_error_msg.stub22 <vendor/phpstan/php-8-stubs/stubs/ext/json/json_validate.stubii>vendor/phpstan/php-8-stubs/stubs/ext/ldap/LDAP/Connection.stubww;ըѤ:vendor/phpstan/php-8-stubs/stubs/ext/ldap/LDAP/Result.stubssA7=?vendor/phpstan/php-8-stubs/stubs/ext/ldap/LDAP/ResultEntry.stubxxoq(?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_8859_to_t61.stubBB-A7vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_add.stubbS;vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_add_ext.stub11)f8vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_bind.stubʸ<vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_bind_ext.stub[[̖9vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_close.stub6j;vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_compare.stub;;|?٤;vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_connect.stub'')Bvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_connect_wallet.stub|sAvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_count_entries.stub7DDvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_count_references.stubR':vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_delete.stubpQ>vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_delete_ext.stub~w:vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_dn2ufn.stub::bŤ;vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_err2str.stub55:3ސ9vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_errno.stub;9vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_error.stublM:vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_escape.stubccD[Gt8vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_exop.stubҝT?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_exop_passwd.stub%0@vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_exop_refresh.stub))=vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_exop_sync.stubLL)/ ?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_exop_whoami.stub*>vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_explode_dn.stubOODCvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_first_attribute.stub6 ?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_first_entry.stubSCvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_first_reference.stub3>?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_free_result.stubM[Bvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_get_attributes.stub;;\4y:vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_get_dn.stub}0?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_get_entries.stub>> (|>vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_get_option.stub Hi>vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_get_values.stubD`Bvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_get_values_len.stubmm.)ͤ8vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_list.stublle%;vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_mod_add.stub  oQv?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_mod_add_ext.stub99};vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_mod_del.stub  6L?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_mod_del_ext.stub99?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_mod_replace.stub=q㧤Cvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_mod_replace_ext.stubAA/:vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_modify.stubGGҙ8@vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_modify_batch.stub//gBvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_next_attribute.stub75\<>vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_next_entry.stub$9Bvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_next_reference.stubmy>vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_parse_exop.stub))a"Cvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_parse_reference.stubHΤ@vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_parse_result.stubXC8vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_read.stubzz~3:vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_rename.stub;>vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_rename_ext.stub4le=vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_sasl_bind.stub!!й:vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_search.stubppZ[Hդ>vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_set_option.stub11h6MCvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_set_rebind_proc.stubf=vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_start_tls.stubg?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_t61_to_8859.stubYY :vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_unbind.stubsɤ<vendor/phpstan/php-8-stubs/stubs/ext/libxml/LibXMLError.stub??Dvendor/phpstan/php-8-stubs/stubs/ext/libxml/libxml_clear_errors.stub00'Mvendor/phpstan/php-8-stubs/stubs/ext/libxml/libxml_disable_entity_loader.stub##ޤBvendor/phpstan/php-8-stubs/stubs/ext/libxml/libxml_get_errors.stub//Rvendor/phpstan/php-8-stubs/stubs/ext/libxml/libxml_get_external_entity_loader.stubTTaAFvendor/phpstan/php-8-stubs/stubs/ext/libxml/libxml_get_last_error.stub@@)Rvendor/phpstan/php-8-stubs/stubs/ext/libxml/libxml_set_external_entity_loader.stubKOKvendor/phpstan/php-8-stubs/stubs/ext/libxml/libxml_set_streams_context.stub__pu+Kvendor/phpstan/php-8-stubs/stubs/ext/libxml/libxml_use_internal_errors.stubOOnu8Dvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_check_encoding.stubggP9vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_chr.stubSS9,Bvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_convert_case.stubaa7).Fvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_convert_encoding.stub8Bvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_convert_kana.stubkkyQI~Gvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_convert_variables.stub}ZGvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_decode_mimeheader.stubAA׽Jvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_decode_numericentity.stubjj3䍤Evendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_detect_encoding.stubEBvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_detect_order.stubTTRZiGvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_encode_mimeheader.stube#Jvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_encode_numericentity.stub}}iܛFvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_encoding_aliases.stubAA.|YT:vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg.stubrr+d@vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_match.stubbb^Bvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_replace.stubDKvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_replace_callback.stubAvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_search.stub[[W<¤Hvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_search_getpos.stub11]5Ivendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_search_getregs.stub::aFvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_search_init.stubppS _Evendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_search_pos.stubff'[Fvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_search_regs.stubggd,8Hvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_search_setpos.stub==d^;vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_eregi.stubssCvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_eregi_replace.stub%7>vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_get_info.stub @vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_http_input.stubLLǾAvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_http_output.stubJJT.Gvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_internal_encoding.stubPP{>vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_language.stubiiq=vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_lcfirst.stubbbUODvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_list_encodings.stub//f-;vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ltrim.stub||o᪤9vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ord.stubPP_Dvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_output_handler.stubKKi0?vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_parse_str.stub]]'&Ivendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_preferred_mime_name.stubKK&YjDvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_regex_encoding.stubaab%KGvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_regex_set_options.stubJJRޘ;vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_rtrim.stub||@;vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_scrub.stubOO(RR?vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_send_mail.stubA;vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_split.stub\\=vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_str_pad.stub 2?vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_str_split.stubcc>nW<vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strcut.stubqqP@vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strimwidth.stubcG=vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_stripos.stubwwn=vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_stristr.stub3<vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strlen.stubMM*j<vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strpos.stubvvB=vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strrchr.stub铤>vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strrichr.stubR>vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strripos.stubxxȴ=vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strrpos.stubwwbi<vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strstr.stubB@vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strtolower.stubTTvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strwidth.stubOO*Jvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_substitute_character.stubkk5sϤ<vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_substr.stubqqWBvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_substr_count.stubeeJ:vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_trim.stub{{=vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ucfirst.stubbbS~ۤ7vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli.stub3#3#Y6Evendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_affected_rows.stubEEBvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_autocommit.stubJJ>6Ivendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_begin_transaction.stubiiwФCvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_change_user.stubttvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_commit.stub^^J?vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_connect.stubpEvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_connect_errno.stub00S>Evendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_connect_error.stub44xAvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_data_seek.stubPP}K=vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_debug.stub+>vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_driver.stubGGAiGvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_dump_debug_info.stubAA+UG=vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_errno.stub66깤=vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_error.stub99H`Bvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_error_list.stub==F[oEvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_escape_string.stubyy0?vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_execute.stubyEvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_execute_query.stub(iۤAvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_all.stub||2+Cvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_array.stubqq_ KΤCvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_assoc.stubQQQD3Dvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_column.stub^ECvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_field.stubMM щJvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_field_direct.stub``g`Dvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_fields.stubGGͤEvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_lengths.stubNNkxDvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_object.stub'UAvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_row.stubOOꛤCvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_field_count.stub<<FGVBvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_field_seek.stublBvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_field_tell.stubCC`Cvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_free_result.stubEE@Cvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_charset.stubGGwޤGvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_client_info.stubKK2ܤHvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_client_stats.stub55FҤJvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_client_version.stub55DCLvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_connection_stats.stubgg"Evendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_host_info.stubAA`Gvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_links_stats.stub44߮Fvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_proto_info.stub??0!Gvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_server_info.stubCC6Jvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_server_version.stubCC"Dvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_warnings.stubOO|<vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_info.stub99nm<vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_init.stub11xfέAvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_insert_id.stubAAƙs<vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_kill.stub.Dvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_more_results.stub>>yCvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_multi_query.stubLLRCvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_next_result.stub==OlBvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_num_fields.stubCCs>@vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_num_rows.stubHHP?vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_options.stubnn<vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_ping.stub  ֩o<vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_poll.stube?vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_prepare.stub]]ڤ=vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_query.stub}}vDvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_real_connect.stuboJvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_real_escape_string.stubVV<1Bvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_real_query.stubKKlHvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_reap_async_query.stubqqK ?vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_refresh.stub3 Ivendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_release_savepoint.stubXX֮>vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_report.stubpͦ>vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_result.stub% % Xo@vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_rollback.stub``Avendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_savepoint.stubIIAvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_select_db.stubMM[Cvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_set_charset.stubNN='6?vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_set_opt.stub=Evendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_sql_exception.stub.@vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_sqlstate.stub<<A4?vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_ssl_set.stubYYOY<vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stat.stub>>ۑ<vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt.stub8 8 rdJvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_affected_rows.stubSSMEvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_attr_get.stubWW}>Evendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_attr_set.stubdd[Gvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_bind_param.stubjjuX̬Hvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_bind_result.stub\\f[Bvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_close.stubxFvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_data_seek.stubVVVqTBvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_errno.stubDD2v6Bvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_error.stubGG}*Gvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_error_list.stubKKGDvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_execute.stub&2ԤBvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_fetch.stubFFzHvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_field_count.stubJJKHvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_free_result.stubKK,Gvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_get_result.stubzzZ}Ivendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_get_warnings.stubdd\'Avendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_init.stubII-1*Fvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_insert_id.stubOO9Ivendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_more_results.stubll#Hvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_next_result.stubKK'4Evendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_num_rows.stubUUIHvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_param_count.stubJJ܌FDvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_prepare.stubVV`Bvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_reset.stubEEoϤLvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_result_metadata.stub__퀞٤Kvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_send_long_data.stubllrEvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_sqlstate.stubJJ}KIvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_store_result.stubLL繽iDvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_store_result.stub]]qAvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_thread_id.stub::YXCvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_thread_safe.stub//GĤBvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_use_result.stubLL˞ ?vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_warning.stub@`<Evendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_warning_count.stub>>Y!%<vendor/phpstan/php-8-stubs/stubs/ext/oci8/OCICollection.stubqX]5vendor/phpstan/php-8-stubs/stubs/ext/oci8/OCILob.stub< < ĤEvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_bind_array_by_name.stub^$?vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_bind_by_name.stubZ9vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_cancel.stubSSAvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_client_version.stub118vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_close.stubUU'^NDvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_collection_append.stub[[Dvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_collection_assign.stubZZLvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_collection_element_assign.stubooAÀIvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_collection_element_get.stubpp Avendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_collection_max.stubNNpoBvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_collection_size.stubOOXBvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_collection_trim.stubTT+S9vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_commit.stubUU&Ф:vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_connect.stubb]mAvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_define_by_name.stub^٬8vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_error.stub4o:vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_execute.stubwwHj8vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_fetch.stubRR&դ<vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_fetch_all.stub(?1>vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_fetch_array.stubQ>vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_fetch_assoc.stub__i?vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_fetch_object.stubVLWͤ<vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_fetch_row.stub]]Һޤ@vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_field_is_null.stubnnJ=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_field_name.stubss%ɤBvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_field_precision.stubuuڙ>vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_field_scale.stubqq=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_field_size.stubppH3Τ=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_field_type.stubwwGAvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_field_type_raw.stubtt+kBvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_free_collection.stubJJM|y>vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_free_cursor.stubyysQBvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_free_descriptor.stub<<# Avendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_free_statement.stub[[+6+Ivendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_get_implicit_resultset.stub{{=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_append.stubEEҒ<;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_copy.stubXXۅњ:vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_eof.stub44D,n<vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_erase.stubee=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_export.stubssH><vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_flush.stubEEţ=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_import.stubII95֤?vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_is_equal.stubIISY;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_load.stub==;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_read.stubJJ=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_rewind.stub77T6R;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_save.stubTTyD*;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_seek.stub^^5ݤ;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_size.stub::!0:;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_tell.stub::yK?vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_truncate.stubJJ<vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_write.stub^^8kAvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_new_collection.stub4 >vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_new_connect.stubqH=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_new_cursor.stubqq ʤAvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_new_descriptor.stub||C"=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_num_fields.stubVVTw;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_num_rows.stubZZ Ƥ8vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_parse.stubyyäBvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_password_change.stubP;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_pconnect.stub+vHvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_register_taf_callback.stubyyN 9vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_result.stubhhG%Ȥ;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_rollback.stubWWUD]Avendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_server_version.stubee=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_action.stubiiDà֤Cvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_call_timeout.stubmm2Hvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_client_identifier.stubwwsBvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_client_info.stubwwJ8Cvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_db_operation.stuboo,}b>vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_edition.stub;;?rBvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_module_name.stubllog?vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_prefetch.stubddקCvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_prefetch_lob.stub <Avendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_statement_type.stubcci%HJvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_unregister_taf_callback.stubffƤ<vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocibindbyname.stubܸt8vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicancel.stubzzV_<vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicollappend.stub15@vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicollassignelem.stub KV=vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicollgetelem.stub"9vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicollmax.stubzz,:vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicollsize.stub||:vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicolltrim.stub>vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicolumnisnull.stubׄ<vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicolumnname.stub:Avendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicolumnprecision.stub/m=vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicolumnscale.stubEF<vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicolumnsize.stub0<vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicolumntype.stubF ?vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicolumntyperaw.stubHuä8vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicommit.stub||Ҥ>vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocidefinebyname.stub7vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocierror.stub;9vendor/phpstan/php-8-stubs/stubs/ext/oci8/ociexecute.stubu7vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocifetch.stubxx;vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocifetchinto.stub%@vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocifetchstatement.stub ex@vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocifreecollection.stub}}~a<vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocifreecursor.stub`Y':vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocifreedesc.stubiitD(?vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocifreestatement.stube Avendor/phpstan/php-8-stubs/stubs/ext/oci8/ocigetbufferinglob.stub;;dȤ9vendor/phpstan/php-8-stubs/stubs/ext/oci8/ociloadlob.stubii#e=8vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocilogoff.stub||Ĭ0y7vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocilogon.stub{c2?vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocinewcollection.stub;vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocinewcursor.stubtգ?vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocinewdescriptor.stubʆH8vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocinlogon.stubd \9vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocinumcols.stub~~NY7vendor/phpstan/php-8-stubs/stubs/ext/oci8/ociparse.stubW[@vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocipasswordchange.stub8vendor/phpstan/php-8-stubs/stubs/ext/oci8/ociplogon.stub<8vendor/phpstan/php-8-stubs/stubs/ext/oci8/ociresult.stubM;:vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocirollback.stub:vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocirowcount.stubԧ9vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocisavelob.stub%y<=vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocisavelobfile.stubyySp?vendor/phpstan/php-8-stubs/stubs/ext/oci8/ociserverversion.stubhAvendor/phpstan/php-8-stubs/stubs/ext/oci8/ocisetbufferinglob.stubGGPD0Ф=vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocisetprefetch.stub9?vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocistatementtype.stubaÅ@vendor/phpstan/php-8-stubs/stubs/ext/oci8/ociwritelobtofile.stubѯ>vendor/phpstan/php-8-stubs/stubs/ext/odbc/Odbc/Connection.stubqqWk:vendor/phpstan/php-8-stubs/stubs/ext/odbc/Odbc/Result.stubmmܕ>b>vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_autocommit.stubbb(I;vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_binmode.stub9V9vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_close.stubX`N =vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_close_all.stubMM]j&Dvendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_columnprivileges.stub__ Q7;vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_columns.stubDl:vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_commit.stub|OC;vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_connect.stubffOvendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_connection_string_is_quoted.stubssPipKvendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_connection_string_quote.stubWWA٤Rvendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_connection_string_should_quote.stub\\q:vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_cursor.stubl?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_data_source.stub.6vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_do.stub  9vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_error.stub{ <vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_errormsg.stubOi}8vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_exec.stubJڮ;vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_execute.stub_e?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_fetch_array.stub%P>vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_fetch_into.stub::Ӷ;@vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_fetch_object.stub119 =vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_fetch_row.stub)=vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_field_len.stub^e>vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_field_name.stub=vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_field_num.stubpCvendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_field_precision.stubPؤ?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_field_scale.stub bV>vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_field_type.stubYi?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_foreignkeys.stub??vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_free_result.stubxD?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_gettypeinfo.stubQ?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_longreadlen.stub?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_next_result.stub  mK>vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_num_fields.stub:}f<vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_num_rows.stubPȤ<vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_pconnect.stubhhSj;vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_prepare.stub㈤?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_primarykeys.stub55!aDvendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_procedurecolumns.stubCCѳc>vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_procedures.stubii9G,:vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_result.stubn|>vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_result_all.stublz<vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_rollback.stubN=vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_setoption.stubp1Bvendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_specialcolumns.stubg`g5>vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_statistics.stubkkf[Cvendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_tableprivileges.stub  H:vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_tables.stubFvendor/phpstan/php-8-stubs/stubs/ext/opcache/opcache_compile_file.stubAA:ÑҤKvendor/phpstan/php-8-stubs/stubs/ext/opcache/opcache_get_configuration.stub==s=Dvendor/phpstan/php-8-stubs/stubs/ext/opcache/opcache_get_status.stubRRFΤDvendor/phpstan/php-8-stubs/stubs/ext/opcache/opcache_invalidate.stubTT1Jvendor/phpstan/php-8-stubs/stubs/ext/opcache/opcache_is_script_cached.stubEEd%Xvendor/phpstan/php-8-stubs/stubs/ext/opcache/opcache_is_script_cached_in_file_cache.stubddGvendor/phpstan/php-8-stubs/stubs/ext/opcache/opcache_jit_blacklist.stubTTֹ?vendor/phpstan/php-8-stubs/stubs/ext/opcache/opcache_reset.stubLLuFvendor/phpstan/php-8-stubs/stubs/ext/openssl/OpenSSLAsymmetricKey.stub,,{ՔDvendor/phpstan/php-8-stubs/stubs/ext/openssl/OpenSSLCertificate.stubLLLYZRvendor/phpstan/php-8-stubs/stubs/ext/openssl/OpenSSLCertificateSigningRequest.stub88wmWJvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_cipher_iv_length.stubMM~Kvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_cipher_key_length.stub__HEvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_cms_decrypt.stub44CzEvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_cms_encrypt.stubsՄBvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_cms_read.stubuu(oBvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_cms_sign.stub]]Yh8Dvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_cms_verify.stub((ۤDvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_csr_export.stubiLvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_csr_export_to_file.stub;!sLvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_csr_get_public_key.stubOXϤIvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_csr_get_subject.stubΤAvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_csr_new.stuba^ABvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_csr_sign.stubäAvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_decrypt.stub~~8Hvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_dh_compute_key.stubqq 6@vendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_digest.stubqq~ՒAvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_encrypt.stublS8Fvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_error_string.stub997G1Bvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_free_key.stubaabZbLvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_get_cert_locations.stub88K]Lvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_get_cipher_methods.stubMMxmNIvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_get_curve_names.stubSS52Hvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_get_md_methods.stubIII[@%Hvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_get_privatekey.stubNdGvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_get_publickey.stubU>vendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_open.stub1̽tGvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_password_hash.stublz3Ivendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_password_verify.stubB;(@vendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pbkdf2.stubsGvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkcs12_export.stub=IWOvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkcs12_export_to_file.stub4bEvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkcs12_read.stubGvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkcs7_decrypt.stub.ͤGvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkcs7_encrypt.stub  h+ !Dvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkcs7_read.stubmmzDvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkcs7_sign.stubDD%Fvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkcs7_verify.stubդEvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkey_derive.stubIGEvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkey_export.stubOkyMvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkey_export_to_file.stubw#Cvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkey_free.stubo"tJvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkey_get_details.stubVVo¤Jvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkey_get_private.stub*oIvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkey_get_public.stub`Bvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkey_new.stubZZNIvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_private_decrypt.stub\\i8Ivendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_private_encrypt.stub ZHvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_public_decrypt.stubHvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_public_encrypt.stub?? Mvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_random_pseudo_bytes.stub%Kp%>vendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_seal.stubK>vendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_sign.stubJ(ܤEvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_spki_export.stubDD]ȤOvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_spki_export_challenge.stubNNBvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_spki_new.stub].Evendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_spki_verify.stub<<N@vendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_verify.stubu\JPvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_check_private_key.stub LKvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_checkpurpose.stubEvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_export.stub[Mvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_export_to_file.stubC mJvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_fingerprint.stubACvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_free.stub))M64Dvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_parse.stubwwT(JCvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_read.stubjjb({eEvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_verify.stubkM>vendor/phpstan/php-8-stubs/stubs/ext/pcntl/Pcntl/QosClass.stub<<:m;vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_alarm.stub33u>Cvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_async_signals.stubDD>8;vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_errno.stubJJ6~:vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_exec.stub:vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_fork.stubHHҤ;vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_forkx.stub[[1ߤDvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_get_last_error.stub00h1<vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_getcpu.stubYY2Dvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_getcpuaffinity.stubInAvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_getpriority.stub||Bvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_getqos_class.stub||%;vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_rfork.stubll Dvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_setcpuaffinity.stubnn~=Ƥ;vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_setns.stubGAvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_setpriority.stub9Bvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_setqos_class.stubttDb<vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_signal.stubEvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_signal_dispatch.stub22:"Hvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_signal_get_handler.stubVV%Avendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_sigprocmask.stubvBvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_sigtimedwait.stubiAvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_sigwaitinfo.stub"O>vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_strerror.stubCCfV=vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_unshare.stubHHk5:vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_wait.stubtM<vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_waitid.stubaa2V`=vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_waitpid.stubAAvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_wexitstatus.stub>>Ӑ !Bvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_wifcontinued.stubQQh?vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_wifexited.stubEE4 5Avendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_wifsignaled.stub@@@vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_wifstopped.stub88p>vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_wstopsig.stub;; tu>vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_wtermsig.stub;;LQ:vendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_filter.stubLJ$8vendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_grep.stubZZ>vendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_last_error.stub++9{j Bvendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_last_error_msg.stub22tK9vendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_match.stub +=vendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_match_all.stubx^9vendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_quote.stubOO-;vendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_replace.stubǤDvendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_replace_callback.stub?jaUJvendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_replace_callback_array.stub?39vendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_split.stubooj<Ĥ1vendor/phpstan/php-8-stubs/stubs/ext/pdo/PDO.stubbZbZΊ:vendor/phpstan/php-8-stubs/stubs/ext/pdo/PDOException.stubZZ44vendor/phpstan/php-8-stubs/stubs/ext/pdo/PDORow.stubӪ!2:vendor/phpstan/php-8-stubs/stubs/ext/pdo/PDOStatement.stubK K xҤ9vendor/phpstan/php-8-stubs/stubs/ext/pdo/pdo_drivers.stub))1j=vendor/phpstan/php-8-stubs/stubs/ext/pdo_dblib/Pdo/Dblib.stubQQM-uCvendor/phpstan/php-8-stubs/stubs/ext/pdo_firebird/Pdo/Firebird.stub8S=vendor/phpstan/php-8-stubs/stubs/ext/pdo_mysql/Pdo/Mysql.stuby y ;vendor/phpstan/php-8-stubs/stubs/ext/pdo_odbc/Pdo/Odbc.stubBBjAvendor/phpstan/php-8-stubs/stubs/ext/pdo_pgsql/PDO_PGSql_Ext.stub^^M,=vendor/phpstan/php-8-stubs/stubs/ext/pdo_pgsql/Pdo/Pgsql.stub[[QCvendor/phpstan/php-8-stubs/stubs/ext/pdo_sqlite/PDO_SQLite_Ext.stubW?vendor/phpstan/php-8-stubs/stubs/ext/pdo_sqlite/Pdo/Sqlite.stubd d  ؤ@vendor/phpstan/php-8-stubs/stubs/ext/pgsql/PgSql/Connection.stubxxZ@ 19vendor/phpstan/php-8-stubs/stubs/ext/pgsql/PgSql/Lob.stubqq<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/PgSql/Result.stubttK}@vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_affected_rows.stubh+?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_cancel_query.stub)2TBvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_change_password.stub-9[Bvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_client_encoding.stub9 Avendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_clientencoding.stubn8vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_close.stub))jI=vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_close_stmt.stublJ<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_cmdtuples.stubޤ:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_connect.stub?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_connect_poll.stub34Bvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_connection_busy.stubQCvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_connection_reset.stubMWDvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_connection_status.stuby;@vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_consume_input.stubEe:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_convert.stubee%˯<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_copy_from.stub((S2:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_copy_to.stub@9vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_dbname.stub)^69vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_delete.stub[[H_%;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_end_copy.stubng?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_errormessage.stubC?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_escape_bytea.stub00WmIDvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_escape_identifier.stubFF;l^Avendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_escape_literal.stub@@yȤ@vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_escape_string.stub22I7vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_exec.stubXXR:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_execute.stub^w<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fetch_all.stub14Dvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fetch_all_columns.stubE>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fetch_array.stubYYmyƤ>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fetch_assoc.stub))Dl灤?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fetch_object.stubiip,ؤ?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fetch_result.stub.<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fetch_row.stubSSVn@vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_field_is_null.stub6=vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_field_name.stuba<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_field_num.stub8,?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_field_prtlen.stub'4=vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_field_size.stub¤>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_field_table.stub  F=vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_field_type.stubD1Avendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_field_type_oid.stubmRk>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fieldisnull.stub}}e<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fieldname.stubt0:;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fieldnum.stubl!>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fieldprtlen.stubzz,>d<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fieldsize.stubSɤ<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fieldtype.stubqa8vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_flush.stub'[>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_free_result.stubD=vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_freeresult.stub =vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_get_notify.stub::%:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_get_pid.stubgr =vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_get_result.stubvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_last_notice.stubWnX;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_last_oid.stubSb;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_close.stubY%$<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_create.stubhh8.<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_export.stub<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_import.stub̮:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_open.stubHT:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_read.stubdO >vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_read_all.stubpH@:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_seek.stubW:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_tell.stubN>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_truncate.stub@I<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_unlink.stub--[VNg;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_write.stub u:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_loclose.stub 7c;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_locreate.stubwuf;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_loexport.stubPP^ni;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_loimport.stubhh= 9vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_loopen.stub2˘9vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_loread.stub <vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_loreadall.stubSgH;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lounlink.stubyy#m:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lowrite.stub!<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_meta_data.stub[[=vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_num_fields.stub ;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_num_rows.stub}h7<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_numfields.stub:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_numrows.stubA:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_options.stubwfSCvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_parameter_status.stub@@ϧݤ;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_pconnect.stubBĤ7vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_ping.stubG7vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_port.stubƤ:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_prepare.stubwwt@vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_put_copy_data.stubggg?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_put_copy_end.stubppܳפ;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_put_line.stubƤ8vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_query.stubCC>[?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_query_params.stubF9vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_result.stub;c?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_result_error.stuba&Evendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_result_error_field.stub  ~ZEvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_result_memory_size.stubyyڤ>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_result_seek.stubƼI@vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_result_status.stub  4J9vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_select.stub]KJ?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_send_execute.stubR?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_send_prepare.stub\*=vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_send_query.stubklDvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_send_query_params.stub  7/:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_service.stubvvVlHvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_set_chunked_rows_size.stub fFvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_set_client_encoding.stub))H)Ovendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_set_error_context_visibility.stubz뇤Fvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_set_error_verbosity.stub++#Dvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_setclientencoding.stub>0Ϥ9vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_socket.stubГ>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_socket_poll.stub@{8vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_trace.stub%Evendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_transaction_status.stub3 6vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_tty.stubM ݤAvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_unescape_bytea.stub>>} T:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_untrace.stub//9vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_update.stubyy:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_version.stub   !3vendor/phpstan/php-8-stubs/stubs/ext/phar/Phar.stube+e+Kn7vendor/phpstan/php-8-stubs/stubs/ext/phar/PharData.stub.(.(]<vendor/phpstan/php-8-stubs/stubs/ext/phar/PharException.stubTTvO;vendor/phpstan/php-8-stubs/stubs/ext/phar/PharFileInfo.stub!yi<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_access.stubPPi=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_ctermid.stubFFQoM=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_eaccess.stubooTk';vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_errno.stubJJǤ?vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_fpathconf.stub<&Dvendor/phpstan/php-8-stubs/stubs/ext/posix/posix_get_last_error.stub77C7<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getcwd.stub11I[=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getegid.stub))&D=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_geteuid.stub))Pޘ%<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getgid.stub//fIE>vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getgrgid.stub??*5>vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getgrnam.stub>>qI?vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getgroups.stubPP&k>vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getlogin.stubOO^dH=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getpgid.stubRR 4e=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getpgrp.stub00x<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getpid.stub((!=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getppid.stub))֤>vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getpwnam.stubBBb>vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getpwuid.stub>>.=?vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getrlimit.stubM<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getsid.stubWWxx<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getuid.stub((0@vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_initgroups.stubccYW<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_isatty.stubeeN:vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_kill.stubeen1<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_mkfifo.stub^^y;vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_mknod.stub}}4>vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_pathconf.stubmmLb+=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_setegid.stubKKrK=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_seteuid.stubJJwpp<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_setgid.stub66ht=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_setpgid.stubWW%N?vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_setrlimit.stubxxhp <vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_setsid.stub;;:|<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_setuid.stub55>>vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_strerror.stub<<.=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_sysconf.stubMMX;vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_times.stub//V =vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_ttyname.stubuuQ;vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_uname.stub662>vendor/phpstan/php-8-stubs/stubs/ext/pspell/PSpell/Config.stubuuFFBvendor/phpstan/php-8-stubs/stubs/ext/pspell/PSpell/Dictionary.stubyySGvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_add_to_personal.stubz&yFvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_add_to_session.stub(=vendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_check.stub8ϤEvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_clear_session.stuboΤEvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_create.stub,,(Gvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_data_dir.stubj<_Gvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_dict_dir.stubtXEvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_ignore.stub`S Cvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_mode.stubA2aGvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_personal.stub0 ۤCvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_repl.stub S,Jvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_runtogether.stubwHvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_save_repl.stubF;vendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_new.stubhh?Bvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_new_config.stubDvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_new_personal.stub||p|Evendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_save_wordlist.stub[WOIvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_store_replacement.stub?vendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_suggest.stub|Ovendor/phpstan/php-8-stubs/stubs/ext/random/Random/BrokenRandomEngineError.stubiHvendor/phpstan/php-8-stubs/stubs/ext/random/Random/CryptoSafeEngine.stubaa?>vendor/phpstan/php-8-stubs/stubs/ext/random/Random/Engine.stubhh*Fvendor/phpstan/php-8-stubs/stubs/ext/random/Random/Engine/Mt19937.stubRvendor/phpstan/php-8-stubs/stubs/ext/random/Random/Engine/PcgOneseq128XslRr64.stub|l!Evendor/phpstan/php-8-stubs/stubs/ext/random/Random/Engine/Secure.stubǥkQvendor/phpstan/php-8-stubs/stubs/ext/random/Random/Engine/Xoshiro256StarStar.stub""n !Hvendor/phpstan/php-8-stubs/stubs/ext/random/Random/IntervalBoundary.stubEEICvendor/phpstan/php-8-stubs/stubs/ext/random/Random/RandomError.stubnnwYGvendor/phpstan/php-8-stubs/stubs/ext/random/Random/RandomException.stubvvaBvendor/phpstan/php-8-stubs/stubs/ext/random/Random/Randomizer.stub e];vendor/phpstan/php-8-stubs/stubs/ext/random/getrandmax.stubSS~Rw:vendor/phpstan/php-8-stubs/stubs/ext/random/lcg_value.stub0>vendor/phpstan/php-8-stubs/stubs/ext/random/mt_getrandmax.stub::g8vendor/phpstan/php-8-stubs/stubs/ext/random/mt_rand.stubZZݐ^9vendor/phpstan/php-8-stubs/stubs/ext/random/mt_srand.stubd5vendor/phpstan/php-8-stubs/stubs/ext/random/rand.stubWW4!=vendor/phpstan/php-8-stubs/stubs/ext/random/random_bytes.stubZZTP;vendor/phpstan/php-8-stubs/stubs/ext/random/random_int.stubIIY6vendor/phpstan/php-8-stubs/stubs/ext/random/srand.stub6x<;vendor/phpstan/php-8-stubs/stubs/ext/readline/readline.stubee%ؤGvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_add_history.stub:Tvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_callback_handler_install.stubǣ.Svendor/phpstan/php-8-stubs/stubs/ext/readline/readline_callback_handler_remove.stub==yNvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_callback_read_char.stub88~qeIvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_clear_history.stubEOvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_completion_function.stubKKqR@vendor/phpstan/php-8-stubs/stubs/ext/readline/readline_info.stubGHvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_list_history.stubLLDAѤGvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_on_new_line.stubIItȸHvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_read_history.stubQQ$7ФEvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_redisplay.stub//''Ivendor/phpstan/php-8-stubs/stubs/ext/readline/readline_write_history.stubKK@bREvendor/phpstan/php-8-stubs/stubs/ext/reflection/PropertyHookType.stub;;1j?vendor/phpstan/php-8-stubs/stubs/ext/reflection/Reflection.stubHvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionAttribute.stub+SDvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionClass.stubK$K$aNLvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionClassConstant.stub. . ۳Gvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionConstant.stuboomCvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionEnum.stub44q6ϤMvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionEnumBackedCase.stub^hKvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionEnumUnitCase.stub~~D%Hvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionException.stubZZ&Hvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionExtension.stubT1Dvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionFiber.stubGvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionFunction.stub|Ovendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionFunctionAbstract.stub|ҤHvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionGenerator.stubCC5Ovendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionIntersectionType.stuboQEvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionMethod.stub8ʤHvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionNamedType.stubLQEvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionObject.stubwwHvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionParameter.stub IGvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionProperty.stub Hvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionReference.stubbb^8Cvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionType.stub9Hvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionUnionType.stubooLvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionZendExtension.stub>vendor/phpstan/php-8-stubs/stubs/ext/reflection/Reflector.stub33@vendor/phpstan/php-8-stubs/stubs/ext/session/SessionHandler.stubIvendor/phpstan/php-8-stubs/stubs/ext/session/SessionHandlerInterface.stub&)Dvendor/phpstan/php-8-stubs/stubs/ext/session/SessionIdInterface.stubbᣤXvendor/phpstan/php-8-stubs/stubs/ext/session/SessionUpdateTimestampHandlerInterface.stub++B?vendor/phpstan/php-8-stubs/stubs/ext/session/session_abort.stub**]ĤFvendor/phpstan/php-8-stubs/stubs/ext/session/session_cache_expire.stubHHGvendor/phpstan/php-8-stubs/stubs/ext/session/session_cache_limiter.stubOOV@vendor/phpstan/php-8-stubs/stubs/ext/session/session_commit.stubMMn =Cvendor/phpstan/php-8-stubs/stubs/ext/session/session_create_id.stubII)i@vendor/phpstan/php-8-stubs/stubs/ext/session/session_decode.stub77쭤Avendor/phpstan/php-8-stubs/stubs/ext/session/session_destroy.stub,,N@vendor/phpstan/php-8-stubs/stubs/ext/session/session_encode.stub33 o4<vendor/phpstan/php-8-stubs/stubs/ext/session/session_gc.stub,,Kvendor/phpstan/php-8-stubs/stubs/ext/session/session_get_cookie_params.stub77ƌwP<vendor/phpstan/php-8-stubs/stubs/ext/session/session_id.stubAA󁬤Evendor/phpstan/php-8-stubs/stubs/ext/session/session_module_name.stubNNrQ>vendor/phpstan/php-8-stubs/stubs/ext/session/session_name.stubggC;Gvendor/phpstan/php-8-stubs/stubs/ext/session/session_regenerate_id.stubRRMchKvendor/phpstan/php-8-stubs/stubs/ext/session/session_register_shutdown.stub66KS?vendor/phpstan/php-8-stubs/stubs/ext/session/session_reset.stub**lCvendor/phpstan/php-8-stubs/stubs/ext/session/session_save_path.stubJJ.ZKvendor/phpstan/php-8-stubs/stubs/ext/session/session_set_cookie_params.stub4Jvendor/phpstan/php-8-stubs/stubs/ext/session/session_set_save_handler.stub_Ӥ?vendor/phpstan/php-8-stubs/stubs/ext/session/session_start.stub==1T@vendor/phpstan/php-8-stubs/stubs/ext/session/session_status.stub**Qe?vendor/phpstan/php-8-stubs/stubs/ext/session/session_unset.stub** P%Evendor/phpstan/php-8-stubs/stubs/ext/session/session_write_close.stub00H85vendor/phpstan/php-8-stubs/stubs/ext/shmop/Shmop.stub??f+;vendor/phpstan/php-8-stubs/stubs/ext/shmop/shmop_close.stub91<vendor/phpstan/php-8-stubs/stubs/ext/shmop/shmop_delete.stub66[:vendor/phpstan/php-8-stubs/stubs/ext/shmop/shmop_open.stubbb::vendor/phpstan/php-8-stubs/stubs/ext/shmop/shmop_read.stubNNRΤ:vendor/phpstan/php-8-stubs/stubs/ext/shmop/shmop_size.stub33;vendor/phpstan/php-8-stubs/stubs/ext/shmop/shmop_write.stubOOME&Dvendor/phpstan/php-8-stubs/stubs/ext/simplexml/SimpleXMLElement.stub  1\ZEvendor/phpstan/php-8-stubs/stubs/ext/simplexml/SimpleXMLIterator.stub== Hvendor/phpstan/php-8-stubs/stubs/ext/simplexml/simplexml_import_dom.stub##u֤Gvendor/phpstan/php-8-stubs/stubs/ext/simplexml/simplexml_load_file.stubIvendor/phpstan/php-8-stubs/stubs/ext/simplexml/simplexml_load_string.stubs,3vendor/phpstan/php-8-stubs/stubs/ext/snmp/SNMP.stubLM<vendor/phpstan/php-8-stubs/stubs/ext/snmp/SNMPException.stub99=w8vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp2_get.stubK<vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp2_getnext.stubD|>vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp2_real_walk.stub}8vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp2_set.stub"a9vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp2_walk.stubuڤ8vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp3_get.stub  -!L<vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp3_getnext.stubZݤ>vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp3_real_walk.stubC`8vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp3_set.stub33x9vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp3_walk.stub'|MCvendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp_get_quick_print.stub11:Fvendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp_get_valueretrieval.stub33K Z<vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp_read_mib.stub::nUBvendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp_set_enum_print.stubiIvendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp_set_oid_numeric_print.stubjΤIvendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp_set_oid_output_format.stub:`MCvendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp_set_quick_print.stub{Fvendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp_set_valueretrieval.stubޤ6vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmpget.stubWޤ:vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmpgetnext.stub3;vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmprealwalk.stubhƤ6vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmpset.stub7vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmpwalk.stubRS:vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmpwalkoid.stubJA̤7vendor/phpstan/php-8-stubs/stubs/ext/soap/Soap/Sdl.stubppWͤ7vendor/phpstan/php-8-stubs/stubs/ext/soap/Soap/Url.stubppR{9vendor/phpstan/php-8-stubs/stubs/ext/soap/SoapClient.stub1 1 `_8vendor/phpstan/php-8-stubs/stubs/ext/soap/SoapFault.stubN9vendor/phpstan/php-8-stubs/stubs/ext/soap/SoapHeader.stubV8vendor/phpstan/php-8-stubs/stubs/ext/soap/SoapParam.stubbbd>9vendor/phpstan/php-8-stubs/stubs/ext/soap/SoapServer.stubtA6vendor/phpstan/php-8-stubs/stubs/ext/soap/SoapVar.stubT|l<vendor/phpstan/php-8-stubs/stubs/ext/soap/is_soap_fault.stub77ת*Evendor/phpstan/php-8-stubs/stubs/ext/soap/use_soap_error_handler.stubhhīd=vendor/phpstan/php-8-stubs/stubs/ext/sockets/AddressInfo.stub##AA8vendor/phpstan/php-8-stubs/stubs/ext/sockets/Socket.stub@@Ro?vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_accept.stubBBjդFvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_addrinfo_bind.stubOOIIvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_addrinfo_connect.stubRR~HGIvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_addrinfo_explain.stubJJі?Hvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_addrinfo_lookup.stubrrhѤ?vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_atmark.stubhh%|=vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_bind.stubWW%Dvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_clear_error.stubFF_{Z>vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_close.stub88Cvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_cmsg_space.stubQQ\դ@vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_connect.stub^^[`?vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_create.stubXXROFvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_create_listen.stub7Dvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_create_pair.stub lFvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_export_stream.stubXXhPCvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_get_option.stubaaC5k?vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_getopt.stub}}'Dvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_getpeername.stubxDvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_getsockname.stubPI2Fvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_import_stream.stub``R7ŤCvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_last_error.stubKK?vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_listen.stubKK%l=vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_read.stubiiqb=vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_recv.stub}}>Avendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_recvfrom.stub4!ˤ@vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_recvmsg.stub``ۓ?vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_select.stubZOޤ=vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_send.stubccN.[4@vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_sendmsg.stub__qp ?vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_sendto.stub6qBvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_set_block.stub<<vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_write.stub``)Pvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_wsaprotocol_info_export.stubttPvPvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_wsaprotocol_info_import.stubSSQvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_wsaprotocol_info_release.stubKK攘@vendor/phpstan/php-8-stubs/stubs/ext/sodium/SodiumException.stub44\;vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_add.stubHHEBvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_base642bin.stub\\GΒBvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_bin2base64.stubmmfߤ?vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_bin2hex.stub;;[,?vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_compare.stubJJ(gIUvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aegis128l_decrypt.stubX᧤Uvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aegis128l_encrypt.stubځTvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aegis128l_keygen.stubSSMTvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aegis256_decrypt.stubTvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aegis256_encrypt.stubmSvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aegis256_keygen.stubRR'0XUvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aes256gcm_decrypt.stubཤUvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aes256gcm_encrypt.stubrZvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aes256gcm_is_available.stubhh<Tvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aes256gcm_keygen.stubBBTE%\vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_chacha20poly1305_decrypt.stuby'o\vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_chacha20poly1305_encrypt.stub'vavendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_chacha20poly1305_ietf_decrypt.stubTmӤavendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_chacha20poly1305_ietf_encrypt.stubJ`vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_chacha20poly1305_ietf_keygen.stubNNu[vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_chacha20poly1305_keygen.stubIImbvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_core_ristretto255_scalar_complement.stubjjyF^vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_core_ristretto255_scalar_invert.stubffw[vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_core_ristretto255_scalar_mul.stubnn> a^vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_core_ristretto255_scalar_negate.stubffUĤ^vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_core_ristretto255_scalar_random.stub]]fz^vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_core_ristretto255_scalar_reduce.stubffD[vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_core_ristretto255_scalar_sub.stubnnKmTvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_core_ristretto255_sub.stubggo:Jvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_generichash.stubפPvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_generichash_final.stub{{;Ovendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_generichash_init.stub||UD8sQvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_generichash_keygen.stub??vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_memcmp.stubII+H ?vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_memzero.stub::;vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_pad.stubHHZO[=vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_unpad.stubJJ<vendor/phpstan/php-8-stubs/stubs/ext/spl/AppendIterator.stubYT;vendor/phpstan/php-8-stubs/stubs/ext/spl/ArrayIterator.stub9vendor/phpstan/php-8-stubs/stubs/ext/spl/ArrayObject.stub]]avFvendor/phpstan/php-8-stubs/stubs/ext/spl/BadFunctionCallException.stubSS7}ҤDvendor/phpstan/php-8-stubs/stubs/ext/spl/BadMethodCallException.stub[[&=vendor/phpstan/php-8-stubs/stubs/ext/spl/CachingIterator.stub IDvendor/phpstan/php-8-stubs/stubs/ext/spl/CallbackFilterIterator.stub ?vendor/phpstan/php-8-stubs/stubs/ext/spl/DirectoryIterator.stub!!iEC=vendor/phpstan/php-8-stubs/stubs/ext/spl/DomainException.stubJJ|HR;vendor/phpstan/php-8-stubs/stubs/ext/spl/EmptyIterator.stubjjGځݤ@vendor/phpstan/php-8-stubs/stubs/ext/spl/FilesystemIterator.stubII+b<vendor/phpstan/php-8-stubs/stubs/ext/spl/FilterIterator.stubŹ:vendor/phpstan/php-8-stubs/stubs/ext/spl/GlobIterator.stubcc >vendor/phpstan/php-8-stubs/stubs/ext/spl/InfiniteIterator.stub3VHFvendor/phpstan/php-8-stubs/stubs/ext/spl/InvalidArgumentException.stubSSW>vendor/phpstan/php-8-stubs/stubs/ext/spl/IteratorIterator.stub,,h絤=vendor/phpstan/php-8-stubs/stubs/ext/spl/LengthException.stubJJ2?;vendor/phpstan/php-8-stubs/stubs/ext/spl/LimitIterator.stub<vendor/phpstan/php-8-stubs/stubs/ext/spl/LogicException.stubccU;>vendor/phpstan/php-8-stubs/stubs/ext/spl/MultipleIterator.stubi i dp>vendor/phpstan/php-8-stubs/stubs/ext/spl/NoRewindIterator.stubKmBvendor/phpstan/php-8-stubs/stubs/ext/spl/OutOfBoundsException.stubQQ$"Avendor/phpstan/php-8-stubs/stubs/ext/spl/OutOfRangeException.stubNN"8;vendor/phpstan/php-8-stubs/stubs/ext/spl/OuterIterator.stub==?vendor/phpstan/php-8-stubs/stubs/ext/spl/OverflowException.stubNNƤ<vendor/phpstan/php-8-stubs/stubs/ext/spl/ParentIterator.stub77ml<vendor/phpstan/php-8-stubs/stubs/ext/spl/RangeException.stubKK7gͤDvendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveArrayIterator.stubqqhœFvendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveCachingIterator.stub)Mvendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveCallbackFilterIterator.stub  :ir&Hvendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveDirectoryIterator.stubt6Evendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveFilterIterator.stub?vendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveIterator.stubۤGvendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveIteratorIterator.stub }\RDvendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveRegexIterator.stub6&Cvendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveTreeIterator.stubx x p;vendor/phpstan/php-8-stubs/stubs/ext/spl/RegexIterator.stub >?>vendor/phpstan/php-8-stubs/stubs/ext/spl/RuntimeException.stubFFG>vendor/phpstan/php-8-stubs/stubs/ext/spl/SeekableIterator.stub֤Avendor/phpstan/php-8-stubs/stubs/ext/spl/SplDoublyLinkedList.stubrr9vendor/phpstan/php-8-stubs/stubs/ext/spl/SplFileInfo.stub..3%;vendor/phpstan/php-8-stubs/stubs/ext/spl/SplFileObject.stub++y<;vendor/phpstan/php-8-stubs/stubs/ext/spl/SplFixedArray.stubᦚ5vendor/phpstan/php-8-stubs/stubs/ext/spl/SplHeap.stub>>I 8vendor/phpstan/php-8-stubs/stubs/ext/spl/SplMaxHeap.stubC08vendor/phpstan/php-8-stubs/stubs/ext/spl/SplMinHeap.stub]>vendor/phpstan/php-8-stubs/stubs/ext/spl/SplObjectStorage.stub9vendor/phpstan/php-8-stubs/stubs/ext/spl/SplObserver.stubMƵ>vendor/phpstan/php-8-stubs/stubs/ext/spl/SplPriorityQueue.stub 06vendor/phpstan/php-8-stubs/stubs/ext/spl/SplQueue.stubtV6vendor/phpstan/php-8-stubs/stubs/ext/spl/SplStack.stub77>8vendor/phpstan/php-8-stubs/stubs/ext/spl/SplSubject.stubjjrϤ?vendor/phpstan/php-8-stubs/stubs/ext/spl/SplTempFileObject.stubhv@vendor/phpstan/php-8-stubs/stubs/ext/spl/UnderflowException.stubOOAFvendor/phpstan/php-8-stubs/stubs/ext/spl/UnexpectedValueException.stubUUh>vendor/phpstan/php-8-stubs/stubs/ext/spl/class_implements.stub=;vendor/phpstan/php-8-stubs/stubs/ext/spl/class_parents.stubzP8vendor/phpstan/php-8-stubs/stubs/ext/spl/class_uses.stubU<vendor/phpstan/php-8-stubs/stubs/ext/spl/iterator_apply.stubii<vendor/phpstan/php-8-stubs/stubs/ext/spl/iterator_count.stubS4?vendor/phpstan/php-8-stubs/stubs/ext/spl/iterator_to_array.stub:6Yؤ:vendor/phpstan/php-8-stubs/stubs/ext/spl/spl_autoload.stubWW5=?vendor/phpstan/php-8-stubs/stubs/ext/spl/spl_autoload_call.stub;;{ń"Evendor/phpstan/php-8-stubs/stubs/ext/spl/spl_autoload_extensions.stubUUc Dvendor/phpstan/php-8-stubs/stubs/ext/spl/spl_autoload_functions.stub44mpiCvendor/phpstan/php-8-stubs/stubs/ext/spl/spl_autoload_register.stubwwn{Evendor/phpstan/php-8-stubs/stubs/ext/spl/spl_autoload_unregister.stubFFW9vendor/phpstan/php-8-stubs/stubs/ext/spl/spl_classes.stub))&=vendor/phpstan/php-8-stubs/stubs/ext/spl/spl_object_hash.stub<<x~;vendor/phpstan/php-8-stubs/stubs/ext/spl/spl_object_id.stub77[ 39vendor/phpstan/php-8-stubs/stubs/ext/sqlite3/SQLite3.stub99}7hBvendor/phpstan/php-8-stubs/stubs/ext/sqlite3/SQLite3Exception.stubkk*Y?vendor/phpstan/php-8-stubs/stubs/ext/sqlite3/SQLite3Result.stubqp=vendor/phpstan/php-8-stubs/stubs/ext/sqlite3/SQLite3Stmt.stubAvendor/phpstan/php-8-stubs/stubs/ext/standard/AssertionError.stub@@6¤<vendor/phpstan/php-8-stubs/stubs/ext/standard/Directory.stub  Ҕ(?vendor/phpstan/php-8-stubs/stubs/ext/standard/RoundingMode.stub..D?vendor/phpstan/php-8-stubs/stubs/ext/standard/StreamBucket.stub55jIvendor/phpstan/php-8-stubs/stubs/ext/standard/__PHP_Incomplete_Class.stub^^LG8H6vendor/phpstan/php-8-stubs/stubs/ext/standard/abs.stub@@D_fӤ7vendor/phpstan/php-8-stubs/stubs/ext/standard/acos.stub,,t׽8vendor/phpstan/php-8-stubs/stubs/ext/standard/acosh.stub--3>vendor/phpstan/php-8-stubs/stubs/ext/standard/addcslashes.stubLLaq=vendor/phpstan/php-8-stubs/stubs/ext/standard/addslashes.stub77PYӛ<vendor/phpstan/php-8-stubs/stubs/ext/standard/array_all.stubWW¤<vendor/phpstan/php-8-stubs/stubs/ext/standard/array_any.stubWWDHvendor/phpstan/php-8-stubs/stubs/ext/standard/array_change_key_case.stubWWQ>vendor/phpstan/php-8-stubs/stubs/ext/standard/array_chunk.stub__ZǤ?vendor/phpstan/php-8-stubs/stubs/ext/standard/array_column.stubvv%@vendor/phpstan/php-8-stubs/stubs/ext/standard/array_combine.stubEEc`Evendor/phpstan/php-8-stubs/stubs/ext/standard/array_count_values.stub<<2N=vendor/phpstan/php-8-stubs/stubs/ext/standard/array_diff.stubFFCCvendor/phpstan/php-8-stubs/stubs/ext/standard/array_diff_assoc.stubLLBAvendor/phpstan/php-8-stubs/stubs/ext/standard/array_diff_key.stubJJ=+Dvendor/phpstan/php-8-stubs/stubs/ext/standard/array_diff_uassoc.stubhhBvendor/phpstan/php-8-stubs/stubs/ext/standard/array_diff_ukey.stubff7 =vendor/phpstan/php-8-stubs/stubs/ext/standard/array_fill.stubRRˤBvendor/phpstan/php-8-stubs/stubs/ext/standard/array_fill_keys.stubFFm?vendor/phpstan/php-8-stubs/stubs/ext/standard/array_filter.stubaa=vendor/phpstan/php-8-stubs/stubs/ext/standard/array_find.stubYYn<Avendor/phpstan/php-8-stubs/stubs/ext/standard/array_find_key.stub]]x#>vendor/phpstan/php-8-stubs/stubs/ext/standard/array_first.stubddb=vendor/phpstan/php-8-stubs/stubs/ext/standard/array_flip.stub448Bvendor/phpstan/php-8-stubs/stubs/ext/standard/array_intersect.stubKK]Hvendor/phpstan/php-8-stubs/stubs/ext/standard/array_intersect_assoc.stubQQ³LFvendor/phpstan/php-8-stubs/stubs/ext/standard/array_intersect_key.stubOO 釤Ivendor/phpstan/php-8-stubs/stubs/ext/standard/array_intersect_uassoc.stubmm=:|Gvendor/phpstan/php-8-stubs/stubs/ext/standard/array_intersect_ukey.stubkk|@vendor/phpstan/php-8-stubs/stubs/ext/standard/array_is_list.stubGG8Cvendor/phpstan/php-8-stubs/stubs/ext/standard/array_key_exists.stub]]^2Bvendor/phpstan/php-8-stubs/stubs/ext/standard/array_key_first.stubCCHrʷAvendor/phpstan/php-8-stubs/stubs/ext/standard/array_key_last.stubBBs7=vendor/phpstan/php-8-stubs/stubs/ext/standard/array_keys.stubiiyp]Z=vendor/phpstan/php-8-stubs/stubs/ext/standard/array_last.stubcc,<vendor/phpstan/php-8-stubs/stubs/ext/standard/array_map.stubZZKcܤ>vendor/phpstan/php-8-stubs/stubs/ext/standard/array_merge.stub99dHvendor/phpstan/php-8-stubs/stubs/ext/standard/array_merge_recursive.stubCC<Bvendor/phpstan/php-8-stubs/stubs/ext/standard/array_multisort.stub__ѓ<vendor/phpstan/php-8-stubs/stubs/ext/standard/array_pad.stubNN{~ <vendor/phpstan/php-8-stubs/stubs/ext/standard/array_pop.stub44mߤ@vendor/phpstan/php-8-stubs/stubs/ext/standard/array_product.stub;;q-=vendor/phpstan/php-8-stubs/stubs/ext/standard/array_push.stubSS^;=vendor/phpstan/php-8-stubs/stubs/ext/standard/array_rand.stubMMBQ?vendor/phpstan/php-8-stubs/stubs/ext/standard/array_reduce.stubaa A@vendor/phpstan/php-8-stubs/stubs/ext/standard/array_replace.stubOO|7cJvendor/phpstan/php-8-stubs/stubs/ext/standard/array_replace_recursive.stubYY>Y@vendor/phpstan/php-8-stubs/stubs/ext/standard/array_reverse.stubTT¼)0?vendor/phpstan/php-8-stubs/stubs/ext/standard/array_search.stubiiai>vendor/phpstan/php-8-stubs/stubs/ext/standard/array_shift.stub660S>vendor/phpstan/php-8-stubs/stubs/ext/standard/array_slice.stubtt?vendor/phpstan/php-8-stubs/stubs/ext/standard/array_splice.stubrrÝ5<vendor/phpstan/php-8-stubs/stubs/ext/standard/array_sum.stub77̮>vendor/phpstan/php-8-stubs/stubs/ext/standard/array_udiff.stubbbKDvendor/phpstan/php-8-stubs/stubs/ext/standard/array_udiff_assoc.stubhhPjEvendor/phpstan/php-8-stubs/stubs/ext/standard/array_udiff_uassoc.stubiiBJӤCvendor/phpstan/php-8-stubs/stubs/ext/standard/array_uintersect.stubggVśIvendor/phpstan/php-8-stubs/stubs/ext/standard/array_uintersect_assoc.stubmmM)wJvendor/phpstan/php-8-stubs/stubs/ext/standard/array_uintersect_uassoc.stubnn?vendor/phpstan/php-8-stubs/stubs/ext/standard/array_unique.stubPP|3J@vendor/phpstan/php-8-stubs/stubs/ext/standard/array_unshift.stubHHb`?vendor/phpstan/php-8-stubs/stubs/ext/standard/array_values.stub66;h@=vendor/phpstan/php-8-stubs/stubs/ext/standard/array_walk.stubZGvendor/phpstan/php-8-stubs/stubs/ext/standard/array_walk_recursive.stubc29vendor/phpstan/php-8-stubs/stubs/ext/standard/arsort.stubD7vendor/phpstan/php-8-stubs/stubs/ext/standard/asin.stub,,+98vendor/phpstan/php-8-stubs/stubs/ext/standard/asinh.stub--ޤ8vendor/phpstan/php-8-stubs/stubs/ext/standard/asort.stubU!9vendor/phpstan/php-8-stubs/stubs/ext/standard/assert.stubxx͢MoAvendor/phpstan/php-8-stubs/stubs/ext/standard/assert_options.stub__X7vendor/phpstan/php-8-stubs/stubs/ext/standard/atan.stub,,ͤ8vendor/phpstan/php-8-stubs/stubs/ext/standard/atan2.stub55zA8vendor/phpstan/php-8-stubs/stubs/ext/standard/atanh.stub--OY@vendor/phpstan/php-8-stubs/stubs/ext/standard/base64_decode.stubVV5lQ@vendor/phpstan/php-8-stubs/stubs/ext/standard/base64_encode.stubII?vendor/phpstan/php-8-stubs/stubs/ext/standard/base_convert.stubTTY!t;vendor/phpstan/php-8-stubs/stubs/ext/standard/basename.stubHH]aפ:vendor/phpstan/php-8-stubs/stubs/ext/standard/bin2hex.stubCCFۤ9vendor/phpstan/php-8-stubs/stubs/ext/standard/bindec.stub==kXa:vendor/phpstan/php-8-stubs/stubs/ext/standard/boolval.stub00#AAvendor/phpstan/php-8-stubs/stubs/ext/standard/call_user_func.stubNNGvendor/phpstan/php-8-stubs/stubs/ext/standard/call_user_func_array.stubQQ+w7vendor/phpstan/php-8-stubs/stubs/ext/standard/ceil.stub00R>8vendor/phpstan/php-8-stubs/stubs/ext/standard/chdir.stub33{RQ=vendor/phpstan/php-8-stubs/stubs/ext/standard/checkdnsrr.stubkk8vendor/phpstan/php-8-stubs/stubs/ext/standard/chgrp.stubEE* 8vendor/phpstan/php-8-stubs/stubs/ext/standard/chmod.stubKK7vendor/phpstan/php-8-stubs/stubs/ext/standard/chop.stubkk8vendor/phpstan/php-8-stubs/stubs/ext/standard/chown.stubDDs6vendor/phpstan/php-8-stubs/stubs/ext/standard/chr.stub004n9vendor/phpstan/php-8-stubs/stubs/ext/standard/chroot.stubtt>vendor/phpstan/php-8-stubs/stubs/ext/standard/chunk_split.stubff-jAvendor/phpstan/php-8-stubs/stubs/ext/standard/clearstatcache.stubkk?;vendor/phpstan/php-8-stubs/stubs/ext/standard/closedir.stub__DyJ;vendor/phpstan/php-8-stubs/stubs/ext/standard/closelog.stubeeI:vendor/phpstan/php-8-stubs/stubs/ext/standard/compact.stubpRb>Bvendor/phpstan/php-8-stubs/stubs/ext/standard/config_get_hash.stub<<_n޶Evendor/phpstan/php-8-stubs/stubs/ext/standard/connection_aborted.stub..7Dvendor/phpstan/php-8-stubs/stubs/ext/standard/connection_status.stub--n ;vendor/phpstan/php-8-stubs/stubs/ext/standard/constant.stubJJk,Cvendor/phpstan/php-8-stubs/stubs/ext/standard/convert_uudecode.stubCC6bCvendor/phpstan/php-8-stubs/stubs/ext/standard/convert_uuencode.stubNN~7vendor/phpstan/php-8-stubs/stubs/ext/standard/copy.stubooK=6vendor/phpstan/php-8-stubs/stubs/ext/standard/cos.stub++YF*7vendor/phpstan/php-8-stubs/stubs/ext/standard/cosh.stub,,ge8vendor/phpstan/php-8-stubs/stubs/ext/standard/count.stubRRG>vendor/phpstan/php-8-stubs/stubs/ext/standard/count_chars.stubMM5֨y8vendor/phpstan/php-8-stubs/stubs/ext/standard/crc32.stub==@8vendor/phpstan/php-8-stubs/stubs/ext/standard/crypt.stubNN7:vendor/phpstan/php-8-stubs/stubs/ext/standard/current.stub88NrBvendor/phpstan/php-8-stubs/stubs/ext/standard/debug_zval_dump.stubJJd5͉9vendor/phpstan/php-8-stubs/stubs/ext/standard/decbin.stub--!K9vendor/phpstan/php-8-stubs/stubs/ext/standard/dechex.stub--•U9vendor/phpstan/php-8-stubs/stubs/ext/standard/decoct.stub--+:vendor/phpstan/php-8-stubs/stubs/ext/standard/deg2rad.stub//C~6vendor/phpstan/php-8-stubs/stubs/ext/standard/dir.stubss?:vendor/phpstan/php-8-stubs/stubs/ext/standard/dirname.stubCC!jФBvendor/phpstan/php-8-stubs/stubs/ext/standard/disk_free_space.stubDD,TCvendor/phpstan/php-8-stubs/stubs/ext/standard/disk_total_space.stubEEBx̤@vendor/phpstan/php-8-stubs/stubs/ext/standard/diskfreespace.stub``kK5vendor/phpstan/php-8-stubs/stubs/ext/standard/dl.stub99-U~Cvendor/phpstan/php-8-stubs/stubs/ext/standard/dns_check_record.stub=vendor/phpstan/php-8-stubs/stubs/ext/standard/dns_get_mx.stub%Avendor/phpstan/php-8-stubs/stubs/ext/standard/dns_get_record.stub.<vendor/phpstan/php-8-stubs/stubs/ext/standard/doubleval.stubJJg(6vendor/phpstan/php-8-stubs/stubs/ext/standard/end.stub55eCvendor/phpstan/php-8-stubs/stubs/ext/standard/error_clear_last.stub--sq8Avendor/phpstan/php-8-stubs/stubs/ext/standard/error_get_last.stub--PΤ<vendor/phpstan/php-8-stubs/stubs/ext/standard/error_log.stub-Avendor/phpstan/php-8-stubs/stubs/ext/standard/escapeshellarg.stub88 ܤAvendor/phpstan/php-8-stubs/stubs/ext/standard/escapeshellcmd.stub<<E-_7vendor/phpstan/php-8-stubs/stubs/ext/standard/exec.stub66vendor/phpstan/php-8-stubs/stubs/ext/standard/exp.stub++ۤ:vendor/phpstan/php-8-stubs/stubs/ext/standard/explode.stub``^8vendor/phpstan/php-8-stubs/stubs/ext/standard/expm1.stub--Bf:vendor/phpstan/php-8-stubs/stubs/ext/standard/extract.stub||f9vendor/phpstan/php-8-stubs/stubs/ext/standard/fclose.stubIIp|<vendor/phpstan/php-8-stubs/stubs/ext/standard/fdatasync.stub]]@7vendor/phpstan/php-8-stubs/stubs/ext/standard/fdiv.stub::]7vendor/phpstan/php-8-stubs/stubs/ext/standard/feof.stubGG=m9vendor/phpstan/php-8-stubs/stubs/ext/standard/fflush.stubIId$_`8vendor/phpstan/php-8-stubs/stubs/ext/standard/fgetc.stubPP̳kh:vendor/phpstan/php-8-stubs/stubs/ext/standard/fgetcsv.stubٰ8vendor/phpstan/php-8-stubs/stubs/ext/standard/fgets.stubeeπ27vendor/phpstan/php-8-stubs/stubs/ext/standard/file.stub~~84>vendor/phpstan/php-8-stubs/stubs/ext/standard/file_exists.stub88^,Dvendor/phpstan/php-8-stubs/stubs/ext/standard/file_get_contents.stubј7Dvendor/phpstan/php-8-stubs/stubs/ext/standard/file_put_contents.stub<vendor/phpstan/php-8-stubs/stubs/ext/standard/fileatime.stubLL|<vendor/phpstan/php-8-stubs/stubs/ext/standard/filectime.stub;;3<vendor/phpstan/php-8-stubs/stubs/ext/standard/filegroup.stub;;4<vendor/phpstan/php-8-stubs/stubs/ext/standard/fileinode.stub;;l6"M<vendor/phpstan/php-8-stubs/stubs/ext/standard/filemtime.stub;;S<vendor/phpstan/php-8-stubs/stubs/ext/standard/fileowner.stub;;Oh<vendor/phpstan/php-8-stubs/stubs/ext/standard/fileperms.stub;;F;vendor/phpstan/php-8-stubs/stubs/ext/standard/filesize.stub::;vendor/phpstan/php-8-stubs/stubs/ext/standard/filetype.stub==L;vendor/phpstan/php-8-stubs/stubs/ext/standard/floatval.stub2228vendor/phpstan/php-8-stubs/stubs/ext/standard/flock.stub)-&8vendor/phpstan/php-8-stubs/stubs/ext/standard/floor.stub11opZ8vendor/phpstan/php-8-stubs/stubs/ext/standard/flush.stub""E7vendor/phpstan/php-8-stubs/stubs/ext/standard/fmod.stub::"-:vendor/phpstan/php-8-stubs/stubs/ext/standard/fnmatch.stubiib8vendor/phpstan/php-8-stubs/stubs/ext/standard/fopen.stubFvendor/phpstan/php-8-stubs/stubs/ext/standard/forward_static_call.stubSSLvendor/phpstan/php-8-stubs/stubs/ext/standard/forward_static_call_array.stubVVq;<vendor/phpstan/php-8-stubs/stubs/ext/standard/fpassthru.stubKK7vendor/phpstan/php-8-stubs/stubs/ext/standard/fpow.stubll`\:vendor/phpstan/php-8-stubs/stubs/ext/standard/fprintf.stubkkU:vendor/phpstan/php-8-stubs/stubs/ext/standard/fputcsv.stub^@"8vendor/phpstan/php-8-stubs/stubs/ext/standard/fputs.stub' r8vendor/phpstan/php-8-stubs/stubs/ext/standard/fread.stub]]kO9vendor/phpstan/php-8-stubs/stubs/ext/standard/fscanf.stubzz8vendor/phpstan/php-8-stubs/stubs/ext/standard/fseek.stubll<vendor/phpstan/php-8-stubs/stubs/ext/standard/fsockopen.stub/A8vendor/phpstan/php-8-stubs/stubs/ext/standard/fstat.stubOOa8vendor/phpstan/php-8-stubs/stubs/ext/standard/fsync.stubYY+ 8vendor/phpstan/php-8-stubs/stubs/ext/standard/ftell.stubMMT47vendor/phpstan/php-8-stubs/stubs/ext/standard/ftok.stubff/'<vendor/phpstan/php-8-stubs/stubs/ext/standard/ftruncate.stubWWӌӣ9vendor/phpstan/php-8-stubs/stubs/ext/standard/fwrite.stubqq>vendor/phpstan/php-8-stubs/stubs/ext/standard/get_browser.stub K>vendor/phpstan/php-8-stubs/stubs/ext/standard/get_cfg_var.stubDDACvendor/phpstan/php-8-stubs/stubs/ext/standard/get_current_user.stub66RAvendor/phpstan/php-8-stubs/stubs/ext/standard/get_debug_type.stub991&D>vendor/phpstan/php-8-stubs/stubs/ext/standard/get_headers.stub+,Mvendor/phpstan/php-8-stubs/stubs/ext/standard/get_html_translation_table.stubiCvendor/phpstan/php-8-stubs/stubs/ext/standard/get_include_path.stub55ha@vendor/phpstan/php-8-stubs/stubs/ext/standard/get_meta_tags.stubaak|.9vendor/phpstan/php-8-stubs/stubs/ext/standard/getcwd.stub2288Ǥ9vendor/phpstan/php-8-stubs/stubs/ext/standard/getenv.stub__sJY@vendor/phpstan/php-8-stubs/stubs/ext/standard/gethostbyaddr.stubCC@vendor/phpstan/php-8-stubs/stubs/ext/standard/gethostbyname.stub<<?NAvendor/phpstan/php-8-stubs/stubs/ext/standard/gethostbynamel.stubBB2X8I>vendor/phpstan/php-8-stubs/stubs/ext/standard/gethostname.stub[[1)?vendor/phpstan/php-8-stubs/stubs/ext/standard/getimagesize.stubuu;*Ivendor/phpstan/php-8-stubs/stubs/ext/standard/getimagesizefromstring.stub}}Q.$}=vendor/phpstan/php-8-stubs/stubs/ext/standard/getlastmod.stub,,Ӥ:vendor/phpstan/php-8-stubs/stubs/ext/standard/getmxrr.stub~ߤ;vendor/phpstan/php-8-stubs/stubs/ext/standard/getmygid.stub**5=vendor/phpstan/php-8-stubs/stubs/ext/standard/getmyinode.stub,,$h;vendor/phpstan/php-8-stubs/stubs/ext/standard/getmypid.stub**o4;vendor/phpstan/php-8-stubs/stubs/ext/standard/getmyuid.stub;;4G 9vendor/phpstan/php-8-stubs/stubs/ext/standard/getopt.stub04P7Avendor/phpstan/php-8-stubs/stubs/ext/standard/getprotobyname.stub__qCvendor/phpstan/php-8-stubs/stubs/ext/standard/getprotobynumber.stubcc=vendor/phpstan/php-8-stubs/stubs/ext/standard/getrandmax.stubBBla<vendor/phpstan/php-8-stubs/stubs/ext/standard/getrusage.stubWWF?@vendor/phpstan/php-8-stubs/stubs/ext/standard/getservbyname.stubgg@vendor/phpstan/php-8-stubs/stubs/ext/standard/getservbyport.stubkkFW?vendor/phpstan/php-8-stubs/stubs/ext/standard/gettimeofday.stubFFJơ:vendor/phpstan/php-8-stubs/stubs/ext/standard/gettype.stubFF_7vendor/phpstan/php-8-stubs/stubs/ext/standard/glob.stubXX e9vendor/phpstan/php-8-stubs/stubs/ext/standard/header.stubpp7^Kvendor/phpstan/php-8-stubs/stubs/ext/standard/header_register_callback.stubYYq&@vendor/phpstan/php-8-stubs/stubs/ext/standard/header_remove.stub>>}?vendor/phpstan/php-8-stubs/stubs/ext/standard/headers_list.stub**\?vendor/phpstan/php-8-stubs/stubs/ext/standard/headers_sent.stubH9vendor/phpstan/php-8-stubs/stubs/ext/standard/hebrev.stubPPJ=I:vendor/phpstan/php-8-stubs/stubs/ext/standard/hex2bin.stub::@Q\19vendor/phpstan/php-8-stubs/stubs/ext/standard/hexdec.stub::ATAvendor/phpstan/php-8-stubs/stubs/ext/standard/highlight_file.stubXXH:Cvendor/phpstan/php-8-stubs/stubs/ext/standard/highlight_string.stubkb9vendor/phpstan/php-8-stubs/stubs/ext/standard/hrtime.stubaa2 Evendor/phpstan/php-8-stubs/stubs/ext/standard/html_entity_decode.stubR{?vendor/phpstan/php-8-stubs/stubs/ext/standard/htmlentities.stub]]Ri~Cvendor/phpstan/php-8-stubs/stubs/ext/standard/htmlspecialchars.stubW֤Jvendor/phpstan/php-8-stubs/stubs/ext/standard/htmlspecialchars_decode.stub+Cvendor/phpstan/php-8-stubs/stubs/ext/standard/http_build_query.stubSvendor/phpstan/php-8-stubs/stubs/ext/standard/http_clear_last_response_headers.stubNNA#Qvendor/phpstan/php-8-stubs/stubs/ext/standard/http_get_last_response_headers.stubNN=ĤEvendor/phpstan/php-8-stubs/stubs/ext/standard/http_response_code.stubIIyg 8vendor/phpstan/php-8-stubs/stubs/ext/standard/hypot.stub55(4Dvendor/phpstan/php-8-stubs/stubs/ext/standard/ignore_user_abort.stubAAJvendor/phpstan/php-8-stubs/stubs/ext/standard/image_type_to_extension.stubeecJvendor/phpstan/php-8-stubs/stubs/ext/standard/image_type_to_mime_type.stubSS1{Τ:vendor/phpstan/php-8-stubs/stubs/ext/standard/implode.stubSSq?V;vendor/phpstan/php-8-stubs/stubs/ext/standard/in_array.stubYY(1ä<vendor/phpstan/php-8-stubs/stubs/ext/standard/inet_ntop.stubUUYt٤<vendor/phpstan/php-8-stubs/stubs/ext/standard/inet_pton.stubUUɔ<vendor/phpstan/php-8-stubs/stubs/ext/standard/ini_alter.stubg}٤:vendor/phpstan/php-8-stubs/stubs/ext/standard/ini_get.stub::>vendor/phpstan/php-8-stubs/stubs/ext/standard/ini_get_all.stub^^˪]FEvendor/phpstan/php-8-stubs/stubs/ext/standard/ini_parse_quantity.stubPP3 >vendor/phpstan/php-8-stubs/stubs/ext/standard/ini_restore.stub66ik:vendor/phpstan/php-8-stubs/stubs/ext/standard/ini_set.stubP9vendor/phpstan/php-8-stubs/stubs/ext/standard/intdiv.stub66]aФ9vendor/phpstan/php-8-stubs/stubs/ext/standard/intval.stub>>Y:vendor/phpstan/php-8-stubs/stubs/ext/standard/ip2long.stub33<vendor/phpstan/php-8-stubs/stubs/ext/standard/iptcembed.stubmm/*<vendor/phpstan/php-8-stubs/stubs/ext/standard/iptcparse.stub??#S;vendor/phpstan/php-8-stubs/stubs/ext/standard/is_array.stub11曤:vendor/phpstan/php-8-stubs/stubs/ext/standard/is_bool.stub00>vendor/phpstan/php-8-stubs/stubs/ext/standard/is_callable.stub(?vendor/phpstan/php-8-stubs/stubs/ext/standard/is_countable.stub55s9vendor/phpstan/php-8-stubs/stubs/ext/standard/is_dir.stub33<vendor/phpstan/php-8-stubs/stubs/ext/standard/is_double.stubII@vendor/phpstan/php-8-stubs/stubs/ext/standard/is_executable.stub::Hp:vendor/phpstan/php-8-stubs/stubs/ext/standard/is_file.stub44J<vendor/phpstan/php-8-stubs/stubs/ext/standard/is_finite.stub00Ar;vendor/phpstan/php-8-stubs/stubs/ext/standard/is_float.stub11ʛ>vendor/phpstan/php-8-stubs/stubs/ext/standard/is_infinite.stub22ko9vendor/phpstan/php-8-stubs/stubs/ext/standard/is_int.stub//^=vendor/phpstan/php-8-stubs/stubs/ext/standard/is_integer.stubHH >vendor/phpstan/php-8-stubs/stubs/ext/standard/is_iterable.stub448ŝ:vendor/phpstan/php-8-stubs/stubs/ext/standard/is_link.stub44:vendor/phpstan/php-8-stubs/stubs/ext/standard/is_long.stubEEH9vendor/phpstan/php-8-stubs/stubs/ext/standard/is_nan.stub--#":vendor/phpstan/php-8-stubs/stubs/ext/standard/is_null.stub00E8=vendor/phpstan/php-8-stubs/stubs/ext/standard/is_numeric.stub33r<vendor/phpstan/php-8-stubs/stubs/ext/standard/is_object.stub22*j>vendor/phpstan/php-8-stubs/stubs/ext/standard/is_readable.stub88[Kz>vendor/phpstan/php-8-stubs/stubs/ext/standard/is_resource.stub44U<vendor/phpstan/php-8-stubs/stubs/ext/standard/is_scalar.stub222m<vendor/phpstan/php-8-stubs/stubs/ext/standard/is_string.stub22xCvendor/phpstan/php-8-stubs/stubs/ext/standard/is_uploaded_file.stub==Էr2>vendor/phpstan/php-8-stubs/stubs/ext/standard/is_writable.stub88b?vendor/phpstan/php-8-stubs/stubs/ext/standard/is_writeable.stubSS7vendor/phpstan/php-8-stubs/stubs/ext/standard/join.stubffa)6vendor/phpstan/php-8-stubs/stubs/ext/standard/key.stub>>{ܠ=vendor/phpstan/php-8-stubs/stubs/ext/standard/key_exists.stubvv@);9vendor/phpstan/php-8-stubs/stubs/ext/standard/krsort.stubbK8vendor/phpstan/php-8-stubs/stubs/ext/standard/ksort.stubUf:vendor/phpstan/php-8-stubs/stubs/ext/standard/lcfirst.stub44 ,<vendor/phpstan/php-8-stubs/stubs/ext/standard/lcg_value.stub33r*9vendor/phpstan/php-8-stubs/stubs/ext/standard/lchgrp.stubFFa;9vendor/phpstan/php-8-stubs/stubs/ext/standard/lchown.stubUUY>vendor/phpstan/php-8-stubs/stubs/ext/standard/levenshtein.stub7vendor/phpstan/php-8-stubs/stubs/ext/standard/link.stub== ;vendor/phpstan/php-8-stubs/stubs/ext/standard/linkinfo.stub66ݍ=vendor/phpstan/php-8-stubs/stubs/ext/standard/localeconv.stub((7&~6vendor/phpstan/php-8-stubs/stubs/ext/standard/log.stub>>G8vendor/phpstan/php-8-stubs/stubs/ext/standard/log10.stub--nɤ8vendor/phpstan/php-8-stubs/stubs/ext/standard/log1p.stub--`9:vendor/phpstan/php-8-stubs/stubs/ext/standard/long2ip.stubQ8vendor/phpstan/php-8-stubs/stubs/ext/standard/lstat.stub99-8vendor/phpstan/php-8-stubs/stubs/ext/standard/ltrim.stubXX;-7vendor/phpstan/php-8-stubs/stubs/ext/standard/mail.stubfc6vendor/phpstan/php-8-stubs/stubs/ext/standard/max.stub??6vendor/phpstan/php-8-stubs/stubs/ext/standard/md5.stubRR);vendor/phpstan/php-8-stubs/stubs/ext/standard/md5_file.stubSS&ۤHvendor/phpstan/php-8-stubs/stubs/ext/standard/memory_get_peak_usage.stubII)*Cvendor/phpstan/php-8-stubs/stubs/ext/standard/memory_get_usage.stubDDENJvendor/phpstan/php-8-stubs/stubs/ext/standard/memory_reset_peak_usage.stubEE4?<vendor/phpstan/php-8-stubs/stubs/ext/standard/metaphone.stubffФ<vendor/phpstan/php-8-stubs/stubs/ext/standard/microtime.stuboooĕ6vendor/phpstan/php-8-stubs/stubs/ext/standard/min.stub??Ԥ8vendor/phpstan/php-8-stubs/stubs/ext/standard/mkdir.stub Evendor/phpstan/php-8-stubs/stubs/ext/standard/move_uploaded_file.stubGGU*@vendor/phpstan/php-8-stubs/stubs/ext/standard/mt_getrandmax.stub))ag:vendor/phpstan/php-8-stubs/stubs/ext/standard/mt_rand.stubII:;vendor/phpstan/php-8-stubs/stubs/ext/standard/mt_srand.stub'>vendor/phpstan/php-8-stubs/stubs/ext/standard/natcasesort.stubAi:vendor/phpstan/php-8-stubs/stubs/ext/standard/natsort.stub}}*#Evendor/phpstan/php-8-stubs/stubs/ext/standard/net_get_interfaces.stubt17vendor/phpstan/php-8-stubs/stubs/ext/standard/next.stub66UP8vendor/phpstan/php-8-stubs/stubs/ext/standard/nl2br.stubJJ;WtB>vendor/phpstan/php-8-stubs/stubs/ext/standard/nl_langinfo.stubNNR?vendor/phpstan/php-8-stubs/stubs/ext/standard/ob_get_flush.stub11x@vendor/phpstan/php-8-stubs/stubs/ext/standard/ob_get_length.stub// ם?vendor/phpstan/php-8-stubs/stubs/ext/standard/ob_get_level.stub((y,@vendor/phpstan/php-8-stubs/stubs/ext/standard/ob_get_status.stubDD< Dvendor/phpstan/php-8-stubs/stubs/ext/standard/ob_implicit_flush.stubAACvendor/phpstan/php-8-stubs/stubs/ext/standard/ob_list_handlers.stub..I1;vendor/phpstan/php-8-stubs/stubs/ext/standard/ob_start.stubrrzv9vendor/phpstan/php-8-stubs/stubs/ext/standard/octdec.stub<<9:vendor/phpstan/php-8-stubs/stubs/ext/standard/opendir.stub#`r:vendor/phpstan/php-8-stubs/stubs/ext/standard/openlog.stub&r`6vendor/phpstan/php-8-stubs/stubs/ext/standard/ord.stub002a/Ivendor/phpstan/php-8-stubs/stubs/ext/standard/output_add_rewrite_var.stubNN]4Lvendor/phpstan/php-8-stubs/stubs/ext/standard/output_reset_rewrite_vars.stub667vendor/phpstan/php-8-stubs/stubs/ext/standard/pack.stubWW1ݤAvendor/phpstan/php-8-stubs/stubs/ext/standard/parse_ini_file.stubwZCvendor/phpstan/php-8-stubs/stubs/ext/standard/parse_ini_string.stubפ<vendor/phpstan/php-8-stubs/stubs/ext/standard/parse_str.stubZZȇPI<vendor/phpstan/php-8-stubs/stubs/ext/standard/parse_url.stubpp|3;vendor/phpstan/php-8-stubs/stubs/ext/standard/passthru.stubu?Avendor/phpstan/php-8-stubs/stubs/ext/standard/password_algos.stub,,פDvendor/phpstan/php-8-stubs/stubs/ext/standard/password_get_info.stubLL5Cͤ@vendor/phpstan/php-8-stubs/stubs/ext/standard/password_hash.stubhh4YHvendor/phpstan/php-8-stubs/stubs/ext/standard/password_needs_rehash.stubjj7OBvendor/phpstan/php-8-stubs/stubs/ext/standard/password_verify.stubJJ;vendor/phpstan/php-8-stubs/stubs/ext/standard/pathinfo.stubTT}˚+9vendor/phpstan/php-8-stubs/stubs/ext/standard/pclose.stubHH=t=vendor/phpstan/php-8-stubs/stubs/ext/standard/pfsockopen.stub{[hFvendor/phpstan/php-8-stubs/stubs/ext/standard/php_ini_loaded_file.stub880 Hvendor/phpstan/php-8-stubs/stubs/ext/standard/php_ini_scanned_files.stub::We@vendor/phpstan/php-8-stubs/stubs/ext/standard/php_sapi_name.stub22YGvendor/phpstan/php-8-stubs/stubs/ext/standard/php_strip_whitespace.stubCC%`<vendor/phpstan/php-8-stubs/stubs/ext/standard/php_uname.stub::Bvendor/phpstan/php-8-stubs/stubs/ext/standard/php_user_filter.stubb@k=vendor/phpstan/php-8-stubs/stubs/ext/standard/phpcredits.stub :vendor/phpstan/php-8-stubs/stubs/ext/standard/phpinfo.stubÒӤ=vendor/phpstan/php-8-stubs/stubs/ext/standard/phpversion.stubHHL5vendor/phpstan/php-8-stubs/stubs/ext/standard/pi.stub _loͤ8vendor/phpstan/php-8-stubs/stubs/ext/standard/popen.stubWWo.6vendor/phpstan/php-8-stubs/stubs/ext/standard/pos.stubJJ6vendor/phpstan/php-8-stubs/stubs/ext/standard/pow.stubGG\4Ϥ7vendor/phpstan/php-8-stubs/stubs/ext/standard/prev.stub66l:vendor/phpstan/php-8-stubs/stubs/ext/standard/print_r.stub"N9vendor/phpstan/php-8-stubs/stubs/ext/standard/printf.stubBB(=vendor/phpstan/php-8-stubs/stubs/ext/standard/proc_close.stubNNמBvendor/phpstan/php-8-stubs/stubs/ext/standard/proc_get_status.stubUU%'<vendor/phpstan/php-8-stubs/stubs/ext/standard/proc_nice.stubDD<vendor/phpstan/php-8-stubs/stubs/ext/standard/proc_open.stub Avendor/phpstan/php-8-stubs/stubs/ext/standard/proc_terminate.stubeeuO9vendor/phpstan/php-8-stubs/stubs/ext/standard/putenv.stubHH+VJvendor/phpstan/php-8-stubs/stubs/ext/standard/quoted_printable_decode.stub^^nJvendor/phpstan/php-8-stubs/stubs/ext/standard/quoted_printable_encode.stubDD0,<vendor/phpstan/php-8-stubs/stubs/ext/standard/quotemeta.stub66V :vendor/phpstan/php-8-stubs/stubs/ext/standard/rad2deg.stub//dO-7vendor/phpstan/php-8-stubs/stubs/ext/standard/rand.stubFF?vendor/phpstan/php-8-stubs/stubs/ext/standard/random_bytes.stubEEO=vendor/phpstan/php-8-stubs/stubs/ext/standard/random_int.stub88#s8vendor/phpstan/php-8-stubs/stubs/ext/standard/range.stubj%>?vendor/phpstan/php-8-stubs/stubs/ext/standard/rawurldecode.stub996?vendor/phpstan/php-8-stubs/stubs/ext/standard/rawurlencode.stub99:vendor/phpstan/php-8-stubs/stubs/ext/standard/readdir.stubff97;vendor/phpstan/php-8-stubs/stubs/ext/standard/readfile.stub;vendor/phpstan/php-8-stubs/stubs/ext/standard/readlink.stubvvHP;vendor/phpstan/php-8-stubs/stubs/ext/standard/realpath.stub99/'~Evendor/phpstan/php-8-stubs/stubs/ext/standard/realpath_cache_get.stub00դFvendor/phpstan/php-8-stubs/stubs/ext/standard/realpath_cache_size.stub//zlMvendor/phpstan/php-8-stubs/stubs/ext/standard/register_shutdown_function.stubJKIvendor/phpstan/php-8-stubs/stubs/ext/standard/register_tick_function.stub\\n(9vendor/phpstan/php-8-stubs/stubs/ext/standard/rename.stubqqEvendor/phpstan/php-8-stubs/stubs/ext/standard/request_parse_body.stub[+8vendor/phpstan/php-8-stubs/stubs/ext/standard/reset.stub77?_9vendor/phpstan/php-8-stubs/stubs/ext/standard/rewind.stubIIBӐ<vendor/phpstan/php-8-stubs/stubs/ext/standard/rewinddir.stub``=8vendor/phpstan/php-8-stubs/stubs/ext/standard/rmdir.stubiipO#8vendor/phpstan/php-8-stubs/stubs/ext/standard/round.stubp|mq8vendor/phpstan/php-8-stubs/stubs/ext/standard/rsort.stub1>\E8vendor/phpstan/php-8-stubs/stubs/ext/standard/rtrim.stubXXt15Gvendor/phpstan/php-8-stubs/stubs/ext/standard/sapi_windows_cp_conv.stubvvI]Fvendor/phpstan/php-8-stubs/stubs/ext/standard/sapi_windows_cp_get.stub@@9Jvendor/phpstan/php-8-stubs/stubs/ext/standard/sapi_windows_cp_is_utf8.stub44VЋFvendor/phpstan/php-8-stubs/stubs/ext/standard/sapi_windows_cp_set.stubeeNv[Svendor/phpstan/php-8-stubs/stubs/ext/standard/sapi_windows_generate_ctrl_event.stubUU`Pvendor/phpstan/php-8-stubs/stubs/ext/standard/sapi_windows_set_ctrl_handler.stub^^|Mvendor/phpstan/php-8-stubs/stubs/ext/standard/sapi_windows_vt100_support.stub?:vendor/phpstan/php-8-stubs/stubs/ext/standard/scandir.stubT<vendor/phpstan/php-8-stubs/stubs/ext/standard/serialize.stub44פBvendor/phpstan/php-8-stubs/stubs/ext/standard/set_file_buffer.stubOKCvendor/phpstan/php-8-stubs/stubs/ext/standard/set_include_path.stubIIAvendor/phpstan/php-8-stubs/stubs/ext/standard/set_time_limit.stubkk,mz<vendor/phpstan/php-8-stubs/stubs/ext/standard/setcookie.stubN~<vendor/phpstan/php-8-stubs/stubs/ext/standard/setlocale.stubAAz?vendor/phpstan/php-8-stubs/stubs/ext/standard/setrawcookie.stub$؃:vendor/phpstan/php-8-stubs/stubs/ext/standard/settype.stub==7vendor/phpstan/php-8-stubs/stubs/ext/standard/sha1.stubTT ¤<vendor/phpstan/php-8-stubs/stubs/ext/standard/sha1_file.stubTTdEW"=vendor/phpstan/php-8-stubs/stubs/ext/standard/shell_exec.stubCCW>vendor/phpstan/php-8-stubs/stubs/ext/standard/show_source.stubrrv6:vendor/phpstan/php-8-stubs/stubs/ext/standard/shuffle.stub}}ʓc~?vendor/phpstan/php-8-stubs/stubs/ext/standard/similar_text.stubww<6vendor/phpstan/php-8-stubs/stubs/ext/standard/sin.stub++֊7vendor/phpstan/php-8-stubs/stubs/ext/standard/sinh.stub,,+.9vendor/phpstan/php-8-stubs/stubs/ext/standard/sizeof.stubggD8vendor/phpstan/php-8-stubs/stubs/ext/standard/sleep.stub--3cLDvendor/phpstan/php-8-stubs/stubs/ext/standard/socket_get_status.stubxxդFvendor/phpstan/php-8-stubs/stubs/ext/standard/socket_set_blocking.stub @~Evendor/phpstan/php-8-stubs/stubs/ext/standard/socket_set_timeout.stubl7vendor/phpstan/php-8-stubs/stubs/ext/standard/sort.stub(vY:vendor/phpstan/php-8-stubs/stubs/ext/standard/soundex.stubDD+/D:vendor/phpstan/php-8-stubs/stubs/ext/standard/sprintf.stub^^S7vendor/phpstan/php-8-stubs/stubs/ext/standard/sqrt.stub,,8vendor/phpstan/php-8-stubs/stubs/ext/standard/srand.stubv N9vendor/phpstan/php-8-stubs/stubs/ext/standard/sscanf.stub\\?%7vendor/phpstan/php-8-stubs/stubs/ext/standard/stat.stub88*Z?vendor/phpstan/php-8-stubs/stubs/ext/standard/str_contains.stubIIi:3ˤ@vendor/phpstan/php-8-stubs/stubs/ext/standard/str_decrement.stubKKzR@vendor/phpstan/php-8-stubs/stubs/ext/standard/str_ends_with.stubJJJO=vendor/phpstan/php-8-stubs/stubs/ext/standard/str_getcsv.stubsܨ@vendor/phpstan/php-8-stubs/stubs/ext/standard/str_increment.stubKKt?vendor/phpstan/php-8-stubs/stubs/ext/standard/str_ireplace.stubfi֤:vendor/phpstan/php-8-stubs/stubs/ext/standard/str_pad.stubzze!=vendor/phpstan/php-8-stubs/stubs/ext/standard/str_repeat.stubCC+>vendor/phpstan/php-8-stubs/stubs/ext/standard/str_replace.stubp<vendor/phpstan/php-8-stubs/stubs/ext/standard/str_rot13.stub66谛;>vendor/phpstan/php-8-stubs/stubs/ext/standard/str_shuffle.stub887j<vendor/phpstan/php-8-stubs/stubs/ext/standard/str_split.stubFF& Bvendor/phpstan/php-8-stubs/stubs/ext/standard/str_starts_with.stubLLYAvendor/phpstan/php-8-stubs/stubs/ext/standard/str_word_count.stubkkU9vendor/phpstan/php-8-stubs/stubs/ext/standard/strchr.stub}}F:vendor/phpstan/php-8-stubs/stubs/ext/standard/strcoll.stubJJ0:vendor/phpstan/php-8-stubs/stubs/ext/standard/strcspn.stubkk~Gvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_bucket_append.stubkOvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_bucket_make_writeable.stub''PΤDvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_bucket_new.stub6놞Hvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_bucket_prepend.stubqmHvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_context_create.stubqqR5RMvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_context_get_default.stub__׬ؤMvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_context_get_options.stubttu콤Lvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_context_get_params.stub__{n'Mvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_context_set_default.stubWWDLvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_context_set_option.stubK Mvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_context_set_options.stub  'hĤLvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_context_set_params.stub9<Hvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_copy_to_stream.stub?KGvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_filter_append.stub;Hvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_filter_prepend.stub)Ivendor/phpstan/php-8-stubs/stubs/ext/standard/stream_filter_register.stubUU-nGvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_filter_remove.stubee8m%Fvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_get_contents.stub0$Evendor/phpstan/php-8-stubs/stubs/ext/standard/stream_get_filters.stub00+2Bvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_get_line.stub||Gvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_get_meta_data.stubXXB؂Hvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_get_transports.stub33NFvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_get_wrappers.stub11[ͤBvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_is_local.stubYYI(Ѥ@vendor/phpstan/php-8-stubs/stubs/ext/standard/stream_isatty.stubPPkJvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_register_wrapper.stubENvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_resolve_include_path.stubPP'F^@vendor/phpstan/php-8-stubs/stubs/ext/standard/stream_select.stubOOݤFvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_set_blocking.stubdduHvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_set_chunk_size.stubii@)Ivendor/phpstan/php-8-stubs/stubs/ext/standard/stream_set_read_buffer.stubccmEvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_set_timeout.stubiهJvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_set_write_buffer.stubddGvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_accept.stub(_Gvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_client.stub11sxNvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_enable_crypto.stub|j"Ivendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_get_name.stuboo QQEvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_pair.stubvv/!rIvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_recvfrom.stubUq5$Gvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_sendto.stubgGvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_server.stub--gYIvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_shutdown.stubyy" Gvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_supports_lock.stubWWx ĤJvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_wrapper_register.stubK$Ivendor/phpstan/php-8-stubs/stubs/ext/standard/stream_wrapper_restore.stubCCAeLvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_wrapper_unregister.stubFFy=vendor/phpstan/php-8-stubs/stubs/ext/standard/strip_tags.stub__f@vendor/phpstan/php-8-stubs/stubs/ext/standard/stripcslashes.stub::N_X:vendor/phpstan/php-8-stubs/stubs/ext/standard/stripos.stubZZBSAѤ?vendor/phpstan/php-8-stubs/stubs/ext/standard/stripslashes.stub99m:vendor/phpstan/php-8-stubs/stubs/ext/standard/stristr.stubiiOz@vendor/phpstan/php-8-stubs/stubs/ext/standard/strnatcasecmp.stubIIA_'<vendor/phpstan/php-8-stubs/stubs/ext/standard/strnatcmp.stubEEhL:vendor/phpstan/php-8-stubs/stubs/ext/standard/strpbrk.stubNNKݤ9vendor/phpstan/php-8-stubs/stubs/ext/standard/strpos.stubYYO?;vendor/phpstan/php-8-stubs/stubs/ext/standard/strptime.stubĩ1:vendor/phpstan/php-8-stubs/stubs/ext/standard/strrchr.stub v9vendor/phpstan/php-8-stubs/stubs/ext/standard/strrev.stub33;vendor/phpstan/php-8-stubs/stubs/ext/standard/strripos.stub[[Ҥ:vendor/phpstan/php-8-stubs/stubs/ext/standard/strrpos.stubZZG} 9vendor/phpstan/php-8-stubs/stubs/ext/standard/strspn.stubjjx9vendor/phpstan/php-8-stubs/stubs/ext/standard/strstr.stubhh<9vendor/phpstan/php-8-stubs/stubs/ext/standard/strtok.stubPPGL=vendor/phpstan/php-8-stubs/stubs/ext/standard/strtolower.stub77=vendor/phpstan/php-8-stubs/stubs/ext/standard/strtoupper.stub779Z+8vendor/phpstan/php-8-stubs/stubs/ext/standard/strtr.stubZZ<9vendor/phpstan/php-8-stubs/stubs/ext/standard/strval.stub119vendor/phpstan/php-8-stubs/stubs/ext/standard/substr.stubUUE#Avendor/phpstan/php-8-stubs/stubs/ext/standard/substr_compare.stubИG?vendor/phpstan/php-8-stubs/stubs/ext/standard/substr_count.stubnnHAvendor/phpstan/php-8-stubs/stubs/ext/standard/substr_replace.stub'7ʤ:vendor/phpstan/php-8-stubs/stubs/ext/standard/symlink.stub@@/jCvendor/phpstan/php-8-stubs/stubs/ext/standard/sys_get_temp_dir.stub66QqAvendor/phpstan/php-8-stubs/stubs/ext/standard/sys_getloadavg.stubPPⰥ9vendor/phpstan/php-8-stubs/stubs/ext/standard/syslog.stubx9vendor/phpstan/php-8-stubs/stubs/ext/standard/system.stuboo7қ6vendor/phpstan/php-8-stubs/stubs/ext/standard/tan.stub++*>BZ7vendor/phpstan/php-8-stubs/stubs/ext/standard/tanh.stub,,ש:vendor/phpstan/php-8-stubs/stubs/ext/standard/tempnam.stubMM>{$Avendor/phpstan/php-8-stubs/stubs/ext/standard/time_nanosleep.stubbbICvendor/phpstan/php-8-stubs/stubs/ext/standard/time_sleep_until.stub==hE:vendor/phpstan/php-8-stubs/stubs/ext/standard/tmpfile.stub<<?8vendor/phpstan/php-8-stubs/stubs/ext/standard/touch.stubiiA7vendor/phpstan/php-8-stubs/stubs/ext/standard/trim.stubWW+9vendor/phpstan/php-8-stubs/stubs/ext/standard/uasort.stubVnH:vendor/phpstan/php-8-stubs/stubs/ext/standard/ucfirst.stub44 ܤ:vendor/phpstan/php-8-stubs/stubs/ext/standard/ucwords.stubXX|Τ9vendor/phpstan/php-8-stubs/stubs/ext/standard/uksort.stubDĄ8vendor/phpstan/php-8-stubs/stubs/ext/standard/umask.stub22&M9vendor/phpstan/php-8-stubs/stubs/ext/standard/uniqid.stub||=79vendor/phpstan/php-8-stubs/stubs/ext/standard/unlink.stubiiȤ9vendor/phpstan/php-8-stubs/stubs/ext/standard/unpack.stubYY|NKvendor/phpstan/php-8-stubs/stubs/ext/standard/unregister_tick_function.stubGG{5>vendor/phpstan/php-8-stubs/stubs/ext/standard/unserialize.stubJJɒ<vendor/phpstan/php-8-stubs/stubs/ext/standard/urldecode.stub66qv<vendor/phpstan/php-8-stubs/stubs/ext/standard/urlencode.stub66ze9vendor/phpstan/php-8-stubs/stubs/ext/standard/usleep.stub448vendor/phpstan/php-8-stubs/stubs/ext/standard/usort.stub>vendor/phpstan/php-8-stubs/stubs/ext/standard/utf8_decode.stubV>vendor/phpstan/php-8-stubs/stubs/ext/standard/utf8_encode.stub&#;vendor/phpstan/php-8-stubs/stubs/ext/standard/var_dump.stubOO}=vendor/phpstan/php-8-stubs/stubs/ext/standard/var_export.stubLLk\}Bvendor/phpstan/php-8-stubs/stubs/ext/standard/version_compare.stubZ5g;vendor/phpstan/php-8-stubs/stubs/ext/standard/vfprintf.stubiiAɤ:vendor/phpstan/php-8-stubs/stubs/ext/standard/vprintf.stub@@^A;vendor/phpstan/php-8-stubs/stubs/ext/standard/vsprintf.stubDD?c;vendor/phpstan/php-8-stubs/stubs/ext/standard/wordwrap.stubzzcEbBvendor/phpstan/php-8-stubs/stubs/ext/sysvmsg/SysvMessageQueue.stubJJ[6M?vendor/phpstan/php-8-stubs/stubs/ext/sysvmsg/msg_get_queue.stub^^+u.Bvendor/phpstan/php-8-stubs/stubs/ext/sysvmsg/msg_queue_exists.stub55zl=vendor/phpstan/php-8-stubs/stubs/ext/sysvmsg/msg_receive.stub""s-Bvendor/phpstan/php-8-stubs/stubs/ext/sysvmsg/msg_remove_queue.stubEE:vendor/phpstan/php-8-stubs/stubs/ext/sysvmsg/msg_send.stub,?vendor/phpstan/php-8-stubs/stubs/ext/sysvmsg/msg_set_queue.stubOOޕ>@vendor/phpstan/php-8-stubs/stubs/ext/sysvmsg/msg_stat_queue.stubJJ~?vendor/phpstan/php-8-stubs/stubs/ext/sysvsem/SysvSemaphore.stubGG|W=vendor/phpstan/php-8-stubs/stubs/ext/sysvsem/sem_acquire.stub]]g9vendor/phpstan/php-8-stubs/stubs/ext/sysvsem/sem_get.stubk=vendor/phpstan/php-8-stubs/stubs/ext/sysvsem/sem_release.stubAA$)"<vendor/phpstan/php-8-stubs/stubs/ext/sysvsem/sem_remove.stub@@!Bvendor/phpstan/php-8-stubs/stubs/ext/sysvshm/SysvSharedMemory.stubJJI_+<vendor/phpstan/php-8-stubs/stubs/ext/sysvshm/shm_attach.stubnn I!<vendor/phpstan/php-8-stubs/stubs/ext/sysvshm/shm_detach.stub,=vendor/phpstan/php-8-stubs/stubs/ext/sysvshm/shm_get_var.stubIIu=vendor/phpstan/php-8-stubs/stubs/ext/sysvshm/shm_has_var.stubHH9=vendor/phpstan/php-8-stubs/stubs/ext/sysvshm/shm_put_var.stubVV¾<vendor/phpstan/php-8-stubs/stubs/ext/sysvshm/shm_remove.stub==BE@vendor/phpstan/php-8-stubs/stubs/ext/sysvshm/shm_remove_var.stubKK)q3vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy.stubY Y q7vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidyNode.stubѲޤ@vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_access_count.stub88@vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_clean_repair.stub99c]@vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_config_count.stub88ŗ<vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_diagnose.stub55¤?vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_error_count.stub77Å@<vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_body.stub;;)>vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_config.stub??=Dvendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_error_buffer.stubEE&+<vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_head.stub;;{`<vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_html.stub;;g5@vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_html_ver.stub88?vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_opt_doc.stubjj->vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_output.stub99J?vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_release.stub//[6G<vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_root.stub;;I>vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_status.stub66731:vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_getopt.stubNN\T-<vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_is_xhtml.stub55>0:vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_is_xml.stub33դ>vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_parse_file.stub_xN@vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_parse_string.stubf*H?vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_repair_file.stub絲Avendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_repair_string.stubc Avendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_warning_count.stub99<vendor/phpstan/php-8-stubs/stubs/ext/tokenizer/PhpToken.stub+nAvendor/phpstan/php-8-stubs/stubs/ext/tokenizer/token_get_all.stubii8L+>vendor/phpstan/php-8-stubs/stubs/ext/tokenizer/token_name.stub00$EEvendor/phpstan/php-8-stubs/stubs/ext/uri/Uri/InvalidUriException.stubzzPd=vendor/phpstan/php-8-stubs/stubs/ext/uri/Uri/Rfc3986/Uri.stubFդCvendor/phpstan/php-8-stubs/stubs/ext/uri/Uri/UriComparisonMode.stubwwAI:vendor/phpstan/php-8-stubs/stubs/ext/uri/Uri/UriError.stubdd>vendor/phpstan/php-8-stubs/stubs/ext/uri/Uri/UriException.stubll&eLvendor/phpstan/php-8-stubs/stubs/ext/uri/Uri/WhatWg/InvalidUrlException.stub..\E[<vendor/phpstan/php-8-stubs/stubs/ext/uri/Uri/WhatWg/Url.stub^ ^ N_Kvendor/phpstan/php-8-stubs/stubs/ext/uri/Uri/WhatWg/UrlValidationError.stubVVCOvendor/phpstan/php-8-stubs/stubs/ext/uri/Uri/WhatWg/UrlValidationErrorType.stub 77vendor/phpstan/php-8-stubs/stubs/ext/xml/XMLParser.stub!!; A>vendor/phpstan/php-8-stubs/stubs/ext/xml/xml_error_string.stub??wKHvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_get_current_byte_index.stubHHqFKvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_get_current_column_number.stubKKVJIvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_get_current_line_number.stubII< @vendor/phpstan/php-8-stubs/stubs/ext/xml/xml_get_error_code.stub@@m:7vendor/phpstan/php-8-stubs/stubs/ext/xml/xml_parse.stub]] NCvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_parse_into_struct.stubeeG?vendor/phpstan/php-8-stubs/stubs/ext/xml/xml_parser_create.stubnnkPBvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_parser_create_ns.stubhh=vendor/phpstan/php-8-stubs/stubs/ext/xml/xml_parser_free.stubӀ LCvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_parser_get_option.stub=tCvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_parser_set_option.stubI\xLvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_character_data_handler.stubw;tEvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_default_handler.stubIJEvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_element_handler.stubPPG] Pvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_end_namespace_decl_handler.stubMhQvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_external_entity_ref_handler.stubN Kvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_notation_decl_handler.stubb<vendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_object.stubz,Tvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_processing_instruction_handler.stub#,mRRvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_start_namespace_decl_handler.stubaRvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_unparsed_entity_decl_handler.stube=vendor/phpstan/php-8-stubs/stubs/ext/xmlreader/XMLReader.stub''1=vendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/XMLWriter.stub::TX Kvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_attribute.stubFF Gvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_cdata.stubBBW@Ivendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_comment.stubDDVJvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_document.stubEEFkuEvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_dtd.stub@@U|Mvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_dtd_attlist.stubHHYJ.Mvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_dtd_element.stubHH JHzLvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_dtd_entity.stubGG&m%Ivendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_element.stubDD򉯤Dvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_pi.stub??C0Cvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_flush.stubXXnŤNvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_full_end_element.stubII `\Ivendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_open_memory.stub>>۽Fvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_open_uri.stubhhsKvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_output_memory.stub\\<-5Hvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_set_indent.stubQQ bHOvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_set_indent_string.stub___pMvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_attribute.stubVV+$UPvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_attribute_ns.stub~~zIvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_cdata.stubDDQ܋2Kvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_comment.stubFFb~oLvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_document.stub.wӤGvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_dtd.stubxN`Ovendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_dtd_attlist.stubXXOvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_dtd_element.stubaa&htNvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_dtd_entity.stubffdKvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_element.stubTT,dNvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_element_ns.stub||ǚ>Fvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_pi.stubQQCBvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_text.stubNNR=kޤMvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_attribute.stubeeϤPvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_attribute_ns.stubVIvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_cdata.stubUUKvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_comment.stubWWdGvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_dtd.stuboOvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_dtd_attlist.stubii"hOvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_dtd_element.stubii Nvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_dtd_entity.stubtd+ʤKvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_element.stubmmNvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_element_ns.stub#Fvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_pi.stubbbVGvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_raw.stubSSkˤ;vendor/phpstan/php-8-stubs/stubs/ext/xsl/XSLTProcessor.stub_Y8vendor/phpstan/php-8-stubs/stubs/ext/zip/ZipArchive.stub7vendor/phpstan/php-8-stubs/stubs/ext/zip/zip_close.stub=vendor/phpstan/php-8-stubs/stubs/ext/zip/zip_entry_close.stub釁ͤFvendor/phpstan/php-8-stubs/stubs/ext/zip/zip_entry_compressedsize.stubKK!#K3Ivendor/phpstan/php-8-stubs/stubs/ext/zip/zip_entry_compressionmethod.stubWW)0p[@vendor/phpstan/php-8-stubs/stubs/ext/zip/zip_entry_filesize.stub??dk<vendor/phpstan/php-8-stubs/stubs/ext/zip/zip_entry_name.stub==><vendor/phpstan/php-8-stubs/stubs/ext/zip/zip_entry_open.stuboo=<vendor/phpstan/php-8-stubs/stubs/ext/zip/zip_entry_read.stubbbX56vendor/phpstan/php-8-stubs/stubs/ext/zip/zip_open.stub]]I6vendor/phpstan/php-8-stubs/stubs/ext/zip/zip_read.stub11 3}=vendor/phpstan/php-8-stubs/stubs/ext/zlib/DeflateContext.stub&&Ǭ=vendor/phpstan/php-8-stubs/stubs/ext/zlib/InflateContext.stubHHI:vendor/phpstan/php-8-stubs/stubs/ext/zlib/deflate_add.stubyy9;vendor/phpstan/php-8-stubs/stubs/ext/zlib/deflate_init.stubl6vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzclose.stub__c9vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzcompress.stubsseֆ7vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzdecode.stubNN]x8vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzdeflate.stubnn{eq7vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzencode.stubnnD9~4vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzeof.stub[[9:l^5vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzfile.stub]5vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzgetc.stubeeZ5vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzgets.stubzzEl8vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzinflate.stubOO6ޤ5vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzopen.stub Ȥ9vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzpassthru.stubddjҤ5vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzputs.stubd5vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzread.stubrr7vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzrewind.stub`` ~d]5vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzseek.stubF5vendor/phpstan/php-8-stubs/stubs/ext/zlib/gztell.stubbb]g;vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzuncompress.stubRR;nx6vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzwrite.stubD:vendor/phpstan/php-8-stubs/stubs/ext/zlib/inflate_add.stubyyuCvendor/phpstan/php-8-stubs/stubs/ext/zlib/inflate_get_read_len.stubHH8Avendor/phpstan/php-8-stubs/stubs/ext/zlib/inflate_get_status.stubFFMsO;vendor/phpstan/php-8-stubs/stubs/ext/zlib/inflate_init.stub^;vendor/phpstan/php-8-stubs/stubs/ext/zlib/ob_gzhandler.stubII F09vendor/phpstan/php-8-stubs/stubs/ext/zlib/readgzfile.stubFs:vendor/phpstan/php-8-stubs/stubs/ext/zlib/zlib_decode.stubQQB:vendor/phpstan/php-8-stubs/stubs/ext/zlib/zlib_encode.stub\\dICvendor/phpstan/php-8-stubs/stubs/ext/zlib/zlib_get_coding_type.stub99s)Lvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/apache_get_modules.stub007ҤLvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/apache_get_version.stub77>֤Gvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/apache_getenv.stub]]]3Kvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/apache_lookup_uri.stubhhkz-Evendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/apache_note.stub]]7dPvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/apache_request_headers.stub44DhH:Qvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/apache_response_headers.stub55Gvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/apache_setenv.stubddKݤGvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/getallheaders.stubPP(Avendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/virtual.stub//{XӤEvendor/phpstan/php-8-stubs/stubs/sapi/cgi/apache_child_terminate.stubUU ϤEvendor/phpstan/php-8-stubs/stubs/sapi/cgi/apache_request_headers.stub44DhH:Fvendor/phpstan/php-8-stubs/stubs/sapi/cgi/apache_response_headers.stub55<vendor/phpstan/php-8-stubs/stubs/sapi/cgi/getallheaders.stubPP(Evendor/phpstan/php-8-stubs/stubs/sapi/cli/apache_request_headers.stub44DhH:Fvendor/phpstan/php-8-stubs/stubs/sapi/cli/apache_response_headers.stub55Dvendor/phpstan/php-8-stubs/stubs/sapi/cli/cli_get_process_title.stub55|}pDvendor/phpstan/php-8-stubs/stubs/sapi/cli/cli_set_process_title.stub??>jCvendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_break_file.stubEEr;cGvendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_break_function.stubBB{&Evendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_break_method.stubMMJCvendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_break_next.stubPPdL,>vendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_clear.stub))jw>vendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_color.stubDDψBvendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_end_oplog.stubBBoq=vendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_exec.stub>>eGvendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_get_executable.stubFF)F?vendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_prompt.stub885SDvendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_start_oplog.stub//)N$vendor/phpstan/phpdoc-parser/LICENSEQQw<vendor/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.phpE2vendor/phpstan/phpdoc-parser/src/Ast/Attribute.phpaa&0vendor/phpstan/phpdoc-parser/src/Ast/Comment.phpIvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php/Evendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php+QEvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php%SDEvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.phpQQʝ2Gvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.phpSS@vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php0KDvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php0Fvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php A#Dvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.phpKƤAvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.phpNvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.php9Τ-vendor/phpstan/phpdoc-parser/src/Ast/Node.phptt3C7vendor/phpstan/phpdoc-parser/src/Ast/NodeAttributes.php6vendor/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php** Ͷ#4vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php ؘtCvendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.phpҾ:Hvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.phpؤJvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.phpUߤBvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php33:R0Fvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php'||Kvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.phpT!Ivendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php88` Fvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.phpPiȤJvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php34Mvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.phpj\Cvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.phpddBCvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.phpwwӤFvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.phpgg9Cvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php` %Bvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php:AKvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.phpGAvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.phpMMXLvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.phpmW[vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.phpmmB$֤Uvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.phpgg{Dvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php2Avendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.phpTTԤ?vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php:vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php33#cX=vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php?JBvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php9e>vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.phpCC*xDvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php Vvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.phphhWJvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.phpVV,Mvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.phpYYM|Bvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.phpNNJ늤Bvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/SealedTagValueNode.phpNNKudCvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.phpQQB;nNDvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php.Bvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.phpNNz'Kvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.phpPPW5Evendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.phpx<Ivendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.phpbG/C@vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.phpaa"m?vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.phpؤ@vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.phpD<vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.phpY Y _Hvendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php7]|;vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.phpS>vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php' Gvendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.phpzMvendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.phpLLG|Avendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.phpvvO;vendor/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.phpw=vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.phpDDt٤@vendor/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php<<cpBvendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php1U=vendor/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php44i8>vendor/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php#jAvendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.phpT=vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php/8Bvendor/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php..E@#:vendor/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php<6vendor/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php]ˤ;vendor/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.phpP30vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php3e;vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php""Y1%b;vendor/phpstan/phpdoc-parser/src/Parser/ParserException.php8vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php>>;vendor/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php9 9 `9vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php))16vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.phpڈ1vendor/phpstan/phpdoc-parser/src/ParserConfig.phpQQȤ5vendor/phpstan/phpdoc-parser/src/Printer/DiffElem.phpZ63vendor/phpstan/phpdoc-parser/src/Printer/Differ.phpG6vendor/psr/http-message/src/ServerRequestInterface.phpA(A(=네/vendor/psr/http-message/src/StreamInterface.php 65vendor/psr/http-message/src/UploadedFileInterface.phpĤZ,vendor/psr/http-message/src/UriInterface.php#2#2ԛvendor/psr/log/LICENSE==pO%vendor/psr/log/src/AbstractLogger.phpǚ /vendor/psr/log/src/InvalidArgumentException.phpssavendor/psr/log/src/LogLevel.phpLL{+vendor/psr/log/src/LoggerAwareInterface.php<<d'vendor/psr/log/src/LoggerAwareTrait.phpш&vendor/psr/log/src/LoggerInterface.php  B $;"vendor/psr/log/src/LoggerTrait.phpLL%V!vendor/psr/log/src/NullLogger.phpF6&vendor/ralouphie/getallheaders/LICENSE88Ka4vendor/ralouphie/getallheaders/src/getallheaders.php.&_vendor/react/cache/LICENSEuu{%vendor/react/cache/src/ArrayCache.php__zµ)vendor/react/cache/src/CacheInterface.php0 0 Nl"vendor/react/child-process/LICENSEuu{*vendor/react/child-process/src/Process.php:: vendor/react/dns/LICENSEuu{+vendor/react/dns/src/BadServerException.phpff.–&vendor/react/dns/src/Config/Config.php??mϳ)vendor/react/dns/src/Config/HostsFile.php<n&vendor/react/dns/src/Model/Message.phpb%vendor/react/dns/src/Model/Record.phpyd8.vendor/react/dns/src/Protocol/BinaryDumper.phpDD\Z (vendor/react/dns/src/Protocol/Parser.php++蛾n.vendor/react/dns/src/Query/CachingExecutor.phpZ Z Ȥ4vendor/react/dns/src/Query/CancellationException.phpvv 7+vendor/react/dns/src/Query/CoopExecutor.php ǵ0vendor/react/dns/src/Query/ExecutorInterface.php~ /vendor/react/dns/src/Query/FallbackExecutor.phps0vendor/react/dns/src/Query/HostsFileExecutor.php O&$vendor/react/dns/src/Query/Query.phpP,vendor/react/dns/src/Query/RetryExecutor.php 19vendor/react/dns/src/Query/SelectiveTransportExecutor.php qߤ3vendor/react/dns/src/Query/TcpTransportExecutor.php662@/vendor/react/dns/src/Query/TimeoutException.phpjj8.vendor/react/dns/src/Query/TimeoutExecutor.php 5KN3vendor/react/dns/src/Query/UdpTransportExecutor.phpT!T!:N,0vendor/react/dns/src/RecordNotFoundException.phpkkS)vendor/react/dns/src/Resolver/Factory.php N*vendor/react/dns/src/Resolver/Resolver.php  7t3vendor/react/dns/src/Resolver/ResolverInterface.phpfvendor/react/event-loop/LICENSEuu{)vendor/react/event-loop/src/ExtEvLoop.phpr&,vendor/react/event-loop/src/ExtEventLoop.php54,vendor/react/event-loop/src/ExtLibevLoop.php/vendor/react/event-loop/src/ExtLibeventLoop.php!! 5j)vendor/react/event-loop/src/ExtUvLoop.php$$0۳'vendor/react/event-loop/src/Factory.php::Ψ1$vendor/react/event-loop/src/Loop.php99-vendor/react/event-loop/src/LoopInterface.phpKK!ߖ.vendor/react/event-loop/src/SignalsHandler.php++p0vendor/react/event-loop/src/StreamSelectLoop.php//@j4vendor/react/event-loop/src/Tick/FutureTickQueue.php'+vendor/react/event-loop/src/Timer/Timer.php66퍲,vendor/react/event-loop/src/Timer/Timers.php ( a1.vendor/react/event-loop/src/TimerInterface.phpVovendor/react/promise/LICENSEggF%vendor/react/promise/src/Deferred.php!!A더9vendor/react/promise/src/Exception/CompositeException.phpssT#6vendor/react/promise/src/Exception/LengthException.phpqqJ67vendor/react/promise/src/Internal/CancellationQueue.php##]ˌ6vendor/react/promise/src/Internal/FulfilledPromise.phpl l ?po5vendor/react/promise/src/Internal/RejectedPromise.php x$vendor/react/promise/src/Promise.php9(9(a}$-vendor/react/promise/src/PromiseInterface.phpggt&vendor/react/promise/src/functions.php},},t`n.vendor/react/promise/src/functions_include.phpivendor/react/socket/LICENSEuu{&vendor/react/socket/src/Connection.phpG/vendor/react/socket/src/ConnectionInterface.phpmms v%vendor/react/socket/src/Connector.phpT.vendor/react/socket/src/ConnectorInterface.php==֤(vendor/react/socket/src/DnsConnector.php$vendor/react/socket/src/FdServer.php&Ȥ-vendor/react/socket/src/FixedUriConnector.php<<Z:vendor/react/socket/src/HappyEyeBallsConnectionBuilder.php--z$2vendor/react/socket/src/HappyEyeBallsConnector.phpR R ^7#*vendor/react/socket/src/LimitingServer.php+vendor/react/socket/src/SecureConnector.php̤(vendor/react/socket/src/SecureServer.phpPPȗi"vendor/react/socket/src/Server.php-+vendor/react/socket/src/ServerInterface.phpפ(vendor/react/socket/src/SocketServer.php""J,vendor/react/socket/src/StreamEncryption.phpx4R(vendor/react/socket/src/TcpConnector.php%vendor/react/socket/src/TcpServer.php""' ,vendor/react/socket/src/TimeoutConnector.phpN N pl)vendor/react/socket/src/UnixConnector.php?"0&vendor/react/socket/src/UnixServer.phpm.vendor/react/stream/LICENSEuu{+vendor/react/stream/src/CompositeStream.phphh h0vendor/react/stream/src/DuplexResourceStream.php]$1vendor/react/stream/src/DuplexStreamInterface.phpR)2vendor/react/stream/src/ReadableResourceStream.php;3vendor/react/stream/src/ReadableStreamInterface.php775c?)vendor/react/stream/src/ThroughStream.php/ vendor/react/stream/src/Util.phpRK2vendor/react/stream/src/WritableResourceStream.phpvޤ3vendor/react/stream/src/WritableStreamInterface.php99Svendor/sebastian/diff/LICENSE  a1#vendor/sebastian/diff/src/Chunk.phpddAǤ"vendor/sebastian/diff/src/Diff.phpqqt݆$vendor/sebastian/diff/src/Differ.php($($>vendor/sebastian/diff/src/Exception/ConfigurationException.phpIİe/1vendor/sebastian/diff/src/Exception/Exception.phpuuO@vendor/sebastian/diff/src/Exception/InvalidArgumentException.php, Ȥ"vendor/sebastian/diff/src/Line.phpUU֤@vendor/sebastian/diff/src/LongestCommonSubsequenceCalculator.php Ovendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php  ,$?vendor/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php~T:vendor/sebastian/diff/src/Output/DiffOnlyOutputBuilder.phpGA?vendor/sebastian/diff/src/Output/DiffOutputBuilderInterface.php5Cvendor/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php((S=vendor/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.phpQQ8Y|$vendor/sebastian/diff/src/Parser.php Mvendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php  &vendor/symfony/console/Application.phpYY.U!.vendor/symfony/console/Attribute/AsCommand.phpJJ(Ҡ2vendor/symfony/console/CI/GithubActionReporter.php  Ƥ vendor/symfony/console/Color.php::Խ*vendor/symfony/console/Command/Command.phpPP3L2vendor/symfony/console/Command/CompleteCommand.php TϤ8vendor/symfony/console/Command/DumpCompletionCommand.phprKK.vendor/symfony/console/Command/HelpCommand.php  ?.vendor/symfony/console/Command/LazyCommand.php11e.vendor/symfony/console/Command/ListCommand.php  E0vendor/symfony/console/Command/LockableTrait.php""v=vendor/symfony/console/Command/SignalableCommandInterface.php@?vendor/symfony/console/CommandLoader/CommandLoaderInterface.php{]ä?vendor/symfony/console/CommandLoader/ContainerCommandLoader.phpP=vendor/symfony/console/CommandLoader/FactoryCommandLoader.phpcc')5vendor/symfony/console/Completion/CompletionInput.phpD D u;vendor/symfony/console/Completion/CompletionSuggestions.phphh-.pAvendor/symfony/console/Completion/Output/BashCompletionOutput.phpx|Fvendor/symfony/console/Completion/Output/CompletionOutputInterface.phpګM0vendor/symfony/console/Completion/Suggestion.phpG(vendor/symfony/console/ConsoleEvents.php%!vendor/symfony/console/Cursor.php  Dvendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php]r<vendor/symfony/console/Descriptor/ApplicationDescription.phpN0vendor/symfony/console/Descriptor/Descriptor.php  +9vendor/symfony/console/Descriptor/DescriptorInterface.phpQQ~ 4vendor/symfony/console/Descriptor/JsonDescriptor.php8vendor/symfony/console/Descriptor/MarkdownDescriptor.phpKK!(֤4vendor/symfony/console/Descriptor/TextDescriptor.php11m^3vendor/symfony/console/Descriptor/XmlDescriptor.php!'!'[{4vendor/symfony/console/Event/ConsoleCommandEvent.php::B<2vendor/symfony/console/Event/ConsoleErrorEvent.php0,p-vendor/symfony/console/Event/ConsoleEvent.php)m3vendor/symfony/console/Event/ConsoleSignalEvent.phpƒ6vendor/symfony/console/Event/ConsoleTerminateEvent.phphh6vendor/symfony/console/EventListener/ErrorListener.phpW W n=vendor/symfony/console/Exception/CommandNotFoundException.php-V7vendor/symfony/console/Exception/ExceptionInterface.phpp=vendor/symfony/console/Exception/InvalidArgumentException.php`;vendor/symfony/console/Exception/InvalidOptionException.php5a3vendor/symfony/console/Exception/LogicException.phpP:vendor/symfony/console/Exception/MissingInputException.php[{oޤ?vendor/symfony/console/Exception/NamespaceNotFoundException.php5vendor/symfony/console/Exception/RuntimeException.php8vendor/symfony/console/Formatter/NullOutputFormatter.phpgg3=vendor/symfony/console/Formatter/NullOutputFormatterStyle.php(4vendor/symfony/console/Formatter/OutputFormatter.php&#&#,r|ܤ=vendor/symfony/console/Formatter/OutputFormatterInterface.phpDDOj9vendor/symfony/console/Formatter/OutputFormatterStyle.php *Bvendor/symfony/console/Formatter/OutputFormatterStyleInterface.phpii9 >vendor/symfony/console/Formatter/OutputFormatterStyleStack.php) ) b/՞Fvendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php 6vendor/symfony/console/Helper/DebugFormatterHelper.phpQ Q ԧ2vendor/symfony/console/Helper/DescriptorHelper.php K(vendor/symfony/console/Helper/Dumper.phpMMS,1vendor/symfony/console/Helper/FormatterHelper.phpx x 6řu(vendor/symfony/console/Helper/Helper.php"21vendor/symfony/console/Helper/HelperInterface.php^^j1+vendor/symfony/console/Helper/HelperSet.phpD D ؓ2vendor/symfony/console/Helper/InputAwareHelper.php!!lޤ/vendor/symfony/console/Helper/ProcessHelper.phpmPq-vendor/symfony/console/Helper/ProgressBar.phpHH?3vendor/symfony/console/Helper/ProgressIndicator.php20vendor/symfony/console/Helper/QuestionHelper.phpLLRbBP7vendor/symfony/console/Helper/SymfonyQuestionHelper.php= = Q7'vendor/symfony/console/Helper/Table.phprr%+vendor/symfony/console/Helper/TableCell.php_}0vendor/symfony/console/Helper/TableCellStyle.phpXXd4M>+vendor/symfony/console/Helper/TableRows.phpUU0vendor/symfony/console/Helper/TableSeparator.php%%Z+V,vendor/symfony/console/Helper/TableStyle.php00Mq*vendor/symfony/console/Input/ArgvInput.php00渜+vendor/symfony/console/Input/ArrayInput.php̤&vendor/symfony/console/Input/Input.php//٤.vendor/symfony/console/Input/InputArgument.php 8F4vendor/symfony/console/Input/InputAwareInterface.phpLLa0vendor/symfony/console/Input/InputDefinition.php<.<.5g/vendor/symfony/console/Input/InputInterface.phpF,vendor/symfony/console/Input/InputOption.phpVVu t[9vendor/symfony/console/Input/StreamableInputInterface.phpzz ,vendor/symfony/console/Input/StringInput.php Q ¤vendor/symfony/console/LICENSE,,U/vendor/symfony/console/Logger/ConsoleLogger.phpM٤0vendor/symfony/console/Output/BufferedOutput.phpcc/=/vendor/symfony/console/Output/ConsoleOutput.php.F8vendor/symfony/console/Output/ConsoleOutputInterface.php00g6vendor/symfony/console/Output/ConsoleSectionOutput.phpH,vendor/symfony/console/Output/NullOutput.php8 8 (vendor/symfony/console/Output/Output.phpee\|A1vendor/symfony/console/Output/OutputInterface.phpt t d .vendor/symfony/console/Output/StreamOutput.phpI|5vendor/symfony/console/Output/TrimmedBufferOutput.phpmm"vendor/symfony/console/PATCHES.txtD2vendor/symfony/console/Question/ChoiceQuestion.phpMˤ8vendor/symfony/console/Question/ConfirmationQuestion.php((,vendor/symfony/console/Question/Question.phpqq&۩N4vendor/symfony/console/Resources/bin/hiddeninput.exe$$v0vendor/symfony/console/Resources/completion.bash 'r8vendor/symfony/console/SignalRegistry/SignalRegistry.phpuum2ߘ3vendor/symfony/console/SingleCommandApplication.php66x,vendor/symfony/console/Style/OutputStyle.phpK K X/vendor/symfony/console/Style/StyleInterface.phpR R 4-vendor/symfony/console/Style/SymfonyStyle.php99 #vendor/symfony/console/Terminal.php#J3vendor/symfony/console/Tester/ApplicationTester.php  9vendor/symfony/console/Tester/CommandCompletionTester.phpFFm2/vendor/symfony/console/Tester/CommandTester.phpI I =Nۤ@vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.phpkä-vendor/symfony/console/Tester/TesterTrait.phpZj,vendor/symfony/deprecation-contracts/LICENSE,, K1vendor/symfony/deprecation-contracts/function.php00 tK/vendor/symfony/finder/Comparator/Comparator.php ɤ3vendor/symfony/finder/Comparator/DateComparator.php˿H5vendor/symfony/finder/Comparator/NumberComparator.php  B9vendor/symfony/finder/Exception/AccessDeniedException.php)!>vendor/symfony/finder/Exception/DirectoryNotFoundException.phps, vendor/symfony/finder/Finder.phpXXA +#vendor/symfony/finder/Gitignore.php  ƢO(vendor/symfony/finder/Glob.phpCCa7vendor/symfony/finder/Iterator/CustomFilterIterator.php334:d:vendor/symfony/finder/Iterator/DateRangeFilterIterator.php*D;vendor/symfony/finder/Iterator/DepthRangeFilterIterator.phpU=Avendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php ^դ9vendor/symfony/finder/Iterator/FileTypeFilterIterator.php+nZ<vendor/symfony/finder/Iterator/FilecontentFilterIterator.php+9vendor/symfony/finder/Iterator/FilenameFilterIterator.php/vendor/symfony/finder/Iterator/LazyIterator.php;=vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php 12G5vendor/symfony/finder/Iterator/PathFilterIterator.phps=vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.phphh!Ө:vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php 3vendor/symfony/finder/Iterator/SortableIterator.phpkk;vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.phpGevendor/symfony/finder/LICENSE,,U%vendor/symfony/finder/SplFileInfo.php(( -'vendor/symfony/polyfill-ctype/Ctype.php%MϤ%vendor/symfony/polyfill-ctype/LICENSE,,+vendor/symfony/polyfill-ctype/bootstrap.php :-vendor/symfony/polyfill-ctype/bootstrap80.php L#ʤ2vendor/symfony/polyfill-intl-grapheme/Grapheme.phpb0b0V%-vendor/symfony/polyfill-intl-grapheme/LICENSE,,H3vendor/symfony/polyfill-intl-grapheme/bootstrap.php 5vendor/symfony/polyfill-intl-grapheme/bootstrap80.php iwP/vendor/symfony/polyfill-intl-normalizer/LICENSE,,H6vendor/symfony/polyfill-intl-normalizer/Normalizer.phpd%d%uFvendor/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php%Rvendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.phpDD'CԤTvendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php{{jeLvendor/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.phpD5D5 Xvendor/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.phpooc,5vendor/symfony/polyfill-intl-normalizer/bootstrap.php#p 7vendor/symfony/polyfill-intl-normalizer/bootstrap80.php,(vendor/symfony/polyfill-mbstring/LICENSE,,H-vendor/symfony/polyfill-mbstring/Mbstring.phpnn<Bvendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.phpa a |ⳤ@vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php__dFvendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php99>|zK@vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.phpffP.vendor/symfony/polyfill-mbstring/bootstrap.php Nc)0vendor/symfony/polyfill-mbstring/bootstrap80.php'' ~ %vendor/symfony/polyfill-php80/LICENSE,, K'vendor/symfony/polyfill-php80/Php80.php )*vendor/symfony/polyfill-php80/PhpToken.phpϴ;vendor/symfony/polyfill-php80/Resources/stubs/Attribute.phpMK<:vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.phpww=7T8<vendor/symfony/polyfill-php80/Resources/stubs/Stringable.phpt]\ڤEvendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.phpGGֈ+<vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php>>g+vendor/symfony/polyfill-php80/bootstrap.php.Ĥ%vendor/symfony/polyfill-php81/LICENSE,,0'vendor/symfony/polyfill-php81/Php81.php$@vendor/symfony/polyfill-php81/Resources/stubs/CURLStringFile.phpJTFvendor/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php5++vendor/symfony/polyfill-php81/bootstrap.php<P%vendor/symfony/polyfill-php83/LICENSE,,t='vendor/symfony/polyfill-php83/Php83.phpm%̤;vendor/symfony/polyfill-php83/Resources/stubs/DateError.php==ˤ?vendor/symfony/polyfill-php83/Resources/stubs/DateException.phpEE Ovendor/symfony/polyfill-php83/Resources/stubs/DateInvalidOperationException.phpYYMߤNvendor/symfony/polyfill-php83/Resources/stubs/DateInvalidTimeZoneException.phpXXgVvendor/symfony/polyfill-php83/Resources/stubs/DateMalformedIntervalStringException.php``6Tvendor/symfony/polyfill-php83/Resources/stubs/DateMalformedPeriodStringException.php^^KNvendor/symfony/polyfill-php83/Resources/stubs/DateMalformedStringException.phpXXWߤAvendor/symfony/polyfill-php83/Resources/stubs/DateObjectError.phpGG .I@vendor/symfony/polyfill-php83/Resources/stubs/DateRangeError.phpFFL;:vendor/symfony/polyfill-php83/Resources/stubs/Override.phpNsEBvendor/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.phpHH<ܐ+vendor/symfony/polyfill-php83/bootstrap.phpXg-vendor/symfony/polyfill-php83/bootstrap80.php[gɤ-vendor/symfony/polyfill-php83/bootstrap81.phpŽp$%vendor/symfony/polyfill-php84/LICENSE,, 'vendor/symfony/polyfill-php84/Php84.phpv=v=[CT6vendor/symfony/polyfill-php84/Resources/Deprecated.php^68vendor/symfony/polyfill-php84/Resources/RoundingMode.php<vendor/symfony/polyfill-php84/Resources/stubs/Deprecated.phpDDŽ;vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Dblib.phpl8>vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Firebird.phpRR?f;vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Mysql.phpQ=/:vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Odbc.php};vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Pgsql.phpO O tj<vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Sqlite.php @&Dvendor/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.phpԷ>vendor/symfony/polyfill-php84/Resources/stubs/RoundingMode.php\\Yj<vendor/symfony/service-contracts/Test/ServiceLocatorTest.phpqs@vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php H"*(vendor/symfony/string/AbstractString.phpOO 4/vendor/symfony/string/AbstractUnicodeString.phphh^Bͤ$vendor/symfony/string/ByteString.php<<*)vendor/symfony/string/CodePointString.php~~@ؤ6vendor/symfony/string/Exception/ExceptionInterface.phpccR<vendor/symfony/string/Exception/InvalidArgumentException.phpƤ4vendor/symfony/string/Exception/RuntimeException.phpq4vendor/symfony/string/Inflector/EnglishInflector.phpBBm3vendor/symfony/string/Inflector/FrenchInflector.phpLĤ6vendor/symfony/string/Inflector/InflectorInterface.phpTTf1vendor/symfony/string/LICENSE,,զ_Ϥ$vendor/symfony/string/LazyString.php\\@r<vendor/symfony/string/Resources/data/wcswidth_table_wide.phpoo啔<vendor/symfony/string/Resources/data/wcswidth_table_zero.phpJJMK-vendor/symfony/string/Resources/functions.phpll`u.vendor/symfony/string/Slugger/AsciiSlugger.php##˹2vendor/symfony/string/Slugger/SluggerInterface.php 4'vendor/symfony/string/UnicodeString.phpW2W2@E}unregister(); // fix missing key for vendor/hoa/protocol/Wrapper.php $existingComposerAutoloadFiles = $GLOBALS['__composer_autoload_files'] ?? []; $GLOBALS['__composer_autoload_files'] = \array_merge($existingComposerAutoloadFiles, \array_fill_keys(['3e76f7f02b41af8cea96018933f6b7e3'], \true)); $autoloaderInWorkingDirectory = $vendorDirectory . '/autoload.php'; $composerAutoloaderProjectPaths = []; /** @var array|false $autoloadFunctionsBefore */ $autoloadFunctionsBefore = \spl_autoload_functions(); if (@\is_file($autoloaderInWorkingDirectory)) { if ($composerJsonPath !== null) { $composerAutoloaderProjectPaths[] = \dirname($composerJsonPath); } 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_33c983f26\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 BisectCommand()); $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(); })(); parameters: featureToggles: bleedingEdge: true checkNonStringableDynamicAccess: true checkParameterCastableToNumberFunctions: true skipCheckGenericClasses!: [] stricterFunctionMap: true reportPreciseLineForUnusedFunctionParameter: true checkPrintfParameterTypes: true internalTag: true newStaticInAbstractClassStaticMethod: true checkExtensionsForComparisonOperators: true checkGenericIterableClasses: true reportTooWideBool: true rawMessageInBaseline: true reportNestedTooWideType: false assignToByRefForeachExpr: true curlSetOptArrayTypes: true checkDateIntervalConstructor: true reportMethodPurityOverride: true checkDynamicConstantNameValues: true parameters: customRulesetUsed: false autowiredAttributeServices: level: 0 conditionalTags: PHPStan\Rules\InternalTag\RestrictedInternalClassConstantUsageExtension: phpstan.restrictedClassConstantUsageExtension: %featureToggles.internalTag% PHPStan\Rules\InternalTag\RestrictedInternalClassNameUsageExtension: phpstan.restrictedClassNameUsageExtension: %featureToggles.internalTag% PHPStan\Rules\InternalTag\RestrictedInternalFunctionUsageExtension: phpstan.restrictedFunctionUsageExtension: %featureToggles.internalTag% PHPStan\Rules\Classes\NewStaticInAbstractClassStaticMethodRule: phpstan.rules.rule: %featureToggles.newStaticInAbstractClassStaticMethod% services: - class: PHPStan\Rules\Classes\NewStaticInAbstractClassStaticMethodRule - class: PHPStan\Rules\InternalTag\RestrictedInternalClassConstantUsageExtension - class: PHPStan\Rules\InternalTag\RestrictedInternalClassNameUsageExtension - class: PHPStan\Rules\InternalTag\RestrictedInternalFunctionUsageExtension includes: - config.level0.neon parameters: checkMaybeUndefinedVariables: true checkExtraArguments: true reportMagicMethods: true reportMagicProperties: true autowiredAttributeServices: level: 1 conditionalTags: PHPStan\Rules\Variables\AssignToByRefExprFromForeachRule: phpstan.rules.rule: %featureToggles.assignToByRefForeachExpr% services: - class: PHPStan\Rules\Variables\AssignToByRefExprFromForeachRule includes: - config.level9.neon parameters: checkImplicitMixed: true autowiredAttributeServices: level: 10 includes: - config.level1.neon parameters: checkClassCaseSensitivity: true checkThisOnly: false checkPhpDocMissingReturn: true autowiredAttributeServices: level: 2 conditionalTags: PHPStan\Rules\InternalTag\RestrictedInternalPropertyUsageExtension: phpstan.restrictedPropertyUsageExtension: %featureToggles.internalTag% PHPStan\Rules\InternalTag\RestrictedInternalMethodUsageExtension: phpstan.restrictedMethodUsageExtension: %featureToggles.internalTag% PHPStan\Rules\Constants\ValueAssignedToDefineRule: phpstan.rules.rule: %featureToggles.checkDynamicConstantNameValues% PHPStan\Rules\Constants\ValueAssignedToGlobalConstantRule: phpstan.rules.rule: %featureToggles.checkDynamicConstantNameValues% services: - class: PHPStan\Rules\InternalTag\RestrictedInternalPropertyUsageExtension - class: PHPStan\Rules\InternalTag\RestrictedInternalMethodUsageExtension - class: PHPStan\Rules\Constants\ValueAssignedToDefineRule - class: PHPStan\Rules\Constants\ValueAssignedToGlobalConstantRule includes: - config.level2.neon autowiredAttributeServices: level: 3 parameters: checkPhpDocMethodSignatures: true includes: - config.level3.neon autowiredAttributeServices: level: 4 conditionalTags: PHPStan\Rules\Exceptions\TooWideFunctionThrowTypeRule: phpstan.rules.rule: %exceptions.check.tooWideThrowType% PHPStan\Rules\Exceptions\TooWideMethodThrowTypeRule: phpstan.rules.rule: %exceptions.check.tooWideThrowType% PHPStan\Rules\Exceptions\TooWidePropertyHookThrowTypeRule: phpstan.rules.rule: %exceptions.check.tooWideThrowType% parameters: checkAdvancedIsset: true services: - class: PHPStan\Rules\Exceptions\TooWideFunctionThrowTypeRule - class: PHPStan\Rules\Exceptions\TooWideMethodThrowTypeRule arguments: checkProtectedAndPublicMethods: %checkTooWideThrowTypesInProtectedAndPublicMethods% tooWideImplicitThrows: %exceptions.check.tooWideImplicitThrowType% - class: PHPStan\Rules\Exceptions\TooWidePropertyHookThrowTypeRule arguments: checkProtectedAndPublicMethods: %checkTooWideThrowTypesInProtectedAndPublicMethods% includes: - config.level4.neon parameters: checkFunctionArgumentTypes: true checkArgumentsPassedByReference: true conditionalTags: PHPStan\Rules\Functions\ParameterCastableToNumberRule: phpstan.rules.rule: %featureToggles.checkParameterCastableToNumberFunctions% PHPStan\Rules\Functions\PrintfParameterTypeRule: phpstan.rules.rule: %featureToggles.checkPrintfParameterTypes% PHPStan\Rules\DateIntervalInstantiationRule: phpstan.rules.rule: %featureToggles.checkDateIntervalConstructor% autowiredAttributeServices: level: 5 services: - class: PHPStan\Rules\Functions\ParameterCastableToNumberRule - class: PHPStan\Rules\Functions\PrintfParameterTypeRule arguments: checkStrictPrintfPlaceholderTypes: %checkStrictPrintfPlaceholderTypes% - class: PHPStan\Rules\DateIntervalInstantiationRule includes: - config.level5.neon parameters: checkMissingVarTagTypehint: true checkMissingTypehints: true autowiredAttributeServices: level: 6 includes: - config.level6.neon parameters: checkUnionTypes: true reportMaybes: true autowiredAttributeServices: level: 7 includes: - config.level7.neon parameters: checkNullables: true autowiredAttributeServices: level: 8 includes: - config.level8.neon parameters: checkExplicitMixed: true autowiredAttributeServices: level: 9 includes: - config.level10.neon includes: - parametersSchema.neon - services.neon - parsers.neon - turbo.neon parameters: bootstrapFiles: - ../stubs/runtime/ReflectionUnionType.php - ../stubs/runtime/ReflectionAttribute.php - ../stubs/runtime/Attribute85.php - ../stubs/runtime/ReflectionIntersectionType.php excludePaths: [] level: null paths: [] exceptions: implicitThrows: true reportUncheckedExceptionDeadCatch: true uncheckedExceptionRegexes: [] uncheckedExceptionClasses: [] checkedExceptionRegexes: [] checkedExceptionClasses: [] check: missingCheckedExceptionInThrows: false tooWideThrowType: true tooWideImplicitThrowType: false throwTypeCovariance: false featureToggles: bleedingEdge: false checkNonStringableDynamicAccess: false checkParameterCastableToNumberFunctions: false skipCheckGenericClasses: - DOMNamedNodeMap stricterFunctionMap: false reportPreciseLineForUnusedFunctionParameter: false checkPrintfParameterTypes: false internalTag: false newStaticInAbstractClassStaticMethod: false checkExtensionsForComparisonOperators: false checkGenericIterableClasses: false reportTooWideBool: false rawMessageInBaseline: false reportNestedTooWideType: false assignToByRefForeachExpr: false curlSetOptArrayTypes: false checkDateIntervalConstructor: false reportMethodPurityOverride: false checkDynamicConstantNameValues: false fileExtensions: - php checkAdvancedIsset: false reportAlwaysTrueInLastCondition: false checkClassCaseSensitivity: false checkExplicitMixed: false checkImplicitMixed: false checkFunctionArgumentTypes: false checkFunctionNameCase: false checkInternalClassCaseSensitivity: false checkMissingCallableSignature: false checkMissingVarTagTypehint: false checkArgumentsPassedByReference: false checkMaybeUndefinedVariables: false checkNullables: false checkThisOnly: true checkUnionTypes: false checkBenevolentUnionTypes: false checkExplicitMixedMissingReturn: false checkPhpDocMissingReturn: false checkPhpDocMethodSignatures: false checkExtraArguments: false checkMissingTypehints: false checkTooWideParameterOutInProtectedAndPublicMethods: false checkTooWideReturnTypesInProtectedAndPublicMethods: false checkTooWideThrowTypesInProtectedAndPublicMethods: false checkUninitializedProperties: false checkDynamicProperties: false strictRulesInstalled: false deprecationRulesInstalled: false inferPrivatePropertyTypeFromConstructor: false checkStrictPrintfPlaceholderTypes: false reportMaybes: false reportMaybesInMethodSignatures: false reportMaybesInPropertyPhpDocTypes: false reportStaticMethodSignatures: false reportWrongPhpDocTypeInVarTag: false reportAnyTypeWideningInVarTag: false reportNonIntStringArrayKey: false reportPossiblyNonexistentGeneralArrayOffset: false reportPossiblyNonexistentConstantArrayOffset: false checkMissingOverrideMethodAttribute: false checkMissingOverridePropertyAttribute: null mixinExcludeClasses: [] scanFiles: [] scanDirectories: [] parallel: jobSize: 20 processTimeout: 600.0 maximumNumberOfProcesses: 8 minimumNumberOfJobsPerProcess: 2 buffer: 134217728 loadLimit: 1.0 phpVersion: null polluteScopeWithLoopInitialAssignments: true polluteScopeWithAlwaysIterableForeach: true polluteScopeWithBlock: true propertyAlwaysWrittenTags: [] propertyAlwaysReadTags: [] additionalConstructors: [] treatPhpDocTypesAsCertain: true usePathConstantsAsConstantString: false rememberPossiblyImpureFunctionValues: true tips: discoveringSymbols: true treatPhpDocTypesAsCertain: true possiblyImpure: true tipsOfTheDay: true reportMagicMethods: false reportMagicProperties: false ignoreErrors: [] internalErrorsCountLimit: 50 cache: nodesByStringCountMax: 256 resolvedPhpDocBlockCacheCountMax: 2048 nameScopeMapMemoryCacheCountMax: 2048 reportUnmatchedIgnoredErrors: true reportIgnoresWithoutComments: false typeAliases: [] universalObjectCratesClasses: - stdClass stubFiles: - ../stubs/Memcached.stub - ../stubs/Redis.stub - ../stubs/ReflectionAttribute.stub - ../stubs/ReflectionClassConstant.stub - ../stubs/ReflectionFunctionAbstract.stub - ../stubs/ReflectionMethod.stub - ../stubs/ReflectionParameter.stub - ../stubs/ReflectionProperty.stub - ../stubs/iterable.stub - ../stubs/ArrayObject.stub - ../stubs/WeakReference.stub - ../stubs/ext-ds.stub - ../stubs/ImagickPixel.stub - ../stubs/PDOStatement.stub - ../stubs/date.stub - ../stubs/ibm_db2.stub - ../stubs/mysqli.stub - ../stubs/zip.stub - ../stubs/dom.stub - ../stubs/spl.stub - ../stubs/SplObjectStorage.stub - ../stubs/Exception.stub - ../stubs/arrayFunctions.stub - ../stubs/core.stub - ../stubs/typeCheckingFunctions.stub - ../stubs/Countable.stub - ../stubs/file.stub - ../stubs/stream_socket_client.stub - ../stubs/stream_socket_server.stub - ../stubs/ctype.stub earlyTerminatingMethodCalls: [] earlyTerminatingFunctionCalls: [] resultCachePath: %tmpDir%/resultCache.php resultCacheSkipIfOlderThanDays: 7 resultCacheChecksProjectExtensionFilesDependencies: false dynamicConstantNames: - ICONV_IMPL - LIBXML_VERSION - LIBXML_DOTTED_VERSION - Memcached::HAVE_ENCODING - Memcached::HAVE_IGBINARY - Memcached::HAVE_JSON - Memcached::HAVE_MSGPACK - Memcached::HAVE_SASL - Memcached::HAVE_SESSION - PHP_VERSION - PHP_MAJOR_VERSION - PHP_MINOR_VERSION - PHP_RELEASE_VERSION - PHP_VERSION_ID - PHP_EXTRA_VERSION - PHP_WINDOWS_VERSION_MAJOR - PHP_WINDOWS_VERSION_MINOR - PHP_WINDOWS_VERSION_BUILD - PHP_ZTS - PHP_DEBUG - PHP_MAXPATHLEN - PHP_OS - PHP_OS_FAMILY - PHP_SAPI - PHP_EOL - PHP_INT_MAX - PHP_INT_MIN - PHP_INT_SIZE - PHP_FLOAT_DIG - PHP_FLOAT_EPSILON - PHP_FLOAT_MIN - PHP_FLOAT_MAX - DEFAULT_INCLUDE_PATH - PEAR_INSTALL_DIR - PEAR_EXTENSION_DIR - PHP_EXTENSION_DIR - PHP_PREFIX - PHP_BINDIR - PHP_BINARY - PHP_MANDIR - PHP_LIBDIR - PHP_DATADIR - PHP_SYSCONFDIR - PHP_LOCALSTATEDIR - PHP_CONFIG_FILE_PATH - PHP_CONFIG_FILE_SCAN_DIR - PHP_SHLIB_SUFFIX - PHP_FD_SETSIZE - OPENSSL_VERSION_NUMBER - ZEND_DEBUG_BUILD - ZEND_THREAD_SAFE - E_ALL customRulesetUsed: null editorUrl: null editorUrlTitle: null errorFormat: null sysGetTempDir: ::sys_get_temp_dir() sourceLocatorPlaygroundMode: false pro: dnsServers: - '1.1.1.2' tmpDir: %sysGetTempDir%/phpstan-fixer __validate: true parametersNotInvalidatingCache: - - parameters - editorUrl - - parameters - editorUrlTitle - - parameters - errorFormat - - parameters - ignoreErrors - - parameters - reportUnmatchedIgnoredErrors - - parameters - tipsOfTheDay - - parameters - parallel - - parameters - internalErrorsCountLimit - - parameters - cache - - parameters - memoryLimitFile - - parameters - pro - parametersSchema extensions: rules: PHPStan\DependencyInjection\RulesExtension expandRelativePaths: PHPStan\DependencyInjection\ExpandRelativePathExtension conditionalTags: PHPStan\DependencyInjection\ConditionalTagsExtension parametersSchema: PHPStan\DependencyInjection\ParametersSchemaExtension validateIgnoredErrors: PHPStan\DependencyInjection\ValidateIgnoredErrorsExtension validateExcludePaths: PHPStan\DependencyInjection\ValidateExcludePathsExtension autowiredAttributeServices: PHPStan\DependencyInjection\AutowiredAttributeServicesExtension validateServiceTags: PHPStan\DependencyInjection\ValidateServiceTagsExtension fnsr: PHPStan\DependencyInjection\FnsrExtension autowiredAttributeServices: level: null conditionalTags: PHPStan\Rules\Exceptions\MissingCheckedExceptionInFunctionThrowsRule: phpstan.rules.rule: %exceptions.check.missingCheckedExceptionInThrows% PHPStan\Rules\Exceptions\MissingCheckedExceptionInMethodThrowsRule: phpstan.rules.rule: %exceptions.check.missingCheckedExceptionInThrows% PHPStan\Rules\Exceptions\MissingCheckedExceptionInPropertyHookThrowsRule: phpstan.rules.rule: %exceptions.check.missingCheckedExceptionInThrows% PHPStan\Rules\Properties\UninitializedPropertyRule: phpstan.rules.rule: %checkUninitializedProperties% PHPStan\Rules\Exceptions\MethodThrowTypeCovarianceRule: phpstan.rules.rule: %exceptions.check.throwTypeCovariance% services: - class: PHPStan\Rules\Exceptions\MissingCheckedExceptionInFunctionThrowsRule - class: PHPStan\Rules\Exceptions\MissingCheckedExceptionInMethodThrowsRule - class: PHPStan\Rules\Exceptions\MissingCheckedExceptionInPropertyHookThrowsRule - class: PHPStan\Rules\Properties\UninitializedPropertyRule - class: PHPStan\Rules\Exceptions\MethodThrowTypeCovarianceRule arguments: implicitThrows: %exceptions.implicitThrows% parameters: checkThisOnly: false checkClassCaseSensitivity: true checkMissingTypehints: true checkMissingCallableSignature: false __validate: false reportMaybes: true reportStatic: true parametersSchema: allStubFiles: listOf(string()) extensions: stubValidatorRules: PHPStan\DependencyInjection\StubValidatorRuleServicesExtension services: - class: PHPStan\PhpDoc\StubSourceLocatorFactory arguments: allStubFiles: %allStubFiles% php8Parser: @php8PhpParser defaultAnalysisParser!: factory: @stubParser nodeScopeResolverReflector: factory: @stubReflector originalBetterReflectionReflector!: factory: @stubReflector reflectionProvider: factory: @stubBetterReflectionProvider autowired: - PHPStan\Reflection\ReflectionProvider currentPhpVersionLexer: factory: @php8Lexer autowired: false currentPhpVersionPhpParser: factory: @php8PhpParser autowired: false stubBetterReflectionProvider: class: PHPStan\Reflection\BetterReflection\BetterReflectionProvider arguments: reflector: @stubReflector universalObjectCratesClasses: %universalObjectCratesClasses% autowired: false stubReflector: class: PHPStan\BetterReflection\Reflector\DefaultReflector arguments: sourceLocator: @stubSourceLocator autowired: false stubSourceLocator: class: PHPStan\BetterReflection\SourceLocator\Type\SourceLocator factory: @PHPStan\PhpDoc\StubSourceLocatorFactory::create() autowired: false parametersSchema: bootstrapFiles: listOf(string()) excludePaths: anyOf(structure({analyse: listOf(string())}), structure({analyseAndScan: listOf(string())}), structure({analyse: listOf(string()), analyseAndScan: listOf(string())})) level: schema(anyOf(int(), string()), nullable()) paths: listOf(string()) exceptions: structure({implicitThrows: bool(), reportUncheckedExceptionDeadCatch: bool(), uncheckedExceptionRegexes: listOf(string()), uncheckedExceptionClasses: listOf(string()), checkedExceptionRegexes: listOf(string()), checkedExceptionClasses: listOf(string()), check: structure({missingCheckedExceptionInThrows: bool(), tooWideThrowType: bool(), throwTypeCovariance: bool(), tooWideImplicitThrowType: bool()})}) featureToggles: structure({bleedingEdge: bool(), checkNonStringableDynamicAccess: bool(), checkParameterCastableToNumberFunctions: bool(), skipCheckGenericClasses: listOf(string()), stricterFunctionMap: bool(), reportPreciseLineForUnusedFunctionParameter: bool(), checkPrintfParameterTypes: bool(), internalTag: bool(), newStaticInAbstractClassStaticMethod: bool(), checkExtensionsForComparisonOperators: bool(), checkGenericIterableClasses: bool(), reportTooWideBool: bool(), rawMessageInBaseline: bool(), reportNestedTooWideType: bool(), assignToByRefForeachExpr: bool(), curlSetOptArrayTypes: bool(), checkDateIntervalConstructor: bool(), reportMethodPurityOverride: bool(), checkDynamicConstantNameValues: bool()}) fileExtensions: listOf(string()) checkAdvancedIsset: bool() reportAlwaysTrueInLastCondition: bool() checkClassCaseSensitivity: bool() checkExplicitMixed: bool() checkImplicitMixed: bool() checkFunctionArgumentTypes: bool() checkFunctionNameCase: bool() checkInternalClassCaseSensitivity: bool() checkMissingCallableSignature: bool() checkMissingVarTagTypehint: bool() checkArgumentsPassedByReference: bool() checkMaybeUndefinedVariables: bool() checkNullables: bool() checkThisOnly: bool() checkUnionTypes: bool() checkBenevolentUnionTypes: bool() checkExplicitMixedMissingReturn: bool() checkPhpDocMissingReturn: bool() checkPhpDocMethodSignatures: bool() checkExtraArguments: bool() checkMissingTypehints: bool() checkTooWideParameterOutInProtectedAndPublicMethods: bool() checkTooWideReturnTypesInProtectedAndPublicMethods: bool() checkTooWideThrowTypesInProtectedAndPublicMethods: bool() checkUninitializedProperties: bool() checkDynamicProperties: bool() strictRulesInstalled: bool() deprecationRulesInstalled: bool() inferPrivatePropertyTypeFromConstructor: bool() checkStrictPrintfPlaceholderTypes: bool() tips: structure({discoveringSymbols: bool(), treatPhpDocTypesAsCertain: bool(), possiblyImpure: bool()}) tipsOfTheDay: bool() reportMaybes: bool() reportMaybesInMethodSignatures: bool() reportMaybesInPropertyPhpDocTypes: bool() reportStaticMethodSignatures: bool() reportWrongPhpDocTypeInVarTag: bool() reportAnyTypeWideningInVarTag: bool() reportNonIntStringArrayKey: bool() reportPossiblyNonexistentGeneralArrayOffset: bool() reportPossiblyNonexistentConstantArrayOffset: bool() checkMissingOverrideMethodAttribute: bool() checkMissingOverridePropertyAttribute: schema(bool(), nullable()) parallel: structure({jobSize: int(), processTimeout: float(), maximumNumberOfProcesses: int(), minimumNumberOfJobsPerProcess: int(), buffer: int(), loadLimit: schema(float(), nullable())}) phpVersion: schema(anyOf(schema(int(), min(70100), max(80599)), structure({min: schema(int(), min(70100), max(80599)), max: schema(int(), min(70100), max(80599))})), nullable()) polluteScopeWithLoopInitialAssignments: bool() polluteScopeWithAlwaysIterableForeach: bool() polluteScopeWithBlock: bool() propertyAlwaysWrittenTags: listOf(string()) propertyAlwaysReadTags: listOf(string()) additionalConstructors: listOf(string()) treatPhpDocTypesAsCertain: bool() usePathConstantsAsConstantString: bool() rememberPossiblyImpureFunctionValues: bool() reportMagicMethods: bool() reportMagicProperties: bool() ignoreErrors: listOf(anyOf(string(), structure({?message: string(), ?messages: listOf(string()), ?rawMessage: string(), ?rawMessages: listOf(string()), ?identifier: string(), ?identifiers: listOf(string()), ?path: string(), ?paths: listOf(string()), ?count: int(), ?reportUnmatched: bool()}))) internalErrorsCountLimit: int() cache: structure({nodesByStringCountMax: int(), resolvedPhpDocBlockCacheCountMax: int(), nameScopeMapMemoryCacheCountMax: int()}) reportUnmatchedIgnoredErrors: bool() reportIgnoresWithoutComments: bool() typeAliases: arrayOf(string()) universalObjectCratesClasses: listOf(string()) stubFiles: listOf(string()) earlyTerminatingMethodCalls: arrayOf(listOf(string())) earlyTerminatingFunctionCalls: listOf(string()) resultCachePath: string() resultCacheSkipIfOlderThanDays: int() resultCacheChecksProjectExtensionFilesDependencies: bool() dynamicConstantNames: arrayOf(string()) customRulesetUsed: schema(bool(), nullable()) rootDir: string() tmpDir: string() currentWorkingDirectory: string() cliArgumentsVariablesRegistered: bool() mixinExcludeClasses: listOf(string()) scanFiles: listOf(string()) scanDirectories: listOf(string()) editorUrl: schema(string(), nullable()) editorUrlTitle: schema(string(), nullable()) errorFormat: schema(string(), nullable()) pro: structure({dnsServers: schema(listOf(string()), min(1)), tmpDir: string()}) env: arrayOf(string(), anyOf(int(), string())) sysGetTempDir: string() parametersNotInvalidatingCache: listOf(schema(anyOf(string(), listOf(string())))) sourceLocatorPlaygroundMode: bool() debugMode: bool() productionMode: bool() tempDir: string() __validate: bool() additionalConfigFiles: listOf(string()) generateBaselineFile: schema(string(), nullable()) analysedPaths: listOf(string()) allConfigFiles: listOf(string()) composerAutoloaderProjectPaths: listOf(string()) analysedPathsFromConfig: listOf(string()) usedLevel: string() cliAutoloadFile: schema(string(), nullable()) singleReflectionFile: schema(string(), nullable()) singleReflectionInsteadOfFile: schema(string(), nullable()) expandRelativePaths: - '[parameters][paths][]' - '[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][consoleApplicationLoader]' - '[parameters][symfony][containerXmlPath]' - '[parameters][doctrine][objectManagerLoader]' services: php8Parser: class: PHPStan\Parser\SimpleParser arguments: parser: @php8PhpParser autowired: false php8Lexer: class: PhpParser\Lexer\Emulative factory: @PHPStan\Parser\LexerFactory::createEmulative() autowired: false php8PhpParser: class: PhpParser\Parser\Php8 arguments: lexer: @php8Lexer autowired: false currentPhpVersionLexer: class: PhpParser\Lexer factory: @PHPStan\Parser\LexerFactory::create() autowired: false currentPhpVersionPhpParser: factory: @currentPhpVersionPhpParserFactory::create() autowired: false currentPhpVersionPhpParserFactory: class: PHPStan\Parser\PhpParserFactory arguments: lexer: @currentPhpVersionLexer autowired: false currentPhpVersionSimpleDirectParser: class: PHPStan\Parser\SimpleParser arguments: parser: @currentPhpVersionPhpParser autowired: false currentPhpVersionSimpleParser: class: PHPStan\Parser\CleaningParser arguments: wrappedParser: @currentPhpVersionSimpleDirectParser autowired: false currentPhpVersionRichParser: class: PHPStan\Parser\RichParser arguments: parser: @currentPhpVersionPhpParser autowired: false pathRoutingParser: class: PHPStan\Parser\PathRoutingParser arguments: currentPhpVersionRichParser: @currentPhpVersionRichParser currentPhpVersionSimpleParser: @currentPhpVersionSimpleParser php8Parser: @php8Parser singleReflectionFile: %singleReflectionFile% autowired: false phpParserDecorator: class: PHPStan\Parser\PhpParserDecorator arguments: wrappedParser: @defaultAnalysisParser autowired: false defaultAnalysisParser: class: PHPStan\Parser\CachedParser arguments: originalParser: @pathRoutingParser cachedNodesByStringCountMax: %cache.nodesByStringCountMax% autowired: false freshStubParser: class: PHPStan\Parser\StubParser arguments: parser: @php8PhpParser autowired: false stubParser: class: PHPStan\Parser\CachedParser arguments: originalParser: @freshStubParser cachedNodesByStringCountMax: %cache.nodesByStringCountMax% autowired: false services: - class: PhpParser\BuilderFactory - class: PhpParser\NodeVisitor\NameResolver arguments: options: preserveOriginalNames: true - class: PHPStan\PhpDocParser\ParserConfig arguments: usedAttributes: lines: true - class: PHPStan\PhpDocParser\Lexer\Lexer - class: PHPStan\PhpDocParser\Parser\TypeParser - class: PHPStan\PhpDocParser\Parser\ConstExprParser - class: PHPStan\PhpDocParser\Parser\PhpDocParser - class: PHPStan\PhpDocParser\Printer\Printer - factory: @PHPStan\Reflection\BetterReflection\SourceStubber\PhpStormStubsSourceStubberFactory::create() autowired: - PHPStan\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber - factory: @PHPStan\Reflection\BetterReflection\SourceStubber\ReflectionSourceStubberFactory::create() autowired: - PHPStan\BetterReflection\SourceLocator\SourceStubber\ReflectionSourceStubber originalBetterReflectionReflector: class: PHPStan\BetterReflection\Reflector\DefaultReflector arguments: sourceLocator: @betterReflectionSourceLocator autowired: false - class: PHPStan\Dependency\ExportedNodeVisitor - class: PHPStan\Reflection\BetterReflection\SourceLocator\CachingVisitor - class: PHPStan\Reflection\Php\PhpClassReflectionExtension arguments: parser: @defaultAnalysisParser inferPrivatePropertyTypeFromConstructor: %inferPrivatePropertyTypeFromConstructor% - class: PHPStan\Reflection\Annotations\AnnotationsMethodsClassReflectionExtension - class: PHPStan\Reflection\Annotations\AnnotationsPropertiesClassReflectionExtension - class: PHPStan\Reflection\Php\UniversalObjectCratesClassReflectionExtension arguments: classes: %universalObjectCratesClasses% - class: PHPStan\Reflection\Mixin\MixinMethodsClassReflectionExtension arguments: mixinExcludeClasses: %mixinExcludeClasses% - class: PHPStan\Reflection\Mixin\MixinPropertiesClassReflectionExtension arguments: mixinExcludeClasses: %mixinExcludeClasses% - class: PHPStan\Reflection\Php\Soap\SoapClientMethodsClassReflectionExtension - class: PHPStan\Reflection\RequireExtension\RequireExtendsMethodsClassReflectionExtension - class: PHPStan\Reflection\RequireExtension\RequireExtendsPropertiesClassReflectionExtension - class: PHPStan\Rules\Methods\MethodSignatureRule arguments: reportMaybes: %reportMaybesInMethodSignatures% reportStatic: %reportStaticMethodSignatures% reportMethodPurityOverride: %featureToggles.reportMethodPurityOverride% phpstanDiagnoseExtension: class: PHPStan\Diagnose\PHPStanDiagnoseExtension arguments: composerAutoloaderProjectPaths: %composerAutoloaderProjectPaths% allConfigFiles: %allConfigFiles% configPhpVersion: %phpVersion% simpleRelativePathHelper: @simpleRelativePathHelper autowired: false - class: PHPStan\Type\Php\ReflectionGetAttributesMethodReturnTypeExtension arguments: className: ReflectionClass tags: - phpstan.broker.dynamicMethodReturnTypeExtension - class: PHPStan\Type\Php\ReflectionGetAttributesMethodReturnTypeExtension arguments: className: ReflectionClassConstant tags: - phpstan.broker.dynamicMethodReturnTypeExtension - class: PHPStan\Type\Php\ReflectionGetAttributesMethodReturnTypeExtension arguments: className: ReflectionFunctionAbstract tags: - phpstan.broker.dynamicMethodReturnTypeExtension - class: PHPStan\Type\Php\ReflectionGetAttributesMethodReturnTypeExtension arguments: className: ReflectionParameter tags: - phpstan.broker.dynamicMethodReturnTypeExtension - class: PHPStan\Type\Php\ReflectionGetAttributesMethodReturnTypeExtension arguments: className: ReflectionProperty tags: - phpstan.broker.dynamicMethodReturnTypeExtension - class: PHPStan\Type\Php\DateTimeModifyReturnTypeExtension tags: - phpstan.broker.dynamicMethodReturnTypeExtension arguments: dateTimeClass: DateTime - class: PHPStan\Type\Php\DateTimeModifyReturnTypeExtension tags: - phpstan.broker.dynamicMethodReturnTypeExtension arguments: dateTimeClass: DateTimeImmutable - class: PHPStan\Reflection\PHPStan\NativeReflectionEnumReturnDynamicReturnTypeExtension tags: - phpstan.broker.dynamicMethodReturnTypeExtension arguments: className: PHPStan\Reflection\ClassReflection methodName: getNativeReflection - class: PHPStan\Reflection\PHPStan\NativeReflectionEnumReturnDynamicReturnTypeExtension tags: - phpstan.broker.dynamicMethodReturnTypeExtension arguments: className: PHPStan\Reflection\Php\BuiltinMethodReflection methodName: getDeclaringClass - class: PHPStan\Reflection\BetterReflection\Type\AdapterReflectionEnumCaseDynamicReturnTypeExtension arguments: class: PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumBackedCase tags: - phpstan.broker.dynamicMethodReturnTypeExtension - class: PHPStan\Reflection\BetterReflection\Type\AdapterReflectionEnumCaseDynamicReturnTypeExtension arguments: class: PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumUnitCase tags: - phpstan.broker.dynamicMethodReturnTypeExtension errorFormatter.json: class: PHPStan\Command\ErrorFormatter\JsonErrorFormatter arguments: pretty: false errorFormatter.prettyJson: class: PHPStan\Command\ErrorFormatter\JsonErrorFormatter arguments: pretty: true stubFileTypeMapper: class: PHPStan\Type\FileTypeMapper arguments: phpParser: @stubParser resolvedPhpDocBlockCacheCountMax: %cache.resolvedPhpDocBlockCacheCountMax% nameScopeMapMemoryCacheCountMax: %cache.nameScopeMapMemoryCacheCountMax% autowired: false fileExcluderAnalyse: class: PHPStan\File\FileExcluder factory: @PHPStan\File\FileExcluderFactory::createAnalyseFileExcluder() autowired: false fileExcluderScan: class: PHPStan\File\FileExcluder factory: @PHPStan\File\FileExcluderFactory::createScanFileExcluder() autowired: false fileFinderAnalyse: class: PHPStan\File\FileFinder arguments: fileExcluder: @fileExcluderAnalyse fileExtensions: %fileExtensions% autowired: false fileFinderScan: class: PHPStan\File\FileFinder arguments: fileExcluder: @fileExcluderScan fileExtensions: %fileExtensions% autowired: false cacheStorage: class: PHPStan\Cache\FileCacheStorage arguments: directory: %tmpDir%/cache/PHPStan autowired: false betterReflectionSourceLocator: factory: @PHPStan\Reflection\BetterReflection\BetterReflectionSourceLocatorFactory::create autowired: false reflectionProvider: factory: @PHPStan\Reflection\ReflectionProvider\ReflectionProviderFactory::create autowired: - PHPStan\Reflection\ReflectionProvider nodeScopeResolverReflector: factory: @betterReflectionReflector autowired: false exceptionTypeResolver: class: PHPStan\Rules\Exceptions\ExceptionTypeResolver factory: @PHPStan\Rules\Exceptions\DefaultExceptionTypeResolver services: - class: PHPStan\Reflection\BetterReflection\SourceLocator\SymbolFinderInFiles arguments: cleaner: @PHPStan\Reflection\BetterReflection\SourceLocator\PhpFileCleaner - class: PHPStan\Reflection\BetterReflection\SourceLocator\PhpFileCleaner 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: | | | | | ' => [', ''=>''] * 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::getChannelId' => ['int<1, 65535>'], 'AMQPChannel::getPrefetchCount' => ['int<0, 65535>'], 'AMQPChannel::getPrefetchSize' => ['int<0, max>'], 'AMQPConnection::getMaxChannels' => ['int<1, 65535>'], 'AMQPConnection::getPort' => ['int<1, 65535>'], 'AMQPConnection::getUsedChannels' => ['int<1, 65535>'], 'AMQPEnvelope::getHeaders' => ['array'], 'AMQPEnvelope::getPriority' => ['int<0, max>'], 'AMQPExchange::bind' => ['void', 'exchangeName'=>'string', 'routingKey='=>'string|null', 'arguments='=>'array'], 'AMQPExchange::getArguments' => ['array'], '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::setName' => ['void', 'exchangeName'=>'string|null'], 'AMQPExchange::setType' => ['void', 'exchangeType'=>'string|null'], 'AMQPExchange::unbind' => ['void', 'exchangeName'=>'string', 'routingKey='=>'string|null', 'arguments='=>'array'], '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::delete' => ['int', 'flags='=>'int|null'], 'AMQPQueue::nack' => ['void', 'deliveryTag'=>'int', 'flags='=>'int|null'], 'AMQPQueue::reject' => ['void', 'deliveryTag'=>'int', 'flags='=>'int|null'], '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' => ['__benevolent|false>', 'limited='=>'bool'], 'apcu_cas' => ['bool', 'key'=>'string', 'old'=>'int', 'new'=>'int'], 'apcu_clear_cache' => ['bool'], 'apcu_dec' => ['false|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' => ['false|int', 'key'=>'string', 'step='=>'int', '&w_success='=>'bool', 'ttl='=>'int'], 'apcu_sma_info' => ['__benevolent', '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?:list,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?:list,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'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], 'bccomp' => ['0|1|-1', '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'], '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'=>'numeric-string', 'exponent'=>'numeric-string', 'scale='=>'int'], 'bcpowmod' => ['numeric-string|null', 'base'=>'numeric-string', 'exponent'=>'numeric-string', 'modulus'=>'string', 'scale='=>'int'], 'bcscale' => ['int', 'scale='=>'int'], 'bcsqrt' => ['numeric-string', 'operand'=>'numeric-string', 'scale='=>'int'], 'bcsub' => ['numeric-string', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-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?:list,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|class-string|\'static\'|null'], 'Closure::bindTo' => ['__benevolent', 'new'=>'?object', 'newscope='=>'object|class-string|\'static\'|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'], 'count' => ['0|positive-int', 'var'=>'Countable|array', 'mode='=>'0|1'], '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?:list,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?:list,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' => ['__benevolent', 'name'=>'string'], 'DOMElement::getAttributeNodeNS' => ['__benevolent', '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' => ['__benevolent', 'newnode'=>'DOMNode'], 'DOMNode::appendChild' => ['__benevolent', 'newnode'=>'DOMNode'], 'DOMNode::C14N' => ['__benevolent', 'exclusive='=>'bool', 'with_comments='=>'bool', 'xpath='=>'array|null', 'ns_prefixes='=>'array|null'], 'DOMNode::C14NFile' => ['__benevolent', 'uri='=>'string', 'exclusive='=>'bool', 'with_comments='=>'bool', 'xpath='=>'array|null', 'ns_prefixes='=>'array|null'], 'DOMNode::cloneNode' => ['__benevolent', 'deep='=>'bool'], 'DOMNode::getLineNo' => ['int'], 'DOMNode::getNodePath' => ['?string'], 'DOMNode::hasAttributes' => ['bool'], 'DOMNode::hasChildNodes' => ['bool'], 'DOMNode::insertBefore' => ['__benevolent', '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' => ['__benevolent', 'oldnode'=>'DOMNode'], 'DOMNode::replaceChild' => ['__benevolent', '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'=>'int|float|__stringNotStringable|bool|array|resource|GMP|SimpleXMLElement|null'], 'Ds\Deque::__construct' => ['void', 'values='=>'mixed'], 'Ds\Deque::count' => ['0|positive-int'], 'Ds\Deque::jsonSerialize' => ['array'], 'Ds\Map::__construct' => ['void', 'values='=>'mixed'], 'Ds\Map::allocate' => ['void', 'capacity'=>'int'], 'Ds\Map::apply' => ['void', 'callback'=>'callable'], 'Ds\Map::count' => ['0|positive-int'], 'Ds\Map::jsonSerialize' => ['array'], 'Ds\Map::ksort' => ['void', 'comparator='=>'callable'], 'Ds\Map::put' => ['void', 'key'=>'mixed', 'value'=>'mixed'], 'Ds\Map::putAll' => ['void', 'values'=>'mixed'], 'Ds\Map::reverse' => ['void'], 'Ds\Map::sort' => ['void', 'comparator='=>'callable'], 'Ds\Pair::jsonSerialize' => ['array'], 'Ds\PriorityQueue::count' => ['0|positive-int'], 'Ds\PriorityQueue::jsonSerialize' => ['array'], 'Ds\PriorityQueue::push' => ['void', 'value'=>'mixed', 'priority'=>'int'], 'Ds\Queue::allocate' => ['void', 'capacity'=>'int'], 'Ds\Queue::count' => ['0|positive-int'], 'Ds\Queue::jsonSerialize' => ['array'], 'Ds\Queue::push' => ['void', '...values='=>'mixed'], 'Ds\Set::add' => ['void', '...values='=>'mixed'], 'Ds\Set::allocate' => ['void', 'capacity'=>'int'], 'Ds\Set::clear' => ['void'], 'Ds\Set::count' => ['0|positive-int'], 'Ds\Set::join' => ['string', 'glue='=>'string'], 'Ds\Set::jsonSerialize' => ['array'], 'Ds\Set::remove' => ['void', '...values='=>'mixed'], 'Ds\Set::reverse' => ['void'], 'Ds\Set::sort' => ['void', 'comparator='=>'callable'], 'Ds\Stack::allocate' => ['void', 'capacity'=>'int'], 'Ds\Stack::count' => ['0|positive-int'], 'Ds\Stack::jsonSerialize' => ['array'], 'Ds\Vector::__construct' => ['void', 'values='=>'mixed'], 'Ds\Vector::count' => ['0|positive-int'], 'Ds\Vector::join' => ['string', 'glue='=>'string'], 'Ds\Vector::jsonSerialize' => ['array'], 'Ds\Vector::sum' => ['int|float'], '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|false', 'delay'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_cancel' => ['void', 'req'=>'resource'], 'eio_chmod' => ['resource|false', 'path'=>'string', 'mode'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_chown' => ['resource|false', 'path'=>'string', 'uid'=>'int', 'gid='=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_close' => ['resource|false', 'fd'=>'mixed', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_custom' => ['resource|false', 'execute'=>'callable', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_dup2' => ['resource|false', 'fd'=>'mixed', 'fd2'=>'mixed', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_event_loop' => ['bool'], 'eio_fallocate' => ['resource|false', 'fd'=>'mixed', 'mode'=>'int', 'offset'=>'int', 'length'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_fchmod' => ['resource|false', 'fd'=>'mixed', 'mode'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_fchown' => ['resource|false', 'fd'=>'mixed', 'uid'=>'int', 'gid='=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_fdatasync' => ['resource|false', 'fd'=>'mixed', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_fstat' => ['resource|false', 'fd'=>'mixed', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_fstatvfs' => ['resource|false', 'fd'=>'mixed', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_fsync' => ['resource|false', 'fd'=>'mixed', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_ftruncate' => ['resource|false', 'fd'=>'mixed', 'offset='=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_futime' => ['resource|false', '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|false', '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|false', 'path'=>'string', 'new_path'=>'string', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_lstat' => ['resource|false', 'path'=>'string', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_mkdir' => ['resource|false', 'path'=>'string', 'mode'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_mknod' => ['resource|false', 'path'=>'string', 'mode'=>'int', 'dev'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_nop' => ['resource|false', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_npending' => ['int'], 'eio_nready' => ['int'], 'eio_nreqs' => ['int'], 'eio_nthreads' => ['int'], 'eio_open' => ['resource|false', 'path'=>'string', 'flags'=>'int', 'mode'=>'int', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_poll' => ['int'], 'eio_read' => ['resource|false', 'fd'=>'mixed', 'length'=>'int', 'offset'=>'int', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_readahead' => ['resource|false', 'fd'=>'mixed', 'offset'=>'int', 'length'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_readdir' => ['resource|false', 'path'=>'string', 'flags'=>'int', 'pri'=>'int', 'callback'=>'callable', 'data='=>'string'], 'eio_readlink' => ['resource|false', 'path'=>'string', 'pri'=>'int', 'callback'=>'callable', 'data='=>'string'], 'eio_realpath' => ['resource|false', 'path'=>'string', 'pri'=>'int', 'callback'=>'callable', 'data='=>'string'], 'eio_rename' => ['resource|false', 'path'=>'string', 'new_path'=>'string', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_rmdir' => ['resource|false', 'path'=>'string', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_seek' => ['resource|false', 'fd'=>'mixed', 'offset'=>'int', 'whence'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_sendfile' => ['resource|false', '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|false', 'path'=>'string', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_statvfs' => ['resource|false', 'path'=>'string', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_symlink' => ['resource|false', 'path'=>'string', 'new_path'=>'string', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_sync' => ['resource|false', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_sync_file_range' => ['resource|false', 'fd'=>'mixed', 'offset'=>'int', 'nbytes'=>'int', 'flags'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_syncfs' => ['resource|false', 'fd'=>'mixed', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_truncate' => ['resource|false', 'path'=>'string', 'offset='=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_unlink' => ['resource|false', 'path'=>'string', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_utime' => ['resource|false', 'path'=>'string', 'atime'=>'float', 'mtime'=>'float', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_write' => ['resource|false', '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?:list,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='=>'0|1|2|3|4', '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?:list,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?:list,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-mask', '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' => ['non-empty-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-mask', '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'=>'int|float|__stringNotStringable|bool|array|resource|GMP|SimpleXMLElement|null'], 'flock' => ['bool', 'fp'=>'resource', 'operation'=>'int-mask', '&w_wouldblock='=>'0|1'], '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='=>'FTP_ASCII|FTP_BINARY'], '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='=>'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_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='=>'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_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='=>'FTP_ASCII|FTP_BINARY', '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|null', 'double_encode='=>'bool'], 'htmlspecialchars' => ['string', 'string'=>'string', 'quote_style='=>'int', 'encoding='=>'string|null', '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<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>'], 'imagecolorat' => ['int<0, max>|false', 'im'=>'resource', 'x'=>'int', 'y'=>'int'], '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>'], 'imagecolordeallocate' => ['bool', 'im'=>'resource', 'index'=>'int'], '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>'], 'imagecolormatch' => ['bool', 'im1'=>'resource', 'im2'=>'resource'], '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>'], '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<1, max>', 'y_size'=>'int<1, max>'], '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<1, max>', 'y_size'=>'int<1, max>'], '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='=>'Imagick::CHANNEL_*'], 'Imagick::adaptiveResizeImage' => ['bool', 'columns'=>'int', 'rows'=>'int', 'bestfit='=>'bool'], 'Imagick::adaptiveSharpenImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::adaptiveThresholdImage' => ['bool', 'width'=>'int', 'height'=>'int', 'offset'=>'int'], 'Imagick::addImage' => ['bool', 'source'=>'imagick'], 'Imagick::addNoiseImage' => ['bool', 'noise_type'=>'Imagick::NOISE_*', 'channel='=>'Imagick::CHANNEL_*'], '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='=>'Imagick::CHANNEL_*'], 'Imagick::autoLevelImage' => ['bool', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::autoOrient' => ['bool'], 'Imagick::averageImages' => ['Imagick'], 'Imagick::blackThresholdImage' => ['bool', 'threshold'=>'mixed'], 'Imagick::blueShiftImage' => ['bool', 'factor='=>'float'], 'Imagick::blurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::borderImage' => ['bool', 'bordercolor'=>'mixed', 'width'=>'int', 'height'=>'int'], 'Imagick::brightnessContrastImage' => ['bool', 'brightness'=>'float', 'contrast'=>'float', 'channel='=>'Imagick::CHANNEL_*'], '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'=>'Imagick::CHANNEL_*'], 'Imagick::commentImage' => ['bool', 'comment'=>'string'], '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::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='=>'Imagick::CHANNEL_*'], 'Imagick::convolveImage' => ['bool', 'kernel'=>'array', 'channel='=>'Imagick::CHANNEL_*'], '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'=>'Imagick::DISTORTION_*', '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'=>'Imagick::EVALUATE_*', 'constant'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::evaluateImages' => ['bool', 'EVALUATE_CONSTANT'=>'int'], 'Imagick::exportImagePixels' => ['list', 'x'=>'int', 'y'=>'int', 'width'=>'int', 'height'=>'int', 'map'=>'string', 'storage'=>'Imagick::PIXEL_*'], '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='=>'Imagick::CHANNEL_*'], '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'=>'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::getColorspace' => ['Imagick::COLORSPACE_*'], 'Imagick::getCompression' => ['Imagick::COMPRESSION_*'], 'Imagick::getCompressionQuality' => ['int'], 'Imagick::getConfigureOptions' => ['array'], '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'=>'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::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'=>'Imagick::METRIC_*'], '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'=>'Imagick::RESOURCETYPE_*'], 'Imagick::getResourceLimit' => ['int', 'type'=>'Imagick::RESOURCETYPE_*'], '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'=>'Imagick::PIXEL_*', '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='=>'Imagick::CHANNEL_*'], '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'=>'Imagick::LAYERMETHOD_*'], 'Imagick::minifyImage' => ['bool'], 'Imagick::modulateImage' => ['bool', 'brightness'=>'float', 'saturation'=>'float', 'hue'=>'float'], 'Imagick::montageImage' => ['Imagick', 'draw'=>'imagickdraw', 'tile_geometry'=>'string', 'thumbnail_geometry'=>'string', 'mode'=>'Imagick::MONTAGEMODE_*', 'frame'=>'string'], 'Imagick::morphImages' => ['Imagick', 'number_frames'=>'int'], 'Imagick::morphology' => ['bool', 'morphologyMethod'=>'Imagick::MORPHOLOGY_*', 'iterations'=>'int', 'ImagickKernel'=>'ImagickKernel', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::mosaicImages' => ['Imagick'], 'Imagick::motionBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'angle'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::negateImage' => ['bool', 'gray'=>'bool', 'channel='=>'Imagick::CHANNEL_*'], '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='=>'Imagick::CHANNEL_*'], 'Imagick::oilPaintImage' => ['bool', 'radius'=>'float'], 'Imagick::opaquePaintImage' => ['bool', 'target'=>'mixed', 'fill'=>'mixed', 'fuzz'=>'float', 'invert'=>'bool', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::optimizeImageLayers' => ['bool'], '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::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='=>'Imagick::CHANNEL_*'], 'Imagick::raiseImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int', 'raise'=>'bool'], 'Imagick::randomThresholdImage' => ['bool', 'low'=>'float', 'high'=>'float', 'channel='=>'Imagick::CHANNEL_*'], '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'=>'Imagick::DITHERMETHOD_*'], '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='=>'Imagick::CHANNEL_*'], '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'=>'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::sepiaToneImage' => ['bool', 'threshold'=>'float'], 'Imagick::setAntiAlias' => ['int', 'antialias'=>'bool'], 'Imagick::setBackgroundColor' => ['bool', 'background'=>'mixed'], 'Imagick::setColorspace' => ['bool', 'colorspace'=>'Imagick::COLORSPACE_*'], 'Imagick::setCompression' => ['bool', 'compression'=>'Imagick::COMPRESSION_*'], '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'=>'Imagick::GRAVITY_*'], 'Imagick::setImage' => ['bool', 'replace'=>'imagick'], 'Imagick::setImageAlpha' => ['bool', 'alpha'=>'float'], 'Imagick::setImageAlphaChannel' => ['bool', 'mode'=>'Imagick::ALPHACHANNEL_*'], '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'=>'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::setImageCompressionQuality' => ['bool', 'quality'=>'int'], 'Imagick::setImageDelay' => ['bool', 'delay'=>'int'], 'Imagick::setImageDepth' => ['bool', 'depth'=>'int'], 'Imagick::setImageDispose' => ['bool', 'dispose'=>'Imagick::DISPOSE_*'], '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'=>'Imagick::GRAVITY_*'], 'Imagick::setImageGreenPrimary' => ['bool', 'x'=>'float', 'y'=>'float'], 'Imagick::setImageIndex' => ['bool', 'index'=>'int'], 'Imagick::setImageInterlaceScheme' => ['bool', 'interlace_scheme'=>'Imagick::INTERLACE_*'], 'Imagick::setImageInterpolateMethod' => ['bool', 'method'=>'Imagick::INTERPOLATE_*'], 'Imagick::setImageIterations' => ['bool', 'iterations'=>'int'], 'Imagick::setImageMatte' => ['bool', 'matte'=>'bool'], 'Imagick::setImageMatteColor' => ['bool', 'matte'=>'mixed'], 'Imagick::setImageOpacity' => ['bool', 'opacity'=>'float'], 'Imagick::setImageOrientation' => ['bool', 'orientation'=>'Imagick::ORIENTATION_*'], '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'=>'Imagick::RENDERINGINTENT_*'], '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'=>'Imagick::IMGTYPE_*'], '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'=>'Imagick::IMGTYPE_*'], '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='=>'Imagick::CHANNEL_*'], '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='=>'Imagick::CHANNEL_*'], 'Imagick::similarityImage' => ['Imagick', 'imagick'=>'Imagick', '&bestMatch'=>'array', '&similarity'=>'float', 'similarity_threshold'=>'float', 'metric'=>'Imagick::METRIC_*'], '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'=>'Imagick::SPARSECOLORMETHOD_*', 'arguments'=>'array', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::spliceImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::spreadImage' => ['bool', 'radius'=>'float'], 'Imagick::statisticImage' => ['bool', 'type'=>'Imagick::STATISTIC_*', 'width'=>'int', 'height'=>'int', 'channel='=>'Imagick::CHANNEL_*'], '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='=>'Imagick::CHANNEL_*'], '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'=>'Imagick::COLORSPACE_*'], '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='=>'Imagick::CHANNEL_*'], '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'=>'Imagick::PAINT_*'], 'ImagickDraw::comment' => ['bool', 'comment'=>'string'], 'ImagickDraw::composite' => ['bool', 'compose'=>'Imagick::COMPOSITE_*', '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'=>'Imagick::PAINT_*'], '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'=>'Imagick::FILLRULE_*'], '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'=>'Imagick::FILLRULE_*'], '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'=>'Imagick::STRETCH_*'], 'ImagickDraw::setFontStyle' => ['bool', 'style'=>'Imagick::STYLE_*'], 'ImagickDraw::setFontWeight' => ['bool', 'font_weight'=>'int'], 'ImagickDraw::setGravity' => ['bool', 'gravity'=>'Imagick::GRAVITY_*'], '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'=>'Imagick::LINECAP_*'], 'ImagickDraw::setStrokeLineJoin' => ['bool', 'linejoin'=>'Imagick::LINEJOIN_*'], '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'=>'Imagick::ALIGN_*'], 'ImagickDraw::setTextAntialias' => ['bool', 'antialias'=>'bool'], 'ImagickDraw::setTextDecoration' => ['bool', 'decoration'=>'Imagick::DECORATION_*'], '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'=>'Imagick::KERNEL_*', 'kernelString'=>'string'], 'ImagickKernel::fromMatrix' => ['ImagickKernel', 'matrix'=>'array', 'origin='=>'array'], 'ImagickKernel::getMatrix' => ['list>'], 'ImagickKernel::scale' => ['void', 'scale'=>'float', 'normalizeFlag'=>'Imagick::NORMALIZE_KERNEL_*'], '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'=>'int|float|__stringNotStringable|bool|array|resource|GMP|SimpleXMLElement|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?:list,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'], 'join\'2' => ['string', 'pieces'=>'array', 'glue'=>'string'], '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?:list,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' => ['list'], '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{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::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|false', 'locale'=>'string', 'displayLocale='=>'string'], 'Locale::getDisplayName' => ['non-empty-string|false', 'locale'=>'string', 'displayLocale='=>'string'], 'Locale::getDisplayRegion' => ['string|false', 'locale'=>'string', 'displayLocale='=>'string'], 'Locale::getDisplayScript' => ['string|false', 'locale'=>'string', 'displayLocale='=>'string'], 'Locale::getDisplayVariant' => ['string|false', '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{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_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|false', 'locale'=>'string', 'displayLocale='=>'string'], 'locale_get_display_name' => ['non-empty-string|false', 'locale'=>'string', 'displayLocale='=>'string'], 'locale_get_display_region' => ['string|false', 'locale'=>'string', 'displayLocale='=>'string'], 'locale_get_display_script' => ['string|false', 'locale'=>'string', 'displayLocale='=>'string'], 'locale_get_display_variant' => ['string|false', '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?:list,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'=>'non-empty-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', 'encoding_list'=>'non-empty-list|non-falsy-string'], 'mb_detect_order\'1' => ['list'], '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'=>'non-empty-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?:list,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'], '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?:list,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?:list,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?:list,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' => ['list', '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' => ['list', '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|false', 'connection_id'=>'resource', 'catalog'=>'string', 'schema'=>'string', 'table'=>'string', 'column'=>'string'], 'odbc_columns' => ['resource|false', '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|false', '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|false', '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|false', '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|false', 'dsn'=>'string', 'user'=>'string', 'password'=>'string', 'cursor_option='=>'int'], 'odbc_prepare' => ['resource|false', 'connection_id'=>'resource', 'query'=>'string'], 'odbc_primarykeys' => ['resource|false', 'connection_id'=>'resource', 'qualifier'=>'string', 'owner'=>'string', 'table'=>'string'], 'odbc_procedurecolumns' => ['resource|false', 'connection_id'=>'', 'qualifier'=>'string', 'owner'=>'string', 'proc'=>'string', 'column'=>'string'], 'odbc_procedures' => ['resource|false', '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|false', 'connection_id'=>'resource', 'type'=>'int', 'qualifier'=>'string', 'owner'=>'string', 'table'=>'string', 'scope'=>'int', 'nullable'=>'int'], 'odbc_statistics' => ['resource|false', 'connection_id'=>'resource', 'qualifier'=>'string', 'owner'=>'string', 'name'=>'string', 'unique'=>'int', 'accuracy'=>'int'], 'odbc_tableprivileges' => ['resource|false', 'connection_id'=>'resource', 'qualifier'=>'string', 'owner'=>'string', 'name'=>'string'], 'odbc_tables' => ['resource|false', 'connection_id'=>'resource', 'qualifier='=>'string', 'owner='=>'string', 'name='=>'string', 'table_types='=>'string'], 'opcache_compile_file' => ['bool', 'file'=>'string'], 'opcache_get_configuration' => ['array{directives: array{\'opcache.enable\': bool, \'opcache.enable_cli\': bool, \'opcache.use_cwd\': bool, \'opcache.validate_timestamps\': bool, \'opcache.validate_permission\': bool, \'opcache.validate_root\'?: bool, \'opcache.dups_fix\': bool, \'opcache.revalidate_path\': bool, \'opcache.log_verbosity_level\': int, \'opcache.memory_consumption\': int, \'opcache.interned_strings_buffer\': int, \'opcache.max_accelerated_files\': int, \'opcache.max_wasted_percentage\': float, \'opcache.consistency_checks\': int, \'opcache.force_restart_timeout\': int, \'opcache.revalidate_freq\': int, \'opcache.preferred_memory_model\': string, \'opcache.blacklist_filename\': string, \'opcache.max_file_size\': int, \'opcache.error_log\': string, \'opcache.protect_memory\': bool, \'opcache.save_comments\': bool, \'opcache.enable_file_override\': bool, \'opcache.optimization_level\': int, \'opcache.lockfile_path\'?: string, \'opcache.mmap_base\'?: string, \'opcache.file_cache\': string, \'opcache.file_cache_only\': bool, \'opcache.file_cache_consistency_checks\': bool, \'opcache.file_cache_fallback\'?: bool, \'opcache.file_update_protection\': int, \'opcache.opt_debug_level\': int, \'opcache.restrict_api\': string, \'opcache.huge_code_pages\'?: bool}, version: array{version: non-empty-string, opcache_product_name: non-empty-string}, blacklist: list}|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?:list,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?:list,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?:list,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?:list,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' => ['(callable(): mixed)|int', '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' => ['__benevolent', '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?:list,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' => ['?bool'], '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'], 'PDOStatement::fetchAll\'1' => ['array|false', 'fetch_column'=>'int', 'colno'=>'int'], 'PDOStatement::fetchAll\'2' => ['array|false', 'fetch_class'=>'int', 'classname'=>'string', 'ctorargs='=>'?array'], 'PDOStatement::fetchAll\'3' => ['array|false', 'fetch_func'=>'int', 'callback'=>'callable'], '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|string|false', 'connection'=>'resource', 'pathname'=>'string', 'oid'=>''], 'pg_lo_import\'1' => ['int|string', '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{name: string, passwd: string, uid: int, gid: int, gecos: string, dir: string, shell: string}|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|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?:list,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?:list,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='=>'RecursiveIteratorIterator::LEAVES_ONLY|RecursiveIteratorIterator::SELF_FIRST|RecursiveIteratorIterator::CHILD_FIRST', 'flags='=>'0|RecursiveIteratorIterator::CATCH_GET_CHILD'], '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::_serialize' => ['mixed', 'value'=>'string'], 'Redis::_unserialize' => ['string', 'value'=>'mixed'], 'Redis::_pack' => ['mixed', 'value'=>'string'], 'Redis::_unpack' => ['string', 'value'=>'mixed'], '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::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::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::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::getDel' => ['__benevolent', 'key'=>'string'], 'Redis::getKeys' => ['array', 'pattern'=>'string'], 'Redis::getMultiple' => ['array', 'keys'=>'string[]'], 'Redis::getOption' => ['int', 'name'=>'int'], 'Redis::getRange' => ['__benevolent', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'Redis::getset' => ['__benevolent', 'key'=>'string', 'value'=>'mixed'], '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::keys' => ['__benevolent|false>', 'pattern'=>'string'], '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::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::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::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::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::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::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::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::watch' => ['__benevolent', 'key'=>'string[]|string', '...other_keys='=>'string'], '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::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::_prefix' => ['string', 'value'=>'mixed'], 'RedisCluster::_serialize' => ['mixed', 'value'=>'mixed'], 'RedisCluster::append' => ['int', 'key'=>'string', 'value'=>'string'], 'RedisCluster::bgrewriteaof' => ['bool', 'nodeParams'=>'string'], 'RedisCluster::bgsave' => ['bool', 'nodeParams'=>'string'], 'RedisCluster::bitCount' => ['int', 'key'=>'string', 'start='=>'int', 'end='=>'int', 'bybit='=>'bool'], 'RedisCluster::bitOp' => ['int', 'operation'=>'string', 'retKey'=>'string', 'key1'=>'string', 'key2'=>'string', 'key3='=>'string'], 'RedisCluster::bitpos' => ['int', 'key'=>'string', 'bit'=>'int', 'start='=>'int', 'end='=>'int', 'bybit='=>'bool'], 'RedisCluster::blPop' => ['array', 'keys'=>'array', 'timeout'=>'int', '...extra_args='=>'mixed'], 'RedisCluster::brPop' => ['array', 'keys'=>'array', 'timeout'=>'int', '...extra_args='=>'mixed'], 'RedisCluster::brpoplpush' => ['string', 'srcKey'=>'string', 'dstKey'=>'string', 'timeout'=>'int'], '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', '...extra_args='=>'mixed'], 'RedisCluster::dbSize' => ['int', 'nodeParams'=>'string'], 'RedisCluster::decr' => ['int', 'key'=>'string', 'by='=>'int'], '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::exec' => ['array|void'], 'RedisCluster::exists' => ['bool', 'key'=>'string', '...other_keys='=>'mixed'], 'RedisCluster::expire' => ['bool', 'key'=>'string', 'ttl'=>'int', 'mode='=>'string|null'], 'RedisCluster::expireAt' => ['bool', 'key'=>'string', 'timestamp'=>'int', 'mode='=>'string|null'], 'RedisCluster::flushAll' => ['bool', 'nodeParams'=>'string', 'async='=>'bool'], 'RedisCluster::flushDB' => ['bool', 'nodeParams'=>'string', 'async='=>'bool'], 'RedisCluster::geoAdd' => ['', 'key'=>'string', 'longitude'=>'float', 'latitude'=>'float', 'member'=>'string', '...other_triples_and_options='=>'mixed'], 'RedisCluster::geoDist' => ['', 'key'=>'string', 'member1'=>'string', 'member2'=>'string', 'unit='=>'string'], 'RedisCluster::geohash' => ['', 'key'=>'', 'member1'=>'', 'member2='=>'mixed', 'memberN='=>'mixed', '...other_members='=>'string'], 'RedisCluster::geopos' => ['', 'key'=>'', 'member1'=>'', 'member2='=>'mixed', 'memberN='=>'mixed', '...other_members='=>'string'], '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::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', '...other_members='=>'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', 'by='=>'int'], 'RedisCluster::incrBy' => ['int', 'key'=>'string', 'value'=>'int'], 'RedisCluster::incrByFloat' => ['float', 'key'=>'string', 'increment'=>'float'], 'RedisCluster::info' => ['string', 'key_or_address='=>'string|array', '...sections='=>'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', 'count='=>'int'], 'RedisCluster::lPush' => ['int', 'key'=>'string', 'value1'=>'string', 'value2='=>'string', 'valueN='=>'string', '...other_values='=>'mixed'], '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' => ['__benevolent', 'mode='=>'int'], 'RedisCluster::object' => ['string', 'string='=>'string', 'key='=>'string'], 'RedisCluster::persist' => ['bool', 'key'=>'string'], 'RedisCluster::pExpire' => ['bool', 'key'=>'string', 'ttl'=>'int', 'mode='=>'string|null'], 'RedisCluster::pExpireAt' => ['bool', 'key'=>'string', 'timestamp'=>'int', 'mode='=>'string|null'], 'RedisCluster::pfAdd' => ['bool', 'key'=>'string', 'elements'=>'array'], 'RedisCluster::pfCount' => ['int', 'key'=>'string'], 'RedisCluster::pfMerge' => ['bool', 'destKey'=>'string', 'sourceKeys'=>'array'], 'RedisCluster::ping' => ['string', 'nodeParams'=>'string', 'message='=>'string|null'], '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'=>'', 'pattern='=>'string', '...other_patterns='=>'string'], 'RedisCluster::randomKey' => ['string', 'nodeParams'=>'string'], 'RedisCluster::rawCommand' => ['mixed', 'key_or_address'=>'string|array', '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', 'options='=>'array|null'], 'RedisCluster::role' => ['array', 'nodeParams'=>'string'], 'RedisCluster::rPop' => ['string', 'key'=>'string', 'count='=>'int'], 'RedisCluster::rpoplpush' => ['string', 'srcKey'=>'string', 'dstKey'=>'string'], 'RedisCluster::rPush' => ['int', 'key'=>'string', 'value1'=>'string', 'value2='=>'string', 'valueN='=>'string', '...elements='=>'mixed'], 'RedisCluster::rPushx' => ['int', 'key'=>'string', 'value'=>'string'], 'RedisCluster::sAdd' => ['int', 'key'=>'string', 'value1'=>'string', 'value2='=>'string', 'valueN='=>'string', '...other_values='=>'mixed'], 'RedisCluster::sAddArray' => ['int', 'key'=>'string', 'valueArray'=>'array'], 'RedisCluster::save' => ['bool', 'nodeParams'=>'string'], 'RedisCluster::scan' => ['array|bool', '&iterator'=>'int|null', 'key_or_address' => 'string|array', 'pattern='=>'string', 'count='=>'int'], 'RedisCluster::sCard' => ['int', 'key'=>'string'], 'RedisCluster::script' => ['mixed', 'nodeParams'=>'string', 'command'=>'string', 'script'=>'string', '...args='=>'mixed'], '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::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', '...args='=>'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', 'count='=>'int'], '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='=>'', 'entries_read='=>'int'], 'RedisCluster::xinfo' => ['', 'str_cmd'=>'string', 'str_key='=>'string', 'str_group='=>'string', 'count='=>'int'], '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='=>'', 'minid='=>'bool', 'limit='=>'int'], 'RedisCluster::zAdd' => ['int', 'key'=>'string', 'score1'=>'float', 'value1'=>'string', 'score2='=>'float', 'value2='=>'string', 'scoreN='=>'float', 'valueN='=>'string', '...more_scores_and_mems='=>'mixed'], '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', 'options='=>'array|bool|null'], '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', 'options='=>'array|null'], 'RedisCluster::zRevRangeByLex' => ['array', 'key'=>'string', 'min'=>'int', 'max'=>'int', 'offset='=>'int', 'limit='=>'int', 'options='=>'array|null'], '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'], 'ReflectionClass::export' => ['string|null', 'argument'=>'string|object', 'return='=>'bool'], 'ReflectionClass::getConstants' => ['array'], 'ReflectionClass::getConstructor' => ['ReflectionMethod|null'], 'ReflectionClass::getDefaultProperties' => ['array'], 'ReflectionClass::getEndLine' => ['positive-int|false'], 'ReflectionClass::getFileName' => ['non-empty-string|false'], 'ReflectionClass::getInterfaceNames' => ['list'], 'ReflectionClass::getInterfaces' => ['array'], 'ReflectionClass::getMethods' => ['list', 'filter='=>'int'], 'ReflectionClass::getName' => ['class-string'], 'ReflectionClass::getProperties' => ['list', 'filter='=>'int'], 'ReflectionClass::getReflectionConstants' => ['list'], 'ReflectionClass::getStartLine' => ['positive-int|false'], 'ReflectionClass::getStaticProperties' => ['array'], 'ReflectionClass::getTraitAliases' => ['array'], 'ReflectionClass::getTraitNames' => ['list'], 'ReflectionClass::getTraits' => ['array'], 'ReflectionClass::implementsInterface' => ['bool', 'interface_name'=>'string|ReflectionClass'], 'ReflectionClass::newInstance' => ['object', 'args='=>'mixed', '...args='=>'mixed'], 'ReflectionClass::newInstanceArgs' => ['object', 'args='=>'array'], 'ReflectionClassConstant::getName' => ['string'], 'ReflectionExtension::getClasses' => ['array'], 'ReflectionExtension::getClassNames' => ['list'], 'ReflectionExtension::getConstants' => ['array'], 'ReflectionExtension::getDependencies' => ['array'], 'ReflectionExtension::getFunctions' => ['array'], 'ReflectionExtension::getINIEntries' => ['array'], 'ReflectionFunctionAbstract::getEndLine' => ['positive-int|false'], 'ReflectionFunctionAbstract::getFileName' => ['non-empty-string|false'], 'ReflectionFunctionAbstract::getName' => ['non-empty-string'], 'ReflectionFunctionAbstract::getParameters' => ['list'], 'ReflectionFunctionAbstract::getStartLine' => ['positive-int|false'], 'ReflectionGenerator::getTrace' => ['list\',args?:list,object?:object}>', 'options'=>'int'], 'ReflectionMethod::__construct' => ['void', 'class'=>'string|object', 'name'=>'string'], 'ReflectionMethod::__construct\'1' => ['void', 'class_method'=>'string'], 'ReflectionParameter::getName' => ['non-empty-string'], 'ReflectionProperty::getName' => ['non-empty-string'], 'ReflectionProperty::setValue' => ['void', 'object'=>'null|object', 'value'=>''], 'ReflectionProperty::setValue\'1' => ['void', 'value'=>''], '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|false', '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?:list,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' => ['__benevolent|false>', 'dir'=>'string', 'sorting_order='=>'SCANDIR_SORT_ASCENDING|SCANDIR_SORT_DESCENDING|SCANDIR_SORT_NONE', '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:\'None\'|\'Lax\'|\'Strict\'|\'none\'|\'lax\'|\'strict\'}'], '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?:\'None\'|\'Lax\'|\'Strict\'|\'none\'|\'lax\'|\'strict\'}'], '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(int):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|false', '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|false|null', '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', 'hostname'=>'string', 'community'=>'non-empty-string', 'object_id'=>'non-empty-string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmp2_get\'1' => ['array|false', 'hostname'=>'string', 'community'=>'non-empty-string', 'object_id'=>'non-empty-array', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmp2_getnext' => ['string|false', 'hostname'=>'string', 'community'=>'non-empty-string', 'object_id'=>'non-empty-string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmp2_real_walk' => ['array|false', 'hostname'=>'string', 'community'=>'non-empty-string', 'object_id'=>'non-empty-string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmp2_set' => ['bool', 'hostname'=>'string', 'community'=>'non-empty-string', 'object_id'=>'non-empty-string', 'type'=>'string', 'value'=>'string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmp2_set\'1' => ['bool', 'hostname'=>'string', 'community'=>'non-empty-string', 'object_id'=>'non-empty-array', 'type'=>'string|non-empty-array', 'value'=>'non-empty-array', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmp2_walk' => ['array|false', 'hostname'=>'string', 'community'=>'non-empty-string', 'object_id'=>'non-empty-string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmp3_get' => ['string|false', 'hostname'=>'string', 'sec_name'=>'string', 'sec_level'=>'\'authPriv\'|\'authNoPriv\'|\'noAuthNoPriv\'', 'auth_protocol'=>'\'SHA\'|\'SHA256\'|\'SHA512\'|\'MD5\'', 'auth_passphrase'=>'string', 'priv_protocol'=>'\'AES\'|\'AES128\'|\'DES\'', 'priv_passphrase'=>'string', 'object_id'=>'non-empty-string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmp3_get\'1' => ['array|false', 'hostname'=>'string', 'sec_name'=>'string', 'sec_level'=>'\'authPriv\'|\'authNoPriv\'|\'noAuthNoPriv\'', 'auth_protocol'=>'\'SHA\'|\'SHA256\'|\'SHA512\'|\'MD5\'', 'auth_passphrase'=>'string', 'priv_protocol'=>'\'AES\'|\'AES128\'|\'DES\'', 'priv_passphrase'=>'string', 'object_id'=>'non-empty-array', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmp3_getnext' => ['string|false', 'hostname'=>'string', 'sec_name'=>'string', 'sec_level'=>'\'authPriv\'|\'authNoPriv\'|\'noAuthNoPriv\'', 'auth_protocol'=>'\'SHA\'|\'SHA256\'|\'SHA512\'|\'MD5\'', 'auth_passphrase'=>'string', 'priv_protocol'=>'\'AES\'|\'AES128\'|\'DES\'', 'priv_passphrase'=>'string', 'object_id'=>'non-empty-string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmp3_real_walk' => ['array|false', 'hostname'=>'string', 'sec_name'=>'string', 'sec_level'=>'\'authPriv\'|\'authNoPriv\'|\'noAuthNoPriv\'', 'auth_protocol'=>'\'SHA\'|\'SHA256\'|\'SHA512\'|\'MD5\'', 'auth_passphrase'=>'string', 'priv_protocol'=>'\'AES\'|\'AES128\'|\'DES\'', 'priv_passphrase'=>'string', 'object_id'=>'non-empty-string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmp3_set' => ['bool', 'hostname'=>'string', 'sec_name'=>'string', 'sec_level'=>'\'authPriv\'|\'authNoPriv\'|\'noAuthNoPriv\'', 'auth_protocol'=>'\'SHA\'|\'SHA256\'|\'SHA512\'|\'MD5\'', 'auth_passphrase'=>'string', 'priv_protocol'=>'\'AES\'|\'AES128\'|\'DES\'', 'priv_passphrase'=>'string', 'object_id'=>'non-empty-string', 'type'=>'string', 'value'=>'string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmp3_set\'1' => ['bool', 'hostname'=>'string', 'sec_name'=>'string', 'sec_level'=>'\'authPriv\'|\'authNoPriv\'|\'noAuthNoPriv\'', 'auth_protocol'=>'\'SHA\'|\'SHA256\'|\'SHA512\'|\'MD5\'', 'auth_passphrase'=>'string', 'priv_protocol'=>'\'AES\'|\'AES128\'|\'DES\'', 'priv_passphrase'=>'string', 'object_id'=>'array', 'type'=>'string|non-empty-array', 'value'=>'non-empty-array', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmp3_walk' => ['array|false', 'hostname'=>'string', 'sec_name'=>'string', 'sec_level'=>'\'authPriv\'|\'authNoPriv\'|\'noAuthNoPriv\'', 'auth_protocol'=>'\'SHA\'|\'SHA256\'|\'SHA512\'|\'MD5\'', 'auth_passphrase'=>'string', 'priv_protocol'=>'\'AES\'|\'AES128\'|\'DES\'', 'priv_passphrase'=>'string', 'object_id'=>'non-empty-string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'SNMP::__construct' => ['void', 'version'=>'int', 'hostname'=>'string', 'community'=>'non-empty-string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'SNMP::close' => ['bool'], 'SNMP::get' => ['array|false', 'objectId'=>'string[]', 'preserveKeys='=>'bool'], 'SNMP::get\'1' => ['string|false', 'objectId'=>'string', 'preserveKeys='=>'bool'], 'SNMP::getErrno' => ['int'], 'SNMP::getError' => ['string'], 'SNMP::getnext' => ['array|false', 'objectId'=>'string[]'], 'SNMP::getnext\'1' => ['string|false', 'objectId'=>'string'], 'SNMP::set' => ['bool', 'objectId'=>'string[]', 'type'=>'string[]|string', 'value'=>'mixed[]'], 'SNMP::set\'1' => ['bool', 'objectId'=>'string', 'type'=>'string', 'value'=>'string'], 'SNMP::setSecurity' => ['bool', 'securityLevel'=>'\'authPriv\'|\'authNoPriv\'|\'noAuthNoPriv\'', 'authProtocol='=>'\'SHA\'|\'SHA256\'|\'SHA512\'|\'MD5\'', 'authPassphrase='=>'string', 'privacyProtocol='=>'\'AES\'|\'AES128\'|\'DES\'', 'privacyPassphrase='=>'string', 'contextName='=>'string', 'contextEngineId='=>'string'], 'SNMP::walk' => ['array|false', 'objectId'=>'string', 'suffixAsKey='=>'bool', 'maxRepetitions='=>'int<-1,max>', 'nonRepeaters='=>'int<-1,max>'], 'snmp_get_quick_print' => ['bool'], 'snmp_get_valueretrieval' => ['int'], 'snmp_read_mib' => ['bool', 'filename'=>'string'], 'snmp_set_enum_print' => ['true', 'enable'=>'bool'], 'snmp_set_oid_numeric_print' => ['true', 'format'=>'int'], 'snmp_set_oid_output_format' => ['true', 'format'=>'int'], 'snmp_set_quick_print' => ['true', 'enable'=>'bool'], 'snmp_set_valueretrieval' => ['true', 'method='=>'int'], 'snmpget' => ['string|false', 'hostname'=>'string', 'community'=>'non-empty-string', 'object_id'=>'non-empty-string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmpget\'1' => ['array|false', 'hostname'=>'string', 'community'=>'non-empty-string', 'object_id'=>'non-empty-array', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmpgetnext' => ['string|false', 'hostname'=>'string', 'community'=>'non-empty-string', 'object_id'=>'non-empty-string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmprealwalk' => ['array|false', 'hostname'=>'string', 'community'=>'non-empty-string', 'object_id'=>'non-empty-string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmpset' => ['bool', 'hostname'=>'string', 'community'=>'non-empty-string', 'object_id'=>'non-empty-string', 'type'=>'string', 'value'=>'string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmpset\'1' => ['bool', 'hostname'=>'string', 'community'=>'non-empty-string', 'object_id'=>'non-empty-array', 'type'=>'string|non-empty-array', 'value'=>'non-empty-array', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmpwalk' => ['array|false', 'hostname'=>'string', 'community'=>'non-empty-string', 'object_id'=>'non-empty-string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], 'snmpwalkoid' => ['array|false', 'hostname'=>'string', 'community'=>'non-empty-string', 'object_id'=>'non-empty-string', 'timeout='=>'int<-1,max>', 'retries='=>'int<-1,max>'], '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::setResponseWriter' => ['void', 'responsewriter'=>'string'], 'SolrDisMaxQuery::addBigramPhraseField' => ['SolrDisMaxQuery', 'field'=>'string', 'boost'=>'string', 'slop='=>'string'], 'SolrDisMaxQuery::addBoostQuery' => ['SolrDisMaxQuery', 'field'=>'string', 'value'=>'string', 'boost='=>'string'], 'SolrDisMaxQuery::addPhraseField' => ['SolrDisMaxQuery', 'field'=>'string', 'boost'=>'string', 'slop='=>'string'], 'SolrDisMaxQuery::addQueryField' => ['SolrDisMaxQuery', 'field'=>'string', 'boost='=>'string'], 'SolrDisMaxQuery::addTrigramPhraseField' => ['SolrDisMaxQuery', 'field'=>'string', 'boost'=>'string', 'slop='=>'string'], 'SolrDisMaxQuery::serialize' => ['string'], 'SolrDisMaxQuery::unserialize' => ['void', 'serialized'=>'string'], 'SolrDocument::__unset' => ['bool', 'fieldname'=>'string'], 'SolrDocument::getField' => ['__benevolent', 'fieldname'=>'string'], 'SolrDocument::getFieldCount' => ['__benevolent'], 'SolrDocument::getFieldNames' => ['__benevolent'], 'SolrDocument::getInputDocument' => ['__benevolent'], 'SolrDocument::next' => ['void'], 'SolrDocument::unserialize' => ['void', 'serialized'=>'string'], 'SolrException::getTrace' => ['list\',args?:list,object?:object}>'], 'SolrInputDocument::addChildDocument' => ['void', 'child'=>'SolrInputDocument'], 'SolrInputDocument::addChildDocuments' => ['void', 'docs'=>'array'], 'SolrInputDocument::getBoost' => ['float'], 'SolrInputDocument::getField' => ['SolrDocumentField', 'fieldname'=>'string'], 'SolrInputDocument::getFieldBoost' => ['float', 'fieldname'=>'string'], 'SolrInputDocument::getFieldCount' => ['int'], 'SolrInputDocument::getFieldNames' => ['array'], 'SolrInputDocument::hasChildDocuments' => ['bool'], 'SolrInputDocument::setFieldBoost' => ['bool', 'fieldname'=>'string', 'fieldboostvalue'=>'float'], 'SolrInputDocument::toArray' => ['array'], 'SolrObject::offsetUnset' => ['void', 'property_name'=>'string'], 'SolrParams::add' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrParams::addParam' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrParams::set' => ['void', 'name'=>'string', 'value'=>'string'], 'SolrParams::setParam' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrParams::toString' => ['string', 'url_encode='=>'bool'], 'SolrQuery::addExpandSortField' => ['SolrQuery', 'field'=>'string', 'order='=>'string'], 'SolrQuery::addFacetDateOther' => ['SolrQuery', 'value'=>'string', 'field_override='=>'string'], 'SolrQuery::addGroupSortField' => ['SolrQuery', 'field'=>'string', 'order='=>'int'], '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::getGroupOffset' => ['int'], '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::removeFacetDateOther' => ['SolrQuery', 'value'=>'string', 'field_override='=>'string'], 'SolrQuery::serialize' => ['string'], '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::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::setHighlightMaxAlternateFieldLength' => ['SolrQuery', 'fieldlength'=>'int', 'field_override='=>'string'], 'SolrQuery::setHighlightMergeContiguous' => ['SolrQuery', 'flag'=>'bool', 'field_override='=>'string'], '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::unserialize' => ['void', 'serialized'=>'string'], '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' => ['non-empty-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-mask', '&w_wouldblock='=>'0|1'], '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' => ['($mode is SQLITE3_NUM ? non-empty-list|false : ($mode is SQLITE3_ASSOC ? non-empty-array|false : non-empty-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' => ['non-negative-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', 'params='=>'mixed'], 'stream_filter_prepend' => ['resource|false', 'stream'=>'resource', 'filtername'=>'string', 'read_write='=>'int', 'params='=>'mixed'], 'stream_filter_register' => ['bool', 'filtername'=>'string', 'classname'=>'string'], 'stream_filter_remove' => ['bool', 'stream_filter'=>'resource'], 'stream_get_contents' => ['__benevolent', '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,crypto?:array{protocol:string,cipher_name:string,cipher_bits:int,cipher_version:string,alpn_protocol?:string}}', '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-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'], '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' => ['non-negative-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|GMP|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{float,float,float}|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?:list,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|false', 'real'=>'array'], 'trader_ad' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'volume'=>'array'], 'trader_add' => ['array|false', 'real0'=>'array', 'real1'=>'array'], 'trader_adosc' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'volume'=>'array', 'fastPeriod='=>'int', 'slowPeriod='=>'int'], 'trader_adx' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_adxr' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_apo' => ['array|false', 'real'=>'array', 'fastPeriod='=>'int', 'slowPeriod='=>'int', 'mAType='=>'int'], 'trader_aroon' => ['array|false', 'high'=>'array', 'low'=>'array', 'timePeriod='=>'int'], 'trader_aroonosc' => ['array|false', 'high'=>'array', 'low'=>'array', 'timePeriod='=>'int'], 'trader_asin' => ['array|false', 'real'=>'array'], 'trader_atan' => ['array|false', 'real'=>'array'], 'trader_atr' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_avgprice' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_bbands' => ['array|false', 'real'=>'array', 'timePeriod='=>'int', 'nbDevUp='=>'float', 'nbDevDn='=>'float', 'mAType='=>'int'], 'trader_beta' => ['array|false', 'real0'=>'array', 'real1'=>'array', 'timePeriod='=>'int'], 'trader_bop' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cci' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_cdl2crows' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3blackcrows' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3inside' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3linestrike' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3outside' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3starsinsouth' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3whitesoldiers' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlabandonedbaby' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdladvanceblock' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlbelthold' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlbreakaway' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlclosingmarubozu' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlconcealbabyswall' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlcounterattack' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdldarkcloudcover' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdldoji' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdldojistar' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdldragonflydoji' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlengulfing' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdleveningdojistar' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdleveningstar' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdlgapsidesidewhite' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlgravestonedoji' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhammer' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhangingman' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlharami' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlharamicross' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhighwave' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhikkake' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhikkakemod' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhomingpigeon' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlidentical3crows' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlinneck' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlinvertedhammer' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlkicking' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlkickingbylength' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlladderbottom' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdllongleggeddoji' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdllongline' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlmarubozu' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlmatchinglow' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlmathold' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdlmorningdojistar' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdlmorningstar' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdlonneck' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlpiercing' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlrickshawman' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlrisefall3methods' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlseparatinglines' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlshootingstar' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlshortline' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlspinningtop' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlstalledpattern' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlsticksandwich' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdltakuri' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdltasukigap' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlthrusting' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdltristar' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlunique3river' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlupsidegap2crows' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlxsidegap3methods' => ['array|false', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_ceil' => ['array|false', 'real'=>'array'], 'trader_cmo' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_correl' => ['array|false', 'real0'=>'array', 'real1'=>'array', 'timePeriod='=>'int'], 'trader_cos' => ['array|false', 'real'=>'array'], 'trader_cosh' => ['array|false', 'real'=>'array'], 'trader_dema' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_div' => ['array|false', 'real0'=>'array', 'real1'=>'array'], 'trader_dx' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_ema' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_errno' => ['int'], 'trader_exp' => ['array|false', 'real'=>'array'], 'trader_floor' => ['array|false', 'real'=>'array'], 'trader_get_compat' => ['int'], 'trader_get_unstable_period' => ['int', 'functionId'=>'int'], 'trader_ht_dcperiod' => ['array|false', 'real'=>'array'], 'trader_ht_dcphase' => ['array|false', 'real'=>'array'], 'trader_ht_phasor' => ['array|false', 'real'=>'array'], 'trader_ht_sine' => ['array|false', 'real'=>'array'], 'trader_ht_trendline' => ['array|false', 'real'=>'array'], 'trader_ht_trendmode' => ['array|false', 'real'=>'array'], 'trader_kama' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_linearreg' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_linearreg_angle' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_linearreg_intercept' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_linearreg_slope' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_ln' => ['array|false', 'real'=>'array'], 'trader_log10' => ['array|false', 'real'=>'array'], 'trader_ma' => ['array|false', 'real'=>'array', 'timePeriod='=>'int', 'mAType='=>'int'], 'trader_macd' => ['array|false', 'real'=>'array', 'fastPeriod='=>'int', 'slowPeriod='=>'int', 'signalPeriod='=>'int'], 'trader_macdext' => ['array|false', 'real'=>'array', 'fastPeriod='=>'int', 'fastMAType='=>'int', 'slowPeriod='=>'int', 'slowMAType='=>'int', 'signalPeriod='=>'int', 'signalMAType='=>'int'], 'trader_macdfix' => ['array|false', 'real'=>'array', 'signalPeriod='=>'int'], 'trader_mama' => ['array|false', 'real'=>'array', 'fastLimit='=>'float', 'slowLimit='=>'float'], 'trader_mavp' => ['array|false', 'real'=>'array', 'periods'=>'array', 'minPeriod='=>'int', 'maxPeriod='=>'int', 'mAType='=>'int'], 'trader_max' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_maxindex' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_medprice' => ['array|false', 'high'=>'array', 'low'=>'array'], 'trader_mfi' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'volume'=>'array', 'timePeriod='=>'int'], 'trader_midpoint' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_midprice' => ['array|false', 'high'=>'array', 'low'=>'array', 'timePeriod='=>'int'], 'trader_min' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_minindex' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_minmax' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_minmaxindex' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_minus_di' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_minus_dm' => ['array|false', 'high'=>'array', 'low'=>'array', 'timePeriod='=>'int'], 'trader_mom' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_mult' => ['array|false', 'real0'=>'array', 'real1'=>'array'], 'trader_natr' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_obv' => ['array|false', 'real'=>'array', 'volume'=>'array'], 'trader_plus_di' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_plus_dm' => ['array|false', 'high'=>'array', 'low'=>'array', 'timePeriod='=>'int'], 'trader_ppo' => ['array|false', 'real'=>'array', 'fastPeriod='=>'int', 'slowPeriod='=>'int', 'mAType='=>'int'], 'trader_roc' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_rocp' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_rocr' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_rocr100' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_rsi' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_sar' => ['array|false', 'high'=>'array', 'low'=>'array', 'acceleration='=>'float', 'maximum='=>'float'], 'trader_sarext' => ['array|false', '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|false', 'real'=>'array'], 'trader_sinh' => ['array|false', 'real'=>'array'], 'trader_sma' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_sqrt' => ['array|false', 'real'=>'array'], 'trader_stddev' => ['array|false', 'real'=>'array', 'timePeriod='=>'int', 'nbDev='=>'float'], 'trader_stoch' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'fastK_Period='=>'int', 'slowK_Period='=>'int', 'slowK_MAType='=>'int', 'slowD_Period='=>'int', 'slowD_MAType='=>'int'], 'trader_stochf' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'fastK_Period='=>'int', 'fastD_Period='=>'int', 'fastD_MAType='=>'int'], 'trader_stochrsi' => ['array|false', 'real'=>'array', 'timePeriod='=>'int', 'fastK_Period='=>'int', 'fastD_Period='=>'int', 'fastD_MAType='=>'int'], 'trader_sub' => ['array|false', 'real0'=>'array', 'real1'=>'array'], 'trader_sum' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_t3' => ['array|false', 'real'=>'array', 'timePeriod='=>'int', 'vFactor='=>'float'], 'trader_tan' => ['array|false', 'real'=>'array'], 'trader_tanh' => ['array|false', 'real'=>'array'], 'trader_tema' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_trange' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_trima' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_trix' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_tsf' => ['array|false', 'real'=>'array', 'timePeriod='=>'int'], 'trader_typprice' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_ultosc' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod1='=>'int', 'timePeriod2='=>'int', 'timePeriod3='=>'int'], 'trader_var' => ['array|false', 'real'=>'array', 'timePeriod='=>'int', 'nbDev='=>'float'], 'trader_wclprice' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_willr' => ['array|false', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_wma' => ['array|false', '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?:list,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?:list,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?:list,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'=>'int', '$all'=>'bool'], 'uopz_add_function\'1' => ['bool', 'function'=>'string', 'handler'=>'Closure', '$flags'=>'int'], '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?:list,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' => ['__benevolent', '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', 'options='=>'array{local_vars?: bool, params_as_values?: bool, from_exception?: Throwable}'], '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|string|null'], 'xml_set_default_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable|string|null'], 'xml_set_element_handler' => ['bool', 'parser'=>'resource', 'shdl'=>'callable|string|null', 'ehdl'=>'callable|string|null'], 'xml_set_end_namespace_decl_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable|string|null'], 'xml_set_external_entity_ref_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable|string|null'], 'xml_set_notation_decl_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable|string|null'], 'xml_set_object' => ['bool', 'parser'=>'resource', 'obj'=>'object'], 'xml_set_processing_instruction_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable|string|null'], 'xml_set_start_namespace_decl_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable|string|null'], 'xml_set_unparsed_entity_decl_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable|string|null'], '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'], ]; [ 'php_uname' => ['string', 'mode='=>'"a"|"s"|"n"|"r"|"v"|"m"'], ], 'old' => [ 'php_uname' => ['string', 'mode='=>'string'], ], ]; [ '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'], 'opcache_get_configuration' => ['array{directives: array{\'opcache.enable\': bool, \'opcache.enable_cli\': bool, \'opcache.use_cwd\': bool, \'opcache.validate_timestamps\': bool, \'opcache.validate_permission\': bool, \'opcache.validate_root\'?: bool, \'opcache.dups_fix\': bool, \'opcache.revalidate_path\': bool, \'opcache.log_verbosity_level\': int, \'opcache.memory_consumption\': int, \'opcache.interned_strings_buffer\': int, \'opcache.max_accelerated_files\': int, \'opcache.max_wasted_percentage\': float, \'opcache.consistency_checks\': int, \'opcache.force_restart_timeout\': int, \'opcache.revalidate_freq\': int, \'opcache.preferred_memory_model\': string, \'opcache.blacklist_filename\': string, \'opcache.max_file_size\': int, \'opcache.error_log\': string, \'opcache.protect_memory\': bool, \'opcache.save_comments\': bool, \'opcache.enable_file_override\': bool, \'opcache.optimization_level\': int, \'opcache.lockfile_path\'?: string, \'opcache.mmap_base\'?: string, \'opcache.file_cache\': string, \'opcache.file_cache_only\': bool, \'opcache.file_cache_consistency_checks\': bool, \'opcache.file_cache_fallback\'?: bool, \'opcache.file_update_protection\': int, \'opcache.opt_debug_level\': int, \'opcache.restrict_api\': string, \'opcache.huge_code_pages\'?: bool, \'opcache.preload\': string, \'opcache.preload_user\'?: string, \'opcache.cache_id\'?: string}, version: array{version: non-empty-string, opcache_product_name: non-empty-string}, blacklist: list}|false'], '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'], 'SplFileObject::fwrite' => ['int|false', 'str'=>'string', 'length='=>'int'], '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'], 'join\'2' => ['string', 'pieces'=>'array', 'glue'=>'string'], 'opcache_get_configuration' => ['array{directives: array{\'opcache.enable\': bool, \'opcache.enable_cli\': bool, \'opcache.use_cwd\': bool, \'opcache.validate_timestamps\': bool, \'opcache.validate_permission\': bool, \'opcache.validate_root\'?: bool, \'opcache.dups_fix\': bool, \'opcache.revalidate_path\': bool, \'opcache.log_verbosity_level\': int, \'opcache.memory_consumption\': int, \'opcache.interned_strings_buffer\': int, \'opcache.max_accelerated_files\': int, \'opcache.max_wasted_percentage\': float, \'opcache.consistency_checks\': int, \'opcache.force_restart_timeout\': int, \'opcache.revalidate_freq\': int, \'opcache.preferred_memory_model\': string, \'opcache.blacklist_filename\': string, \'opcache.max_file_size\': int, \'opcache.error_log\': string, \'opcache.protect_memory\': bool, \'opcache.save_comments\': bool, \'opcache.enable_file_override\': bool, \'opcache.optimization_level\': int, \'opcache.lockfile_path\'?: string, \'opcache.mmap_base\'?: string, \'opcache.file_cache\': string, \'opcache.file_cache_only\': bool, \'opcache.file_cache_consistency_checks\': bool, \'opcache.file_cache_fallback\'?: bool, \'opcache.file_update_protection\': int, \'opcache.opt_debug_level\': int, \'opcache.restrict_api\': string, \'opcache.huge_code_pages\'?: bool}, version: array{version: non-empty-string, opcache_product_name: non-empty-string}, blacklist: list}|false'], ], ]; [ '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'], 'error_log' => ['bool', 'message'=>'string', 'message_type='=>'0|1|3|4', 'destination='=>'string', 'extra_headers='=>'string'], 'explode' => ['list', 'separator'=>'non-empty-string', 'str'=>'string', 'limit='=>'int'], 'fdiv' => ['float', 'dividend'=>'float', 'divisor'=>'float'], 'fgetcsv' => ['non-empty-list|array{0: null}|false', 'fp'=>'resource', 'length='=>'0|positive-int|null', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'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'], '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'=>'non-falsy-string', 'key'=>'string', 'length='=>'0|positive-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'=>'non-falsy-string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'positive-int', 'length='=>'0|positive-int', 'raw_output='=>'bool'], 'imageaffine' => ['false|object', 'src'=>'resource', 'affine'=>'array', 'clip='=>'array'], 'imagecreate' => ['__benevolent', 'width'=>'int<1, max>', 'height'=>'int<1, max>'], '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<1, max>', 'height'=>'int<1, max>'], '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_detect_order' => ['bool', 'encoding_list'=>'non-empty-list|non-falsy-string'], 'mb_detect_order\'1' => ['list', 'encoding_list='=>'null'], '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'], 'odbc_do' => ['resource|false', 'connection_id'=>'resource', 'query'=>'string'], 'opcache_get_configuration' => ['array{directives: array{\'opcache.enable\': bool, \'opcache.enable_cli\': bool, \'opcache.use_cwd\': bool, \'opcache.validate_timestamps\': bool, \'opcache.validate_permission\': bool, \'opcache.validate_root\'?: bool, \'opcache.dups_fix\': bool, \'opcache.revalidate_path\': bool, \'opcache.log_verbosity_level\': int, \'opcache.memory_consumption\': int, \'opcache.interned_strings_buffer\': int, \'opcache.max_accelerated_files\': int, \'opcache.max_wasted_percentage\': float, \'opcache.consistency_checks\': int, \'opcache.force_restart_timeout\': int, \'opcache.revalidate_freq\': int, \'opcache.preferred_memory_model\': string, \'opcache.blacklist_filename\': string, \'opcache.max_file_size\': int, \'opcache.error_log\': string, \'opcache.protect_memory\': bool, \'opcache.save_comments\': bool, \'opcache.record_warnings\': bool, \'opcache.enable_file_override\': bool, \'opcache.optimization_level\': int, \'opcache.lockfile_path\'?: string, \'opcache.mmap_base\'?: string, \'opcache.file_cache\': string, \'opcache.file_cache_only\': bool, \'opcache.file_cache_consistency_checks\': bool, \'opcache.file_cache_fallback\'?: bool, \'opcache.file_update_protection\': int, \'opcache.opt_debug_level\': int, \'opcache.restrict_api\': string, \'opcache.huge_code_pages\'?: bool, \'opcache.preload\': string, \'opcache.preload_user\'?: string, \'opcache.cache_id\'?: string, \'opcache.jit\'?: string, \'opcache.jit_buffer_size\'?: int, \'opcache.jit_debug\'?: int, \'opcache.jit_bisect_limit\'?: int, \'opcache.jit_blacklist_root_trace\'?: int, \'opcache.jit_blacklist_side_trace\'?: int, \'opcache.jit_hot_func\'?: int, \'opcache.jit_hot_loop\'?: int, \'opcache.jit_hot_return\'?: int, \'opcache.jit_hot_side_exit\'?: int, \'opcache.jit_max_exit_counters\'?: int, \'opcache.jit_max_loop_unrolls\'?: int, \'opcache.jit_max_polymorphic_calls\'?: int, \'opcache.jit_max_recursive_calls\'?: int, \'opcache.jit_max_recursive_returns\'?: int, \'opcache.jit_max_root_traces\'?: int, \'opcache.jit_max_side_traces\'?: int, \'opcache.jit_prof_threshold\'?: int}, version: array{version: non-empty-string, opcache_product_name: non-empty-string}, blacklist: list}|false'], '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', 'mode='=>'int'], 'PDOStatement::fetchAll\'1' => ['array', 'mode'=>'int', 'column'=>'int'], 'PDOStatement::fetchAll\'2' => ['array', 'mode'=>'int', 'class'=>'string', 'constructorArgs='=>'?array'], 'PDOStatement::fetchAll\'3' => ['array', 'mode'=>'int', 'callback'=>'callable'], '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'], 'scandir' => ['__benevolent|false>', 'dir'=>'string', 'sorting_order='=>'SCANDIR_SORT_ASCENDING|SCANDIR_SORT_DESCENDING|SCANDIR_SORT_NONE', 'context='=>'?resource'], 'session_set_cookie_params' => ['bool', 'lifetime'=>'int', 'path='=>'string|null', 'domain='=>'string|null', 'secure='=>'bool|null', 'httponly='=>'bool|null'], 'session_set_cookie_params\'1' => ['bool', 'options'=>'array{lifetime?:int,path?:string|null,domain?:string|null,secure?:bool|null,httponly?:bool|null,samesite?:\'None\'|\'Lax\'|\'Strict\'|\'none\'|\'lax\'|\'strict\'}'], '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'], 'opcache_get_configuration' => ['array{directives: array{\'opcache.enable\': bool, \'opcache.enable_cli\': bool, \'opcache.use_cwd\': bool, \'opcache.validate_timestamps\': bool, \'opcache.validate_permission\': bool, \'opcache.validate_root\'?: bool, \'opcache.dups_fix\': bool, \'opcache.revalidate_path\': bool, \'opcache.log_verbosity_level\': int, \'opcache.memory_consumption\': int, \'opcache.interned_strings_buffer\': int, \'opcache.max_accelerated_files\': int, \'opcache.max_wasted_percentage\': float, \'opcache.consistency_checks\': int, \'opcache.force_restart_timeout\': int, \'opcache.revalidate_freq\': int, \'opcache.preferred_memory_model\': string, \'opcache.blacklist_filename\': string, \'opcache.max_file_size\': int, \'opcache.error_log\': string, \'opcache.protect_memory\': bool, \'opcache.save_comments\': bool, \'opcache.enable_file_override\': bool, \'opcache.optimization_level\': int, \'opcache.lockfile_path\'?: string, \'opcache.mmap_base\'?: string, \'opcache.file_cache\': string, \'opcache.file_cache_only\': bool, \'opcache.file_cache_consistency_checks\': bool, \'opcache.file_cache_fallback\'?: bool, \'opcache.file_update_protection\': int, \'opcache.opt_debug_level\': int, \'opcache.restrict_api\': string, \'opcache.huge_code_pages\'?: bool, \'opcache.preload\': string, \'opcache.preload_user\'?: string, \'opcache.cache_id\'?: string}, version: array{version: non-empty-string, opcache_product_name: non-empty-string}, blacklist: list}|false'], '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'], '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?:\'None\'|\'Lax\'|\'Strict\'|\'none\'|\'lax\'|\'strict\'}'], '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'], ] ]; [ 'array_rand' => ['int|string|array|array', 'input'=>'non-empty-array', 'num_req'=>'positive-int'], 'array_rand\'1' => ['int|string', 'input'=>'non-empty-array'], ], 'old' => [ 'array_rand' => ['int|string|array|array', 'input'=>'array', 'num_req'=>'int'], 'array_rand\'1' => ['int|string', 'input'=>'array'], ], ]; [ '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|string|false', 'connection'=>'resource', 'pathname'=>'string', 'oid'=>''], 'pg_lo_import\'1' => ['int|string', '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'], ] ]; [ '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'], 'Random\Randomizer::pickArrayKeys' => ['non-empty-array', 'array'=>'non-empty-array', 'num'=>'positive-int'], ], 'old' => [ ] ]; [ 'DateInterval::createFromDateString' => ['static', 'modify'=>'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}'], 'opcache_get_configuration' => ['array{directives: array{\'opcache.enable\': bool, \'opcache.enable_cli\': bool, \'opcache.use_cwd\': bool, \'opcache.validate_timestamps\': bool, \'opcache.validate_permission\': bool, \'opcache.validate_root\'?: bool, \'opcache.dups_fix\': bool, \'opcache.revalidate_path\': bool, \'opcache.log_verbosity_level\': int, \'opcache.memory_consumption\': int, \'opcache.interned_strings_buffer\': int, \'opcache.max_accelerated_files\': int, \'opcache.max_wasted_percentage\': float, \'opcache.force_restart_timeout\': int, \'opcache.revalidate_freq\': int, \'opcache.preferred_memory_model\': string, \'opcache.blacklist_filename\': string, \'opcache.max_file_size\': int, \'opcache.error_log\': string, \'opcache.protect_memory\': bool, \'opcache.save_comments\': bool, \'opcache.record_warnings\': bool, \'opcache.enable_file_override\': bool, \'opcache.optimization_level\': int, \'opcache.lockfile_path\'?: string, \'opcache.mmap_base\'?: string, \'opcache.file_cache\': string, \'opcache.file_cache_only\': bool, \'opcache.file_cache_consistency_checks\': bool, \'opcache.file_cache_fallback\'?: bool, \'opcache.file_update_protection\': int, \'opcache.opt_debug_level\': int, \'opcache.restrict_api\': string, \'opcache.huge_code_pages\'?: bool, \'opcache.preload\': string, \'opcache.preload_user\'?: string, \'opcache.cache_id\'?: string, \'opcache.jit\'?: string, \'opcache.jit_buffer_size\'?: int, \'opcache.jit_debug\'?: int, \'opcache.jit_bisect_limit\'?: int, \'opcache.jit_blacklist_root_trace\'?: int, \'opcache.jit_blacklist_side_trace\'?: int, \'opcache.jit_hot_func\'?: int, \'opcache.jit_hot_loop\'?: int, \'opcache.jit_hot_return\'?: int, \'opcache.jit_hot_side_exit\'?: int, \'opcache.jit_max_exit_counters\'?: int, \'opcache.jit_max_loop_unrolls\'?: int, \'opcache.jit_max_polymorphic_calls\'?: int, \'opcache.jit_max_recursive_calls\'?: int, \'opcache.jit_max_recursive_returns\'?: int, \'opcache.jit_max_root_traces\'?: int, \'opcache.jit_max_side_traces\'?: int, \'opcache.jit_prof_threshold\'?: float, \'opcache.jit_max_trace_length\'?: int}, version: array{version: non-empty-string, opcache_product_name: non-empty-string}, blacklist: list}|false'], ], 'old' => [ 'dba_fetch\'1' => ['string|false', 'key'=>'string', 'handle'=>'resource'], 'opcache_get_configuration' => ['array{directives: array{\'opcache.enable\': bool, \'opcache.enable_cli\': bool, \'opcache.use_cwd\': bool, \'opcache.validate_timestamps\': bool, \'opcache.validate_permission\': bool, \'opcache.validate_root\'?: bool, \'opcache.dups_fix\': bool, \'opcache.revalidate_path\': bool, \'opcache.log_verbosity_level\': int, \'opcache.memory_consumption\': int, \'opcache.interned_strings_buffer\': int, \'opcache.max_accelerated_files\': int, \'opcache.max_wasted_percentage\': float, \'opcache.consistency_checks\': int, \'opcache.force_restart_timeout\': int, \'opcache.revalidate_freq\': int, \'opcache.preferred_memory_model\': string, \'opcache.blacklist_filename\': string, \'opcache.max_file_size\': int, \'opcache.error_log\': string, \'opcache.protect_memory\': bool, \'opcache.save_comments\': bool, \'opcache.record_warnings\': bool, \'opcache.enable_file_override\': bool, \'opcache.optimization_level\': int, \'opcache.lockfile_path\'?: string, \'opcache.mmap_base\'?: string, \'opcache.file_cache\': string, \'opcache.file_cache_only\': bool, \'opcache.file_cache_consistency_checks\': bool, \'opcache.file_cache_fallback\'?: bool, \'opcache.file_update_protection\': int, \'opcache.opt_debug_level\': int, \'opcache.restrict_api\': string, \'opcache.huge_code_pages\'?: bool, \'opcache.preload\': string, \'opcache.preload_user\'?: string, \'opcache.cache_id\'?: string, \'opcache.jit\'?: string, \'opcache.jit_buffer_size\'?: int, \'opcache.jit_debug\'?: int, \'opcache.jit_bisect_limit\'?: int, \'opcache.jit_blacklist_root_trace\'?: int, \'opcache.jit_blacklist_side_trace\'?: int, \'opcache.jit_hot_func\'?: int, \'opcache.jit_hot_loop\'?: int, \'opcache.jit_hot_return\'?: int, \'opcache.jit_hot_side_exit\'?: int, \'opcache.jit_max_exit_counters\'?: int, \'opcache.jit_max_loop_unrolls\'?: int, \'opcache.jit_max_polymorphic_calls\'?: int, \'opcache.jit_max_recursive_calls\'?: int, \'opcache.jit_max_recursive_returns\'?: int, \'opcache.jit_max_root_traces\'?: int, \'opcache.jit_max_side_traces\'?: int, \'opcache.jit_prof_threshold\'?: int}, version: array{version: non-empty-string, opcache_product_name: non-empty-string}, blacklist: list}|false'], ] ]; [ 'bcround' => ['numeric-string', 'num'=>'numeric-string', 'precision='=>'int', 'mode='=>'RoundingMode'], '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' => [ ] ]; [ 'chr' => ['non-empty-string', 'ascii'=>'int<0,255>'], 'SQLite3Result::fetchAll' => ['($mode is SQLITE3_NUM ? list>|false : ($mode is SQLITE3_ASSOC ? list>|false : list>|false))', 'mode='=>'int'], ], 'old' => [ 'chr' => ['non-empty-string', 'ascii'=>'int'], ] ]; 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], 'DateTimeInterface::diff' => ['hasSideEffects' => false], 'DateTimeInterface::format' => ['hasSideEffects' => false], 'DateTimeInterface::getOffset' => ['hasSideEffects' => false], 'DateTimeInterface::getTimestamp' => ['hasSideEffects' => false], 'DateTimeInterface::getTimezone' => ['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], '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], '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], 'SQLite3Result::fetchArray' => ['hasSideEffects' => true], '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], 'SplDoublyLinkedList::pop' => ['hasSideEffects' => true], 'SplDoublyLinkedList::shift' => ['hasSideEffects' => true], '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], 'SplFixedArray::setSize' => ['hasSideEffects' => true], 'SplHeap::extract' => ['hasSideEffects' => true], 'SplHeap::insert' => ['hasSideEffects' => true], 'SplHeap::recoverFromCorruption' => ['hasSideEffects' => true], 'SplObjectStorage::addAll' => ['hasSideEffects' => true], 'SplObjectStorage::attach' => ['hasSideEffects' => true], 'SplObjectStorage::detach' => ['hasSideEffects' => true], 'SplObjectStorage::removeAll' => ['hasSideEffects' => true], 'SplObjectStorage::removeAllExcept' => ['hasSideEffects' => true], 'SplPriorityQueue::extract' => ['hasSideEffects' => true], 'SplPriorityQueue::insert' => ['hasSideEffects' => true], 'SplPriorityQueue::recoverFromCorruption' => ['hasSideEffects' => true], 'SplQueue::dequeue' => ['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\\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], 'apcu_add' => ['hasSideEffects' => true], 'apcu_cache_info' => ['hasSideEffects' => true], 'apcu_cas' => ['hasSideEffects' => true], 'apcu_clear_cache' => ['hasSideEffects' => true], 'apcu_dec' => ['hasSideEffects' => true], 'apcu_delete' => ['hasSideEffects' => true], 'apcu_enabled' => ['hasSideEffects' => true], 'apcu_entry' => ['hasSideEffects' => true], 'apcu_exists' => ['hasSideEffects' => true], 'apcu_fetch' => ['hasSideEffects' => true], 'apcu_inc' => ['hasSideEffects' => true], 'apcu_key_info' => ['hasSideEffects' => true], 'apcu_sma_info' => ['hasSideEffects' => true], 'apcu_store' => ['hasSideEffects' => true], '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_first' => ['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_last' => ['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], 'bcceil' => ['hasSideEffects' => false], 'bccomp' => ['hasSideEffects' => false], 'bcdiv' => ['hasSideEffects' => false], 'bcfloor' => ['hasSideEffects' => false], 'bcmod' => ['hasSideEffects' => false], 'bcmul' => ['hasSideEffects' => false], 'bcpow' => ['hasSideEffects' => false], 'bcpowmod' => ['hasSideEffects' => false], 'bcround' => ['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' => true], 'collator_compare' => ['hasSideEffects' => false], 'collator_create' => ['hasSideEffects' => false], 'collator_get_attribute' => ['hasSideEffects' => false], 'collator_get_error_code' => ['hasSideEffects' => true], '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' => true], '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' => true], 'curl_error' => ['hasSideEffects' => true], 'curl_escape' => ['hasSideEffects' => false], 'curl_file_create' => ['hasSideEffects' => false], 'curl_getinfo' => ['hasSideEffects' => true], 'curl_multi_errno' => ['hasSideEffects' => true], 'curl_multi_getcontent' => ['hasSideEffects' => false], 'curl_multi_info_read' => ['hasSideEffects' => false], 'curl_share_errno' => ['hasSideEffects' => true], 'curl_share_strerror' => ['hasSideEffects' => false], 'curl_strerror' => ['hasSideEffects' => false], 'curl_unescape' => ['hasSideEffects' => false], 'curl_version' => ['hasSideEffects' => false], 'current' => ['hasSideEffects' => false], 'date' => ['hasSideEffects' => true], 'date_create' => ['hasSideEffects' => true], 'date_create_from_format' => ['hasSideEffects' => true], 'date_create_immutable' => ['hasSideEffects' => true], 'date_create_immutable_from_format' => ['hasSideEffects' => true], 'date_default_timezone_get' => ['hasSideEffects' => false], 'date_diff' => ['hasSideEffects' => true], 'date_format' => ['hasSideEffects' => true], 'date_get_last_errors' => ['hasSideEffects' => true], 'date_interval_create_from_date_string' => ['hasSideEffects' => true], 'date_interval_format' => ['hasSideEffects' => true], 'date_offset_get' => ['hasSideEffects' => true], 'date_parse' => ['hasSideEffects' => true], 'date_parse_from_format' => ['hasSideEffects' => true], 'date_sun_info' => ['hasSideEffects' => true], 'date_sunrise' => ['hasSideEffects' => true], 'date_sunset' => ['hasSideEffects' => true], 'date_timestamp_get' => ['hasSideEffects' => true], 'date_timezone_get' => ['hasSideEffects' => true], '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' => true], 'datefmt_get_error_message' => ['hasSideEffects' => true], '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], 'debug_backtrace' => ['hasSideEffects' => true], 'decbin' => ['hasSideEffects' => false], 'dechex' => ['hasSideEffects' => false], 'decoct' => ['hasSideEffects' => false], 'defined' => ['hasSideEffects' => true], 'deflate_init' => ['hasSideEffects' => false], 'deg2rad' => ['hasSideEffects' => false], 'dirname' => ['hasSideEffects' => false], 'disk_free_space' => ['hasSideEffects' => true], 'disk_total_space' => ['hasSideEffects' => true], 'diskfreespace' => ['hasSideEffects' => true], 'dngettext' => ['hasSideEffects' => false], 'doubleval' => ['hasSideEffects' => false], 'error_get_last' => ['hasSideEffects' => true], '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' => true], 'fflush' => ['hasSideEffects' => true], 'fgetc' => ['hasSideEffects' => true], 'fgetcsv' => ['hasSideEffects' => true], 'fgets' => ['hasSideEffects' => true], 'fgetss' => ['hasSideEffects' => true], 'file' => ['hasSideEffects' => true], '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' => true], 'fopen' => ['hasSideEffects' => true], 'fpassthru' => ['hasSideEffects' => true], 'fputcsv' => ['hasSideEffects' => true], 'fputs' => ['hasSideEffects' => true], 'fread' => ['hasSideEffects' => true], 'fscanf' => ['hasSideEffects' => true], 'fseek' => ['hasSideEffects' => true], 'fstat' => ['hasSideEffects' => true], 'ftell' => ['hasSideEffects' => false], 'ftok' => ['hasSideEffects' => true], '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' => true], 'gc_status' => ['hasSideEffects' => true], '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' => true], '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' => true], 'get_debug_type' => ['hasSideEffects' => false], 'get_declared_classes' => ['hasSideEffects' => true], 'get_declared_interfaces' => ['hasSideEffects' => true], 'get_declared_traits' => ['hasSideEffects' => true], 'get_defined_constants' => ['hasSideEffects' => true], 'get_defined_functions' => ['hasSideEffects' => true], 'get_defined_vars' => ['hasSideEffects' => true], 'get_extension_funcs' => ['hasSideEffects' => false], 'get_headers' => ['hasSideEffects' => true], 'get_html_translation_table' => ['hasSideEffects' => false], 'get_include_path' => ['hasSideEffects' => true], 'get_included_files' => ['hasSideEffects' => true], 'get_loaded_extensions' => ['hasSideEffects' => false], 'get_meta_tags' => ['hasSideEffects' => true], 'get_object_vars' => ['hasSideEffects' => true], 'get_parent_class' => ['hasSideEffects' => false], 'get_required_files' => ['hasSideEffects' => true], 'get_resource_id' => ['hasSideEffects' => false], 'get_resource_type' => ['hasSideEffects' => true], 'get_resources' => ['hasSideEffects' => true], 'getallheaders' => ['hasSideEffects' => false], 'getcwd' => ['hasSideEffects' => true], 'getdate' => ['hasSideEffects' => true], 'getenv' => ['hasSideEffects' => true], 'gethostbyaddr' => ['hasSideEffects' => false], 'gethostbyname' => ['hasSideEffects' => false], 'gethostbynamel' => ['hasSideEffects' => false], 'gethostname' => ['hasSideEffects' => false], 'getlastmod' => ['hasSideEffects' => true], 'getmygid' => ['hasSideEffects' => false], 'getmyinode' => ['hasSideEffects' => false], 'getmypid' => ['hasSideEffects' => false], 'getmyuid' => ['hasSideEffects' => false], 'getopt' => ['hasSideEffects' => true], 'getprotobyname' => ['hasSideEffects' => false], 'getprotobynumber' => ['hasSideEffects' => false], 'getrandmax' => ['hasSideEffects' => false], 'getrusage' => ['hasSideEffects' => true], 'getservbyname' => ['hasSideEffects' => false], 'getservbyport' => ['hasSideEffects' => false], 'gettext' => ['hasSideEffects' => false], 'gettimeofday' => ['hasSideEffects' => true], 'gettype' => ['hasSideEffects' => false], 'glob' => ['hasSideEffects' => true], 'gmdate' => ['hasSideEffects' => true], 'gmmktime' => ['hasSideEffects' => true], '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' => true], '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' => true], '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' => true], 'intcal_get_maximum' => ['hasSideEffects' => false], 'intdiv' => ['hasSideEffects' => false], 'intl_error_name' => ['hasSideEffects' => false], 'intl_get' => ['hasSideEffects' => false], 'intl_get_error_code' => ['hasSideEffects' => true], 'intl_get_error_message' => ['hasSideEffects' => true], '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' => true], 'intlcal_get_error_message' => ['hasSideEffects' => true], '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' => true], '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' => true], 'intltz_get_error_message' => ['hasSideEffects' => true], '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' => true], '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' => true], 'libxml_get_last_error' => ['hasSideEffects' => true], 'link' => ['hasSideEffects' => true], 'linkinfo' => ['hasSideEffects' => true], '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' => true], 'localtime' => ['hasSideEffects' => true], '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_lcfirst' => ['hasSideEffects' => false], 'mb_list_encodings' => ['hasSideEffects' => false], 'mb_ltrim' => ['hasSideEffects' => false], 'mb_ord' => ['hasSideEffects' => false], 'mb_output_handler' => ['hasSideEffects' => false], 'mb_preferred_mime_name' => ['hasSideEffects' => false], 'mb_rtrim' => ['hasSideEffects' => false], 'mb_scrub' => ['hasSideEffects' => false], 'mb_split' => ['hasSideEffects' => false], 'mb_str_pad' => ['hasSideEffects' => true], '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], 'mb_trim' => ['hasSideEffects' => false], 'mb_ucfirst' => ['hasSideEffects' => false], 'mbereg_search_setpos' => ['hasSideEffects' => false], 'md5' => ['hasSideEffects' => false], 'md5_file' => ['hasSideEffects' => true], 'memory_get_peak_usage' => ['hasSideEffects' => true], 'memory_get_usage' => ['hasSideEffects' => true], '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' => true], 'min' => ['hasSideEffects' => false], 'mkdir' => ['hasSideEffects' => true], 'mktime' => ['hasSideEffects' => true], 'move_uploaded_file' => ['hasSideEffects' => true], 'msgfmt_create' => ['hasSideEffects' => false], 'msgfmt_format' => ['hasSideEffects' => false], 'msgfmt_format_message' => ['hasSideEffects' => false], 'msgfmt_get_error_code' => ['hasSideEffects' => true], 'msgfmt_get_error_message' => ['hasSideEffects' => true], '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], 'mysqli_affected_rows' => ['hasSideEffects' => true], 'mysqli_autocommit' => ['hasSideEffects' => true], 'mysqli_begin_transaction' => ['hasSideEffects' => true], 'mysqli_bind_param' => ['hasSideEffects' => true], 'mysqli_bind_result' => ['hasSideEffects' => true], 'mysqli_change_user' => ['hasSideEffects' => true], 'mysqli_character_set_name' => ['hasSideEffects' => true], 'mysqli_client_encoding' => ['hasSideEffects' => true], 'mysqli_close' => ['hasSideEffects' => true], 'mysqli_commit' => ['hasSideEffects' => true], 'mysqli_connect' => ['hasSideEffects' => true], 'mysqli_connect_errno' => ['hasSideEffects' => true], 'mysqli_connect_error' => ['hasSideEffects' => true], 'mysqli_data_seek' => ['hasSideEffects' => true], 'mysqli_debug' => ['hasSideEffects' => true], 'mysqli_dump_debug_info' => ['hasSideEffects' => true], 'mysqli_errno' => ['hasSideEffects' => true], 'mysqli_error' => ['hasSideEffects' => true], 'mysqli_error_list' => ['hasSideEffects' => true], 'mysqli_escape_string' => ['hasSideEffects' => true], 'mysqli_execute' => ['hasSideEffects' => true], 'mysqli_execute_query' => ['hasSideEffects' => true], 'mysqli_fetch' => ['hasSideEffects' => true], 'mysqli_fetch_all' => ['hasSideEffects' => true], 'mysqli_fetch_array' => ['hasSideEffects' => true], 'mysqli_fetch_assoc' => ['hasSideEffects' => true], 'mysqli_fetch_column' => ['hasSideEffects' => true], 'mysqli_fetch_field' => ['hasSideEffects' => true], 'mysqli_fetch_lengths' => ['hasSideEffects' => true], 'mysqli_fetch_object' => ['hasSideEffects' => true], 'mysqli_fetch_row' => ['hasSideEffects' => true], 'mysqli_field_count' => ['hasSideEffects' => true], 'mysqli_field_seek' => ['hasSideEffects' => true], 'mysqli_field_tell' => ['hasSideEffects' => true], 'mysqli_free_result' => ['hasSideEffects' => true], 'mysqli_get_cache_stats' => ['hasSideEffects' => true], 'mysqli_get_charset' => ['hasSideEffects' => true], 'mysqli_get_client_info' => ['hasSideEffects' => true], 'mysqli_get_client_stats' => ['hasSideEffects' => true], 'mysqli_get_client_version' => ['hasSideEffects' => true], 'mysqli_get_connection_stats' => ['hasSideEffects' => true], 'mysqli_get_host_info' => ['hasSideEffects' => true], 'mysqli_get_links_stats' => ['hasSideEffects' => true], 'mysqli_get_metadata' => ['hasSideEffects' => true], 'mysqli_get_proto_info' => ['hasSideEffects' => true], 'mysqli_get_server_info' => ['hasSideEffects' => true], 'mysqli_get_server_version' => ['hasSideEffects' => true], 'mysqli_get_warnings' => ['hasSideEffects' => true], 'mysqli_info' => ['hasSideEffects' => true], 'mysqli_init' => ['hasSideEffects' => true], 'mysqli_insert_id' => ['hasSideEffects' => true], 'mysqli_kill' => ['hasSideEffects' => true], 'mysqli_more_results' => ['hasSideEffects' => true], 'mysqli_multi_query' => ['hasSideEffects' => true], 'mysqli_next_result' => ['hasSideEffects' => true], 'mysqli_options' => ['hasSideEffects' => true], 'mysqli_param_count' => ['hasSideEffects' => true], 'mysqli_ping' => ['hasSideEffects' => true], 'mysqli_poll' => ['hasSideEffects' => true], 'mysqli_prepare' => ['hasSideEffects' => true], 'mysqli_query' => ['hasSideEffects' => true], 'mysqli_real_connect' => ['hasSideEffects' => true], 'mysqli_real_escape_string' => ['hasSideEffects' => true], 'mysqli_real_query' => ['hasSideEffects' => true], 'mysqli_reap_async_query' => ['hasSideEffects' => true], 'mysqli_refresh' => ['hasSideEffects' => true], 'mysqli_release_savepoint' => ['hasSideEffects' => true], 'mysqli_report' => ['hasSideEffects' => true], 'mysqli_rollback' => ['hasSideEffects' => true], 'mysqli_savepoint' => ['hasSideEffects' => true], 'mysqli_select_db' => ['hasSideEffects' => true], 'mysqli_send_long_data' => ['hasSideEffects' => true], 'mysqli_set_charset' => ['hasSideEffects' => true], 'mysqli_set_local_infile_default' => ['hasSideEffects' => true], 'mysqli_set_local_infile_handler' => ['hasSideEffects' => true], 'mysqli_set_opt' => ['hasSideEffects' => true], 'mysqli_sqlstate' => ['hasSideEffects' => true], 'mysqli_ssl_set' => ['hasSideEffects' => true], 'mysqli_stat' => ['hasSideEffects' => true], 'mysqli_stmt_affected_rows' => ['hasSideEffects' => true], 'mysqli_stmt_attr_get' => ['hasSideEffects' => true], 'mysqli_stmt_attr_set' => ['hasSideEffects' => true], 'mysqli_stmt_bind_param' => ['hasSideEffects' => true], 'mysqli_stmt_bind_result' => ['hasSideEffects' => true], 'mysqli_stmt_close' => ['hasSideEffects' => true], 'mysqli_stmt_data_seek' => ['hasSideEffects' => true], 'mysqli_stmt_errno' => ['hasSideEffects' => true], 'mysqli_stmt_error' => ['hasSideEffects' => true], 'mysqli_stmt_error_list' => ['hasSideEffects' => true], 'mysqli_stmt_execute' => ['hasSideEffects' => true], 'mysqli_stmt_fetch' => ['hasSideEffects' => true], 'mysqli_stmt_field_count' => ['hasSideEffects' => true], 'mysqli_stmt_free_result' => ['hasSideEffects' => true], 'mysqli_stmt_get_result' => ['hasSideEffects' => true], 'mysqli_stmt_get_warnings' => ['hasSideEffects' => true], 'mysqli_stmt_init' => ['hasSideEffects' => true], 'mysqli_stmt_insert_id' => ['hasSideEffects' => true], 'mysqli_stmt_more_results' => ['hasSideEffects' => true], 'mysqli_stmt_next_result' => ['hasSideEffects' => true], 'mysqli_stmt_num_rows' => ['hasSideEffects' => true], 'mysqli_stmt_param_count' => ['hasSideEffects' => true], 'mysqli_stmt_prepare' => ['hasSideEffects' => true], 'mysqli_stmt_reset' => ['hasSideEffects' => true], 'mysqli_stmt_result_metadata' => ['hasSideEffects' => true], 'mysqli_stmt_send_long_data' => ['hasSideEffects' => true], 'mysqli_stmt_sqlstate' => ['hasSideEffects' => true], 'mysqli_stmt_store_result' => ['hasSideEffects' => true], 'mysqli_store_result' => ['hasSideEffects' => true], 'mysqli_thread_id' => ['hasSideEffects' => true], 'mysqli_thread_safe' => ['hasSideEffects' => true], 'mysqli_use_result' => ['hasSideEffects' => true], 'mysqli_warning_count' => ['hasSideEffects' => true], 'net_get_interfaces' => ['hasSideEffects' => false], 'ngettext' => ['hasSideEffects' => false], 'nl2br' => ['hasSideEffects' => false], 'nl_langinfo' => ['hasSideEffects' => true], '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' => true], 'numfmt_get_error_message' => ['hasSideEffects' => true], '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_clean' => ['hasSideEffects' => true], 'ob_end_clean' => ['hasSideEffects' => true], 'ob_end_flush' => ['hasSideEffects' => true], 'ob_etaghandler' => ['hasSideEffects' => false], 'ob_flush' => ['hasSideEffects' => true], 'ob_get_clean' => ['hasSideEffects' => true], 'ob_get_contents' => ['hasSideEffects' => true], 'ob_get_length' => ['hasSideEffects' => true], 'ob_get_level' => ['hasSideEffects' => true], 'ob_get_status' => ['hasSideEffects' => true], 'ob_iconv_handler' => ['hasSideEffects' => false], 'ob_list_handlers' => ['hasSideEffects' => true], 'octdec' => ['hasSideEffects' => false], 'ord' => ['hasSideEffects' => false], 'output_add_rewrite_var' => ['hasSideEffects' => true], 'output_reset_rewrite_vars' => ['hasSideEffects' => true], 'pack' => ['hasSideEffects' => false], 'pam_auth' => ['hasSideEffects' => false], 'pam_chpass' => ['hasSideEffects' => false], 'parse_ini_file' => ['hasSideEffects' => true], 'parse_ini_string' => ['hasSideEffects' => false], 'parse_url' => ['hasSideEffects' => false], 'pathinfo' => ['hasSideEffects' => true], 'pclose' => ['hasSideEffects' => true], 'pcntl_errno' => ['hasSideEffects' => true], 'pcntl_get_last_error' => ['hasSideEffects' => true], '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' => true], 'php_uname' => ['hasSideEffects' => true], 'phpversion' => ['hasSideEffects' => false], 'pi' => ['hasSideEffects' => false], 'popen' => ['hasSideEffects' => true], 'pos' => ['hasSideEffects' => false], 'posix_ctermid' => ['hasSideEffects' => false], 'posix_errno' => ['hasSideEffects' => true], 'posix_get_last_error' => ['hasSideEffects' => true], 'posix_getcwd' => ['hasSideEffects' => true], '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' => true], 'preg_last_error_msg' => ['hasSideEffects' => true], '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' => true], 'realpath' => ['hasSideEffects' => true], 'realpath_cache_get' => ['hasSideEffects' => true], 'realpath_cache_size' => ['hasSideEffects' => true], 'rename' => ['hasSideEffects' => true], 'resourcebundle_count' => ['hasSideEffects' => false], 'resourcebundle_create' => ['hasSideEffects' => false], 'resourcebundle_get' => ['hasSideEffects' => false], 'resourcebundle_get_error_code' => ['hasSideEffects' => true], 'resourcebundle_get_error_message' => ['hasSideEffects' => true], 'resourcebundle_locales' => ['hasSideEffects' => false], 'rewind' => ['hasSideEffects' => true], 'rmdir' => ['hasSideEffects' => true], 'round' => ['hasSideEffects' => false], 'rtrim' => ['hasSideEffects' => false], 'sha1' => ['hasSideEffects' => false], 'sha1_file' => ['hasSideEffects' => true], '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' => true], 'stream_get_transports' => ['hasSideEffects' => true], 'stream_get_wrappers' => ['hasSideEffects' => true], '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' => true], 'strrchr' => ['hasSideEffects' => false], 'strrev' => ['hasSideEffects' => false], 'strripos' => ['hasSideEffects' => false], 'strrpos' => ['hasSideEffects' => false], 'strspn' => ['hasSideEffects' => false], 'strstr' => ['hasSideEffects' => false], 'strtolower' => ['hasSideEffects' => false], 'strtotime' => ['hasSideEffects' => true], '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' => true], 'tan' => ['hasSideEffects' => false], 'tanh' => ['hasSideEffects' => false], 'tempnam' => ['hasSideEffects' => true], 'time' => ['hasSideEffects' => true], 'timezone_abbreviations_list' => ['hasSideEffects' => false], 'timezone_identifiers_list' => ['hasSideEffects' => true], 'timezone_location_get' => ['hasSideEffects' => true], 'timezone_name_from_abbr' => ['hasSideEffects' => true], 'timezone_name_get' => ['hasSideEffects' => false], 'timezone_offset_get' => ['hasSideEffects' => true], 'timezone_open' => ['hasSideEffects' => true], 'timezone_transitions_get' => ['hasSideEffects' => true], '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' => true], 'transliterator_get_error_message' => ['hasSideEffects' => true], 'transliterator_list_ids' => ['hasSideEffects' => false], 'transliterator_transliterate' => ['hasSideEffects' => false], 'trim' => ['hasSideEffects' => false], 'ucfirst' => ['hasSideEffects' => false], 'ucwords' => ['hasSideEffects' => false], 'umask' => ['hasSideEffects' => true], 'uniqid' => ['hasSideEffects' => true], 'unlink' => ['hasSideEffects' => true], 'unpack' => ['hasSideEffects' => false], 'urldecode' => ['hasSideEffects' => false], 'urlencode' => ['hasSideEffects' => false], 'utf8_decode' => ['hasSideEffects' => false], 'utf8_encode' => ['hasSideEffects' => false], 'version_compare' => ['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], ];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, list=): 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 CollectorData $collectedData */ $collectedData = []; $internalErrorsCount = 0; $reachedInternalErrorsCountLimit = \false; $dependencies = []; $usedTraitDependencies = []; $exportedNodes = []; $allProcessedFiles = []; 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()); $processedFiles = $fileAnalyserResult->getProcessedFiles(); $allProcessedFiles = array_merge($allProcessedFiles, $processedFiles); $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()]); $processedFiles = [$file]; if ($internalErrorsCount >= $this->internalErrorsCountLimit) { $reachedInternalErrorsCountLimit = \true; break; } } if ($postFileCallback === null) { continue; } $postFileCallback(1, $processedFiles); } 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), $allProcessedFiles); } } */ private array $unorderedErrors; /** * @var list */ private array $filteredPhpErrors; /** * @var list */ private array $allPhpErrors; /** * @var list */ private array $locallyIgnoredErrors; /** * @var array */ private array $linesToIgnore; /** * @var array */ private array $unmatchedLineIgnores; /** * @var list */ private array $internalErrors; /** * @var CollectorData */ private array $collectedData; /** * @var array>|null */ private ?array $dependencies; /** * @var array>|null */ private ?array $usedTraitDependencies; /** * @var array> */ private array $exportedNodes; private bool $reachedInternalErrorsCountLimit; private int $peakMemoryUsageBytes; /** * @var list */ private array $processedFiles; /** @var list|null */ private ?array $errors = null; /** * @param list $unorderedErrors * @param list $filteredPhpErrors * @param list $allPhpErrors * @param list $locallyIgnoredErrors * @param array $linesToIgnore * @param array $unmatchedLineIgnores * @param CollectorData $collectedData * @param list $internalErrors * @param array>|null $dependencies * @param array>|null $usedTraitDependencies * @param array> $exportedNodes * @param list $processedFiles */ 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, array $processedFiles) { $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; $this->processedFiles = $processedFiles; } /** * @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 fn(\PHPStan\Analyser\Error $a, \PHPStan\Analyser\Error $b): int => [$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 CollectorData */ 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; } /** * @return list */ public function getProcessedFiles(): array { return $this->processedFiles; } } ruleRegistry = $ruleRegistry; $this->ignoreErrorExtensionProvider = $ignoreErrorExtensionProvider; $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) { $error = $this->ruleErrorTransformer->transform($ruleError, $scope, [], $node); if ($error->canBeIgnored()) { foreach ($this->ignoreErrorExtensionProvider->getExtensions() as $ignoreErrorExtension) { if ($ignoreErrorExtension->shouldIgnore($error, $node, $scope)) { continue 2; } } } $tempCollectorErrors[] = $error; } } $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(), $analyserResult->getProcessedFiles()), $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(), $analyserResult->getProcessedFiles()); } /** * @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['name'], $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(), $analyserResult->getProcessedFiles()), $collectorErrors, $locallyIgnoredCollectorErrors); } } 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 = TrinaryLogic::createYes(); foreach ($callableParametersAcceptors as $callableParametersAcceptor) { $acceptsNamedArguments = $acceptsNamedArguments->and($callableParametersAcceptor->acceptsNamedArguments()); } return [$parametersAcceptor, new FuncCall($callbackArg->value, $passThruArgs, $callUserFuncCall->getAttributes()), $acceptsNamedArguments]; } /** * @return array{ParametersAcceptor, FuncCall, TrinaryLogic}|null */ public static function reorderCallUserFuncArrayArguments(FuncCall $callUserFuncArrayCall, \PHPStan\Analyser\Scope $scope): ?array { $args = $callUserFuncArrayCall->getArgs(); if (count($args) < 2) { return null; } $callbackArg = null; $argsArrayArg = 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; } } if ($argsArrayArg !== null) { continue; } if ($arg->name === null && $i === 1) { $argsArrayArg = $arg; continue; } if ($arg->name === null || $arg->name->toString() !== 'args') { continue; } $argsArrayArg = $arg; } if ($callbackArg === null || $argsArrayArg === null) { return null; } if (!$argsArrayArg->value instanceof Array_) { return null; } $passThruArgs = []; foreach ($argsArrayArg->value->items as $item) { $key = null; if ($item->key instanceof String_) { /** @var int|string $key */ $key = key([$item->key->value => null]); if ($key === '') { return null; } } elseif ($item->key !== null && !$item->key instanceof Int_) { // Dynamic key, we cannot be sure. return null; } $passThruArgs[] = new Arg($item->value, $item->byRef, $item->unpack, $item->getAttributes(), is_string($key) ? new Identifier($key) : null); } $calledOnType = $scope->getType($callbackArg->value); if (!$calledOnType->isCallable()->yes()) { return null; } $callableParametersAcceptors = $calledOnType->getCallableParametersAcceptors($scope); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $passThruArgs, $callableParametersAcceptors, null); $acceptsNamedArguments = TrinaryLogic::createYes(); foreach ($callableParametersAcceptors as $callableParametersAcceptor) { $acceptsNamedArguments = $acceptsNamedArguments->and($callableParametersAcceptor->acceptsNamedArguments()); } return [$parametersAcceptor, new FuncCall($callbackArg->value, $passThruArgs, $callUserFuncArrayCall->getAttributes()), $acceptsNamedArguments]; } public static function reorderFuncArguments(ParametersAcceptor $parametersAcceptor, FuncCall $functionCall): ?FuncCall { $args = $functionCall->getArgs(); $reorderedArgs = self::reorderArgs($parametersAcceptor, $args); if ($reorderedArgs === null) { return null; } // return identical object if not reordered, as TypeSpecifier relies on object identity if ($reorderedArgs === $args) { return $functionCall; } return new FuncCall($functionCall->name, $reorderedArgs, $functionCall->getAttributes()); } public static function reorderMethodArguments(ParametersAcceptor $parametersAcceptor, MethodCall $methodCall): ?MethodCall { $args = $methodCall->getArgs(); $reorderedArgs = self::reorderArgs($parametersAcceptor, $args); if ($reorderedArgs === null) { return null; } // return identical object if not reordered, as TypeSpecifier relies on object identity if ($reorderedArgs === $args) { return $methodCall; } return new MethodCall($methodCall->var, $methodCall->name, $reorderedArgs, $methodCall->getAttributes()); } public static function reorderStaticCallArguments(ParametersAcceptor $parametersAcceptor, StaticCall $staticCall): ?StaticCall { $args = $staticCall->getArgs(); $reorderedArgs = self::reorderArgs($parametersAcceptor, $args); if ($reorderedArgs === null) { return null; } // return identical object if not reordered, as TypeSpecifier relies on object identity if ($reorderedArgs === $args) { return $staticCall; } return new StaticCall($staticCall->class, $staticCall->name, $reorderedArgs, $staticCall->getAttributes()); } public static function reorderNewArguments(ParametersAcceptor $parametersAcceptor, New_ $new): ?New_ { $args = $new->getArgs(); $reorderedArgs = self::reorderArgs($parametersAcceptor, $args); if ($reorderedArgs === null) { return null; } // return identical object if not reordered, as TypeSpecifier relies on object identity if ($reorderedArgs === $args) { return $new; } return new New_($new->class, $reorderedArgs, $new->getAttributes()); } /** * @param Arg[] $callArgs * @return ?list */ public static function reorderArgs(ParametersAcceptor $parametersAcceptor, array $callArgs): ?array { if (count($callArgs) === 0) { return []; } $hasNamedArgs = \false; foreach ($callArgs as $arg) { if ($arg->name !== null) { $hasNamedArgs = \true; break; } } if (!$hasNamedArgs) { return array_values($callArgs); } $hasVariadic = \false; $argumentPositions = []; $signatureParameters = $parametersAcceptor->getParameters(); 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 $attributes = $arg->getAttributes(); $attributes[self::ORIGINAL_ARG_ATTRIBUTE] = $arg; $reorderedArgs[$i] = new Arg($arg->value, $arg->byRef, $arg->unpack, $attributes, null); } 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; if (array_key_exists($argumentPositions[$argName], $reorderedArgs)) { continue; } $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)) { return null; } $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(sprintf('An optional parameter $%s must have a default value', $parameter->getName())); } $defaultValue = new ConstantArrayType([], []); } $reorderedArgs[$j] = new Arg(new TypeExpr($defaultValue)); } ksort($reorderedArgs); foreach ($appendArgs as $arg) { $reorderedArgs[] = $arg; } if (!array_is_list($reorderedArgs)) { $reorderedArgs = array_values($reorderedArgs); } return $reorderedArgs; } } */ private array $conditionExpressionTypeHolders; private \PHPStan\Analyser\ExpressionTypeHolder $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()); } } */ private array $currentlyResolving = []; /** @var array */ private array $configuredTypesCache = []; /** * @param string[] $dynamicConstantNames * @param int|array{min: int, max: int}|null $phpVersion */ public function __construct(ReflectionProviderProvider $reflectionProviderProvider, array $dynamicConstantNames, $phpVersion, ComposerPhpVersionFactory $composerPhpVersionFactory, ?Container $container) { $this->reflectionProviderProvider = $reflectionProviderProvider; $this->dynamicConstantNames = $dynamicConstantNames; $this->phpVersion = $phpVersion; $this->composerPhpVersionFactory = $composerPhpVersionFactory; $this->container = $container; } 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()]); } $minPhpVersion = null; $maxPhpVersion = null; if (in_array($resolvedConstantName, ['PHP_VERSION_ID', 'PHP_MAJOR_VERSION', 'PHP_MINOR_VERSION', 'PHP_RELEASE_VERSION'], \true)) { $minPhpVersion = $this->getMinPhpVersion(); $maxPhpVersion = $this->getMaxPhpVersion(); } if ($resolvedConstantName === 'PHP_MAJOR_VERSION') { $minMajor = 5; $maxMajor = null; if ($minPhpVersion !== null) { $minMajor = max($minMajor, $minPhpVersion->getMajorVersionId()); } if ($maxPhpVersion !== null) { $maxMajor = $maxPhpVersion->getMajorVersionId(); } return $this->createInteger($minMajor, $maxMajor); } if ($resolvedConstantName === 'PHP_MINOR_VERSION') { $minMinor = 0; $maxMinor = null; if ($minPhpVersion !== null && $maxPhpVersion !== null && $maxPhpVersion->getMajorVersionId() === $minPhpVersion->getMajorVersionId()) { $minMinor = $minPhpVersion->getMinorVersionId(); $maxMinor = $maxPhpVersion->getMinorVersionId(); } return $this->createInteger($minMinor, $maxMinor); } if ($resolvedConstantName === 'PHP_RELEASE_VERSION') { $minRelease = 0; $maxRelease = null; if ($minPhpVersion !== null && $maxPhpVersion !== null && $maxPhpVersion->getMajorVersionId() === $minPhpVersion->getMajorVersionId() && $maxPhpVersion->getMinorVersionId() === $minPhpVersion->getMinorVersionId()) { $minRelease = $minPhpVersion->getPatchVersionId(); $maxRelease = $maxPhpVersion->getPatchVersionId(); } return $this->createInteger($minRelease, $maxRelease); } if ($resolvedConstantName === 'PHP_VERSION_ID') { $minVersion = self::PHP_MIN_ANALYZABLE_VERSION_ID; $maxVersion = null; if ($minPhpVersion !== null) { $minVersion = max($minVersion, $minPhpVersion->getVersionId()); } if ($maxPhpVersion !== null) { $maxVersion = $maxPhpVersion->getVersionId(); } return $this->createInteger($minVersion, $maxVersion); } // added in PHP 8.5 if ($resolvedConstantName === 'PHP_BUILD_DATE') { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } 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; } private function getMinPhpVersion(): ?PhpVersion { if (is_int($this->phpVersion)) { return null; } if (is_array($this->phpVersion)) { if ($this->phpVersion['max'] < $this->phpVersion['min']) { throw new ShouldNotHappenException('Invalid PHP version range: phpVersion.max should be greater or equal to phpVersion.min.'); } return new PhpVersion($this->phpVersion['min']); } return $this->composerPhpVersionFactory->getMinVersion(); } private function getMaxPhpVersion(): ?PhpVersion { if (is_int($this->phpVersion)) { return null; } if (is_array($this->phpVersion)) { if ($this->phpVersion['max'] < $this->phpVersion['min']) { throw new ShouldNotHappenException('Invalid PHP version range: phpVersion.max should be greater or equal to phpVersion.min.'); } return new PhpVersion($this->phpVersion['max']); } return $this->composerPhpVersionFactory->getMaxVersion(); } public function getConfiguredGlobalConstantType(string $constantName): ?Type { if (array_key_exists($constantName, $this->configuredTypesCache)) { return $this->configuredTypesCache[$constantName]; } $result = null; if (array_key_exists($constantName, $this->dynamicConstantNames)) { $phpdocTypes = $this->dynamicConstantNames[$constantName]; if ($this->container !== null) { $typeStringResolver = $this->container->getByType(TypeStringResolver::class); $result = $typeStringResolver->resolve($phpdocTypes, new \PHPStan\Analyser\NameScope(null, [], null)); } } $this->configuredTypesCache[$constantName] = $result; return $result; } public function getConfiguredClassConstantType(string $className, string $constantName): ?Type { $lookupConstantName = sprintf('%s::%s', $className, $constantName); if (array_key_exists($lookupConstantName, $this->configuredTypesCache)) { return $this->configuredTypesCache[$lookupConstantName]; } $result = null; if (array_key_exists($lookupConstantName, $this->dynamicConstantNames)) { $phpdocTypes = $this->dynamicConstantNames[$lookupConstantName]; if ($this->container !== null) { $typeStringResolver = $this->container->getByType(TypeStringResolver::class); $result = $typeStringResolver->resolve($phpdocTypes, new \PHPStan\Analyser\NameScope(null, [], $className)); } } $this->configuredTypesCache[$lookupConstantName] = $result; return $result; } public function resolveConstantType(string $constantName, Type $constantType): Type { if ($constantType->isConstantValue()->yes()) { if (array_key_exists($constantName, $this->dynamicConstantNames)) { return $this->getConfiguredGlobalConstantType($constantName) ?? $constantType; } if (in_array($constantName, $this->dynamicConstantNames, \true)) { return $this->generalizeDynamicConstantType($constantType); } } return $constantType; } public function resolveClassConstantType(string $className, string $constantName, Type $constantType, ?Type $nativeType, ?Type $phpDocType): Type { $lookupConstantName = sprintf('%s::%s', $className, $constantName); if (array_key_exists($lookupConstantName, $this->dynamicConstantNames)) { if ($constantType->isConstantValue()->yes()) { $explicitType = $this->getConfiguredClassConstantType($className, $constantName); if ($explicitType !== null) { return $explicitType; } } if ($nativeType !== null) { return $nativeType; } return $constantType; } if (in_array($lookupConstantName, $this->dynamicConstantNames, \true)) { if ($nativeType !== null) { return $nativeType; } if ($phpDocType !== null) { return $phpDocType; } if ($constantType->isConstantValue()->yes()) { return $this->generalizeDynamicConstantType($constantType); } } return $constantType; } private function generalizeDynamicConstantType(Type $constantType): Type { $generalized = $constantType->generalize(GeneralizePrecision::lessSpecific()); if ($generalized->equals(new ConstantArrayType([], []))) { return new ArrayType(new MixedType(), new MixedType()); } return $generalized; } private function createInteger(?int $min, ?int $max): Type { if ($min !== null && $min === $max) { return new ConstantIntegerType($min); } return IntegerRangeType::fromInterval($min, $max); } private function getReflectionProvider(): ReflectionProvider { return $this->reflectionProviderProvider->getReflectionProvider(); } } reflectionProviderProvider = $reflectionProviderProvider; $this->container = $container; } public function create(): \PHPStan\Analyser\ConstantResolver { $composerFactory = $this->container->getByType(ComposerPhpVersionFactory::class); return new \PHPStan\Analyser\ConstantResolver($this->reflectionProviderProvider, $this->container->getParameter('dynamicConstantNames'), $this->container->getParameter('phpVersion'), $composerFactory, $this->container); } } container = $container; $this->reflectionProvider = $reflectionProvider; $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->expressionTypeResolverExtensionRegistryProvider = $expressionTypeResolverExtensionRegistryProvider; $this->exprPrinter = $exprPrinter; $this->typeSpecifier = $typeSpecifier; $this->propertyReflectionFinder = $propertyReflectionFinder; $this->parser = $parser; $this->phpVersion = $phpVersion; $this->attributeReflectionFactory = $attributeReflectionFactory; $this->configPhpVersion = $configPhpVersion; $this->nodeCallback = $nodeCallback; $this->constantResolver = $constantResolver; $this->fiber = $fiber; } /** * @param \PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection|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 = [], ?ClosureType $anonymousFunctionReflection = null, bool $inFirstLevelStatement = \true, array $currentlyAssignedExpressions = [], array $currentlyAllowedUndefinedExpressions = [], array $inFunctionCallsStack = [], bool $afterExtractCall = \false, ?\PHPStan\Analyser\MutatingScope $parentScope = null, bool $nativeTypesPromoted = \false): \PHPStan\Analyser\MutatingScope { $className = \PHPStan\Analyser\MutatingScope::class; if ($this->fiber) { $className = FiberScope::class; } return new $className($this->container, $this, $this->reflectionProvider, $this->initializerExprTypeResolver, $this->expressionTypeResolverExtensionRegistryProvider->getRegistry(), $this->exprPrinter, $this->typeSpecifier, $this->propertyReflectionFinder, $this->parser, $this->constantResolver, $context, $this->phpVersion, $this->attributeReflectionFactory, $this->configPhpVersion, $this->nodeCallback, $declareStrictTypes, $function, $namespace, $expressionTypes, $nativeExpressionTypes, $conditionalExpressions, $inClosureBindScopeClasses, $anonymousFunctionReflection, $inFirstLevelStatement, $currentlyAssignedExpressions, $currentlyAllowedUndefinedExpressions, $inFunctionCallsStack, $afterExtractCall, $parentScope, $nativeTypesPromoted); } public function toFiberFactory(): \PHPStan\Analyser\InternalScopeFactory { return new self($this->container, $this->reflectionProvider, $this->initializerExprTypeResolver, $this->expressionTypeResolverExtensionRegistryProvider, $this->exprPrinter, $this->typeSpecifier, $this->propertyReflectionFinder, $this->parser, $this->phpVersion, $this->attributeReflectionFactory, $this->configPhpVersion, $this->nodeCallback, $this->constantResolver, \true); } public function toMutatingFactory(): \PHPStan\Analyser\InternalScopeFactory { return new self($this->container, $this->reflectionProvider, $this->initializerExprTypeResolver, $this->expressionTypeResolverExtensionRegistryProvider, $this->exprPrinter, $this->typeSpecifier, $this->propertyReflectionFinder, $this->parser, $this->phpVersion, $this->attributeReflectionFactory, $this->configPhpVersion, $this->nodeCallback, $this->constantResolver, \false); } } container = $container; $this->reflectionProvider = $reflectionProvider; $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->expressionTypeResolverExtensionRegistryProvider = $expressionTypeResolverExtensionRegistryProvider; $this->exprPrinter = $exprPrinter; $this->typeSpecifier = $typeSpecifier; $this->propertyReflectionFinder = $propertyReflectionFinder; $this->parser = $parser; $this->phpVersion = $phpVersion; $this->attributeReflectionFactory = $attributeReflectionFactory; $this->configPhpVersion = $configPhpVersion; $this->constantResolver = $constantResolver; } /** * @param callable(Node $node, Scope $scope): void|null $nodeCallback */ public function create(?callable $nodeCallback): \PHPStan\Analyser\DirectInternalScopeFactory { return new \PHPStan\Analyser\DirectInternalScopeFactory($this->container, $this->reflectionProvider, $this->initializerExprTypeResolver, $this->expressionTypeResolverExtensionRegistryProvider, $this->exprPrinter, $this->typeSpecifier, $this->propertyReflectionFinder, $this->parser, $this->phpVersion, $this->attributeReflectionFactory, $this->configPhpVersion, $nodeCallback, $this->constantResolver); } } statement = $statement; $this->result = $result; } public function getStatement(): Stmt { return $this->statement; } public function getResult(): \PHPStan\Analyser\StatementResult { return $this->result; } } scope = $scope; $this->specifiedExpressions = $specifiedExpressions; } public function getScope(): \PHPStan\Analyser\MutatingScope { return $this->scope; } /** * @return EnsuredNonNullabilityResultExpression[] */ public function getSpecifiedExpressions(): array { return $this->specifiedExpressions; } } 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; } } |null */ private ?string $nodeType; private ?string $identifier; /** * @var mixed[] */ private array $metadata; private ?\PHPStan\Analyser\FixedErrorDiff $fixedErrorDiff; 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 = [], ?\PHPStan\Analyser\FixedErrorDiff $fixedErrorDiff = null) { $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; $this->fixedErrorDiff = $fixedErrorDiff; 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, $this->fixedErrorDiff); } 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, $this->fixedErrorDiff); } 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, $this->identifier, $this->metadata, $this->fixedErrorDiff); } 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, $this->identifier, $this->metadata, $this->fixedErrorDiff); } 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, $this->fixedErrorDiff); } /** * @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, $this->fixedErrorDiff); } 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; } /** * @internal Experimental */ public function getFixedErrorDiff(): ?\PHPStan\Analyser\FixedErrorDiff { return $this->fixedErrorDiff; } /** * @return mixed */ #[ReturnTypeWillChange] #[Override] public function jsonSerialize() { $fixedErrorDiffHash = null; $fixedErrorDiffDiff = null; if ($this->fixedErrorDiff !== null) { $fixedErrorDiffHash = $this->fixedErrorDiff->originalHash; $fixedErrorDiffDiff = $this->fixedErrorDiff->diff; } 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, 'fixedErrorDiffHash' => $fixedErrorDiffHash, 'fixedErrorDiffDiff' => $fixedErrorDiffDiff]; } /** * @param mixed[] $json */ public static function decode(array $json): self { $fixedErrorDiff = null; if ($json['fixedErrorDiffHash'] !== null && $json['fixedErrorDiffDiff'] !== null) { $fixedErrorDiff = new \PHPStan\Analyser\FixedErrorDiff($json['fixedErrorDiffHash'], $json['fixedErrorDiffDiff']); } 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'] ?? [], $fixedErrorDiff); } /** * @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'] ?? [], $properties['fixedErrorDiff'] ?? null); } public static function validateIdentifier(string $identifier): bool { return Strings::match($identifier, '~^' . self::PATTERN_IDENTIFIER . '$~') !== null; } } */ #[AutowiredService] final class ArrayDimFetchHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof ArrayDimFetch; } public function resolveType(MutatingScope $scope, Expr $expr): Type { if ($expr->dim === null) { return new NeverType(); } $offsetAccessibleType = $scope->getType($expr->var); if (!$offsetAccessibleType->isArray()->yes() && (new ObjectType(ArrayAccess::class))->isSuperTypeOf($offsetAccessibleType)->yes()) { return NullsafeShortCircuitingHelper::getType($scope, $expr->var, $scope->getType(new MethodCall($expr->var, new Identifier('offsetGet'), [new Arg($expr->dim)]))); } $offsetType = $scope->getType($expr->dim); return NullsafeShortCircuitingHelper::getType($scope, $expr->var, $offsetAccessibleType->getOffsetValueType($offsetType)); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { if ($expr->dim === null) { $varResult = $nodeScopeResolver->processExprNode($stmt, $expr->var, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $varResult->getScope(); return new ExpressionResult($scope, $varResult->hasYield(), $varResult->isAlwaysTerminating(), $varResult->getThrowPoints(), $varResult->getImpurePoints(), static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } $dimResult = $nodeScopeResolver->processExprNode($stmt, $expr->dim, $scope, $storage, $nodeCallback, $context->enterDeep()); $varResult = $nodeScopeResolver->processExprNode($stmt, $expr->var, $dimResult->getScope(), $storage, $nodeCallback, $context->enterDeep()); $throwPoints = array_merge($dimResult->getThrowPoints(), $varResult->getThrowPoints()); $impurePoints = array_merge($dimResult->getImpurePoints(), $varResult->getImpurePoints()); $scope = $varResult->getScope(); $varType = $scope->getType($expr->var); if (!$varType->isArray()->yes() && !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->no()) { $throwPoints = array_merge($throwPoints, $nodeScopeResolver->processExprNode($stmt, new MethodCall(new TypeExpr($varType), 'offsetGet'), $scope, $storage, new NoopNodeCallback(), $context)->getThrowPoints()); } return new ExpressionResult($scope, $dimResult->hasYield() || $varResult->hasYield(), $dimResult->isAlwaysTerminating() || $varResult->isAlwaysTerminating(), $throwPoints, $impurePoints, static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } } */ #[AutowiredService] final class ArrayHandler implements ExprHandler { private InitializerExprTypeResolver $initializerExprTypeResolver; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; } public function supports(Expr $expr): bool { return $expr instanceof Array_; } public function resolveType(MutatingScope $scope, Expr $expr): Type { $type = $this->initializerExprTypeResolver->getArrayType($expr, static fn(Expr $expr): Type => $scope->getType($expr)); if (count($expr->items) === 2 && isset($expr->items[0], $expr->items[1]) && $type->isCallable()->maybe()) { $isCallableCall = new FuncCall(new FullyQualified('is_callable'), [new Arg($expr)]); if ($scope->hasExpressionType($isCallableCall)->yes() && $scope->getType($isCallableCall)->isTrue()->yes()) { $type = TypeCombinator::intersect($type, new CallableType()); } } return $type; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $itemNodes = []; $hasYield = \false; $throwPoints = []; $impurePoints = []; $isAlwaysTerminating = \false; foreach ($expr->items as $arrayItem) { $itemNodes[] = new LiteralArrayItem($scope, $arrayItem); $nodeScopeResolver->callNodeCallback($nodeCallback, $arrayItem, $scope, $storage); if ($arrayItem->key !== null) { $keyResult = $nodeScopeResolver->processExprNode($stmt, $arrayItem->key, $scope, $storage, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $keyResult->hasYield(); $throwPoints = array_merge($throwPoints, $keyResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $keyResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $keyResult->isAlwaysTerminating(); $scope = $keyResult->getScope(); } $valueResult = $nodeScopeResolver->processExprNode($stmt, $arrayItem->value, $scope, $storage, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $valueResult->hasYield(); $throwPoints = array_merge($throwPoints, $valueResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $valueResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $valueResult->isAlwaysTerminating(); $scope = $valueResult->getScope(); } $nodeScopeResolver->callNodeCallback($nodeCallback, new LiteralArrayNode($expr, $itemNodes), $scope, $storage); return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints); } } */ #[AutowiredService] final class ArrowFunctionHandler implements ExprHandler { private ClosureTypeResolver $closureTypeResolver; public function __construct(ClosureTypeResolver $closureTypeResolver) { $this->closureTypeResolver = $closureTypeResolver; } public function supports(Expr $expr): bool { return $expr instanceof ArrowFunction; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $result = $nodeScopeResolver->processArrowFunctionNode($stmt, $expr, $scope, $storage, $nodeCallback, null); return new ExpressionResult($result->getScope(), $result->hasYield(), \false, [], []); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $this->closureTypeResolver->getClosureType($scope, $expr); } } */ #[AutowiredService] final class AssignHandler implements ExprHandler { private TypeSpecifier $typeSpecifier; private PhpVersion $phpVersion; public function __construct(TypeSpecifier $typeSpecifier, PhpVersion $phpVersion) { $this->typeSpecifier = $typeSpecifier; $this->phpVersion = $phpVersion; } public function supports(Expr $expr): bool { return $expr instanceof Assign || $expr instanceof AssignRef; } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $scope->getType($expr->expr); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $result = $this->processAssignVar($nodeScopeResolver, $scope, $storage, $stmt, $expr->var, $expr->expr, $nodeCallback, $context, static function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $storage, $nodeScopeResolver): 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 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, $expr->expr); } $nodeScopeResolver->storeBeforeScope($storage, $expr, $scope); $result = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context->enterDeep()); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $isAlwaysTerminating = $result->isAlwaysTerminating(); $scope = $result->getScope(); if ($expr instanceof AssignRef) { $scope = $scope->exitExpressionAssign($expr->expr); } return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints); }, \true); $scope = $result->getScope(); if ($expr instanceof AssignRef && $expr->var instanceof Variable && is_string($expr->var->name) && $expr->expr instanceof Variable && is_string($expr->expr->name)) { $varName = $expr->var->name; $refName = $expr->expr->name; $type = $scope->getType($expr->var); $nativeType = $scope->getNativeType($expr->var); // When $varName is assigned, update $refName $scope = $scope->assignExpression(new IntertwinedVariableByReferenceWithExpr($varName, new Variable($refName), new Variable($varName)), $type, $nativeType); // When $refName is assigned, update $varName $scope = $scope->assignExpression(new IntertwinedVariableByReferenceWithExpr($refName, new Variable($varName), new Variable($refName)), $type, $nativeType); } $vars = $nodeScopeResolver->getAssignedVariables($expr->var); if (count($vars) > 0) { $varChangedScope = \false; $scope = $nodeScopeResolver->processVarAnnotation($scope, $vars, $stmt, $varChangedScope); if (!$varChangedScope) { $scope = $nodeScopeResolver->processStmtVarAnnotation($scope, $storage, $stmt, null, $nodeCallback); } } return new ExpressionResult($scope, $result->hasYield(), $result->isAlwaysTerminating(), $result->getThrowPoints(), $result->getImpurePoints(), static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } /** * @param callable(Node $node, Scope $scope): void $nodeCallback * @param Closure(MutatingScope $scope): ExpressionResult $processExprCallback */ public function processAssignVar(NodeScopeResolver $nodeScopeResolver, MutatingScope $scope, ExpressionResultStorage $storage, Node\Stmt $stmt, Expr $var, Expr $assignedExpr, callable $nodeCallback, ExpressionContext $context, Closure $processExprCallback, bool $enterExpressionAssign): ExpressionResult { $nodeScopeResolver->callNodeCallback($nodeCallback, $var, $enterExpressionAssign ? $scope->enterExpressionAssign($var) : $scope, $storage); $hasYield = \false; $throwPoints = []; $impurePoints = []; $isAlwaysTerminating = \false; $isAssignOp = $assignedExpr instanceof Expr\AssignOp && !$enterExpressionAssign; if ($var instanceof Variable) { $nodeScopeResolver->storeBeforeScope($storage, $var, $scope); $result = $processExprCallback($scope); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $isAlwaysTerminating = $result->isAlwaysTerminating(); $scopeBeforeAssignEval = $scope; $scope = $result->getScope(); if (is_string($var->name)) { if (in_array($var->name, Scope::SUPERGLOBAL_VARIABLES, \true)) { $impurePoints[] = new ImpurePoint($scopeBeforeAssignEval, $var, 'superglobal', 'assign to superglobal variable', \true); } $assignedExpr = $this->unwrapAssign($assignedExpr); $type = $scopeBeforeAssignEval->getType($assignedExpr); $conditionalExpressions = []; if ($assignedExpr instanceof Ternary) { $if = $assignedExpr->if; if ($if === null) { $if = $assignedExpr->cond; } $condScope = $nodeScopeResolver->processExprNode($stmt, $assignedExpr->cond, $scope, $storage->duplicate(), new NoopNodeCallback(), ExpressionContext::createDeep())->getScope(); $truthySpecifiedTypes = $this->typeSpecifier->specifyTypesInCondition($condScope, $assignedExpr->cond, TypeSpecifierContext::createTruthy()); $falseySpecifiedTypes = $this->typeSpecifier->specifyTypesInCondition($condScope, $assignedExpr->cond, 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, $impurePoints, $assignedExpr); $conditionalExpressions = $this->processSureNotTypesForConditionalExpressionsAfterAssign($condScope, $var->name, $conditionalExpressions, $truthySpecifiedTypes, $truthyType, $impurePoints, $assignedExpr); $conditionalExpressions = $this->processSureTypesForConditionalExpressionsAfterAssign($condScope, $var->name, $conditionalExpressions, $falseySpecifiedTypes, $falseyType, $impurePoints, $assignedExpr); $conditionalExpressions = $this->processSureNotTypesForConditionalExpressionsAfterAssign($condScope, $var->name, $conditionalExpressions, $falseySpecifiedTypes, $falseyType, $impurePoints, $assignedExpr); } } $truthyType = TypeCombinator::removeFalsey($type); if ($truthyType !== $type) { $truthySpecifiedTypes = $this->typeSpecifier->specifyTypesInCondition($scope, $assignedExpr, TypeSpecifierContext::createTruthy()); $conditionalExpressions = $this->processSureTypesForConditionalExpressionsAfterAssign($scope, $var->name, $conditionalExpressions, $truthySpecifiedTypes, $truthyType, $impurePoints, $assignedExpr); $conditionalExpressions = $this->processSureNotTypesForConditionalExpressionsAfterAssign($scope, $var->name, $conditionalExpressions, $truthySpecifiedTypes, $truthyType, $impurePoints, $assignedExpr); $falseyType = TypeCombinator::intersect($type, StaticTypeFactory::falsey()); $falseySpecifiedTypes = $this->typeSpecifier->specifyTypesInCondition($scope, $assignedExpr, TypeSpecifierContext::createFalsey()); $conditionalExpressions = $this->processSureTypesForConditionalExpressionsAfterAssign($scope, $var->name, $conditionalExpressions, $falseySpecifiedTypes, $falseyType, $impurePoints, $assignedExpr); $conditionalExpressions = $this->processSureNotTypesForConditionalExpressionsAfterAssign($scope, $var->name, $conditionalExpressions, $falseySpecifiedTypes, $falseyType, $impurePoints, $assignedExpr); } foreach ([null, \false, 0, 0.0, '', '0', []] as $falseyScalar) { $falseyType = ConstantTypeHelper::getTypeFromValue($falseyScalar); $withoutFalseyType = TypeCombinator::remove($type, $falseyType); if ($withoutFalseyType->equals($type) || $withoutFalseyType->equals($truthyType)) { continue; } if ($falseyScalar === null) { $astNode = new ConstFetch(new Name('null')); } elseif ($falseyScalar === \false) { $astNode = new ConstFetch(new Name('false')); } elseif ($falseyScalar === 0) { $astNode = new Node\Scalar\Int_($falseyScalar); } elseif ($falseyScalar === 0.0) { $astNode = new Node\Scalar\Float_($falseyScalar); } elseif (in_array($falseyScalar, ['', '0'], \true)) { $astNode = new Node\Scalar\String_($falseyScalar); } elseif ($falseyScalar === []) { $astNode = new Node\Expr\Array_($falseyScalar); } $notIdenticalConditionExpr = new Expr\BinaryOp\NotIdentical($assignedExpr, $astNode); $notIdenticalSpecifiedTypes = $this->typeSpecifier->specifyTypesInCondition($scope, $notIdenticalConditionExpr, TypeSpecifierContext::createTrue()); $conditionalExpressions = $this->processSureTypesForConditionalExpressionsAfterAssign($scope, $var->name, $conditionalExpressions, $notIdenticalSpecifiedTypes, $withoutFalseyType, $impurePoints, $assignedExpr); $conditionalExpressions = $this->processSureNotTypesForConditionalExpressionsAfterAssign($scope, $var->name, $conditionalExpressions, $notIdenticalSpecifiedTypes, $withoutFalseyType, $impurePoints, $assignedExpr); $identicalConditionExpr = new Expr\BinaryOp\Identical($assignedExpr, $astNode); $identicalSpecifiedTypes = $this->typeSpecifier->specifyTypesInCondition($scope, $identicalConditionExpr, TypeSpecifierContext::createTrue()); $conditionalExpressions = $this->processSureTypesForConditionalExpressionsAfterAssign($scope, $var->name, $conditionalExpressions, $identicalSpecifiedTypes, $falseyType, $impurePoints, $assignedExpr); $conditionalExpressions = $this->processSureNotTypesForConditionalExpressionsAfterAssign($scope, $var->name, $conditionalExpressions, $identicalSpecifiedTypes, $falseyType, $impurePoints, $assignedExpr); } $nodeScopeResolver->callNodeCallback($nodeCallback, new VariableAssignNode($var, $assignedExpr), $scopeBeforeAssignEval, $storage); $scope = $scope->assignVariable($var->name, $type, $scope->getNativeType($assignedExpr), TrinaryLogic::createYes()); foreach ($conditionalExpressions as $exprString => $holders) { $scope = $scope->addConditionalExpressions((string) $exprString, $holders); } if ($assignedExpr instanceof Expr\Array_) { $scope = $this->processArrayByRefItems($scope, $var->name, $assignedExpr, new Variable($var->name)); } } else { $nameExprResult = $nodeScopeResolver->processExprNode($stmt, $var->name, $scope, $storage, $nodeCallback, $context); $hasYield = $hasYield || $nameExprResult->hasYield(); $throwPoints = array_merge($throwPoints, $nameExprResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $nameExprResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $nameExprResult->isAlwaysTerminating(); $scope = $nameExprResult->getScope(); } } 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); } if ($var === $originalVar && $var->dim !== null && $scope->hasExpressionType($var)->yes()) { $assignedPropertyExpr = new SetExistingOffsetValueTypeExpr($varForSetOffsetValue, $var->dim, $assignedPropertyExpr); } else { $assignedPropertyExpr = new SetOffsetValueTypeExpr($varForSetOffsetValue, $var->dim, $assignedPropertyExpr); } $dimFetchStack[] = $var; $var = $var->var; } // 1. eval root expr if ($enterExpressionAssign) { $scope = $scope->enterExpressionAssign($var); } $result = $nodeScopeResolver->processExprNode($stmt, $var, $scope, $storage, $nodeCallback, $context->enterDeep()); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $isAlwaysTerminating = $result->isAlwaysTerminating(); $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) { $nodeScopeResolver->callNodeCallback($nodeCallback, $dimFetch, $enterExpressionAssign ? $scope->enterExpressionAssign($dimFetch) : $scope, $storage); } if ($dimExpr === null) { $offsetTypes[] = [null, $dimFetch]; $offsetNativeTypes[] = [null, $dimFetch]; $nodeScopeResolver->storeBeforeScope($storage, $dimFetch, $scope); } else { $offsetTypes[] = [$scope->getType($dimExpr), $dimFetch]; $offsetNativeTypes[] = [$scope->getNativeType($dimExpr), $dimFetch]; if ($enterExpressionAssign) { $scope->enterExpressionAssign($dimExpr); } $nodeScopeResolver->storeBeforeScope($storage, $dimFetch, $scope); $result = $nodeScopeResolver->processExprNode($stmt, $dimExpr, $scope, $storage, $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); $scopeBeforeAssignEval = $scope; // 3. eval assigned expr $result = $processExprCallback($scope); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $result->isAlwaysTerminating(); $scope = $result->getScope(); $varType = $scope->getType($var); $varNativeType = $scope->getNativeType($var); // 4. compose types $isImplicitArrayCreation = $this->isImplicitArrayCreation($dimFetchStack, $scope); if ($isImplicitArrayCreation->yes()) { $varType = new ConstantArrayType([], []); $varNativeType = new ConstantArrayType([], []); } $offsetValueType = $varType; $offsetNativeValueType = $varNativeType; [$valueToWrite, $additionalExpressions] = $this->produceArrayDimFetchAssignValueToWrite($dimFetchStack, $offsetTypes, $offsetValueType, $valueToWrite, $scope); if (!$offsetValueType->equals($offsetNativeValueType) || !$valueToWrite->equals($nativeValueToWrite)) { [$nativeValueToWrite, $additionalNativeExpressions] = $this->produceArrayDimFetchAssignValueToWrite($dimFetchStack, $offsetNativeTypes, $offsetNativeValueType, $nativeValueToWrite, $scope); } 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($dimFetchStack, $offsetNativeTypes, $offsetNativeValueType, $nativeValueToWrite, $scope); $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)) { $nodeScopeResolver->callNodeCallback($nodeCallback, new VariableAssignNode($var, new TypeExpr($valueToWrite)), $scopeBeforeAssignEval, $storage); $scope = $scope->assignVariable($var->name, $valueToWrite, $nativeValueToWrite, TrinaryLogic::createYes()); } else { if ($var instanceof PropertyFetch || $var instanceof StaticPropertyFetch) { $nodeScopeResolver->callNodeCallback($nodeCallback, new PropertyAssignNode($var, $assignedPropertyExpr, $isAssignOp), $scopeBeforeAssignEval, $storage); 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); } } else if ($var instanceof Variable) { $nodeScopeResolver->callNodeCallback($nodeCallback, new VariableAssignNode($var, $assignedPropertyExpr), $scopeBeforeAssignEval, $storage); } elseif ($var instanceof PropertyFetch || $var instanceof StaticPropertyFetch) { $nodeScopeResolver->callNodeCallback($nodeCallback, new PropertyAssignNode($var, $assignedPropertyExpr, $isAssignOp), $scopeBeforeAssignEval, $storage); if ($var instanceof PropertyFetch && $var->name instanceof Node\Identifier && !$isAssignOp) { $scope = $scope->assignInitializedProperty($scope->getType($var->var), $var->name->toString()); } } foreach ($additionalExpressions as $k => $additionalExpression) { [$expr, $type] = $additionalExpression; $nativeType = $type; if (isset($additionalNativeExpressions[$k])) { [, $nativeType] = $additionalNativeExpressions[$k]; } $scope = $scope->assignExpression($expr, $type, $nativeType); } $setVarType = $scope->getType($originalVar->var); if (!$setVarType instanceof ErrorType && !$setVarType->isArray()->yes() && !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($setVarType)->no()) { $throwPoints = array_merge($throwPoints, $nodeScopeResolver->processExprNode($stmt, new MethodCall(new TypeExpr($setVarType), 'offsetSet'), $scope, $storage, new NoopNodeCallback(), $context)->getThrowPoints()); } } elseif ($var instanceof PropertyFetch) { $nodeScopeResolver->storeBeforeScope($storage, $var, $scope); $objectResult = $nodeScopeResolver->processExprNode($stmt, $var->var, $scope, $storage, $nodeCallback, $context); $hasYield = $objectResult->hasYield(); $throwPoints = $objectResult->getThrowPoints(); $impurePoints = $objectResult->getImpurePoints(); $isAlwaysTerminating = $objectResult->isAlwaysTerminating(); $scope = $objectResult->getScope(); $propertyName = null; if ($var->name instanceof Node\Identifier) { $propertyName = $var->name->name; } else { $propertyNameResult = $nodeScopeResolver->processExprNode($stmt, $var->name, $scope, $storage, $nodeCallback, $context); $hasYield = $hasYield || $propertyNameResult->hasYield(); $throwPoints = array_merge($throwPoints, $propertyNameResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $propertyNameResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $propertyNameResult->isAlwaysTerminating(); $scope = $propertyNameResult->getScope(); } $scopeBeforeAssignEval = $scope; $result = $processExprCallback($scope); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $result->isAlwaysTerminating(); $scope = $result->getScope(); if ($var->name instanceof Expr && $this->phpVersion->supportsPropertyHooks()) { $throwPoints[] = InternalThrowPoint::createImplicit($scope, $var); } $propertyHolderType = $scope->getType($var->var); if ($propertyName !== null && $propertyHolderType->hasInstanceProperty($propertyName)->yes()) { $propertyReflection = $propertyHolderType->getInstanceProperty($propertyName, $scope); $assignedExprType = $scope->getType($assignedExpr); $nodeScopeResolver->callNodeCallback($nodeCallback, new PropertyAssignNode($var, $assignedExpr, $isAssignOp), $scopeBeforeAssignEval, $storage); if ($propertyReflection->canChangeTypeAfterAssignment()) { if ($propertyReflection->hasNativeType()) { $propertyNativeType = $propertyReflection->getNativeType(); $assignedTypeIsCompatible = $propertyNativeType->isSuperTypeOf($assignedExprType)->yes(); if (!$assignedTypeIsCompatible) { foreach (TypeUtils::flattenTypes($propertyNativeType) as $type) { if ($type->isSuperTypeOf($assignedExprType)->yes()) { $assignedTypeIsCompatible = \true; break; } } } if ($assignedTypeIsCompatible) { $scope = $scope->assignExpression($var, $assignedExprType, $scope->getNativeType($assignedExpr)); } else { $scope = $scope->assignExpression($var, TypeCombinator::intersect($assignedExprType->toCoercedArgumentType($scope->isDeclareStrictTypes()), $propertyNativeType), TypeCombinator::intersect($scope->getNativeType($assignedExpr)->toCoercedArgumentType($scope->isDeclareStrictTypes()), $propertyNativeType)); } } else { $scope = $scope->assignExpression($var, $assignedExprType, $scope->getNativeType($assignedExpr)); } } $declaringClass = $propertyReflection->getDeclaringClass(); if ($declaringClass->hasNativeProperty($propertyName)) { $nativeProperty = $declaringClass->getNativeProperty($propertyName); $propertyNativeType = $nativeProperty->getNativeType(); $assignedTypeIsCompatible = $propertyNativeType->isSuperTypeOf($assignedExprType)->yes(); if (!$assignedTypeIsCompatible && !$assignedExprType instanceof MixedType) { foreach (TypeUtils::flattenTypes($assignedExprType->toCoercedArgumentType(\true)) as $type) { $accepts = $propertyNativeType->accepts($type, \true); if ($accepts->yes()) { $assignedTypeIsCompatible = \true; continue; } $assignedTypeIsCompatible = \false; break; } } if (!$assignedTypeIsCompatible) { $throwPoints[] = InternalThrowPoint::createExplicit($scope, new ObjectType(TypeError::class), $assignedExpr, \false); } if ($this->phpVersion->supportsPropertyHooks()) { $throwPoints = array_merge($throwPoints, $nodeScopeResolver->getThrowPointsFromPropertyHook($scope, $var, $nativeProperty, 'set')); } if ($enterExpressionAssign) { $scope = $scope->assignInitializedProperty($propertyHolderType, $propertyName); } } } else { // fallback $assignedExprType = $scope->getType($assignedExpr); $nodeScopeResolver->callNodeCallback($nodeCallback, new PropertyAssignNode($var, $assignedExpr, $isAssignOp), $scopeBeforeAssignEval, $storage); $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, $nodeScopeResolver->processExprNode($stmt, new MethodCall($var->var, '__set'), $scope, $storage, new NoopNodeCallback(), $context)->getThrowPoints()); } } } elseif ($var instanceof Expr\StaticPropertyFetch) { $nodeScopeResolver->storeBeforeScope($storage, $var, $scope); if ($var->class instanceof Node\Name) { $propertyHolderType = $scope->resolveTypeByName($var->class); } else { $nodeScopeResolver->processExprNode($stmt, $var->class, $scope, $storage, $nodeCallback, $context); $propertyHolderType = $scope->getType($var->class); } $propertyName = null; if ($var->name instanceof Node\Identifier) { $propertyName = $var->name->name; } else { $propertyNameResult = $nodeScopeResolver->processExprNode($stmt, $var->name, $scope, $storage, $nodeCallback, $context); $hasYield = $propertyNameResult->hasYield(); $throwPoints = $propertyNameResult->getThrowPoints(); $impurePoints = $propertyNameResult->getImpurePoints(); $isAlwaysTerminating = $propertyNameResult->isAlwaysTerminating(); $scope = $propertyNameResult->getScope(); } $scopeBeforeAssignEval = $scope; $result = $processExprCallback($scope); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $result->isAlwaysTerminating(); $scope = $result->getScope(); if ($propertyName !== null) { $propertyReflection = $scope->getStaticPropertyReflection($propertyHolderType, $propertyName); $assignedExprType = $scope->getType($assignedExpr); $nodeScopeResolver->callNodeCallback($nodeCallback, new PropertyAssignNode($var, $assignedExpr, $isAssignOp), $scopeBeforeAssignEval, $storage); if ($propertyReflection !== null && $propertyReflection->canChangeTypeAfterAssignment()) { if ($propertyReflection->hasNativeType()) { $propertyNativeType = $propertyReflection->getNativeType(); $assignedTypeIsCompatible = $propertyNativeType->isSuperTypeOf($assignedExprType)->yes(); if (!$assignedTypeIsCompatible) { foreach (TypeUtils::flattenTypes($propertyNativeType) as $type) { if ($type->isSuperTypeOf($assignedExprType)->yes()) { $assignedTypeIsCompatible = \true; break; } } } if ($assignedTypeIsCompatible) { $scope = $scope->assignExpression($var, $assignedExprType, $scope->getNativeType($assignedExpr)); } else { $scope = $scope->assignExpression($var, TypeCombinator::intersect($assignedExprType->toCoercedArgumentType($scope->isDeclareStrictTypes()), $propertyNativeType), TypeCombinator::intersect($scope->getNativeType($assignedExpr)->toCoercedArgumentType($scope->isDeclareStrictTypes()), $propertyNativeType)); } } else { $scope = $scope->assignExpression($var, $assignedExprType, $scope->getNativeType($assignedExpr)); } } } else { // fallback $assignedExprType = $scope->getType($assignedExpr); $nodeScopeResolver->callNodeCallback($nodeCallback, new PropertyAssignNode($var, $assignedExpr, $isAssignOp), $scopeBeforeAssignEval, $storage); $scope = $scope->assignExpression($var, $assignedExprType, $scope->getNativeType($assignedExpr)); } } elseif ($var instanceof List_) { $nodeScopeResolver->storeBeforeScope($storage, $var, $scope); $result = $processExprCallback($scope); $hasYield = $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $isAlwaysTerminating = $result->isAlwaysTerminating(); $scope = $result->getScope(); foreach ($var->items as $i => $arrayItem) { if ($arrayItem === null) { continue; } $itemScope = $scope; if ($enterExpressionAssign) { $itemScope = $itemScope->enterExpressionAssign($arrayItem->value); } $itemScope = $nodeScopeResolver->lookForSetAllowedUndefinedExpressions($itemScope, $arrayItem->value); $nodeScopeResolver->callNodeCallback($nodeCallback, $arrayItem, $itemScope, $storage); if ($arrayItem->key !== null) { $keyResult = $nodeScopeResolver->processExprNode($stmt, $arrayItem->key, $itemScope, $storage, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $keyResult->hasYield(); $throwPoints = array_merge($throwPoints, $keyResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $keyResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $keyResult->isAlwaysTerminating(); $scope = $keyResult->getScope(); } if ($arrayItem->key === null) { $dimExpr = new Node\Scalar\Int_($i); } else { $dimExpr = $arrayItem->key; } $result = $this->processAssignVar($nodeScopeResolver, $scope, $storage, $stmt, $arrayItem->value, new GetOffsetValueTypeExpr($assignedExpr, $dimExpr), $nodeCallback, $context, static fn(MutatingScope $scope): ExpressionResult => new ExpressionResult($scope, \false, \false, [], []), $enterExpressionAssign); $scope = $result->getScope(); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $result->isAlwaysTerminating(); } } 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), $dimFetch]; $offsetNativeTypes[] = [$scope->getNativeType($dimExpr), $dimFetch]; } $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)) { $nodeScopeResolver->callNodeCallback($nodeCallback, new VariableAssignNode($var, $assignedPropertyExpr), $scope, $storage); $scope = $scope->assignVariable($var->name, $valueToWrite, $nativeValueToWrite, TrinaryLogic::createYes()); } else { if ($var instanceof PropertyFetch || $var instanceof StaticPropertyFetch) { $nodeScopeResolver->callNodeCallback($nodeCallback, new PropertyAssignNode($var, $assignedPropertyExpr, $isAssignOp), $scope, $storage); } $scope = $scope->assignExpression($var, $valueToWrite, $nativeValueToWrite); } } else { $varResult = $nodeScopeResolver->processExprNode($stmt, $var, $scope, $storage, $nodeCallback, $context); $hasYield = $varResult->hasYield(); $throwPoints = array_merge($throwPoints, $varResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $varResult->getImpurePoints()); $isAlwaysTerminating = $varResult->isAlwaysTerminating(); $scope = $varResult->getScope(); $result = $processExprCallback($scope); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $result->isAlwaysTerminating(); $scope = $result->getScope(); } // stored where processAssignVar is called return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints); } private function unwrapAssign(Expr $expr): Expr { if ($expr instanceof Assign) { return $this->unwrapAssign($expr->expr); } return $expr; } /** * @param array $conditionalExpressions * @param ImpurePoint[] $rhsImpurePoints * @return array */ private function processSureTypesForConditionalExpressionsAfterAssign(Scope $scope, string $variableName, array $conditionalExpressions, SpecifiedTypes $specifiedTypes, Type $variableType, array $rhsImpurePoints, Expr $assignedExpr): array { foreach ($specifiedTypes->getSureTypes() as $exprString => [$expr, $exprType]) { if (!$this->isExprSafeToProjectThroughVariable($expr, $variableName, $rhsImpurePoints, $assignedExpr)) { continue; } $exprString = (string) $exprString; if (!isset($conditionalExpressions[$exprString])) { $conditionalExpressions[$exprString] = []; } $holder = new ConditionalExpressionHolder(['$' . $variableName => ExpressionTypeHolder::createYes(new Variable($variableName), $variableType)], ExpressionTypeHolder::createYes($expr, TypeCombinator::intersect($scope->getType($expr), $exprType))); $conditionalExpressions[$exprString][$holder->getKey()] = $holder; } return $conditionalExpressions; } /** * @param array $conditionalExpressions * @param ImpurePoint[] $rhsImpurePoints * @return array */ private function processSureNotTypesForConditionalExpressionsAfterAssign(Scope $scope, string $variableName, array $conditionalExpressions, SpecifiedTypes $specifiedTypes, Type $variableType, array $rhsImpurePoints, Expr $assignedExpr): array { foreach ($specifiedTypes->getSureNotTypes() as $exprString => [$expr, $exprType]) { if (!$this->isExprSafeToProjectThroughVariable($expr, $variableName, $rhsImpurePoints, $assignedExpr)) { continue; } $exprString = (string) $exprString; if (!isset($conditionalExpressions[$exprString])) { $conditionalExpressions[$exprString] = []; } $holder = new ConditionalExpressionHolder(['$' . $variableName => ExpressionTypeHolder::createYes(new Variable($variableName), $variableType)], ExpressionTypeHolder::createYes($expr, TypeCombinator::remove($scope->getType($expr), $exprType))); $conditionalExpressions[$exprString][$holder->getKey()] = $holder; } return $conditionalExpressions; } /** * We're about to remember "when $variableName is truthy/falsy, $expr has a narrower type". * Whether that's safe to project forward depends on whether re-evaluating $expr later will * still return the same value as when we observed the narrowing — i.e. whether $expr is * referentially transparent with respect to the intervening code. * * Scalar/const-fetch literals are never narrowing targets, so skip them up front (they also * happen to stringify to numeric exprStrings which collide with PHP's numeric-string * array-key autocast). * * A plain variable is always safe: reading it doesn't produce side effects, and if it gets * reassigned the existing conditional-expression-holder machinery invalidates the binding. * This case matters for e.g. `$ok = preg_match(..., $matches); if ($ok) { use $matches }` — * `preg_match` itself has impure points, but `$matches` is a plain variable and the * narrowing attached to it should still survive. * * Other common tracked expressions (property/dim fetches, function/method calls) can always * carry narrowings: PHPStan already memoises their types per exprString, and condition * checks like `$x = $obj->foo() !== null; if ($x) { $obj->foo(); }` rely on this even when * the RHS itself has impure points (as a method call without @phpstan-pure always does). * * Anything else is accepted only when the right-hand side evaluation recorded zero impure * points — in that case all sub-expressions it produced sure types for were evaluated * without side effects and can be re-evaluated later with the same result. * * @param ImpurePoint[] $rhsImpurePoints */ private function isExprSafeToProjectThroughVariable(Expr $expr, string $variableName, array $rhsImpurePoints, Expr $assignedExpr): bool { // Scalar/const-fetch literals and PHPStan virtual nodes (e.g. NativeTypeExpr) are never // narrowing targets at a usage site — skip them so they don't collide with PHP's // numeric-string array-key autocast or leak internal virtual expressions into the // conditional-expression map. if ($expr instanceof Node\Scalar || $expr instanceof ConstFetch || $expr instanceof VirtualNode || $expr instanceof Expr\UnaryMinus && $expr->expr instanceof Node\Scalar) { return \false; } if ($expr instanceof Variable) { return is_string($expr->name) && $expr->name !== $variableName; } if ($expr instanceof PropertyFetch || $expr instanceof ArrayDimFetch) { return \true; } if ($expr instanceof FuncCall || $expr instanceof MethodCall || $expr instanceof NullsafeMethodCall || $expr instanceof StaticCall) { // A call's type can change between evaluations. We're willing to project the // narrowing through a stored boolean only when the sure-type expression is a // *sub*-expression of the assigned RHS — e.g. `$ok = $x->foo() !== null` builds // a sure type for the sub-call `$x->foo()`. In that case the RHS as a whole // carries the comparison result, and later `if ($ok)` usefully re-narrows the // remembered sub-call. When the sure-type expression IS the whole RHS (e.g. // `$device = $this->nullable(); if ($device === null) { … }` with the // falsey-scalar loop producing `$this->nullable() === null` narrowings), the // projection would survive across subsequent reassignments of the target // expression and wrongly re-narrow fresh calls — so skip it. return $expr !== $assignedExpr; } return count($rhsImpurePoints) === 0; } /** * @param list $dimFetchStack */ private function isImplicitArrayCreation(array $dimFetchStack, Scope $scope): TrinaryLogic { if (count($dimFetchStack) === 0) { return TrinaryLogic::createNo(); } $varNode = $dimFetchStack[0]->var; if (!$varNode instanceof Variable) { return TrinaryLogic::createNo(); } if (!is_string($varNode->name)) { return TrinaryLogic::createNo(); } return $scope->hasVariableType($varNode->name)->negate(); } private function processArrayByRefItems(MutatingScope $scope, string $rootVarName, Expr\Array_ $arrayExpr, Expr $parentExpr): MutatingScope { $implicitIndex = 0; foreach ($arrayExpr->items as $arrayItem) { if ($arrayItem->key !== null) { $keyType = $scope->getType($arrayItem->key)->toArrayKey(); if ($implicitIndex !== null) { $keyValues = $keyType->getConstantScalarValues(); if (count($keyValues) === 1) { $keyValue = $keyValues[0]; if (is_int($keyValue) && $keyValue >= $implicitIndex) { $implicitIndex = $keyValue + 1; } } elseif (!$keyType->isInteger()->no()) { // Key could be an integer, but we don't know which one, // so subsequent implicit indices are unpredictable $implicitIndex = null; } } $dimExpr = $arrayItem->key; } elseif ($implicitIndex !== null) { $dimExpr = new Node\Scalar\Int_($implicitIndex); $implicitIndex++; } else { $dimExpr = new TypeExpr(new IntegerType()); } if ($arrayItem->value instanceof Expr\Array_) { $dimFetchExpr = new ArrayDimFetch($parentExpr, $dimExpr); $scope = $this->processArrayByRefItems($scope, $rootVarName, $arrayItem->value, $dimFetchExpr); } if (!$arrayItem->byRef || !$arrayItem->value instanceof Variable || !is_string($arrayItem->value->name)) { continue; } $refVarName = $arrayItem->value->name; $dimFetchExpr = new ArrayDimFetch($parentExpr, $dimExpr); $refType = $scope->getType(new Variable($refVarName)); $refNativeType = $scope->getNativeType(new Variable($refVarName)); // When $rootVarName's array key changes, update $refVarName $scope = $scope->assignExpression(new IntertwinedVariableByReferenceWithExpr($rootVarName, new Variable($refVarName), $dimFetchExpr), $refType, $refNativeType); // When $refVarName changes, update $rootVarName's array key $scope = $scope->assignExpression(new IntertwinedVariableByReferenceWithExpr($refVarName, $dimFetchExpr, new Variable($refVarName)), $refType, $refNativeType); } return $scope; } /** * @param non-empty-list $dimFetchStack * @param non-empty-list $offsetTypes * * @return array{Type, list} */ private function produceArrayDimFetchAssignValueToWrite(array $dimFetchStack, array $offsetTypes, Type $offsetValueType, Type $valueToWrite, Scope $scope): array { $originalValueToWrite = $valueToWrite; $offsetValueTypeStack = [$offsetValueType]; $generalizeOnWrite = $offsetTypes[array_key_last($offsetTypes)][0] !== null; foreach (array_slice($offsetTypes, 0, -1) as [$offsetType, $dimFetch]) { if ($offsetType === null) { $offsetValueType = new ConstantArrayType([], []); $generalizeOnWrite = \false; } else { $has = $offsetValueType->hasOffsetValueType($offsetType); if ($has->yes()) { if ($scope->hasExpressionType($dimFetch)->yes()) { $offsetValueType = $scope->getType($dimFetch); } else { $offsetValueType = $offsetValueType->getOffsetValueType($offsetType); } } elseif ($has->maybe()) { if ($scope->hasExpressionType($dimFetch)->yes()) { $generalizeOnWrite = \false; $offsetValueType = $scope->getType($dimFetch); } else { $offsetValueType = TypeCombinator::union($offsetValueType->getOffsetValueType($offsetType), new ConstantArrayType([], [])); } } else { $generalizeOnWrite = \false; $offsetValueType = new ConstantArrayType([], []); } } $offsetValueTypeStack[] = $offsetValueType; } $lastDimKey = array_key_last($dimFetchStack); $computedContainerValues = []; foreach (array_reverse($offsetTypes) as $i => [$offsetType]) { /** @var Type $offsetValueType */ $offsetValueType = array_pop($offsetValueTypeStack); if (!$offsetValueType instanceof MixedType && !$offsetValueType->isArray()->yes()) { if ($offsetType !== null && $offsetType->isInteger()->yes()) { $offsetValueType = TypeCombinator::intersect($offsetValueType, StaticTypeFactory::intOffsetAccessibleType()); } else { $offsetValueType = TypeCombinator::intersect($offsetValueType, StaticTypeFactory::generalOffsetAccessibleType()); } } $arrayDimFetch = $dimFetchStack[$i] ?? null; if ($offsetType !== null && $arrayDimFetch !== null && $scope->hasExpressionType($arrayDimFetch)->yes() && !$offsetValueType->hasOffsetValueType($offsetType)->no()) { $hasOffsetType = null; if ($offsetType instanceof ConstantStringType || $offsetType instanceof ConstantIntegerType) { $hasOffsetType = new HasOffsetValueType($offsetType, $valueToWrite); } $valueToWrite = $offsetValueType->setExistingOffsetValueType($offsetType, $valueToWrite); if ($valueToWrite->isArray()->yes()) { if ($hasOffsetType !== null) { $valueToWrite = TypeCombinator::intersect($valueToWrite, $hasOffsetType); } else { $valueToWrite = TypeCombinator::intersect($valueToWrite, new NonEmptyArrayType()); } } } else { // when $unionValues=false the array item-type will be replaced with $valueToWrite // when $unionValues=true the existing array item-type will be union'ed with $valueToWrite -> type gets wider $unionValues = \false; if ($i === 0) { $unionValues = \true; } elseif ($generalizeOnWrite && $i === count($offsetTypes) - 1 && ($originalValueToWrite->isConstantScalarValue()->yes() || !$offsetValueType->getIterableValueType()->isSuperTypeOf($valueToWrite)->yes())) { $unionValues = \true; } $valueToWrite = $offsetValueType->setOffsetValueType($offsetType, $valueToWrite, $unionValues); } if ($arrayDimFetch !== null && $offsetValueType->isList()->yes() && $this->shouldKeepList($arrayDimFetch, $scope, $offsetValueType)) { $valueToWrite = TypeCombinator::intersect($valueToWrite, new AccessoryArrayListType()); } $containerKey = $lastDimKey - $i - 1; if ($containerKey < 0) { continue; } $computedContainerValues[$containerKey] = $valueToWrite; } $additionalExpressions = []; foreach ($dimFetchStack as $key => $dimFetch) { if ($dimFetch->dim === null) { continue; } if ($key === $lastDimKey) { $additionalValueType = $originalValueToWrite; } elseif (isset($computedContainerValues[$key])) { $additionalValueType = $computedContainerValues[$key]; } else { $offsetType = $scope->getType($dimFetch->dim); $additionalValueType = $valueToWrite->getOffsetValueType($offsetType); } $additionalExpressions[] = [$dimFetch, $additionalValueType]; } return [$valueToWrite, $additionalExpressions]; } private function shouldKeepList(ArrayDimFetch $arrayDimFetch, Scope $scope, Type $offsetValueType): bool { if ($arrayDimFetch->dim instanceof Expr\BinaryOp\Plus) { if ($arrayDimFetch->dim->right instanceof Variable && $arrayDimFetch->dim->left instanceof Node\Scalar\Int_ && $arrayDimFetch->dim->left->value === 1 && $scope->hasExpressionType(new ArrayDimFetch($arrayDimFetch->var, $arrayDimFetch->dim->right))->yes()) { return \true; } elseif ($arrayDimFetch->dim->left instanceof Variable && $arrayDimFetch->dim->right instanceof Node\Scalar\Int_ && $arrayDimFetch->dim->right->value === 1 && $scope->hasExpressionType(new ArrayDimFetch($arrayDimFetch->var, $arrayDimFetch->dim->left))->yes()) { return \true; } } elseif ($arrayDimFetch->dim instanceof Expr\BinaryOp\Minus && $arrayDimFetch->dim->right instanceof Node\Scalar\Int_ && $arrayDimFetch->dim->left instanceof Expr\FuncCall && $arrayDimFetch->dim->left->name instanceof Name && in_array($arrayDimFetch->dim->left->name->toLowerString(), ['count', 'sizeof'], \true) && count($arrayDimFetch->dim->left->getArgs()) === 1 && $this->isSameVariable($arrayDimFetch->var, $arrayDimFetch->dim->left->getArgs()[0]->value) && IntegerRangeType::fromInterval(0, null)->isSuperTypeOf($scope->getType($arrayDimFetch->dim))->yes() && $offsetValueType->isIterableAtLeastOnce()->yes()) { return \true; } elseif ($arrayDimFetch->dim instanceof Expr\FuncCall && $arrayDimFetch->dim->name instanceof Name && in_array($arrayDimFetch->dim->name->toLowerString(), ['array_key_last', 'array_key_first'], \true) && count($arrayDimFetch->dim->getArgs()) >= 1 && $this->isSameVariable($arrayDimFetch->var, $arrayDimFetch->dim->getArgs()[0]->value)) { return \true; } elseif ($arrayDimFetch->dim instanceof Expr\FuncCall && $arrayDimFetch->dim->name instanceof Name && $arrayDimFetch->dim->name->toLowerString() === 'array_search' && count($arrayDimFetch->dim->getArgs()) >= 1 && $this->isSameVariable($arrayDimFetch->var, $arrayDimFetch->dim->getArgs()[1]->value)) { return \true; } return \false; } private function isSameVariable(Expr $a, Expr $b): bool { if ($a instanceof Variable && $b instanceof Variable && is_string($a->name) && is_string($b->name)) { return $a->name === $b->name; } return \false; } } */ #[AutowiredService] final class AssignOpHandler implements ExprHandler { private \PHPStan\Analyser\ExprHandler\AssignHandler $assignHandler; private InitializerExprTypeResolver $initializerExprTypeResolver; private ImplicitToStringCallHelper $implicitToStringCallHelper; public function __construct(\PHPStan\Analyser\ExprHandler\AssignHandler $assignHandler, InitializerExprTypeResolver $initializerExprTypeResolver, ImplicitToStringCallHelper $implicitToStringCallHelper) { $this->assignHandler = $assignHandler; $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->implicitToStringCallHelper = $implicitToStringCallHelper; } public function supports(Expr $expr): bool { return $expr instanceof AssignOp; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $assignResult = $this->assignHandler->processAssignVar($nodeScopeResolver, $scope, $storage, $stmt, $expr->var, $expr, $nodeCallback, $context, static function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $storage, $nodeScopeResolver): ExpressionResult { $originalScope = $scope; if ($expr instanceof Expr\AssignOp\Coalesce) { $scope = $scope->filterByFalseyValue(new BinaryOp\NotIdentical($expr->var, new ConstFetch(new Name('null')))); } $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context->enterDeep()); if ($expr instanceof Expr\AssignOp\Coalesce) { $nodeScopeResolver->storeBeforeScope($storage, $expr, $originalScope); $isAlwaysTerminating = $exprResult->isAlwaysTerminating() && $originalScope->getType($expr->var)->isNull()->yes(); return new ExpressionResult($exprResult->getScope()->mergeWith($originalScope), $exprResult->hasYield(), $isAlwaysTerminating, $exprResult->getThrowPoints(), $exprResult->getImpurePoints()); } return $exprResult; }, $expr instanceof Expr\AssignOp\Coalesce); if (!$expr instanceof Expr\AssignOp\Coalesce) { $nodeScopeResolver->storeBeforeScope($storage, $expr, $scope); } $scope = $assignResult->getScope(); $throwPoints = $assignResult->getThrowPoints(); $impurePoints = $assignResult->getImpurePoints(); if (($expr instanceof Expr\AssignOp\Div || $expr instanceof Expr\AssignOp\Mod) && !$scope->getType($expr->expr)->toNumber()->isSuperTypeOf(new ConstantIntegerType(0))->no()) { $throwPoints[] = InternalThrowPoint::createExplicit($scope, new ObjectType(DivisionByZeroError::class), $expr, \false); } if ($expr instanceof Expr\AssignOp\Concat) { $toStringResult = $this->implicitToStringCallHelper->processImplicitToStringCall($expr->expr, $scope); $throwPoints = array_merge($throwPoints, $toStringResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $toStringResult->getImpurePoints()); } return new ExpressionResult($scope, $assignResult->hasYield(), $assignResult->isAlwaysTerminating(), $throwPoints, $impurePoints, static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } public function resolveType(MutatingScope $scope, Expr $expr): Type { $getType = static fn(Expr $expr): Type => $scope->getType($expr); if ($expr instanceof Expr\AssignOp\Coalesce) { return $scope->getType(new BinaryOp\Coalesce($expr->var, $expr->expr, $expr->getAttributes())); } if ($expr instanceof Expr\AssignOp\Concat) { return $this->initializerExprTypeResolver->getConcatType($expr->var, $expr->expr, $getType); } if ($expr instanceof Expr\AssignOp\BitwiseAnd) { return $this->initializerExprTypeResolver->getBitwiseAndType($expr->var, $expr->expr, $getType); } if ($expr instanceof Expr\AssignOp\BitwiseOr) { return $this->initializerExprTypeResolver->getBitwiseOrType($expr->var, $expr->expr, $getType); } if ($expr instanceof Expr\AssignOp\BitwiseXor) { return $this->initializerExprTypeResolver->getBitwiseXorType($expr->var, $expr->expr, $getType); } if ($expr instanceof Expr\AssignOp\Div) { return $this->initializerExprTypeResolver->getDivType($expr->var, $expr->expr, $getType); } if ($expr instanceof Expr\AssignOp\Mod) { return $this->initializerExprTypeResolver->getModType($expr->var, $expr->expr, $getType); } if ($expr instanceof Expr\AssignOp\Plus) { return $this->initializerExprTypeResolver->getPlusType($expr->var, $expr->expr, $getType); } if ($expr instanceof Expr\AssignOp\Minus) { return $this->initializerExprTypeResolver->getMinusType($expr->var, $expr->expr, $getType); } if ($expr instanceof Expr\AssignOp\Mul) { return $this->initializerExprTypeResolver->getMulType($expr->var, $expr->expr, $getType); } if ($expr instanceof Expr\AssignOp\Pow) { return $this->initializerExprTypeResolver->getPowType($expr->var, $expr->expr, $getType); } if ($expr instanceof Expr\AssignOp\ShiftLeft) { return $this->initializerExprTypeResolver->getShiftLeftType($expr->var, $expr->expr, $getType); } if ($expr instanceof Expr\AssignOp\ShiftRight) { return $this->initializerExprTypeResolver->getShiftRightType($expr->var, $expr->expr, $getType); } throw new ShouldNotHappenException(sprintf('Unhandled %s', get_class($expr))); } } */ #[AutowiredService] final class BinaryOpHandler implements ExprHandler { private InitializerExprTypeResolver $initializerExprTypeResolver; private RicherScopeGetTypeHelper $richerScopeGetTypeHelper; private PhpVersion $phpVersion; private ImplicitToStringCallHelper $implicitToStringCallHelper; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver, RicherScopeGetTypeHelper $richerScopeGetTypeHelper, PhpVersion $phpVersion, ImplicitToStringCallHelper $implicitToStringCallHelper) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->richerScopeGetTypeHelper = $richerScopeGetTypeHelper; $this->phpVersion = $phpVersion; $this->implicitToStringCallHelper = $implicitToStringCallHelper; } public function supports(Expr $expr): bool { return $expr instanceof BinaryOp && !$expr instanceof BooleanAnd && !$expr instanceof BinaryOp\LogicalAnd && !$expr instanceof BooleanOr && !$expr instanceof BinaryOp\LogicalOr && !$expr instanceof BinaryOp\Coalesce && !$expr instanceof BinaryOp\Pipe; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $leftResult = $nodeScopeResolver->processExprNode($stmt, $expr->left, $scope, $storage, $nodeCallback, $context->enterDeep()); $rightResult = $nodeScopeResolver->processExprNode($stmt, $expr->right, $leftResult->getScope(), $storage, $nodeCallback, $context->enterDeep()); $throwPoints = array_merge($leftResult->getThrowPoints(), $rightResult->getThrowPoints()); $impurePoints = array_merge($leftResult->getImpurePoints(), $rightResult->getImpurePoints()); if (($expr instanceof BinaryOp\Div || $expr instanceof BinaryOp\Mod) && !$leftResult->getScope()->getType($expr->right)->toNumber()->isSuperTypeOf(new ConstantIntegerType(0))->no()) { $throwPoints[] = InternalThrowPoint::createExplicit($leftResult->getScope(), new ObjectType(DivisionByZeroError::class), $expr, \false); } if ($expr instanceof BinaryOp\Concat) { $leftToStringResult = $this->implicitToStringCallHelper->processImplicitToStringCall($expr->left, $scope); $rightToStringResult = $this->implicitToStringCallHelper->processImplicitToStringCall($expr->right, $leftResult->getScope()); $throwPoints = array_merge($throwPoints, $leftToStringResult->getThrowPoints(), $rightToStringResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $leftToStringResult->getImpurePoints(), $rightToStringResult->getImpurePoints()); } $scope = $rightResult->getScope(); return new ExpressionResult($scope, $leftResult->hasYield() || $rightResult->hasYield(), $leftResult->isAlwaysTerminating() || $rightResult->isAlwaysTerminating(), $throwPoints, $impurePoints, static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } public function resolveType(MutatingScope $scope, Expr $expr): Type { $getType = static fn(Expr $expr): Type => $scope->getType($expr); if ($expr instanceof BinaryOp\Smaller) { return $scope->getType($expr->left)->isSmallerThan($scope->getType($expr->right), $this->phpVersion)->toBooleanType(); } if ($expr instanceof BinaryOp\SmallerOrEqual) { return $scope->getType($expr->left)->isSmallerThanOrEqual($scope->getType($expr->right), $this->phpVersion)->toBooleanType(); } if ($expr instanceof BinaryOp\Greater) { return $scope->getType($expr->right)->isSmallerThan($scope->getType($expr->left), $this->phpVersion)->toBooleanType(); } if ($expr instanceof BinaryOp\GreaterOrEqual) { return $scope->getType($expr->right)->isSmallerThanOrEqual($scope->getType($expr->left), $this->phpVersion)->toBooleanType(); } if ($expr instanceof BinaryOp\Equal) { 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 ConstantBooleanType(\true); } $leftType = $scope->getType($expr->left); $rightType = $scope->getType($expr->right); return $this->initializerExprTypeResolver->resolveEqualType($leftType, $rightType)->type; } if ($expr instanceof BinaryOp\NotEqual) { return $scope->getType(new Expr\BooleanNot(new BinaryOp\Equal($expr->left, $expr->right))); } if ($expr instanceof BinaryOp\Identical) { return $this->richerScopeGetTypeHelper->getIdenticalResult($scope, $expr)->type; } if ($expr instanceof BinaryOp\NotIdentical) { return $this->richerScopeGetTypeHelper->getNotIdenticalResult($scope, $expr)->type; } if ($expr instanceof BinaryOp\LogicalXor) { $leftBooleanType = $scope->getType($expr->left)->toBoolean(); $rightBooleanType = $scope->getType($expr->right)->toBoolean(); if ($leftBooleanType instanceof ConstantBooleanType && $rightBooleanType instanceof ConstantBooleanType) { return new ConstantBooleanType($leftBooleanType->getValue() xor $rightBooleanType->getValue()); } return new BooleanType(); } if ($expr instanceof BinaryOp\Spaceship) { return $this->initializerExprTypeResolver->getSpaceshipType($expr->left, $expr->right, $getType); } if ($expr instanceof BinaryOp\Concat) { return $this->initializerExprTypeResolver->getConcatType($expr->left, $expr->right, $getType); } if ($expr instanceof BinaryOp\BitwiseAnd) { return $this->initializerExprTypeResolver->getBitwiseAndType($expr->left, $expr->right, $getType); } if ($expr instanceof BinaryOp\BitwiseOr) { return $this->initializerExprTypeResolver->getBitwiseOrType($expr->left, $expr->right, $getType); } if ($expr instanceof BinaryOp\BitwiseXor) { return $this->initializerExprTypeResolver->getBitwiseXorType($expr->left, $expr->right, $getType); } if ($expr instanceof BinaryOp\Div) { return $this->initializerExprTypeResolver->getDivType($expr->left, $expr->right, $getType); } if ($expr instanceof BinaryOp\Mod) { return $this->initializerExprTypeResolver->getModType($expr->left, $expr->right, $getType); } if ($expr instanceof BinaryOp\Plus) { return $this->initializerExprTypeResolver->getPlusType($expr->left, $expr->right, $getType); } if ($expr instanceof BinaryOp\Minus) { return $this->initializerExprTypeResolver->getMinusType($expr->left, $expr->right, $getType); } if ($expr instanceof BinaryOp\Mul) { return $this->initializerExprTypeResolver->getMulType($expr->left, $expr->right, $getType); } if ($expr instanceof BinaryOp\Pow) { return $this->initializerExprTypeResolver->getPowType($expr->left, $expr->right, $getType); } if ($expr instanceof BinaryOp\ShiftLeft) { return $this->initializerExprTypeResolver->getShiftLeftType($expr->left, $expr->right, $getType); } if ($expr instanceof BinaryOp\ShiftRight) { return $this->initializerExprTypeResolver->getShiftRightType($expr->left, $expr->right, $getType); } throw new ShouldNotHappenException(sprintf('Unhandled %s', get_class($expr))); } } */ #[AutowiredService] final class BitwiseNotHandler implements ExprHandler { private InitializerExprTypeResolver $initializerExprTypeResolver; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; } public function supports(Expr $expr): bool { return $expr instanceof BitwiseNot; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context->enterDeep()); return new ExpressionResult($exprResult->getScope(), $exprResult->hasYield(), $exprResult->isAlwaysTerminating(), $exprResult->getThrowPoints(), $exprResult->getImpurePoints()); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $this->initializerExprTypeResolver->getBitwiseNotType($expr->expr, static fn(Expr $expr): Type => $scope->getType($expr)); } } */ #[AutowiredService] final class BooleanAndHandler implements ExprHandler { private NodeScopeResolver $nodeScopeResolver; private const BOOLEAN_EXPRESSION_MAX_PROCESS_DEPTH = 4; public function __construct(NodeScopeResolver $nodeScopeResolver) { $this->nodeScopeResolver = $nodeScopeResolver; } public function supports(Expr $expr): bool { return $expr instanceof BooleanAnd || $expr instanceof LogicalAnd; } public function resolveType(MutatingScope $scope, Expr $expr): Type { $leftBooleanType = $scope->getType($expr->left)->toBoolean(); if ($leftBooleanType->isFalse()->yes()) { return new ConstantBooleanType(\false); } if (self::getBooleanExpressionDepth($expr->left) <= self::BOOLEAN_EXPRESSION_MAX_PROCESS_DEPTH) { $leftResult = $this->nodeScopeResolver->processExprNode(new Stmt\Expression($expr->left), $expr->left, $scope, new ExpressionResultStorage(), new NoopNodeCallback(), ExpressionContext::createDeep()); $rightBooleanType = $leftResult->getTruthyScope()->getType($expr->right)->toBoolean(); } else { $rightBooleanType = $scope->filterByTruthyValue($expr->left)->getType($expr->right)->toBoolean(); } if ($rightBooleanType->isFalse()->yes()) { return new ConstantBooleanType(\false); } if ($leftBooleanType->isTrue()->yes() && $rightBooleanType->isTrue()->yes()) { return new ConstantBooleanType(\true); } return new BooleanType(); } public static function getBooleanExpressionDepth(Expr $expr, int $depth = 0): int { while ($expr instanceof BooleanOr || $expr instanceof LogicalOr || $expr instanceof BooleanAnd || $expr instanceof LogicalAnd) { return self::getBooleanExpressionDepth($expr->left, $depth + 1); } return $depth; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $leftResult = $nodeScopeResolver->processExprNode($stmt, $expr->left, $scope, $storage, $nodeCallback, $context->enterDeep()); $leftTruthyScope = $leftResult->getTruthyScope(); $rightResult = $nodeScopeResolver->processExprNode($stmt, $expr->right, $leftTruthyScope, $storage, $nodeCallback, $context); $rightExprType = $rightResult->getScope()->getType($expr->right); if ($rightExprType instanceof NeverType && $rightExprType->isExplicit()) { $leftMergedWithRightScope = $leftResult->getFalseyScope(); } else { $leftMergedWithRightScope = $leftResult->getScope()->mergeWith($rightResult->getScope()); } $nodeScopeResolver->callNodeCallbackWithExpression($nodeCallback, new BooleanAndNode($expr, $leftTruthyScope), $scope, $storage, $context); return new ExpressionResult($leftMergedWithRightScope, $leftResult->hasYield() || $rightResult->hasYield(), $leftResult->isAlwaysTerminating(), array_merge($leftResult->getThrowPoints(), $rightResult->getThrowPoints()), array_merge($leftResult->getImpurePoints(), $rightResult->getImpurePoints()), static fn(): MutatingScope => $rightResult->getScope()->filterByTruthyValue($expr->right), static fn(): MutatingScope => $leftMergedWithRightScope->filterByFalseyValue($expr)); } } */ #[AutowiredService] final class BooleanNotHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof BooleanNot; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $exprResult->getScope(); return new ExpressionResult($scope, $exprResult->hasYield(), $exprResult->isAlwaysTerminating(), $exprResult->getThrowPoints(), $exprResult->getImpurePoints(), static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } public function resolveType(MutatingScope $scope, Expr $expr): Type { $exprBooleanType = $scope->getType($expr->expr)->toBoolean(); if ($exprBooleanType instanceof ConstantBooleanType) { return new ConstantBooleanType(!$exprBooleanType->getValue()); } return new BooleanType(); } } */ #[AutowiredService] final class BooleanOrHandler implements ExprHandler { private NodeScopeResolver $nodeScopeResolver; private const BOOLEAN_EXPRESSION_MAX_PROCESS_DEPTH = 4; public function __construct(NodeScopeResolver $nodeScopeResolver) { $this->nodeScopeResolver = $nodeScopeResolver; } public function supports(Expr $expr): bool { return $expr instanceof BooleanOr || $expr instanceof LogicalOr; } public function resolveType(MutatingScope $scope, Expr $expr): Type { $leftBooleanType = $scope->getType($expr->left)->toBoolean(); if ($leftBooleanType->isTrue()->yes()) { return new ConstantBooleanType(\true); } if (\PHPStan\Analyser\ExprHandler\BooleanAndHandler::getBooleanExpressionDepth($expr->left) <= self::BOOLEAN_EXPRESSION_MAX_PROCESS_DEPTH) { $leftResult = $this->nodeScopeResolver->processExprNode(new Stmt\Expression($expr->left), $expr->left, $scope, new ExpressionResultStorage(), new NoopNodeCallback(), ExpressionContext::createDeep()); $rightBooleanType = $leftResult->getFalseyScope()->getType($expr->right)->toBoolean(); } else { $rightBooleanType = $scope->filterByFalseyValue($expr->left)->getType($expr->right)->toBoolean(); } if ($rightBooleanType->isTrue()->yes()) { return new ConstantBooleanType(\true); } if ($leftBooleanType->isFalse()->yes() && $rightBooleanType->isFalse()->yes()) { return new ConstantBooleanType(\false); } return new BooleanType(); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $leftResult = $nodeScopeResolver->processExprNode($stmt, $expr->left, $scope, $storage, $nodeCallback, $context->enterDeep()); $leftFalseyScope = $leftResult->getFalseyScope(); $rightResult = $nodeScopeResolver->processExprNode($stmt, $expr->right, $leftFalseyScope, $storage, $nodeCallback, $context); $rightExprType = $rightResult->getScope()->getType($expr->right); if ($rightExprType instanceof NeverType && $rightExprType->isExplicit()) { $leftMergedWithRightScope = $leftResult->getTruthyScope(); } else { $leftMergedWithRightScope = $leftResult->getScope()->mergeWith($rightResult->getScope()); } $nodeScopeResolver->callNodeCallbackWithExpression($nodeCallback, new BooleanOrNode($expr, $leftFalseyScope), $scope, $storage, $context); return new ExpressionResult($leftMergedWithRightScope, $leftResult->hasYield() || $rightResult->hasYield(), $leftResult->isAlwaysTerminating(), array_merge($leftResult->getThrowPoints(), $rightResult->getThrowPoints()), array_merge($leftResult->getImpurePoints(), $rightResult->getImpurePoints()), static fn(): MutatingScope => $leftMergedWithRightScope->filterByTruthyValue($expr), static fn(): MutatingScope => $rightResult->getScope()->filterByFalseyValue($expr->right)); } } */ #[AutowiredService] final class CastHandler implements ExprHandler { private InitializerExprTypeResolver $initializerExprTypeResolver; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; } public function supports(Expr $expr): bool { return $expr instanceof Cast && !$expr instanceof Cast\String_; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $exprResult->getScope(); return new ExpressionResult($scope, $exprResult->hasYield(), $exprResult->isAlwaysTerminating(), $exprResult->getThrowPoints(), $exprResult->getImpurePoints(), static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } public function resolveType(MutatingScope $scope, Expr $expr): Type { if ($expr instanceof Cast\Unset_) { return new NullType(); } return $this->initializerExprTypeResolver->getCastType($expr, static fn(Expr $expr): Type => $scope->getType($expr)); } } */ #[AutowiredService] final class CastStringHandler implements ExprHandler { private InitializerExprTypeResolver $initializerExprTypeResolver; private ImplicitToStringCallHelper $implicitToStringCallHelper; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver, ImplicitToStringCallHelper $implicitToStringCallHelper) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->implicitToStringCallHelper = $implicitToStringCallHelper; } public function supports(Expr $expr): bool { return $expr instanceof Cast\String_; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context->enterDeep()); $impurePoints = $exprResult->getImpurePoints(); $throwPoints = $exprResult->getThrowPoints(); $toStringResult = $this->implicitToStringCallHelper->processImplicitToStringCall($expr->expr, $scope); $throwPoints = array_merge($throwPoints, $toStringResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $toStringResult->getImpurePoints()); $scope = $exprResult->getScope(); return new ExpressionResult($scope, $exprResult->hasYield(), $exprResult->isAlwaysTerminating(), $throwPoints, $impurePoints, static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $this->initializerExprTypeResolver->getCastType($expr, static fn(Expr $expr): Type => $scope->getType($expr)); } } */ #[AutowiredService] final class ClassConstFetchHandler implements ExprHandler { private InitializerExprTypeResolver $initializerExprTypeResolver; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; } public function supports(Expr $expr): bool { return $expr instanceof ClassConstFetch; } public function resolveType(MutatingScope $scope, Expr $expr): Type { if (!$expr->name instanceof Identifier) { return new MixedType(); } return $this->initializerExprTypeResolver->getClassConstFetchTypeByReflection($expr->class, $expr->name->name, $scope->isInClass() ? $scope->getClassReflection() : null, static fn(Expr $e): Type => $scope->getType($e)); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $hasYield = \false; $throwPoints = []; $impurePoints = []; $isAlwaysTerminating = \false; if ($expr->class instanceof Expr) { $classResult = $nodeScopeResolver->processExprNode($stmt, $expr->class, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $classResult->getScope(); $hasYield = $classResult->hasYield(); $throwPoints = $classResult->getThrowPoints(); $impurePoints = $classResult->getImpurePoints(); $isAlwaysTerminating = $classResult->isAlwaysTerminating(); } else { $nodeScopeResolver->callNodeCallback($nodeCallback, $expr->class, $scope, $storage); } if ($expr->name instanceof Identifier) { $nodeScopeResolver->callNodeCallback($nodeCallback, $expr->name, $scope, $storage); } else { $nameResult = $nodeScopeResolver->processExprNode($stmt, $expr->name, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $nameResult->getScope(); $hasYield = $hasYield || $nameResult->hasYield(); $throwPoints = array_merge($throwPoints, $nameResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $nameResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $nameResult->isAlwaysTerminating(); } return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints, static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } } */ #[AutowiredService] final class CloneHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof Clone_; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context->enterDeep()); return new ExpressionResult($exprResult->getScope(), $exprResult->hasYield(), $exprResult->isAlwaysTerminating(), $exprResult->getThrowPoints(), $exprResult->getImpurePoints()); } public function resolveType(MutatingScope $scope, Expr $expr): Type { $cloneType = TypeCombinator::intersect($scope->getType($expr->expr), new ObjectWithoutClassType()); return TypeTraverser::map($cloneType, new CloneTypeTraverser()); } } */ #[AutowiredService] final class ClosureHandler implements ExprHandler { private ClosureTypeResolver $closureTypeResolver; public function __construct(ClosureTypeResolver $closureTypeResolver) { $this->closureTypeResolver = $closureTypeResolver; } public function supports(Expr $expr): bool { return $expr instanceof Closure; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $processClosureResult = $nodeScopeResolver->processClosureNode($stmt, $expr, $scope, $storage, $nodeCallback, $context, null); $scope = $processClosureResult->applyByRefUseScope($processClosureResult->getScope()); return new ExpressionResult($scope, \false, \false, [], []); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $this->closureTypeResolver->getClosureType($scope, $expr); } } */ #[AutowiredService] final class CoalesceHandler implements ExprHandler { private NonNullabilityHelper $nonNullabilityHelper; public function __construct(NonNullabilityHelper $nonNullabilityHelper) { $this->nonNullabilityHelper = $nonNullabilityHelper; } public function supports(Expr $expr): bool { return $expr instanceof Coalesce; } public function resolveType(MutatingScope $scope, Expr $expr): Type { $issetLeftExpr = new Expr\Isset_([$expr->left]); $result = $scope->issetCheck($expr->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($scope->filterByTruthyValue($issetLeftExpr)->getType($expr->left)); } $rightType = $scope->filterByFalseyValue($issetLeftExpr)->getType($expr->right); if ($result === null) { return TypeCombinator::union(TypeCombinator::removeNull($scope->filterByTruthyValue($issetLeftExpr)->getType($expr->left)), $rightType); } return $rightType; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $nonNullabilityResult = $this->nonNullabilityHelper->ensureNonNullability($scope, $expr->left); $condScope = $nodeScopeResolver->lookForSetAllowedUndefinedExpressions($nonNullabilityResult->getScope(), $expr->left); $condResult = $nodeScopeResolver->processExprNode($stmt, $expr->left, $condScope, $storage, $nodeCallback, $context->enterDeep()); $scope = $this->nonNullabilityHelper->revertNonNullability($condResult->getScope(), $nonNullabilityResult->getSpecifiedExpressions()); $scope = $nodeScopeResolver->lookForUnsetAllowedUndefinedExpressions($scope, $expr->left); $rightScope = $scope->filterByFalseyValue($expr); $rightResult = $nodeScopeResolver->processExprNode($stmt, $expr->right, $rightScope, $storage, $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()); } return new ExpressionResult($scope, $condResult->hasYield() || $rightResult->hasYield(), $condResult->isAlwaysTerminating(), array_merge($condResult->getThrowPoints(), $rightResult->getThrowPoints()), array_merge($condResult->getImpurePoints(), $rightResult->getImpurePoints()), static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } } */ #[AutowiredService] final class ConstFetchHandler implements ExprHandler { private ConstantResolver $constantResolver; public function __construct(ConstantResolver $constantResolver) { $this->constantResolver = $constantResolver; } public function supports(Expr $expr): bool { return $expr instanceof ConstFetch; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $nodeScopeResolver->callNodeCallback($nodeCallback, $expr->name, $scope, $storage); return new ExpressionResult($scope, \false, \false, [], [], static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } public function resolveType(MutatingScope $scope, Expr $expr): Type { $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(); } $namespacedName = null; if (!$expr->name->isFullyQualified() && $scope->getNamespace() !== null) { $namespacedName = new FullyQualified([$scope->getNamespace(), $expr->name->toString()]); } $globalName = new FullyQualified($expr->name->toString()); foreach ([$namespacedName, $globalName] as $name) { if ($name === null) { continue; } $constFetch = new ConstFetch($name); if ($scope->hasExpressionType($constFetch)->yes()) { return $this->constantResolver->resolveConstantType($name->toString(), $scope->expressionTypes[$scope->getNodeKey($constFetch)]->getType()); } } $constantType = $this->constantResolver->resolveConstant($expr->name, $scope); if ($constantType !== null) { return $constantType; } return new ErrorType(); } } */ #[AutowiredService] final class EmptyHandler implements ExprHandler { private NonNullabilityHelper $nonNullabilityHelper; public function __construct(NonNullabilityHelper $nonNullabilityHelper) { $this->nonNullabilityHelper = $nonNullabilityHelper; } public function supports(Expr $expr): bool { return $expr instanceof Empty_; } public function resolveType(MutatingScope $scope, Expr $expr): Type { $result = $scope->issetCheck($expr->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); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $nonNullabilityResult = $this->nonNullabilityHelper->ensureNonNullability($scope, $expr->expr); $scope = $nodeScopeResolver->lookForSetAllowedUndefinedExpressions($nonNullabilityResult->getScope(), $expr->expr); $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $exprResult->getScope(); $scope = $this->nonNullabilityHelper->revertNonNullability($scope, $nonNullabilityResult->getSpecifiedExpressions()); $scope = $nodeScopeResolver->lookForUnsetAllowedUndefinedExpressions($scope, $expr->expr); return new ExpressionResult($scope, $exprResult->hasYield(), $exprResult->isAlwaysTerminating(), $exprResult->getThrowPoints(), $exprResult->getImpurePoints(), static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } } */ #[AutowiredService] final class ErrorSuppressHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof ErrorSuppress; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context); return new ExpressionResult($exprResult->getScope(), $exprResult->hasYield(), $exprResult->isAlwaysTerminating(), $exprResult->getThrowPoints(), $exprResult->getImpurePoints(), static fn(): MutatingScope => $exprResult->getTruthyScope(), static fn(): MutatingScope => $exprResult->getFalseyScope()); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $scope->getType($expr->expr); } } */ #[AutowiredService] final class EvalHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof Eval_; } public function resolveType(MutatingScope $scope, Expr $expr): Type { return new MixedType(); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $exprResult->getScope(); return new ExpressionResult($scope, $exprResult->hasYield(), $exprResult->isAlwaysTerminating(), array_merge($exprResult->getThrowPoints(), [InternalThrowPoint::createImplicit($scope, $expr)]), array_merge($exprResult->getImpurePoints(), [new ImpurePoint($scope, $expr, 'eval', 'eval', \true)])); } } */ #[AutowiredService] final class ExitHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof Exit_; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $kind = $expr->getAttribute('kind', Exit_::KIND_EXIT); $identifier = $kind === Exit_::KIND_DIE ? 'die' : 'exit'; $impurePoints = [new ImpurePoint($scope, $expr, $identifier, $identifier, \true)]; $hasYield = \false; $throwPoints = []; if ($expr->expr !== null) { $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context->enterDeep()); $hasYield = $exprResult->hasYield(); $throwPoints = $exprResult->getThrowPoints(); $impurePoints = array_merge($impurePoints, $exprResult->getImpurePoints()); $scope = $exprResult->getScope(); } return new ExpressionResult($scope, $hasYield, \true, $throwPoints, $impurePoints); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return new NonAcceptingNeverType(); } } */ #[AutowiredService] final class FirstClassCallableFuncCallHandler implements ExprHandler { private InitializerExprTypeResolver $initializerExprTypeResolver; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; } public function supports(Expr $expr): bool { return $expr instanceof FuncCall && $expr->isFirstClassCallable(); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { // handled in NodeScopeResolver before ExprHandlers are called throw new ShouldNotHappenException(); } public function resolveType(MutatingScope $scope, Expr $expr): Type { if ($expr->name instanceof Expr) { $callableType = $scope->getType($expr->name); if (!$callableType->isCallable()->yes()) { return new ObjectType(Closure::class); } return $this->initializerExprTypeResolver->createFirstClassCallable(null, $callableType->getCallableParametersAcceptors($scope), $scope->nativeTypesPromoted); } return $this->initializerExprTypeResolver->getFirstClassCallableType($expr, InitializerExprContext::fromScope($scope), $scope->nativeTypesPromoted); } } */ #[AutowiredService] final class FirstClassCallableMethodCallHandler implements ExprHandler { private InitializerExprTypeResolver $initializerExprTypeResolver; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; } public function supports(Expr $expr): bool { return $expr instanceof MethodCall && $expr->isFirstClassCallable(); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { // handled in NodeScopeResolver before ExprHandlers are called throw new ShouldNotHappenException(); } public function resolveType(MutatingScope $scope, Expr $expr): Type { if (!$expr->name instanceof Identifier) { return new ObjectType(Closure::class); } $varType = $scope->getType($expr->var); $method = $scope->getMethodReflection($varType, $expr->name->toString()); if ($method === null) { return new ObjectType(Closure::class); } return $this->initializerExprTypeResolver->createFirstClassCallable($method, $method->getVariants(), $scope->nativeTypesPromoted); } } */ #[AutowiredService] final class FirstClassCallableNewHandler implements ExprHandler { private InitializerExprTypeResolver $initializerExprTypeResolver; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; } public function supports(Expr $expr): bool { return $expr instanceof New_ && !$expr->class instanceof Class_ && $expr->isFirstClassCallable(); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { // handled in NodeScopeResolver before ExprHandlers are called throw new ShouldNotHappenException(); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $this->initializerExprTypeResolver->getFirstClassCallableType($expr, InitializerExprContext::fromScope($scope), $scope->nativeTypesPromoted); } } */ #[AutowiredService] final class FirstClassCallableStaticCallHandler implements ExprHandler { private InitializerExprTypeResolver $initializerExprTypeResolver; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; } public function supports(Expr $expr): bool { return $expr instanceof StaticCall && $expr->isFirstClassCallable(); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { // handled in NodeScopeResolver before ExprHandlers are called throw new ShouldNotHappenException(); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $this->initializerExprTypeResolver->getFirstClassCallableType($expr, InitializerExprContext::fromScope($scope), $scope->nativeTypesPromoted); } } */ #[AutowiredService] final class FuncCallHandler implements ExprHandler { private ReflectionProvider $reflectionProvider; private DynamicThrowTypeExtensionProvider $dynamicThrowTypeExtensionProvider; private DynamicReturnTypeExtensionRegistryProvider $dynamicReturnTypeExtensionRegistryProvider; private bool $implicitThrows; private bool $rememberPossiblyImpureFunctionValues; public function __construct( ReflectionProvider $reflectionProvider, DynamicThrowTypeExtensionProvider $dynamicThrowTypeExtensionProvider, DynamicReturnTypeExtensionRegistryProvider $dynamicReturnTypeExtensionRegistryProvider, #[AutowiredParameter('%exceptions.implicitThrows%')] bool $implicitThrows, #[AutowiredParameter] bool $rememberPossiblyImpureFunctionValues ) { $this->reflectionProvider = $reflectionProvider; $this->dynamicThrowTypeExtensionProvider = $dynamicThrowTypeExtensionProvider; $this->dynamicReturnTypeExtensionRegistryProvider = $dynamicReturnTypeExtensionRegistryProvider; $this->implicitThrows = $implicitThrows; $this->rememberPossiblyImpureFunctionValues = $rememberPossiblyImpureFunctionValues; } public function supports(Expr $expr): bool { return $expr instanceof FuncCall && !$expr->isFirstClassCallable(); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $parametersAcceptor = null; $functionReflection = null; $throwPoints = []; $impurePoints = []; $isAlwaysTerminating = \false; 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 = $nodeScopeResolver->processExprNode($stmt, $expr->name, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $nameResult->getScope(); $throwPoints = $nameResult->getThrowPoints(); $impurePoints = $nameResult->getImpurePoints(); $isAlwaysTerminating = $nameResult->isAlwaysTerminating(); if ($nameType->isObject()->yes() && $nameType->isCallable()->yes() && (new ObjectType(Closure::class))->isSuperTypeOf($nameType)->no()) { // processed later } elseif ($parametersAcceptor instanceof CallableParametersAcceptor) { $callableThrowPoints = array_map(static fn(SimpleThrowPoint $throwPoint) => $throwPoint->isExplicit() ? InternalThrowPoint::createExplicit($scope, $throwPoint->getType(), $expr, $throwPoint->canContainAnyThrowable()) : InternalThrowPoint::createImplicit($scope, $expr), $parametersAcceptor->getThrowPoints()); if (!$this->implicitThrows) { $callableThrowPoints = array_values(array_filter($callableThrowPoints, static fn(InternalThrowPoint $throwPoint) => $throwPoint->isExplicit())); } $throwPoints = array_merge($throwPoints, $callableThrowPoints); $impurePoints = array_merge($impurePoints, array_map(static fn(SimpleImpurePoint $impurePoint) => new ImpurePoint($scope, $expr, $impurePoint->getIdentifier(), $impurePoint->getDescription(), $impurePoint->isCertain()), $parametersAcceptor->getImpurePoints())); $scope = $nodeScopeResolver->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, $scope, $expr->getArgs()); if ($impurePoint !== null) { $impurePoints[] = new ImpurePoint($scope, $expr, $impurePoint->getIdentifier(), $impurePoint->getDescription(), $impurePoint->isCertain()); } } else { $impurePoints[] = new ImpurePoint($scope, $expr, 'functionCall', 'call to unknown function', \false); } $normalizedExpr = $expr; if ($parametersAcceptor !== null) { $normalizedExpr = ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $expr) ?? $expr; $returnType = $parametersAcceptor->getReturnType(); $isAlwaysTerminating = $isAlwaysTerminating || $returnType instanceof NeverType && $returnType->isExplicit(); } if ($normalizedExpr->name instanceof Name && $functionReflection !== null && $functionReflection->getName() === 'clone' && count($normalizedExpr->getArgs()) === 2) { $clonePropertiesArgType = $scope->getType($normalizedExpr->getArgs()[1]->value); $cloneExpr = new TypeExpr($scope->getType(new Expr\Clone_($normalizedExpr->getArgs()[0]->value))); $clonePropertiesArgTypeConstantArrays = $clonePropertiesArgType->getConstantArrays(); foreach ($clonePropertiesArgTypeConstantArrays as $clonePropertiesArgTypeConstantArray) { foreach ($clonePropertiesArgTypeConstantArray->getKeyTypes() as $i => $clonePropertyKeyType) { $clonePropertyKeyTypeScalars = $clonePropertyKeyType->getConstantScalarValues(); $propertyAttributes = $normalizedExpr->getAttributes(); $propertyAttributes['inCloneWith'] = \true; if (count($clonePropertyKeyTypeScalars) === 1) { $nodeScopeResolver->processVirtualAssign($scope, $storage, $stmt, new PropertyFetch($cloneExpr, (string) $clonePropertyKeyTypeScalars[0], $propertyAttributes), new TypeExpr($clonePropertiesArgTypeConstantArray->getValueTypes()[$i]), $nodeCallback); continue; } $nodeScopeResolver->processVirtualAssign($scope, $storage, $stmt, new PropertyFetch($cloneExpr, new TypeExpr($clonePropertyKeyType), $propertyAttributes), new TypeExpr($clonePropertiesArgTypeConstantArray->getValueTypes()[$i]), $nodeCallback); } } } /** @var array{Type, Type}|null $arrayWalkValueTypes */ $arrayWalkValueTypes = null; $arrayWalkArrayArg = null; $arrayWalkOriginalArrayType = null; $arrayWalkOriginalArrayNativeType = null; $nodeCallbackForArgs = $nodeCallback; if ($functionReflection !== null && $functionReflection->getName() === 'array_walk' && count($normalizedExpr->getArgs()) >= 2) { $callbackArg = $normalizedExpr->getArgs()[1]->value; $firstParamName = null; if ($callbackArg instanceof Expr\Closure && isset($callbackArg->params[0]) && $callbackArg->params[0]->byRef && $callbackArg->params[0]->var instanceof Variable && is_string($callbackArg->params[0]->var->name)) { $firstParamName = $callbackArg->params[0]->var->name; } if ($firstParamName !== null) { $arrayWalkArrayArg = $normalizedExpr->getArgs()[0]->value; $arrayWalkOriginalArrayType = $scope->getType($arrayWalkArrayArg); $arrayWalkOriginalArrayNativeType = $scope->getNativeType($arrayWalkArrayArg); $nodeCallbackForArgs = static function (Node $node, Scope $scope) use ($nodeCallback, $callbackArg, $firstParamName, &$arrayWalkValueTypes): void { if ($node instanceof ClosureReturnStatementsNode && $node->getClosureExpr() === $callbackArg) { $types = []; $nativeTypes = []; $stmtResult = $node->getStatementResult(); foreach ($stmtResult->getExitPoints() as $exitPoint) { $exitScope = $exitPoint->getScope(); if (!$exitScope->hasVariableType($firstParamName)->yes()) { continue; } $types[] = $exitScope->getVariableType($firstParamName); $nativeTypes[] = $exitScope->getNativeType(new Variable($firstParamName)); } if (!$stmtResult->isAlwaysTerminating()) { $stmtScope = $stmtResult->getScope(); if ($stmtScope->hasVariableType($firstParamName)->yes()) { $types[] = $stmtScope->getVariableType($firstParamName); $nativeTypes[] = $stmtScope->getNativeType(new Variable($firstParamName)); } } if (count($types) > 0) { $arrayWalkValueTypes = [TypeCombinator::union(...$types), TypeCombinator::union(...$nativeTypes)]; } } $nodeCallback($node, $scope); }; } } $scopeBeforeArgs = $scope; $argsResult = $nodeScopeResolver->processArgs($stmt, $functionReflection, null, $parametersAcceptor, $normalizedExpr, $scope, $storage, $nodeCallbackForArgs, $context); $scope = $argsResult->getScope(); $hasYield = $argsResult->hasYield(); $throwPoints = array_merge($throwPoints, $argsResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $argsResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $argsResult->isAlwaysTerminating(); if ($arrayWalkValueTypes !== null && $arrayWalkArrayArg !== null) { $arrayWalkValueType = $arrayWalkValueTypes[0]; $arrayWalkValueNativeType = $arrayWalkValueTypes[1]; $newArrayType = $arrayWalkOriginalArrayType->mapValueType(static fn(Type $type): Type => $arrayWalkValueType); $newArrayNativeType = $arrayWalkOriginalArrayNativeType->mapValueType(static fn(Type $type): Type => $arrayWalkValueNativeType); $scope = $nodeScopeResolver->processVirtualAssign($scope, $storage, $stmt, $arrayWalkArrayArg, new NativeTypeExpr($newArrayType, $newArrayNativeType), $nodeCallback)->getScope(); } if ($normalizedExpr->name instanceof Expr) { $nameType = $scope->getType($normalizedExpr->name); if ($nameType->isObject()->yes() && $nameType->isCallable()->yes() && (new ObjectType(Closure::class))->isSuperTypeOf($nameType)->no()) { $invokeResult = $nodeScopeResolver->processExprNode($stmt, new MethodCall($normalizedExpr->name, '__invoke', $normalizedExpr->getArgs(), $normalizedExpr->getAttributes()), $scope, $storage, new NoopNodeCallback(), $context->enterDeep()); $throwPoints = array_merge($throwPoints, $invokeResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $invokeResult->getImpurePoints()); $isAlwaysTerminating = $invokeResult->isAlwaysTerminating(); } } if ($functionReflection !== null) { $functionThrowPoint = $this->getFunctionThrowPoint($functionReflection, $parametersAcceptor, $normalizedExpr, $scope); if ($functionThrowPoint !== null) { $throwPoints[] = $functionThrowPoint; } } else { $throwPoints[] = InternalThrowPoint::createImplicit($scope, $expr); } if ($parametersAcceptor instanceof ClosureType && count($parametersAcceptor->getImpurePoints()) > 0 && $scope->isInClass()) { $scope = $scope->invalidateExpression(new Variable('this'), \true); } if ($functionReflection !== null && $this->rememberPossiblyImpureFunctionValues && $parametersAcceptor !== null && $functionReflection->hasSideEffects()->maybe() && !$functionReflection->isBuiltin()) { $scope = $scope->assignExpression(new PossiblyImpureCallExpr($normalizedExpr, $normalizedExpr, sprintf('%s()', $functionReflection->getName())), $parametersAcceptor->getReturnType(), new MixedType()); } 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($normalizedExpr->getArgs()) > 0) { $scope = $scope->invalidateExpression(new FuncCall(new Name('file_get_contents'), [$normalizedExpr->getArgs()[0]]))->invalidateExpression(new FuncCall(new Name\FullyQualified('file_get_contents'), [$normalizedExpr->getArgs()[0]])); } if ($functionReflection !== null && in_array($functionReflection->getName(), ['array_pop', 'array_shift'], \true) && count($normalizedExpr->getArgs()) >= 1) { $arrayArg = $normalizedExpr->getArgs()[0]->value; $arrayArgType = $scope->getType($arrayArg); $arrayArgNativeType = $scope->getNativeType($arrayArg); $isArrayPop = $functionReflection->getName() === 'array_pop'; $scope = $nodeScopeResolver->processVirtualAssign($scope, $storage, $stmt, $arrayArg, new NativeTypeExpr($isArrayPop ? $arrayArgType->popArray() : $arrayArgType->shiftArray(), $isArrayPop ? $arrayArgNativeType->popArray() : $arrayArgNativeType->shiftArray()), $nodeCallback)->getScope(); } if ($functionReflection !== null && in_array($functionReflection->getName(), ['array_push', 'array_unshift'], \true) && count($normalizedExpr->getArgs()) >= 2) { $arrayArg = $normalizedExpr->getArgs()[0]->value; $scope = $nodeScopeResolver->processVirtualAssign($scope, $storage, $stmt, $arrayArg, new NativeTypeExpr($this->getArrayFunctionAppendingType($functionReflection, $scopeBeforeArgs, $normalizedExpr), $this->getArrayFunctionAppendingType($functionReflection, $scopeBeforeArgs->doNotTreatPhpDocTypesAsCertain(), $normalizedExpr)), $nodeCallback)->getScope(); } if ($functionReflection !== null && in_array($functionReflection->getName(), ['fopen', 'file_get_contents'], \true)) { $scope = $scope->assignVariable('http_response_header', new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new StringType()), new AccessoryArrayListType()]), new ArrayType(new IntegerType(), new StringType()), TrinaryLogic::createYes()); } if ($functionReflection !== null && $functionReflection->getName() === 'shuffle') { $arrayArg = $normalizedExpr->getArgs()[0]->value; $scope = $nodeScopeResolver->processVirtualAssign($scope, $storage, $stmt, $arrayArg, new NativeTypeExpr($scope->getType($arrayArg)->shuffleArray(), $scope->getNativeType($arrayArg)->shuffleArray()), $nodeCallback)->getScope(); } if ($functionReflection !== null && $functionReflection->getName() === 'array_splice' && count($normalizedExpr->getArgs()) >= 2) { $arrayArg = $normalizedExpr->getArgs()[0]->value; $arrayArgType = $scope->getType($arrayArg); $arrayArgNativeType = $scope->getNativeType($arrayArg); $offsetType = $scopeBeforeArgs->getType($normalizedExpr->getArgs()[1]->value); if (isset($normalizedExpr->getArgs()[2])) { $lengthType = $scopeBeforeArgs->getType($normalizedExpr->getArgs()[2]->value); } else { $lengthType = new NullType(); } if (isset($normalizedExpr->getArgs()[3])) { $replacementArg = $normalizedExpr->getArgs()[3]->value; $replacementType = $scopeBeforeArgs->getType($replacementArg); $replacementNativeType = $scopeBeforeArgs->getNativeType($replacementArg); } else { $replacementType = new ConstantArrayType([], []); $replacementNativeType = new ConstantArrayType([], []); } $scope = $nodeScopeResolver->processVirtualAssign($scope, $storage, $stmt, $arrayArg, new NativeTypeExpr($arrayArgType->spliceArray($offsetType, $lengthType, $replacementType), $arrayArgNativeType->spliceArray($offsetType, $lengthType, $replacementNativeType)), $nodeCallback)->getScope(); } if ($functionReflection !== null && in_array($functionReflection->getName(), ['sort', 'rsort', 'usort'], \true) && count($normalizedExpr->getArgs()) >= 1) { $arrayArg = $normalizedExpr->getArgs()[0]->value; $scope = $nodeScopeResolver->processVirtualAssign($scope, $storage, $stmt, $arrayArg, new NativeTypeExpr($scope->getType($arrayArg)->shuffleArray(), $scope->getNativeType($arrayArg)->shuffleArray()), $nodeCallback)->getScope(); } if ($functionReflection !== null && in_array($functionReflection->getName(), ['natcasesort', 'natsort', 'arsort', 'asort', 'ksort', 'krsort', 'uasort', 'uksort'], \true) && count($normalizedExpr->getArgs()) >= 1) { $arrayArg = $normalizedExpr->getArgs()[0]->value; $scope = $nodeScopeResolver->processVirtualAssign($scope, $storage, $stmt, $arrayArg, new NativeTypeExpr($scope->getType($arrayArg)->makeListMaybe(), $scope->getNativeType($arrayArg)->makeListMaybe()), $nodeCallback)->getScope(); } if ($functionReflection !== null && $functionReflection->getName() === 'extract') { $extractedArg = $normalizedExpr->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); if (!$optional) { $scope = $scope->assignVariable($name, $type, $type, TrinaryLogic::createYes()); } else { $hasVariable = $scope->hasVariableType($name); if (!$hasVariable->no()) { $type = TypeCombinator::union($scope->getVariableType($name), $type); } $scope = $scope->assignVariable($name, $type, $type, $scope->hasVariableType($name)->or(TrinaryLogic::createMaybe())); } } } 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()); } return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints, static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } private function getFunctionThrowPoint(FunctionReflection $functionReflection, ?ParametersAcceptor $parametersAcceptor, FuncCall $normalizedFuncCall, MutatingScope $scope): ?InternalThrowPoint { foreach ($this->dynamicThrowTypeExtensionProvider->getDynamicFunctionThrowTypeExtensions() as $extension) { if (!$extension->isFunctionSupported($functionReflection)) { continue; } $throwType = $extension->getThrowTypeFromFunctionCall($functionReflection, $normalizedFuncCall, $scope); if ($throwType === null) { return null; } return InternalThrowPoint::createExplicit($scope, $throwType, $normalizedFuncCall, \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 InternalThrowPoint::createExplicit($scope, $throwType, $normalizedFuncCall, \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($normalizedFuncCall->getArgs()) > 0) { $functionReturnedType = $scope->getType($normalizedFuncCall); if (!(new ObjectType(Throwable::class))->isSuperTypeOf($functionReturnedType)->yes()) { return InternalThrowPoint::createImplicit($scope, $normalizedFuncCall); } } } return null; } private function getArrayFunctionAppendingType(FunctionReflection $functionReflection, 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 (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() ? new IntersectionType([$array, new NonEmptyArrayType()]) : $array; $constantArray = $isList ? TypeCombinator::intersect($constantArray, new AccessoryArrayListType()) : $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; } public function resolveType(MutatingScope $scope, Expr $expr): Type { if ($expr->name instanceof Expr) { $calledOnType = $scope->getType($expr->name); if ($calledOnType->isCallable()->no()) { return new ErrorType(); } $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $calledOnType->getCallableParametersAcceptors($scope), null); $functionName = null; if ($expr->name instanceof String_) { /** @var non-empty-string $name */ $name = $expr->name->value; $functionName = new Name($name); } elseif ($expr->name instanceof FuncCall && $expr->name->name instanceof Name && $expr->name->isFirstClassCallable()) { $functionName = $expr->name->name; } $normalizedNode = ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $expr); if ($normalizedNode !== null && $functionName !== null && $this->reflectionProvider->hasFunction($functionName, $scope)) { $functionReflection = $this->reflectionProvider->getFunction($functionName, $scope); $resolvedType = $this->getDynamicFunctionReturnType($scope, $normalizedNode, $functionReflection); if ($resolvedType !== null) { return $resolvedType; } } return $parametersAcceptor->getReturnType(); } if (!$this->reflectionProvider->hasFunction($expr->name, $scope)) { return new ErrorType(); } $functionReflection = $this->reflectionProvider->getFunction($expr->name, $scope); if ($scope->nativeTypesPromoted) { return ParametersAcceptorSelector::combineAcceptors($functionReflection->getVariants())->getNativeReturnType(); } if ($functionReflection->getName() === 'call_user_func') { $result = ArgumentsNormalizer::reorderCallUserFuncArguments($expr, $scope); if ($result !== null) { [, $innerFuncCall] = $result; return $scope->getType($innerFuncCall); } } if ($functionReflection->getName() === 'call_user_func_array') { $result = ArgumentsNormalizer::reorderCallUserFuncArrayArguments($expr, $scope); if ($result !== null) { [, $innerFuncCall] = $result; return $scope->getType($innerFuncCall); } } $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $functionReflection->getVariants(), $functionReflection->getNamedArgumentsVariants()); $normalizedNode = ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $expr); if ($normalizedNode !== null) { if ($functionReflection->getName() === 'clone' && count($normalizedNode->getArgs()) > 0) { $cloneType = $scope->getType(new Expr\Clone_($normalizedNode->getArgs()[0]->value)); if (count($normalizedNode->getArgs()) === 2) { $propertiesType = $scope->getType($normalizedNode->getArgs()[1]->value); if ($propertiesType->isConstantArray()->yes()) { $constantArrays = $propertiesType->getConstantArrays(); if (count($constantArrays) === 1) { $accessories = []; foreach ($constantArrays[0]->getKeyTypes() as $keyType) { $constantKeyTypes = $keyType->getConstantScalarValues(); if (count($constantKeyTypes) !== 1) { return $cloneType; } $accessories[] = new HasPropertyType((string) $constantKeyTypes[0]); } if (count($accessories) > 0 && count($accessories) <= 16) { return TypeCombinator::intersect($cloneType, ...$accessories); } } } } return $cloneType; } $resolvedType = $this->getDynamicFunctionReturnType($scope, $normalizedNode, $functionReflection); if ($resolvedType !== null) { return $resolvedType; } } return VoidToNullTypeTransformer::transform($parametersAcceptor->getReturnType(), $expr); } private function getDynamicFunctionReturnType(MutatingScope $scope, FuncCall $normalizedNode, FunctionReflection $functionReflection): ?Type { foreach ($this->dynamicReturnTypeExtensionRegistryProvider->getRegistry()->getDynamicFunctionReturnTypeExtensions($functionReflection) as $dynamicFunctionReturnTypeExtension) { $resolvedType = $dynamicFunctionReturnTypeExtension->getTypeFromFunctionCall($functionReflection, $normalizedNode, $scope); if ($resolvedType !== null) { return $resolvedType; } } return null; } } nodeScopeResolver = $nodeScopeResolver; } /** * @param \PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $expr */ public function getClosureType(MutatingScope $scope, $expr): ClosureType { $parameters = []; $isVariadic = \false; $firstOptionalParameterIndex = null; foreach ($expr->params as $i => $param) { $isOptionalCandidate = $param->default !== null || $param->variadic; if ($isOptionalCandidate) { if ($firstOptionalParameterIndex === null) { $firstOptionalParameterIndex = $i; } } else { $firstOptionalParameterIndex = null; } } foreach ($expr->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, $scope->getFunctionType($param->type, $scope->isParameterValueNullable($param), \false), $param->byRef ? PassedByReference::createCreatesNewVariable() : PassedByReference::createNo(), $param->variadic, $param->default !== null ? $scope->getType($param->default) : null); } $callableParameters = null; $arrayMapArgs = $expr->getAttribute(ArrayMapArgVisitor::ATTRIBUTE_NAME); $immediatelyInvokedArgs = $expr->getAttribute(ImmediatelyInvokedClosureVisitor::ARGS_ATTRIBUTE_NAME); if ($arrayMapArgs !== null) { $callableParameters = []; foreach ($arrayMapArgs as $funcCallArg) { $callableParameters[] = new DummyParameter('item', $scope->getType($funcCallArg->value)->getIterableValueType(), \false, PassedByReference::createNo(), \false, null); } } elseif ($immediatelyInvokedArgs !== null) { foreach ($immediatelyInvokedArgs as $immediatelyInvokedArg) { $callableParameters[] = new DummyParameter('item', $scope->getType($immediatelyInvokedArg->value), \false, PassedByReference::createNo(), \false, null); } } else { $inFunctionCallsStackCount = count($scope->inFunctionCallsStack); if ($inFunctionCallsStackCount > 0) { [, $inParameter] = $scope->inFunctionCallsStack[$inFunctionCallsStackCount - 1]; if ($inParameter !== null) { $callableParameters = $this->nodeScopeResolver->createCallableParameters($scope, $expr, null, $inParameter->getType()); } } } if ($expr instanceof ArrowFunction) { $arrowScope = $scope->enterArrowFunctionWithoutReflection($expr, $callableParameters); if ($expr->expr instanceof Yield_ || $expr->expr instanceof YieldFrom) { $yieldNode = $expr->expr; if ($yieldNode instanceof 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($expr->expr); if ($expr->returnType !== null) { $nativeReturnType = $scope->getFunctionType($expr->returnType, \false, \false); $returnType = MutatingScope::intersectButNotNever($nativeReturnType, $returnType); } } $arrowFunctionImpurePoints = []; $invalidateExpressions = []; $arrowFunctionExprResult = $this->nodeScopeResolver->processExprNode(new Node\Stmt\Expression($expr->expr), $expr->expr, $arrowScope, new ExpressionResultStorage(), static function (Node $node, 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 ImpurePoint($scope, $node, 'propertyAssign', 'property assignment', \true); $invalidateExpressions[] = new InvalidateExprNode($node->getPropertyFetch()); }, ExpressionContext::createDeep()); $throwPoints = array_map(static fn($throwPoint) => $throwPoint->toPublic(), $arrowFunctionExprResult->getThrowPoints()); $impurePoints = array_merge($arrowFunctionImpurePoints, $arrowFunctionExprResult->getImpurePoints()); $usedVariables = []; } else { $cachedTypes = $expr->getAttribute('phpstanCachedTypes', []); $cacheKey = $scope->getClosureScopeCacheKey(); if (array_key_exists($cacheKey, $cachedTypes)) { $cachedClosureData = $cachedTypes[$cacheKey]; $mustUseReturnValue = TrinaryLogic::createNo(); foreach ($expr->attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { if ($attr->name->toLowerString() === 'nodiscard') { $mustUseReturnValue = TrinaryLogic::createYes(); break; } } } return new ClosureType($parameters, $cachedClosureData['returnType'], $isVariadic, TemplateTypeMap::createEmpty(), TemplateTypeMap::createEmpty(), TemplateTypeVarianceMap::createEmpty(), [], $cachedClosureData['throwPoints'], $cachedClosureData['impurePoints'], $cachedClosureData['invalidateExpressions'], $cachedClosureData['usedVariables'], TrinaryLogic::createYes(), $mustUseReturnValue); } if (self::$resolveClosureTypeDepth >= 2) { return new ClosureType($parameters, $scope->getFunctionType($expr->returnType, \false, \false), $isVariadic); } self::$resolveClosureTypeDepth++; $closureScope = $scope->enterAnonymousFunctionWithoutReflection($expr, $callableParameters); $closureReturnStatements = []; $closureYieldStatements = []; $onlyNeverExecutionEnds = null; $closureImpurePoints = []; $invalidateExpressions = []; try { $closureStatementResult = $this->nodeScopeResolver->processStmtNodes($expr, $expr->stmts, $closureScope, static function (Node $node, 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 ImpurePoint($scope, $node, 'propertyAssign', 'property assignment', \true); $invalidateExpressions[] = new InvalidateExprNode($node->getPropertyFetch()); 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 Yield_ && !$node instanceof YieldFrom) { return; } $closureYieldStatements[] = [$node, $scope]; }, 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->toMutatingScope()->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 Yield_) { if ($yieldNode->key === null) { $keyTypes[] = new IntegerType(); } else { $keyTypes[] = $yieldScope->toMutatingScope()->getType($yieldNode->key); } if ($yieldNode->value === null) { $valueTypes[] = new NullType(); } else { $valueTypes[] = $yieldScope->toMutatingScope()->getType($yieldNode->value); } continue; } $yieldFromType = $yieldScope->toMutatingScope()->getType($yieldNode->expr); $keyTypes[] = $yieldScope->toMutatingScope()->getIterableKeyType($yieldFromType); $valueTypes[] = $yieldScope->toMutatingScope()->getIterableValueType($yieldFromType); } $returnType = new GenericObjectType(Generator::class, [TypeCombinator::union(...$keyTypes), TypeCombinator::union(...$valueTypes), new MixedType(), $returnType]); } else if ($expr->returnType !== null) { $nativeReturnType = $scope->getFunctionType($expr->returnType, \false, \false); $returnType = MutatingScope::intersectButNotNever($nativeReturnType, $returnType); } $usedVariables = []; foreach ($expr->uses as $use) { if (!is_string($use->var->name)) { continue; } $usedVariables[] = $use->var->name; } foreach ($expr->uses as $use) { if (!$use->byRef) { continue; } $impurePoints[] = new ImpurePoint($scope, $expr, 'functionCall', 'call to a Closure with by-ref use', \true); break; } } foreach ($parameters as $parameter) { if ($parameter->passedByReference()->no()) { continue; } $impurePoints[] = new ImpurePoint($scope, $expr, 'functionCall', 'call to a Closure with by-ref parameter', \true); } $throwPointsForClosureType = array_map(static fn(ThrowPoint $throwPoint) => $throwPoint->isExplicit() ? SimpleThrowPoint::createExplicit($throwPoint->getType(), $throwPoint->canContainAnyThrowable()) : SimpleThrowPoint::createImplicit(), $throwPoints); $impurePointsForClosureType = array_map(static fn(ImpurePoint $impurePoint) => new SimpleImpurePoint($impurePoint->getIdentifier(), $impurePoint->getDescription(), $impurePoint->isCertain()), $impurePoints); $cachedTypes = $expr->getAttribute('phpstanCachedTypes', []); $cachedTypes[$scope->getClosureScopeCacheKey()] = ['returnType' => $returnType, 'throwPoints' => $throwPointsForClosureType, 'impurePoints' => $impurePointsForClosureType, 'invalidateExpressions' => $invalidateExpressions, 'usedVariables' => $usedVariables]; $expr->setAttribute('phpstanCachedTypes', $cachedTypes); $mustUseReturnValue = TrinaryLogic::createNo(); foreach ($expr->attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { if ($attr->name->toLowerString() === 'nodiscard') { $mustUseReturnValue = TrinaryLogic::createYes(); break; } } } return new ClosureType($parameters, $returnType, $isVariadic, TemplateTypeMap::createEmpty(), TemplateTypeMap::createEmpty(), TemplateTypeVarianceMap::createEmpty(), [], $throwPointsForClosureType, $impurePointsForClosureType, $invalidateExpressions, $usedVariables, TrinaryLogic::createYes(), $mustUseReturnValue); } } phpVersion = $phpVersion; $this->methodThrowPointHelper = $methodThrowPointHelper; } public function processImplicitToStringCall(Expr $expr, MutatingScope $scope): ExpressionResult { $throwPoints = []; $impurePoints = []; $exprType = $scope->getType($expr); $toStringMethod = null; if (!$exprType->isObject()->no()) { $toStringMethod = $scope->getMethodReflection($exprType, '__toString'); } if ($toStringMethod === null) { return new ExpressionResult($scope, \false, \false, [], []); } if (!$toStringMethod->hasSideEffects()->no()) { $impurePoints[] = new ImpurePoint($scope, $expr, 'methodCall', sprintf('call to method %s::%s()', $toStringMethod->getDeclaringClass()->getDisplayName(), $toStringMethod->getName()), $toStringMethod->isPure()->no()); } if ($this->phpVersion->throwsOnStringCast()) { $throwPoint = $this->methodThrowPointHelper->getThrowPoint($toStringMethod, $toStringMethod->getOnlyVariant(), new Expr\MethodCall($expr, new Identifier('__toString')), $scope); if ($throwPoint !== null) { $throwPoints[] = $throwPoint; } } return new ExpressionResult($scope, \false, \false, $throwPoints, $impurePoints); } } dynamicReturnTypeExtensionRegistryProvider = $dynamicReturnTypeExtensionRegistryProvider; } /** * @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $methodCall */ public function methodCallReturnType(MutatingScope $scope, Type $typeWithMethod, string $methodName, $methodCall): ?Type { $typeWithMethod = $scope->filterTypeWithMethod($typeWithMethod, $methodName); if ($typeWithMethod === null) { return null; } $methodReflection = $typeWithMethod->getMethod($methodName, $scope); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $methodCall->getArgs(), $methodReflection->getVariants(), $methodReflection->getNamedArgumentsVariants()); if ($methodCall instanceof MethodCall) { $normalizedMethodCall = ArgumentsNormalizer::reorderMethodArguments($parametersAcceptor, $methodCall); } else { $normalizedMethodCall = ArgumentsNormalizer::reorderStaticCallArguments($parametersAcceptor, $methodCall); } if ($normalizedMethodCall === null) { return \PHPStan\Analyser\ExprHandler\Helper\VoidToNullTypeTransformer::transform($parametersAcceptor->getReturnType(), $methodCall); } $resolvedTypes = []; $allClassNames = $typeWithMethod->getObjectClassNames(); $handledClassNames = []; foreach ($allClassNames as $className) { if ($normalizedMethodCall instanceof MethodCall) { foreach ($this->dynamicReturnTypeExtensionRegistryProvider->getRegistry()->getDynamicMethodReturnTypeExtensionsForClass($className) as $dynamicMethodReturnTypeExtension) { if (!$dynamicMethodReturnTypeExtension->isMethodSupported($methodReflection)) { continue; } $resolvedType = $dynamicMethodReturnTypeExtension->getTypeFromMethodCall($methodReflection, $normalizedMethodCall, $scope); if ($resolvedType === null) { continue; } $resolvedTypes[] = $resolvedType; $handledClassNames[] = $className; } } else { foreach ($this->dynamicReturnTypeExtensionRegistryProvider->getRegistry()->getDynamicStaticMethodReturnTypeExtensionsForClass($className) as $dynamicStaticMethodReturnTypeExtension) { if (!$dynamicStaticMethodReturnTypeExtension->isStaticMethodSupported($methodReflection)) { continue; } $resolvedType = $dynamicStaticMethodReturnTypeExtension->getTypeFromStaticMethodCall($methodReflection, $normalizedMethodCall, $scope); if ($resolvedType === null) { continue; } $resolvedTypes[] = $resolvedType; $handledClassNames[] = $className; } } } if (count($resolvedTypes) > 0) { if (count($allClassNames) !== count($handledClassNames)) { $remainingType = $typeWithMethod; foreach ($handledClassNames as $handledClassName) { $remainingType = TypeCombinator::remove($remainingType, new ObjectType($handledClassName)); } if ($remainingType->hasMethod($methodName)->yes()) { $remainingMethod = $remainingType->getMethod($methodName, $scope); $remainingParametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $methodCall->getArgs(), $remainingMethod->getVariants(), $remainingMethod->getNamedArgumentsVariants()); $resolvedTypes[] = $remainingParametersAcceptor->getReturnType(); } } return \PHPStan\Analyser\ExprHandler\Helper\VoidToNullTypeTransformer::transform(TypeCombinator::union(...$resolvedTypes), $methodCall); } return \PHPStan\Analyser\ExprHandler\Helper\VoidToNullTypeTransformer::transform($parametersAcceptor->getReturnType(), $methodCall); } } dynamicThrowTypeExtensionProvider = $dynamicThrowTypeExtensionProvider; $this->implicitThrows = $implicitThrows; } /** * @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $normalizedMethodCall */ public function getThrowPoint(MethodReflection $methodReflection, ParametersAcceptor $parametersAcceptor, $normalizedMethodCall, MutatingScope $scope): ?InternalThrowPoint { if ($normalizedMethodCall instanceof MethodCall) { foreach ($this->dynamicThrowTypeExtensionProvider->getDynamicMethodThrowTypeExtensions() as $extension) { if (!$extension->isMethodSupported($methodReflection)) { continue; } $throwType = $extension->getThrowTypeFromMethodCall($methodReflection, $normalizedMethodCall, $scope); if ($throwType === null) { return null; } return InternalThrowPoint::createExplicit($scope, $throwType, $normalizedMethodCall, \false); } } else { foreach ($this->dynamicThrowTypeExtensionProvider->getDynamicStaticMethodThrowTypeExtensions() as $extension) { if (!$extension->isStaticMethodSupported($methodReflection)) { continue; } $throwType = $extension->getThrowTypeFromStaticMethodCall($methodReflection, $normalizedMethodCall, $scope); if ($throwType === null) { return null; } return InternalThrowPoint::createExplicit($scope, $throwType, $normalizedMethodCall, \false); } } if ($normalizedMethodCall instanceof MethodCall && in_array($methodReflection->getName(), ['invoke', 'invokeArgs'], \true) && in_array($methodReflection->getDeclaringClass()->getName(), [ReflectionMethod::class, ReflectionFunction::class], \true)) { return InternalThrowPoint::createImplicit($scope, $normalizedMethodCall); } $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 InternalThrowPoint::createExplicit($scope, $throwType, $normalizedMethodCall, \true); } } elseif ($this->implicitThrows) { $methodReturnedType = $scope->getType($normalizedMethodCall); if (!(new ObjectType(Throwable::class))->isSuperTypeOf($methodReturnedType)->yes()) { return InternalThrowPoint::createImplicit($scope, $normalizedMethodCall); } } return null; } } getType($exprToSpecify); $isNull = $exprType->isNull(); if ($isNull->yes()) { return new EnsuredNonNullabilityResult($scope, []); } $hasExpressionType = $originalScope->hasExpressionType($exprToSpecify); $exprTypeWithoutNull = TypeCombinator::removeNull($exprType); if ($exprType->equals($exprTypeWithoutNull)) { $originalExprType = $originalScope->getType($exprToSpecify); if (!$originalExprType->equals($exprTypeWithoutNull)) { $originalNativeType = $originalScope->getNativeType($exprToSpecify); return new EnsuredNonNullabilityResult($scope, [new EnsuredNonNullabilityResultExpression($exprToSpecify, $originalExprType, $originalNativeType, $hasExpressionType)]); } return new EnsuredNonNullabilityResult($scope, []); } $specifiedExpressions = []; // When narrowing an ArrayDimFetch, specifyExpressionType also recursively // narrows the parent array's offset type via intersection with HasOffsetValueType. // To properly revert this, we must also save and restore the parent expression's type. if ($exprToSpecify instanceof Expr\ArrayDimFetch && $exprToSpecify->dim !== null) { $parentExpr = $exprToSpecify->var; $specifiedExpressions[] = new EnsuredNonNullabilityResultExpression($parentExpr, $scope->getType($parentExpr), $scope->getNativeType($parentExpr), $originalScope->hasExpressionType($parentExpr)); } // keep certainty $certainty = TrinaryLogic::createYes(); if (!$hasExpressionType->no()) { $certainty = $hasExpressionType; } $nativeType = $scope->getNativeType($exprToSpecify); $specifiedExpressions[] = new EnsuredNonNullabilityResultExpression($exprToSpecify, $exprType, $nativeType, $certainty); $scope = $scope->specifyExpressionType($exprToSpecify, $exprTypeWithoutNull, TypeCombinator::removeNull($nativeType), TrinaryLogic::createYes()); return new EnsuredNonNullabilityResult($scope, $specifiedExpressions); } public function ensureNonNullability(MutatingScope $scope, Expr $expr): 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 EnsuredNonNullabilityResult($scope, $specifiedExpressions); } /** * @param EnsuredNonNullabilityResultExpression[] $specifiedExpressions */ public function revertNonNullability(MutatingScope $scope, array $specifiedExpressions): MutatingScope { foreach ($specifiedExpressions as $specifiedExpressionResult) { if ($specifiedExpressionResult->getCertainty()->no()) { $scope = $scope->invalidateExpression($specifiedExpressionResult->getExpression()); continue; } $scope = $scope->specifyExpressionType($specifiedExpressionResult->getExpression(), $specifiedExpressionResult->getOriginalType(), $specifiedExpressionResult->getOriginalNativeType(), $specifiedExpressionResult->getCertainty()); } return $scope; } /** * @param Closure(MutatingScope, Expr): MutatingScope $callback */ private function lookForExpressionCallback(MutatingScope $scope, Expr $expr, Closure $callback): 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 List_) { foreach ($expr->items as $item) { if ($item === null) { continue; } $scope = $this->lookForExpressionCallback($scope, $item->value, $callback); } } return $scope; } } getType($expr->var); if (TypeCombinator::containsNull($varType)) { return TypeCombinator::addNull($type); } return $type; } if ($expr instanceof ArrayDimFetch) { return self::getType($scope, $expr->var, $type); } if ($expr instanceof PropertyFetch) { return self::getType($scope, $expr->var, $type); } if ($expr instanceof StaticPropertyFetch && $expr->class instanceof Expr) { return self::getType($scope, $expr->class, $type); } if ($expr instanceof MethodCall) { return self::getType($scope, $expr->var, $type); } if ($expr instanceof StaticCall && $expr->class instanceof Expr) { return self::getType($scope, $expr->class, $type); } return $type; } } getAttribute(MutatingScope::KEEP_VOID_ATTRIBUTE_NAME) === \true) { return $type; } return TypeTraverser::map($type, new VoidToNullTraverser()); } } */ #[AutowiredService] final class IncludeHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof Include_; } public function resolveType(MutatingScope $scope, Expr $expr): Type { return new MixedType(); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context->enterDeep()); $identifier = in_array($expr->type, [Include_::TYPE_INCLUDE, Include_::TYPE_INCLUDE_ONCE], \true) ? 'include' : 'require'; $scope = $exprResult->getScope()->afterExtractCall(); return new ExpressionResult($scope, $exprResult->hasYield(), $exprResult->isAlwaysTerminating(), array_merge($exprResult->getThrowPoints(), [InternalThrowPoint::createImplicit($scope, $expr)]), array_merge($exprResult->getImpurePoints(), [new ImpurePoint($scope, $expr, $identifier, $identifier, \true)])); } } */ #[AutowiredService] final class InstanceofHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof Instanceof_; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context->enterDeep()); $hasYield = $exprResult->hasYield(); $throwPoints = $exprResult->getThrowPoints(); $impurePoints = $exprResult->getImpurePoints(); $isAlwaysTerminating = $exprResult->isAlwaysTerminating(); $scope = $exprResult->getScope(); if (!$expr->class instanceof Name) { $classResult = $nodeScopeResolver->processExprNode($stmt, $expr->class, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $classResult->getScope(); $hasYield = $hasYield || $classResult->hasYield(); $throwPoints = array_merge($throwPoints, $classResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $classResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $classResult->isAlwaysTerminating(); } return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints, static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } public function resolveType(MutatingScope $scope, Expr $expr): Type { $expressionType = $scope->getType($expr->expr); if ($scope->isInTrait() && TypeUtils::findThisType($expressionType) !== null) { return new BooleanType(); } if ($expressionType instanceof NeverType) { return new ConstantBooleanType(\false); } $uncertainty = \false; if ($expr->class instanceof Name) { $unresolvedClassName = $expr->class->toString(); if (strtolower($unresolvedClassName) === 'static' && $scope->isInClass()) { $classType = new StaticType($scope->getClassReflection()); } else { $className = $scope->resolveName($expr->class); $classType = new ObjectType($className); } } else { $result = $scope->getType($expr->class)->toObjectTypeForInstanceofCheck(); $classType = $result->type; $uncertainty = $result->uncertainty; } 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(); } } */ #[AutowiredService] final class InterpolatedStringHandler implements ExprHandler { private InitializerExprTypeResolver $initializerExprTypeResolver; private ImplicitToStringCallHelper $implicitToStringCallHelper; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver, ImplicitToStringCallHelper $implicitToStringCallHelper) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->implicitToStringCallHelper = $implicitToStringCallHelper; } public function supports(Expr $expr): bool { return $expr instanceof InterpolatedString; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $hasYield = \false; $throwPoints = []; $impurePoints = []; $isAlwaysTerminating = \false; foreach ($expr->parts as $part) { if (!$part instanceof Expr) { continue; } $partResult = $nodeScopeResolver->processExprNode($stmt, $part, $scope, $storage, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $partResult->hasYield(); $throwPoints = array_merge($throwPoints, $partResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $partResult->getImpurePoints()); $toStringResult = $this->implicitToStringCallHelper->processImplicitToStringCall($part, $scope); $throwPoints = array_merge($throwPoints, $toStringResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $toStringResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $partResult->isAlwaysTerminating(); $scope = $partResult->getScope(); } return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints); } public function resolveType(MutatingScope $scope, Expr $expr): Type { $resultType = null; foreach ($expr->parts as $part) { if ($part instanceof InterpolatedStringPart) { $partType = new ConstantStringType($part->value); } else { $partType = $scope->getType($part)->toString(); } if ($resultType === null) { $resultType = $partType; continue; } $resultType = $this->initializerExprTypeResolver->resolveConcatType($resultType, $partType); } return $resultType ?? new ConstantStringType(''); } } */ #[AutowiredService] final class IssetHandler implements ExprHandler { private NonNullabilityHelper $nonNullabilityHelper; public function __construct(NonNullabilityHelper $nonNullabilityHelper) { $this->nonNullabilityHelper = $nonNullabilityHelper; } public function supports(Expr $expr): bool { return $expr instanceof Isset_; } public function resolveType(MutatingScope $scope, Expr $expr): Type { $issetResult = \true; foreach ($expr->vars as $var) { $result = $scope->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); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $hasYield = \false; $throwPoints = []; $impurePoints = []; $nonNullabilityResults = []; $isAlwaysTerminating = \false; foreach ($expr->vars as $var) { $nonNullabilityResult = $this->nonNullabilityHelper->ensureNonNullability($scope, $var); $scope = $nodeScopeResolver->lookForSetAllowedUndefinedExpressions($nonNullabilityResult->getScope(), $var); $varResult = $nodeScopeResolver->processExprNode($stmt, $var, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $varResult->getScope(); $hasYield = $hasYield || $varResult->hasYield(); $throwPoints = array_merge($throwPoints, $varResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $varResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $varResult->isAlwaysTerminating(); $nonNullabilityResults[] = $nonNullabilityResult; if (!$var instanceof ArrayDimFetch) { continue; } $varType = $scope->getType($var->var); if ($varType->isArray()->yes() || (new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->no()) { continue; } $throwPoints = array_merge($throwPoints, $nodeScopeResolver->processExprNode($stmt, new MethodCall(new TypeExpr($varType), 'offsetExists'), $scope, $storage, new NoopNodeCallback(), $context)->getThrowPoints()); } foreach (array_reverse($expr->vars) as $var) { $scope = $nodeScopeResolver->lookForUnsetAllowedUndefinedExpressions($scope, $var); } foreach (array_reverse($nonNullabilityResults) as $nonNullabilityResult) { $scope = $this->nonNullabilityHelper->revertNonNullability($scope, $nonNullabilityResult->getSpecifiedExpressions()); } return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints, static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } } */ #[AutowiredService] final class MatchHandler implements ExprHandler { private bool $treatPhpDocTypesAsCertain; public function __construct( #[AutowiredParameter] bool $treatPhpDocTypesAsCertain ) { $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; } public function supports(Expr $expr): bool { return $expr instanceof Match_; } public function resolveType(MutatingScope $scope, Expr $expr): Type { $cond = $expr->cond; $condType = $scope->getType($cond); $types = []; $matchScope = $scope; $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; } $conditionCases = []; foreach ($arm->conds as $armCond) { if (!$armCond instanceof Expr\ClassConstFetch) { continue 2; } if (!$armCond->class instanceof Name) { continue 2; } if (!$armCond->name instanceof Identifier) { continue 2; } $fetchedClassName = $scope->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 ($expr->hasAttribute(MutatingScope::KEEP_VOID_ATTRIBUTE_NAME)) { $arm->body->setAttribute(MutatingScope::KEEP_VOID_ATTRIBUTE_NAME, $expr->getAttribute(MutatingScope::KEEP_VOID_ATTRIBUTE_NAME)); } $types[] = $matchScope->getType($arm->body); continue; } if (count($arm->conds) === 0) { throw new ShouldNotHappenException(); } $filteringExpr = $this->getFilteringExprForMatchArm($expr, $arm->conds); $filteringExprType = $matchScope->getType($filteringExpr); if (!$filteringExprType->isFalse()->yes()) { $truthyScope = $matchScope->filterByTruthyValue($filteringExpr); if ($expr->hasAttribute(MutatingScope::KEEP_VOID_ATTRIBUTE_NAME)) { $arm->body->setAttribute(MutatingScope::KEEP_VOID_ATTRIBUTE_NAME, $expr->getAttribute(MutatingScope::KEEP_VOID_ATTRIBUTE_NAME)); } $types[] = $truthyScope->getType($arm->body); } $matchScope = $matchScope->filterByFalseyValue($filteringExpr); } return TypeCombinator::union(...$types); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $deepContext = $context->enterDeep(); $condType = $scope->getType($expr->cond); $condNativeType = $scope->getNativeType($expr->cond); $condResult = $nodeScopeResolver->processExprNode($stmt, $expr->cond, $scope, $storage, $nodeCallback, $deepContext); $scope = $condResult->getScope(); $hasYield = $condResult->hasYield(); $throwPoints = $condResult->getThrowPoints(); $impurePoints = $condResult->getImpurePoints(); $isAlwaysTerminating = $condResult->isAlwaysTerminating(); $matchScope = $scope->enterMatch($expr, $condType, $condNativeType); $armNodes = []; $hasDefaultCond = \false; $hasAlwaysTrueCond = \false; $arms = $expr->arms; $armCondsToSkip = []; $armBodyScopes = []; 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; } // Pre-validate all conditions before processing to avoid // partial consumption of enum cases when a later condition // causes the arm to be skipped. // Use break instead of continue to stop fast-path processing // entirely - subsequent arms must also go through the slow // path to preserve correct evaluation order. foreach ($arm->conds as $cond) { if (!$cond instanceof Expr\ClassConstFetch) { break 2; } if (!$cond->class instanceof Name) { break 2; } if (!$cond->name instanceof Identifier) { break 2; } $fetchedClassName = $scope->resolveName($cond->class); $loweredFetchedClassName = strtolower($fetchedClassName); if (!array_key_exists($loweredFetchedClassName, $indexedEnumCases)) { break 2; } $caseName = $cond->name->toString(); if (!array_key_exists($caseName, $indexedEnumCases[$loweredFetchedClassName])) { break 2; } } $condNodes = []; $conditionCases = []; $conditionExprs = []; foreach ($arm->conds as $j => $cond) { if (!$cond instanceof Expr\ClassConstFetch) { throw new ShouldNotHappenException(); } if (!$cond->class instanceof Name) { throw new ShouldNotHappenException(); } if (!$cond->name instanceof Identifier) { throw new ShouldNotHappenException(); } $fetchedClassName = $scope->resolveName($cond->class); $loweredFetchedClassName = strtolower($fetchedClassName); if (!array_key_exists($loweredFetchedClassName, $indexedEnumCases)) { throw new ShouldNotHappenException(); } if (!array_key_exists($loweredFetchedClassName, $unusedIndexedEnumCases)) { throw new ShouldNotHappenException(); } $caseName = $cond->name->toString(); if (!array_key_exists($caseName, $indexedEnumCases[$loweredFetchedClassName])) { throw new ShouldNotHappenException(); } $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); } } $nodeScopeResolver->processExprNode($stmt, $cond, $armConditionScope, $storage, $nodeCallback, $deepContext); $condNodes[] = new MatchExpressionArmCondition($cond, $armConditionScope, $cond->getStartLine()); $conditionExprs[] = $cond; unset($unusedIndexedEnumCases[$loweredFetchedClassName][$caseName]); $armCondsToSkip[$i][$j] = \true; } $conditionCasesCount = count($conditionCases); if ($conditionCasesCount === 0) { throw new ShouldNotHappenException(); } elseif ($conditionCasesCount === 1) { $conditionCaseType = $conditionCases[0]; } else { $conditionCaseType = new UnionType($conditionCases); } $filteringExpr = $this->getFilteringExprForMatchArm($expr, $conditionExprs); $matchArmBodyScope = $matchScope->addTypeToExpression($expr->cond, $conditionCaseType)->filterByTruthyValue($filteringExpr); $matchArmBody = new MatchExpressionArmBody($matchArmBodyScope, $arm->body); $armNodes[$i] = new MatchExpressionArm($matchArmBody, $condNodes, $arm->getStartLine()); $armResult = $nodeScopeResolver->processExprNode($stmt, $arm->body, $matchArmBodyScope, $storage, $nodeCallback, ExpressionContext::createTopLevel()); $armScope = $armResult->getScope(); if (!$armResult->isAlwaysTerminating()) { $armBodyScopes[] = $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 = $nodeScopeResolver->processExprNode($stmt, $arm->body, $matchScope, $storage, $nodeCallback, ExpressionContext::createTopLevel()); $matchScope = $armResult->getScope(); $hasYield = $hasYield || $armResult->hasYield(); $throwPoints = array_merge($throwPoints, $armResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $armResult->getImpurePoints()); if (!$armResult->isAlwaysTerminating()) { $armBodyScopes[] = $matchScope; } continue; } if (count($arm->conds) === 0) { throw new ShouldNotHappenException(); } $filteringExprs = []; $armCondScope = $matchScope; $condNodes = []; $armCondResultScope = $matchScope; $bodyScope = null; foreach ($arm->conds as $j => $armCond) { if (isset($armCondsToSkip[$i][$j])) { continue; } $condNodes[] = new MatchExpressionArmCondition($armCond, $armCondScope, $armCond->getStartLine()); $armCondResult = $nodeScopeResolver->processExprNode($stmt, $armCond, $armCondScope, $storage, $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 = $armCondResultScope->filterByFalseyValue($armCondExpr); if ($bodyScope === null) { $bodyScope = $armCondResultScope->filterByTruthyValue($armCondExpr); } else { $bodyScope = $bodyScope->mergeWith($armCondResultScope->filterByTruthyValue($armCondExpr)); } $filteringExprs[] = $armCond; } $filteringExpr = $this->getFilteringExprForMatchArm($expr, $filteringExprs); $bodyScope ??= $matchScope->filterByTruthyValue($filteringExpr); $matchArmBody = new MatchExpressionArmBody($bodyScope, $arm->body); $armNodes[$i] = new MatchExpressionArm($matchArmBody, $condNodes, $arm->getStartLine()); $armResult = $nodeScopeResolver->processExprNode($stmt, $arm->body, $bodyScope, $storage, $nodeCallback, ExpressionContext::createTopLevel()); $armScope = $armResult->getScope(); if (!$armResult->isAlwaysTerminating()) { $armBodyScopes[] = $armScope; } $hasYield = $hasYield || $armResult->hasYield(); $throwPoints = array_merge($throwPoints, $armResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $armResult->getImpurePoints()); $matchScope = $armCondScope->filterByFalseyValue($filteringExpr); } if (!$hasDefaultCond && !$hasAlwaysTrueCond && $condType->isBoolean()->yes() && $condType->isConstantScalarValue()->yes()) { if ($this->isScopeConditionallyImpossible($matchScope)) { $hasAlwaysTrueCond = \true; $matchScope = $matchScope->addTypeToExpression($expr->cond, new NeverType()); } } $scopeForMatchNodeCallback = $scope; $isExhaustive = $hasDefaultCond || $hasAlwaysTrueCond; if (!$isExhaustive) { $remainingType = $matchScope->getType($expr->cond); if ($remainingType instanceof NeverType) { $isExhaustive = \true; } } if ($isExhaustive) { $armBodyFinalScope = null; foreach ($armBodyScopes as $armBodyScope) { $armBodyFinalScope = $armBodyScope->mergeWith($armBodyFinalScope); } $scope = $armBodyFinalScope ?? $scope; } else { $armBodyFinalScope = null; foreach ($armBodyScopes as $armBodyScope) { $armBodyFinalScope = $armBodyScope->mergeWith($armBodyFinalScope); } if ($armBodyFinalScope !== null) { $scope = $scope->mergeWith($armBodyFinalScope); } $throwPoints[] = InternalThrowPoint::createExplicit($scope, new ObjectType(UnhandledMatchError::class), $expr, \false); } ksort($armNodes, SORT_NUMERIC); $nodeScopeResolver->callNodeCallback($nodeCallback, new MatchExpressionNode($expr->cond, array_values($armNodes), $expr, $matchScope), $scopeForMatchNodeCallback, $storage); if ($expr->cond instanceof AlwaysRememberedExpr) { $expr->cond = $expr->cond->getExpr(); } return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints); } /** * @param Expr[] $conditions * @return \PhpParser\Node\Expr\BinaryOp\Identical|\PhpParser\Node\Expr\FuncCall */ private function getFilteringExprForMatchArm(Match_ $expr, array $conditions) { if (count($conditions) === 1) { return new BinaryOp\Identical($expr->cond, $conditions[0]); } $items = []; foreach ($conditions as $filteringExpr) { $items[] = new Node\ArrayItem($filteringExpr); } return new FuncCall(new Name\FullyQualified('in_array'), [new Arg($expr->cond), new Arg(new Array_($items)), new Arg(new ConstFetch(new Name\FullyQualified('true')))]); } private function isScopeConditionallyImpossible(MutatingScope $scope): bool { $boolVars = []; foreach ($scope->getDefinedVariables() as $varName) { $varType = $scope->getVariableType($varName); if (!$varType->isBoolean()->yes() || $varType->isConstantScalarValue()->yes()) { continue; } $boolVars[] = $varName; } if ($boolVars === []) { return \false; } // Check if any boolean variable's both truth values lead to contradictions foreach ($boolVars as $varName) { $varExpr = new Variable($varName); $truthyScope = $scope->filterByTruthyValue($varExpr); $truthyContradiction = $this->scopeHasNeverVariable($truthyScope, $boolVars); if (!$truthyContradiction) { continue; } $falseyScope = $scope->filterByFalseyValue($varExpr); $falseyContradiction = $this->scopeHasNeverVariable($falseyScope, $boolVars); if ($falseyContradiction) { return \true; } } return \false; } /** * @param string[] $varNames */ private function scopeHasNeverVariable(MutatingScope $scope, array $varNames): bool { foreach ($varNames as $varName) { $type = $scope->getVariableType($varName); if ($type instanceof NeverType) { return \true; } } return \false; } } */ #[AutowiredService] final class MethodCallHandler implements ExprHandler { private MethodCallReturnTypeHelper $methodCallReturnTypeHelper; private MethodThrowPointHelper $methodThrowPointHelper; private bool $rememberPossiblyImpureFunctionValues; public function __construct( MethodCallReturnTypeHelper $methodCallReturnTypeHelper, MethodThrowPointHelper $methodThrowPointHelper, #[AutowiredParameter] bool $rememberPossiblyImpureFunctionValues ) { $this->methodCallReturnTypeHelper = $methodCallReturnTypeHelper; $this->methodThrowPointHelper = $methodThrowPointHelper; $this->rememberPossiblyImpureFunctionValues = $rememberPossiblyImpureFunctionValues; } public function supports(Expr $expr): bool { return $expr instanceof MethodCall && !$expr->isFirstClassCallable(); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $originalScope = $scope; if (($expr->var instanceof Expr\Closure || $expr->var instanceof Expr\ArrowFunction) && $expr->name instanceof 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)); } $varResult = $nodeScopeResolver->processExprNode($stmt, $expr->var, $closureCallScope ?? $scope, $storage, $nodeCallback, $context->enterDeep()); $hasYield = $varResult->hasYield(); $throwPoints = $varResult->getThrowPoints(); $impurePoints = $varResult->getImpurePoints(); $isAlwaysTerminating = $varResult->isAlwaysTerminating(); $scope = $varResult->getScope(); if (isset($closureCallScope)) { $scope = $scope->restoreOriginalScopeAfterClosureBind($originalScope); } $parametersAcceptor = null; $methodReflection = null; $calledOnType = $scope->getType($expr->var); if ($expr->name instanceof Identifier) { $methodName = $expr->name->name; $methodReflection = $scope->getMethodReflection($calledOnType, $methodName); if ($methodReflection !== null) { $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $methodReflection->getVariants(), $methodReflection->getNamedArgumentsVariants()); } } else { $methodNameResult = $nodeScopeResolver->processExprNode($stmt, $expr->name, $scope, $storage, $nodeCallback, $context->enterDeep()); $throwPoints = array_merge($throwPoints, $methodNameResult->getThrowPoints()); $scope = $methodNameResult->getScope(); } if ($methodReflection !== null) { $impurePoint = SimpleImpurePoint::createFromVariant($methodReflection, $parametersAcceptor, $scope, $expr->getArgs()); if ($impurePoint !== null) { $impurePoints[] = new ImpurePoint($scope, $expr, $impurePoint->getIdentifier(), $impurePoint->getDescription(), $impurePoint->isCertain()); } } else { $impurePoints[] = new ImpurePoint($scope, $expr, 'methodCall', 'call to unknown method', \false); } $normalizedExpr = $expr; if ($parametersAcceptor !== null) { $normalizedExpr = ArgumentsNormalizer::reorderMethodArguments($parametersAcceptor, $expr) ?? $expr; $returnType = $parametersAcceptor->getReturnType(); $isAlwaysTerminating = $isAlwaysTerminating || $returnType instanceof NeverType && $returnType->isExplicit(); } $argsResult = $nodeScopeResolver->processArgs($stmt, $methodReflection, $methodReflection !== null ? $scope->getNakedMethod($calledOnType, $methodReflection->getName()) : null, $parametersAcceptor, $normalizedExpr, $scope, $storage, $nodeCallback, $context); $scope = $argsResult->getScope(); if ($methodReflection !== null) { $methodThrowPoint = $this->methodThrowPointHelper->getThrowPoint($methodReflection, $parametersAcceptor, $normalizedExpr, $scope); if ($methodThrowPoint !== null) { $throwPoints[] = $methodThrowPoint; } if ($methodReflection->getName() === '__construct' || $methodReflection->hasSideEffects()->yes()) { $nodeScopeResolver->callNodeCallback($nodeCallback, new InvalidateExprNode($normalizedExpr->var), $scope, $storage); $scope = $scope->invalidateExpression($normalizedExpr->var, \true, $methodReflection->getDeclaringClass()); } elseif ($this->rememberPossiblyImpureFunctionValues && $methodReflection->hasSideEffects()->maybe() && !$methodReflection->getDeclaringClass()->isBuiltin()) { $scope = $scope->assignExpression(new PossiblyImpureCallExpr($normalizedExpr, $normalizedExpr->var, sprintf('%s::%s()', $methodReflection->getDeclaringClass()->getDisplayName(), $methodReflection->getName())), $parametersAcceptor->getReturnType(), new MixedType()); } if (!$methodReflection->isStatic()) { $selfOutType = $methodReflection->getSelfOutType(); if ($selfOutType !== null) { $scope = $scope->assignExpression($normalizedExpr->var, TemplateTypeHelper::resolveTemplateTypes($selfOutType, $parametersAcceptor->getResolvedTemplateTypeMap(), $parametersAcceptor instanceof ExtendedParametersAcceptor ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createCovariant()), $scope->getNativeType($normalizedExpr->var)); } } } else { $nodeScopeResolver->callNodeCallback($nodeCallback, new InvalidateExprNode($normalizedExpr->var), $scope, $storage); $scope = $scope->invalidateExpression($normalizedExpr->var, \true); $throwPoints[] = InternalThrowPoint::createImplicit($scope, $expr); } $hasYield = $hasYield || $argsResult->hasYield(); $throwPoints = array_merge($throwPoints, $argsResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $argsResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $argsResult->isAlwaysTerminating(); $result = new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints, static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); $calledOnType = $originalScope->getType($expr->var); if (!$expr->name instanceof Identifier) { return $result; } $methodName = $expr->name->name; $methodReflection = $originalScope->getMethodReflection($calledOnType, $methodName); if ($methodReflection === null) { return $result; } if ($scope->isInClass() && $scope->getClassReflection()->getName() === $methodReflection->getDeclaringClass()->getName() && ($scope->getFunctionName() !== null && strtolower($scope->getFunctionName()) === '__construct') && TypeUtils::findThisType($calledOnType) !== null) { $calledMethodScope = $nodeScopeResolver->processCalledMethod($methodReflection); if ($calledMethodScope !== null) { $scope = $scope->mergeInitializedProperties($calledMethodScope); return new ExpressionResult($scope, $result->hasYield(), $result->isAlwaysTerminating(), $result->getThrowPoints(), $result->getImpurePoints(), static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } } return $result; } public function resolveType(MutatingScope $scope, Expr $expr): Type { if ($expr->name instanceof Identifier) { if ($scope->nativeTypesPromoted) { $methodReflection = $scope->getMethodReflection($scope->getNativeType($expr->var), $expr->name->name); if ($methodReflection === null) { $returnType = new ErrorType(); } else { $returnType = ParametersAcceptorSelector::combineAcceptors($methodReflection->getVariants())->getNativeReturnType(); } return NullsafeShortCircuitingHelper::getType($scope, $expr->var, $returnType); } $returnType = $this->methodCallReturnTypeHelper->methodCallReturnType($scope, $scope->getType($expr->var), $expr->name->name, $expr); if ($returnType === null) { $returnType = new ErrorType(); } return NullsafeShortCircuitingHelper::getType($scope, $expr->var, $returnType); } $nameType = $scope->getType($expr->name); if (count($nameType->getConstantStrings()) > 0) { return TypeCombinator::union(...array_map(static fn($constantString) => $constantString->getValue() === '' ? new ErrorType() : $scope->filterByTruthyValue(new Identical($expr->name, new String_($constantString->getValue())))->getType(new MethodCall($expr->var, new Identifier($constantString->getValue()), $expr->args)), $nameType->getConstantStrings())); } return new MixedType(); } } */ #[AutowiredService] final class NewHandler implements ExprHandler { private ReflectionProvider $reflectionProvider; private DynamicThrowTypeExtensionProvider $dynamicThrowTypeExtensionProvider; private DynamicReturnTypeExtensionRegistryProvider $dynamicReturnTypeExtensionRegistryProvider; private PropertyReflectionFinder $propertyReflectionFinder; private bool $implicitThrows; public function __construct( ReflectionProvider $reflectionProvider, DynamicThrowTypeExtensionProvider $dynamicThrowTypeExtensionProvider, DynamicReturnTypeExtensionRegistryProvider $dynamicReturnTypeExtensionRegistryProvider, PropertyReflectionFinder $propertyReflectionFinder, #[AutowiredParameter('%exceptions.implicitThrows%')] bool $implicitThrows ) { $this->reflectionProvider = $reflectionProvider; $this->dynamicThrowTypeExtensionProvider = $dynamicThrowTypeExtensionProvider; $this->dynamicReturnTypeExtensionRegistryProvider = $dynamicReturnTypeExtensionRegistryProvider; $this->propertyReflectionFinder = $propertyReflectionFinder; $this->implicitThrows = $implicitThrows; } public function supports(Expr $expr): bool { return $expr instanceof New_ && !$expr->isFirstClassCallable(); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $parametersAcceptor = null; $constructorReflection = null; $classReflection = null; $hasYield = \false; $throwPoints = []; $impurePoints = []; $isAlwaysTerminating = \false; $normalizedExpr = $expr; if ($expr->class instanceof Name) { $className = $scope->resolveName($expr->class); [$constructorReflection, $classReflection, $parametersAcceptor, $constructorImpurePoints] = $this->processConstructorReflection($className, $expr, $scope); $impurePoints = array_merge($impurePoints, $constructorImpurePoints); if ($parametersAcceptor !== null) { $normalizedExpr = ArgumentsNormalizer::reorderNewArguments($parametersAcceptor, $expr) ?? $expr; } } elseif ($expr->class instanceof Node\Stmt\Class_) { $classReflection = $this->reflectionProvider->getAnonymousClassReflection($expr->class, $scope); // populates $expr->class->name if ($classReflection->hasConstructor()) { $constructorReflection = $classReflection->getConstructor(); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $constructorReflection->getVariants(), $constructorReflection->getNamedArgumentsVariants()); if ($constructorReflection->getDeclaringClass()->getName() === $classReflection->getName()) { $constructorResult = null; $nodeScopeResolver->processStmtNode($expr->class, $scope, $storage, static function (Node $node, 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; }, StatementContext::createTopLevel()); if ($constructorResult !== null) { $throwPoints = array_map(static fn(ThrowPoint $point): InternalThrowPoint => InternalThrowPoint::createFromPublic($point, $scope), $constructorResult->getStatementResult()->getThrowPoints()); $impurePoints = $constructorResult->getImpurePoints(); } } else { $nodeScopeResolver->processStmtNode($expr->class, $scope, $storage, $nodeCallback, StatementContext::createTopLevel()); if (!$constructorReflection->hasSideEffects()->no()) { $certain = $constructorReflection->isPure()->no(); $impurePoints[] = new ImpurePoint($scope, $expr, 'new', sprintf('instantiation of class %s', $constructorReflection->getDeclaringClass()->getDisplayName()), $certain); } } } else { $nodeScopeResolver->processStmtNode($expr->class, $scope, $storage, $nodeCallback, StatementContext::createTopLevel()); } } else { $objectClasses = $scope->getType($expr)->getObjectClassNames(); if (count($objectClasses) === 1) { $objectExprResult = $nodeScopeResolver->processExprNode($stmt, new New_(new Name($objectClasses[0])), $scope, $storage, new NoopNodeCallback(), $context->enterDeep()); $className = $objectClasses[0]; $additionalThrowPoints = $objectExprResult->getThrowPoints(); } else { $className = null; $additionalThrowPoints = [InternalThrowPoint::createImplicit($scope, $expr)]; } $classResult = $nodeScopeResolver->processExprNode($stmt, $expr->class, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $classResult->getScope(); $hasYield = $classResult->hasYield(); $throwPoints = $classResult->getThrowPoints(); $impurePoints = $classResult->getImpurePoints(); $isAlwaysTerminating = $classResult->isAlwaysTerminating(); $throwPoints = array_merge($throwPoints, $additionalThrowPoints); if ($className !== null) { [$constructorReflection, $classReflection, $parametersAcceptor, $constructorImpurePoints] = $this->processConstructorReflection($className, $expr, $scope); $impurePoints = array_merge($impurePoints, $constructorImpurePoints); } else { $impurePoints[] = new ImpurePoint($scope, $expr, 'new', 'instantiation of unknown class', \false); } if ($parametersAcceptor !== null) { $normalizedExpr = ArgumentsNormalizer::reorderNewArguments($parametersAcceptor, $expr) ?? $expr; } } $argsResult = $nodeScopeResolver->processArgs($stmt, $constructorReflection, null, $parametersAcceptor, $normalizedExpr, $scope, $storage, $nodeCallback, $context); $scope = $argsResult->getScope(); $hasYield = $hasYield || $argsResult->hasYield(); $throwPoints = array_merge($throwPoints, $argsResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $argsResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $argsResult->isAlwaysTerminating(); if ($constructorReflection !== null && $parametersAcceptor !== null) { $className ??= $constructorReflection->getDeclaringClass()->getName(); $constructorThrowPoint = $this->getConstructorThrowPoint($constructorReflection, $parametersAcceptor, $expr, new Name\FullyQualified($className), $expr->getArgs(), $scope); if ($constructorThrowPoint !== null) { $throwPoints[] = $constructorThrowPoint; } } elseif ($classReflection === null) { $throwPoints[] = InternalThrowPoint::createImplicit($scope, $expr); } return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints); } /** * @return array{?MethodReflection, ?ClassReflection, ?ParametersAcceptor, ImpurePoint[]} */ private function processConstructorReflection(string $className, New_ $expr, MutatingScope $scope): array { $constructorReflection = null; $parametersAcceptor = null; $impurePoints = []; $classReflection = null; if ($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()); } } if ($constructorReflection !== null) { if (!$constructorReflection->hasSideEffects()->no()) { $certain = $constructorReflection->isPure()->no(); $impurePoints[] = new ImpurePoint($scope, $expr, 'new', sprintf('instantiation of class %s', $constructorReflection->getDeclaringClass()->getDisplayName()), $certain); } } elseif ($classReflection === null) { $impurePoints[] = new ImpurePoint($scope, $expr, 'new', 'instantiation of unknown class', \false); } return [$constructorReflection, $classReflection, $parametersAcceptor, $impurePoints]; } /** * @param list $args */ private function getConstructorThrowPoint(MethodReflection $constructorReflection, ParametersAcceptor $parametersAcceptor, New_ $new, Name $className, array $args, MutatingScope $scope): ?InternalThrowPoint { $methodCall = new StaticCall($className, $constructorReflection->getName(), $args); $normalizedMethodCall = 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 InternalThrowPoint::createExplicit($scope, $throwType, $new, \false); } } if ($constructorReflection->getThrowType() !== null) { $throwType = $constructorReflection->getThrowType(); if (!$throwType->isVoid()->yes()) { return InternalThrowPoint::createExplicit($scope, $throwType, $new, \true); } } elseif ($this->implicitThrows) { if (!$constructorReflection->getDeclaringClass()->is(Throwable::class)) { return InternalThrowPoint::createImplicit($scope, $methodCall); } } return null; } public function resolveType(MutatingScope $scope, Expr $expr): Type { if ($expr->class instanceof Name) { return $this->exactInstantiation($scope, $expr, $expr->class); } if ($expr->class instanceof Node\Stmt\Class_) { $anonymousClassReflection = $this->reflectionProvider->getAnonymousClassReflection($expr->class, $scope); return new ObjectType($anonymousClassReflection->getName()); } $exprType = $scope->getType($expr->class); return $exprType->getObjectTypeOrClassStringObjectType(); } private function exactInstantiation(MutatingScope $scope, New_ $node, Name $className): Type { $resolvedClassName = $scope->resolveName($className); $isStatic = \false; $lowercasedClassName = $className->toLowerString(); if ($lowercasedClassName === 'static') { $isStatic = \true; } if (!$this->reflectionProvider->hasClass($resolvedClassName)) { if ($lowercasedClassName === 'static') { if (!$scope->isInClass()) { return new ErrorType(); } return new StaticType($scope->getClassReflection()); } if ($lowercasedClassName === 'parent') { return new NonexistentParentClassType(); } return new ObjectType($resolvedClassName); } $classReflection = $this->reflectionProvider->getClass($resolvedClassName); $nonFinalClassReflection = $classReflection; if (!$isStatic) { $classReflection = $classReflection->asFinal(); } if ($classReflection->hasConstructor()) { $constructorMethod = $classReflection->getConstructor(); } else { $constructorMethod = new DummyConstructorReflection($classReflection); } if ($constructorMethod->getName() === '') { throw new ShouldNotHappenException(); } $resolvedTypes = []; $methodCall = new Expr\StaticCall(new Name($resolvedClassName), new Node\Identifier($constructorMethod->getName()), $node->getArgs()); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $methodCall->getArgs(), $constructorMethod->getVariants(), $constructorMethod->getNamedArgumentsVariants()); $normalizedMethodCall = ArgumentsNormalizer::reorderStaticCallArguments($parametersAcceptor, $methodCall); if ($normalizedMethodCall !== null) { foreach ($this->dynamicReturnTypeExtensionRegistryProvider->getRegistry()->getDynamicStaticMethodReturnTypeExtensionsForClass($classReflection->getName()) as $dynamicStaticMethodReturnTypeExtension) { if (!$dynamicStaticMethodReturnTypeExtension->isStaticMethodSupported($constructorMethod)) { continue; } $resolvedType = $dynamicStaticMethodReturnTypeExtension->getTypeFromStaticMethodCall($constructorMethod, $normalizedMethodCall, $scope); if ($resolvedType === null) { continue; } $resolvedTypes[] = $resolvedType; } } if (count($resolvedTypes) > 0) { return TypeCombinator::union(...$resolvedTypes); } $methodResult = $scope->getType($methodCall); if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { return $methodResult; } $objectType = $isStatic ? new StaticType($classReflection) : new ObjectType($resolvedClassName, \null, $classReflection); if (!$classReflection->isGeneric()) { return $objectType; } $assignedToProperty = $node->getAttribute(NewAssignedToPropertyVisitor::ATTRIBUTE_NAME); if ($assignedToProperty !== null) { $constructorVariants = $constructorMethod->getVariants(); if (count($constructorVariants) === 1) { $constructorVariant = $constructorVariants[0]; $classTemplateTypes = $classReflection->getTemplateTypeMap()->getTypes(); $originalClassTemplateTypes = $classTemplateTypes; $traverser = new ConstructorClassTemplateTraverser($classTemplateTypes); foreach ($constructorVariant->getParameters() as $parameter) { if (!$parameter->getType()->hasTemplateOrLateResolvableType()) { continue; } TypeTraverser::map($parameter->getType(), $traverser); } $classTemplateTypes = $traverser->getClassTemplateTypes(); if (count($classTemplateTypes) === count($originalClassTemplateTypes)) { $foundProperty = $this->propertyReflectionFinder->findPropertyReflectionFromNode($assignedToProperty, $scope); if ($foundProperty !== null) { $nonFinalObjectType = $isStatic ? new StaticType($nonFinalClassReflection) : new ObjectType($resolvedClassName, \null, $nonFinalClassReflection); $propertyType = TypeCombinator::intersect($foundProperty->getWritableType(), $nonFinalObjectType); if (!$propertyType instanceof NeverType) { return $propertyType; } } } } } if ($constructorMethod instanceof DummyConstructorReflection) { if ($isStatic) { return new GenericStaticType($classReflection, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()), null, []); } $types = $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()); return new GenericObjectType($resolvedClassName, $types, \null, $classReflection->withTypes($types)->asFinal()); } if ($constructorMethod->getDeclaringClass()->getName() !== $classReflection->getName()) { if (!$constructorMethod->getDeclaringClass()->isGeneric()) { if ($isStatic) { return new GenericStaticType($classReflection, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()), null, []); } $types = $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()); return new GenericObjectType($resolvedClassName, $types, \null, $classReflection->withTypes($types)->asFinal()); } $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, []); } $types = $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()); return new GenericObjectType($resolvedClassName, $types, \null, $classReflection->withTypes($types)->asFinal()); } $ancestorClassReflections = $ancestorType->getObjectClassReflections(); if (count($ancestorClassReflections) !== 1) { if ($isStatic) { return new GenericStaticType($classReflection, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()), null, []); } $types = $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()); return new GenericObjectType($resolvedClassName, $types, \null, $classReflection->withTypes($types)->asFinal()); } $newParentNode = new New_(new Name($constructorMethod->getDeclaringClass()->getName()), $node->args); $newParentType = $scope->getType($newParentNode); $newParentTypeClassReflections = $newParentType->getObjectClassReflections(); if (count($newParentTypeClassReflections) !== 1) { if ($isStatic) { return new GenericStaticType($classReflection, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()), null, []); } $types = $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()); return new GenericObjectType($resolvedClassName, $types, \null, $classReflection->withTypes($types)->asFinal()); } $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, []); } $types = $classReflection->typeMapToList(new TemplateTypeMap($resolvedTypeMap)); return new GenericObjectType($resolvedClassName, $types, \null, $classReflection->withTypes($types)->asFinal()); } $resolvedTemplateTypeMap = $parametersAcceptor->getResolvedTemplateTypeMap(); $types = $classReflection->typeMapToList($classReflection->getTemplateTypeMap()); $newGenericType = new GenericObjectType($resolvedClassName, $types, \null, $classReflection->withTypes($types)->asFinal()); if ($isStatic) { $newGenericType = new GenericStaticType($classReflection, $types, null, []); } if (!$newGenericType->hasTemplateOrLateResolvableType()) { return $newGenericType; } return TypeTraverser::map($newGenericType, new GenericTypeTemplateTraverser($resolvedTemplateTypeMap)); } } */ #[AutowiredService] final class NullsafeMethodCallHandler implements ExprHandler { private NonNullabilityHelper $nonNullabilityHelper; public function __construct(NonNullabilityHelper $nonNullabilityHelper) { $this->nonNullabilityHelper = $nonNullabilityHelper; } public function supports(Expr $expr): bool { return $expr instanceof NullsafeMethodCall; } public function resolveType(MutatingScope $scope, Expr $expr): Type { $varType = $scope->getType($expr->var); if ($varType->isNull()->yes()) { return new NullType(); } if (!TypeCombinator::containsNull($varType)) { return $scope->getType(new MethodCall($expr->var, $expr->name, $expr->args)); } return TypeCombinator::union($scope->filterByTruthyValue(new NotIdentical($expr->var, new ConstFetch(new Name('null'))))->getType(new MethodCall($expr->var, $expr->name, $expr->args)), new NullType()); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $scopeBeforeNullsafe = $scope; $varType = $scope->getType($expr->var); $nonNullabilityResult = $this->nonNullabilityHelper->ensureShallowNonNullability($scope, $scope, $expr->var); $attributes = array_merge($expr->getAttributes(), ['virtualNullsafeMethodCall' => \true]); unset($attributes[ExprPrinter::ATTRIBUTE_CACHE_KEY]); $exprResult = $nodeScopeResolver->processExprNode($stmt, new MethodCall($expr->var, $expr->name, $expr->args, $attributes), $nonNullabilityResult->getScope(), $storage, $nodeCallback, $context); $scope = $this->nonNullabilityHelper->revertNonNullability($exprResult->getScope(), $nonNullabilityResult->getSpecifiedExpressions()); $varIsNull = $varType->isNull(); if ($varIsNull->yes()) { // Arguments are never evaluated when the var is always null. $scope = $scopeBeforeNullsafe; } elseif ($varIsNull->maybe()) { // Arguments might not be evaluated (short-circuit). // Merge with the original scope so variables assigned in arguments become "maybe defined". $scope = $scope->mergeWith($scopeBeforeNullsafe); } return new ExpressionResult($scope, $exprResult->hasYield(), \false, $exprResult->getThrowPoints(), $exprResult->getImpurePoints(), static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } } */ #[AutowiredService] final class NullsafePropertyFetchHandler implements ExprHandler { private NonNullabilityHelper $nonNullabilityHelper; public function __construct(NonNullabilityHelper $nonNullabilityHelper) { $this->nonNullabilityHelper = $nonNullabilityHelper; } public function supports(Expr $expr): bool { return $expr instanceof NullsafePropertyFetch; } public function resolveType(MutatingScope $scope, Expr $expr): Type { $varType = $scope->getType($expr->var); if ($varType->isNull()->yes()) { return new NullType(); } if (!TypeCombinator::containsNull($varType)) { return $scope->getType(new PropertyFetch($expr->var, $expr->name)); } return TypeCombinator::union($scope->filterByTruthyValue(new NotIdentical($expr->var, new ConstFetch(new Name('null'))))->getType(new PropertyFetch($expr->var, $expr->name)), new NullType()); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $nonNullabilityResult = $this->nonNullabilityHelper->ensureShallowNonNullability($scope, $scope, $expr->var); $attributes = array_merge($expr->getAttributes(), ['virtualNullsafePropertyFetch' => \true]); unset($attributes[ExprPrinter::ATTRIBUTE_CACHE_KEY]); $exprResult = $nodeScopeResolver->processExprNode($stmt, new PropertyFetch($expr->var, $expr->name, $attributes), $nonNullabilityResult->getScope(), $storage, $nodeCallback, $context); $scope = $this->nonNullabilityHelper->revertNonNullability($exprResult->getScope(), $nonNullabilityResult->getSpecifiedExpressions()); return new ExpressionResult($scope, $exprResult->hasYield(), \false, $exprResult->getThrowPoints(), $exprResult->getImpurePoints(), static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } } */ #[AutowiredService] final class PipeHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof Pipe; } public function resolveType(MutatingScope $scope, Expr $expr): Type { if ($expr->right instanceof FuncCall && $expr->right->isFirstClassCallable()) { return $scope->getType(new FuncCall($expr->right->name, [new Arg($expr->left)])); } elseif ($expr->right instanceof MethodCall && $expr->right->isFirstClassCallable()) { return $scope->getType(new MethodCall($expr->right->var, $expr->right->name, [new Arg($expr->left)])); } elseif ($expr->right instanceof StaticCall && $expr->right->isFirstClassCallable()) { return $scope->getType(new StaticCall($expr->right->class, $expr->right->name, [new Arg($expr->left)])); } return $scope->getType(new FuncCall($expr->right, [new Arg($expr->left)])); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $rightAttributes = array_merge($expr->right->getAttributes(), ['virtualPipeOperatorCall' => \true]); unset($rightAttributes[ExprPrinter::ATTRIBUTE_CACHE_KEY]); $argAttributes = $expr->getAttribute(ReversePipeTransformerVisitor::ARG_ATTRIBUTES_NAME, []); if ($expr->right instanceof FuncCall && $expr->right->isFirstClassCallable()) { $callExpr = new FuncCall($expr->right->name, [new Arg($expr->left, \false, \false, $argAttributes)], $rightAttributes); } elseif ($expr->right instanceof MethodCall && $expr->right->isFirstClassCallable()) { $callExpr = new MethodCall($expr->right->var, $expr->right->name, [new Arg($expr->left, \false, \false, $argAttributes)], $rightAttributes); } elseif ($expr->right instanceof StaticCall && $expr->right->isFirstClassCallable()) { $callExpr = new StaticCall($expr->right->class, $expr->right->name, [new Arg($expr->left, \false, \false, $argAttributes)], $rightAttributes); } else { $callExpr = new FuncCall($expr->right, [new Arg($expr->left, \false, \false, $argAttributes)], $rightAttributes); } $callResult = $nodeScopeResolver->processExprNode($stmt, $callExpr, $scope, $storage, $nodeCallback, $context); return new ExpressionResult($callResult->getScope(), $callResult->hasYield(), $callResult->isAlwaysTerminating(), $callResult->getThrowPoints(), $callResult->getImpurePoints()); } } */ #[AutowiredService] final class PostDecHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof PostDec; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $varResult = $nodeScopeResolver->processExprNode($stmt, $expr->var, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $nodeScopeResolver->processVirtualAssign($varResult->getScope(), $storage, $stmt, $expr->var, new PreDec($expr->var), $nodeCallback)->getScope(); return new ExpressionResult($scope, $varResult->hasYield(), $varResult->isAlwaysTerminating(), $varResult->getThrowPoints(), $varResult->getImpurePoints()); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $scope->getType($expr->var); } } */ #[AutowiredService] final class PostIncHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof PostInc; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $varResult = $nodeScopeResolver->processExprNode($stmt, $expr->var, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $nodeScopeResolver->processVirtualAssign($varResult->getScope(), $storage, $stmt, $expr->var, new PreInc($expr->var), $nodeCallback)->getScope(); return new ExpressionResult($scope, $varResult->hasYield(), $varResult->isAlwaysTerminating(), $varResult->getThrowPoints(), $varResult->getImpurePoints()); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $scope->getType($expr->var); } } */ #[AutowiredService] final class PreDecHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof PreDec; } public function resolveType(MutatingScope $scope, Expr $expr): Type { $varType = $scope->getType($expr->var); $varScalars = $varType->getConstantScalarValues(); if (count($varScalars) > 0) { $newTypes = []; foreach ($varScalars as $varValue) { if ($varValue === '') { $varValue = -1; } elseif (is_string($varValue) && !is_numeric($varValue)) { try { $varValue = str_decrement($varValue); } catch (ValueError $e) { return new NeverType(); } } elseif (is_numeric($varValue)) { --$varValue; } $newTypes[] = $scope->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()]); } return $scope->getType(new Minus($expr->var, new Int_(1))); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $varResult = $nodeScopeResolver->processExprNode($stmt, $expr->var, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $nodeScopeResolver->processVirtualAssign($varResult->getScope(), $storage, $stmt, $expr->var, $expr, $nodeCallback)->getScope(); return new ExpressionResult($scope, $varResult->hasYield(), $varResult->isAlwaysTerminating(), $varResult->getThrowPoints(), $varResult->getImpurePoints()); } } */ #[AutowiredService] final class PreIncHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof PreInc; } public function resolveType(MutatingScope $scope, Expr $expr): Type { $varType = $scope->getType($expr->var); $varScalars = $varType->getConstantScalarValues(); if (count($varScalars) > 0) { $newTypes = []; foreach ($varScalars as $varValue) { if ($varValue === '') { $varValue = '1'; } elseif (is_string($varValue) && !is_numeric($varValue)) { try { $varValue = str_increment($varValue); } catch (ValueError $e) { return new NeverType(); } } elseif (!is_bool($varValue)) { ++$varValue; } $newTypes[] = $scope->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()]); } return $scope->getType(new Plus($expr->var, new Int_(1))); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $varResult = $nodeScopeResolver->processExprNode($stmt, $expr->var, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $nodeScopeResolver->processVirtualAssign($varResult->getScope(), $storage, $stmt, $expr->var, $expr, $nodeCallback)->getScope(); return new ExpressionResult($scope, $varResult->hasYield(), $varResult->isAlwaysTerminating(), $varResult->getThrowPoints(), $varResult->getImpurePoints()); } } */ #[AutowiredService] final class PrintHandler implements ExprHandler { private ImplicitToStringCallHelper $implicitToStringCallHelper; public function __construct(ImplicitToStringCallHelper $implicitToStringCallHelper) { $this->implicitToStringCallHelper = $implicitToStringCallHelper; } public function supports(Expr $expr): bool { return $expr instanceof Print_; } public function resolveType(MutatingScope $scope, Expr $expr): Type { return new ConstantIntegerType(1); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context->enterDeep()); $throwPoints = $exprResult->getThrowPoints(); $impurePoints = $exprResult->getImpurePoints(); $toStringResult = $this->implicitToStringCallHelper->processImplicitToStringCall($expr->expr, $scope); $throwPoints = array_merge($throwPoints, $toStringResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $toStringResult->getImpurePoints()); $scope = $exprResult->getScope(); return new ExpressionResult($scope, $exprResult->hasYield(), $exprResult->isAlwaysTerminating(), $throwPoints, array_merge($impurePoints, [new ImpurePoint($scope, $expr, 'print', 'print', \true)])); } } */ #[AutowiredService] final class PropertyFetchHandler implements ExprHandler { private PhpVersion $phpVersion; private PropertyReflectionFinder $propertyReflectionFinder; public function __construct(PhpVersion $phpVersion, PropertyReflectionFinder $propertyReflectionFinder) { $this->phpVersion = $phpVersion; $this->propertyReflectionFinder = $propertyReflectionFinder; } public function supports(Expr $expr): bool { return $expr instanceof PropertyFetch; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $scopeBeforeVar = $scope; $varResult = $nodeScopeResolver->processExprNode($stmt, $expr->var, $scope, $storage, $nodeCallback, $context->enterDeep()); $hasYield = $varResult->hasYield(); $throwPoints = $varResult->getThrowPoints(); $impurePoints = $varResult->getImpurePoints(); $isAlwaysTerminating = $varResult->isAlwaysTerminating(); $scope = $varResult->getScope(); if ($expr->name instanceof Identifier) { $propertyName = $expr->name->toString(); $propertyHolderType = $scopeBeforeVar->getType($expr->var); $propertyReflection = $scopeBeforeVar->getInstancePropertyReflection($propertyHolderType, $propertyName); if ($propertyReflection !== null && $this->phpVersion->supportsPropertyHooks()) { $propertyDeclaringClass = $propertyReflection->getDeclaringClass(); if ($propertyDeclaringClass->hasNativeProperty($propertyName)) { $nativeProperty = $propertyDeclaringClass->getNativeProperty($propertyName); $throwPoints = array_merge($throwPoints, $nodeScopeResolver->getThrowPointsFromPropertyHook($scopeBeforeVar, $expr, $nativeProperty, 'get')); } } } else { $nameResult = $nodeScopeResolver->processExprNode($stmt, $expr->name, $scope, $storage, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $nameResult->hasYield(); $throwPoints = array_merge($throwPoints, $nameResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $nameResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $nameResult->isAlwaysTerminating(); $scope = $nameResult->getScope(); if ($this->phpVersion->supportsPropertyHooks()) { $throwPoints[] = InternalThrowPoint::createImplicit($scope, $expr); } } return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints, static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } public function resolveType(MutatingScope $scope, Expr $expr): Type { if ($expr->name instanceof Identifier) { if ($scope->nativeTypesPromoted) { $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($expr, $scope); if ($propertyReflection === null) { return new ErrorType(); } if (!$propertyReflection->hasNativeType()) { return new MixedType(); } $nativeType = $propertyReflection->getNativeType(); return NullsafeShortCircuitingHelper::getType($scope, $expr->var, $nativeType); } $returnType = $this->propertyFetchType($scope, $scope->getType($expr->var), $expr->name->name, $expr); if ($returnType === null) { $returnType = new ErrorType(); } return NullsafeShortCircuitingHelper::getType($scope, $expr->var, $returnType); } $nameType = $scope->getType($expr->name); if (count($nameType->getConstantStrings()) > 0) { return TypeCombinator::union(...array_map(static fn($constantString) => $constantString->getValue() === '' ? new ErrorType() : $scope->filterByTruthyValue(new Expr\BinaryOp\Identical($expr->name, new String_($constantString->getValue())))->getType(new PropertyFetch($expr->var, new Identifier($constantString->getValue()))), $nameType->getConstantStrings())); } return new MixedType(); } private function propertyFetchType(MutatingScope $scope, Type $fetchedOnType, string $propertyName, PropertyFetch $propertyFetch): ?Type { $propertyReflection = $scope->getInstancePropertyReflection($fetchedOnType, $propertyName); if ($propertyReflection === null) { return null; } if ($scope->isInExpressionAssign($propertyFetch)) { return $propertyReflection->getWritableType(); } return $propertyReflection->getReadableType(); } } */ #[AutowiredService] final class ScalarHandler implements ExprHandler { private InitializerExprTypeResolver $initializerExprTypeResolver; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; } public function supports(Expr $expr): bool { return $expr instanceof Scalar && !$expr instanceof InterpolatedString; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { return new ExpressionResult($scope, \false, \false, [], []); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $this->initializerExprTypeResolver->getType($expr, InitializerExprContext::fromScope($scope)); } } */ #[AutowiredService] final class StaticCallHandler implements ExprHandler { private MethodCallReturnTypeHelper $methodCallReturnTypeHelper; private MethodThrowPointHelper $methodThrowPointHelper; private bool $rememberPossiblyImpureFunctionValues; public function __construct( MethodCallReturnTypeHelper $methodCallReturnTypeHelper, MethodThrowPointHelper $methodThrowPointHelper, #[AutowiredParameter] bool $rememberPossiblyImpureFunctionValues ) { $this->methodCallReturnTypeHelper = $methodCallReturnTypeHelper; $this->methodThrowPointHelper = $methodThrowPointHelper; $this->rememberPossiblyImpureFunctionValues = $rememberPossiblyImpureFunctionValues; } public function supports(Expr $expr): bool { return $expr instanceof StaticCall && !$expr->isFirstClassCallable(); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $hasYield = \false; $throwPoints = []; $impurePoints = []; $isAlwaysTerminating = \false; if ($expr->class instanceof Expr) { $classResult = $nodeScopeResolver->processExprNode($stmt, $expr->class, $scope, $storage, $nodeCallback, $context->enterDeep()); $hasYield = $classResult->hasYield(); $throwPoints = array_merge($throwPoints, $classResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $classResult->getImpurePoints()); $isAlwaysTerminating = $classResult->isAlwaysTerminating(); $scope = $classResult->getScope(); } $parametersAcceptor = null; $methodReflection = null; $closureBindScope = null; if ($expr->name instanceof Identifier) { if ($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()); $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[] = InternalThrowPoint::createImplicit($scope, $expr); } } elseif ($expr->class instanceof Expr) { $classType = $scope->getType($expr->class)->getObjectTypeOrClassStringObjectType(); $methodName = $expr->name->name; $methodReflection = $scope->getMethodReflection($classType, $methodName); if ($methodReflection !== null) { $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $methodReflection->getVariants(), $methodReflection->getNamedArgumentsVariants()); } } } else { $nameResult = $nodeScopeResolver->processExprNode($stmt, $expr->name, $scope, $storage, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $nameResult->hasYield(); $throwPoints = array_merge($throwPoints, $nameResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $nameResult->getImpurePoints()); $scope = $nameResult->getScope(); } 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 = $nodeScopeResolver->processExprNode($stmt, new StaticCall(new Name($objectClasses[0]), $expr->name, []), $scope, $storage, new NoopNodeCallback(), $context->enterDeep()); $additionalThrowPoints = $objectExprResult->getThrowPoints(); } else { $additionalThrowPoints = [InternalThrowPoint::createImplicit($scope, $expr)]; } foreach ($additionalThrowPoints as $throwPoint) { $throwPoints[] = $throwPoint; } } if ($methodReflection !== null) { $impurePoint = SimpleImpurePoint::createFromVariant($methodReflection, $parametersAcceptor, $scope, $expr->getArgs()); if ($impurePoint !== null) { $impurePoints[] = new ImpurePoint($scope, $expr, $impurePoint->getIdentifier(), $impurePoint->getDescription(), $impurePoint->isCertain()); } } else { $impurePoints[] = new ImpurePoint($scope, $expr, 'methodCall', 'call to unknown method', \false); } $normalizedExpr = $expr; if ($parametersAcceptor !== null) { $normalizedExpr = ArgumentsNormalizer::reorderStaticCallArguments($parametersAcceptor, $expr) ?? $expr; $returnType = $parametersAcceptor->getReturnType(); $isAlwaysTerminating = $isAlwaysTerminating || $returnType instanceof NeverType && $returnType->isExplicit(); } $argsResult = $nodeScopeResolver->processArgs($stmt, $methodReflection, null, $parametersAcceptor, $normalizedExpr, $scope, $storage, $nodeCallback, $context, $closureBindScope); $scope = $argsResult->getScope(); $scopeFunction = $scope->getFunction(); if ($methodReflection !== null) { $methodThrowPoint = $this->methodThrowPointHelper->getThrowPoint($methodReflection, $parametersAcceptor, $normalizedExpr, $scope); if ($methodThrowPoint !== null) { $throwPoints[] = $methodThrowPoint; } } if ($expr->class instanceof Name && $methodReflection !== null && (!$methodReflection->isStatic() && $methodReflection->getName() === '__construct' || $methodReflection->hasSideEffects()->yes()) && $scope->isInClass() && $scope->getClassReflection()->is($methodReflection->getDeclaringClass()->getName())) { $scope = $scope->invalidateExpression(new Variable('this'), \true, $methodReflection->getDeclaringClass()); } elseif ($expr->class instanceof Name && $methodReflection !== null && $this->rememberPossiblyImpureFunctionValues && $scope->isInClass() && $scope->getClassReflection()->is($methodReflection->getDeclaringClass()->getName()) && $methodReflection->hasSideEffects()->maybe() && !$methodReflection->getDeclaringClass()->isBuiltin()) { $scope = $scope->assignExpression(new PossiblyImpureCallExpr($normalizedExpr, new Variable('this'), sprintf('%s::%s()', $methodReflection->getDeclaringClass()->getDisplayName(), $methodReflection->getName())), $parametersAcceptor->getReturnType(), new MixedType()); } if ($expr->class instanceof Name && $methodReflection !== null && !$methodReflection->isStatic() && $methodReflection->getName() === '__construct' && $scopeFunction instanceof MethodReflection && !$scopeFunction->isStatic() && $scope->isInClass() && $scope->getClassReflection()->isSubclassOfClass($methodReflection->getDeclaringClass())) { $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 || $argsResult->hasYield(); $throwPoints = array_merge($throwPoints, $argsResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $argsResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $argsResult->isAlwaysTerminating(); return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints, static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } public function resolveType(MutatingScope $scope, Expr $expr): Type { if ($expr->name instanceof Identifier) { if ($scope->nativeTypesPromoted) { if ($expr->class instanceof Name) { $staticMethodCalledOnType = $this->resolveTypeByNameWithLateStaticBinding($scope, $expr->class, $expr->name); } else { $staticMethodCalledOnType = $scope->getNativeType($expr->class); } $methodReflection = $scope->getMethodReflection($staticMethodCalledOnType, $expr->name->name); if ($methodReflection === null) { $callType = new ErrorType(); } else { $callType = ParametersAcceptorSelector::combineAcceptors($methodReflection->getVariants())->getNativeReturnType(); } if ($expr->class instanceof Expr) { return NullsafeShortCircuitingHelper::getType($scope, $expr->class, $callType); } return $callType; } if ($expr->class instanceof Name) { $staticMethodCalledOnType = $this->resolveTypeByNameWithLateStaticBinding($scope, $expr->class, $expr->name); } else { $staticMethodCalledOnType = TypeCombinator::removeNull($scope->getType($expr->class))->getObjectTypeOrClassStringObjectType(); } $callType = $this->methodCallReturnTypeHelper->methodCallReturnType($scope, $staticMethodCalledOnType, $expr->name->toString(), $expr); if ($callType === null) { $callType = new ErrorType(); } if ($expr->class instanceof Expr) { return NullsafeShortCircuitingHelper::getType($scope, $expr->class, $callType); } return $callType; } $nameType = $scope->getType($expr->name); if (count($nameType->getConstantStrings()) > 0) { return TypeCombinator::union(...array_map(static fn($constantString) => $constantString->getValue() === '' ? new ErrorType() : $scope->filterByTruthyValue(new Identical($expr->name, new String_($constantString->getValue())))->getType(new Expr\StaticCall($expr->class, new Identifier($constantString->getValue()), $expr->args)), $nameType->getConstantStrings())); } return new MixedType(); } private function resolveTypeByNameWithLateStaticBinding(MutatingScope $scope, Name $class, Identifier $name): TypeWithClassName { $classType = $scope->resolveTypeByName($class); if ($classType instanceof StaticType && !in_array($class->toLowerString(), ['self', 'static', 'parent'], \true)) { $methodReflectionCandidate = $scope->getMethodReflection($classType, $name->name); if ($methodReflectionCandidate !== null && $methodReflectionCandidate->isStatic()) { $classType = $classType->getStaticObjectType(); } } return $classType; } } */ #[AutowiredService] final class StaticPropertyFetchHandler implements ExprHandler { private PropertyReflectionFinder $propertyReflectionFinder; public function __construct(PropertyReflectionFinder $propertyReflectionFinder) { $this->propertyReflectionFinder = $propertyReflectionFinder; } public function supports(Expr $expr): bool { return $expr instanceof StaticPropertyFetch; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $hasYield = \false; $throwPoints = []; $impurePoints = [new ImpurePoint($scope, $expr, 'staticPropertyAccess', 'static property access', \true)]; $isAlwaysTerminating = \false; if ($expr->class instanceof Expr) { $classResult = $nodeScopeResolver->processExprNode($stmt, $expr->class, $scope, $storage, $nodeCallback, $context->enterDeep()); $hasYield = $classResult->hasYield(); $throwPoints = $classResult->getThrowPoints(); $impurePoints = $classResult->getImpurePoints(); $isAlwaysTerminating = $classResult->isAlwaysTerminating(); $scope = $classResult->getScope(); } if (!$expr->name instanceof VarLikeIdentifier) { $nameResult = $nodeScopeResolver->processExprNode($stmt, $expr->name, $scope, $storage, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $nameResult->hasYield(); $throwPoints = array_merge($throwPoints, $nameResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $nameResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $nameResult->isAlwaysTerminating(); $scope = $nameResult->getScope(); } return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints, static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } public function resolveType(MutatingScope $scope, Expr $expr): Type { if ($expr->name instanceof VarLikeIdentifier) { if ($scope->nativeTypesPromoted) { $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($expr, $scope); if ($propertyReflection === null) { return new ErrorType(); } if (!$propertyReflection->hasNativeType()) { return new MixedType(); } $nativeType = $propertyReflection->getNativeType(); if ($expr->class instanceof Expr) { return NullsafeShortCircuitingHelper::getType($scope, $expr->class, $nativeType); } return $nativeType; } if ($expr->class instanceof Name) { $staticPropertyFetchedOnType = $scope->resolveTypeByName($expr->class); } else { $staticPropertyFetchedOnType = TypeCombinator::removeNull($scope->getType($expr->class))->getObjectTypeOrClassStringObjectType(); } $fetchType = $this->propertyFetchType($scope, $staticPropertyFetchedOnType, $expr->name->toString(), $expr); if ($fetchType === null) { $fetchType = new ErrorType(); } if ($expr->class instanceof Expr) { return NullsafeShortCircuitingHelper::getType($scope, $expr->class, $fetchType); } return $fetchType; } $nameType = $scope->getType($expr->name); if (count($nameType->getConstantStrings()) > 0) { return TypeCombinator::union(...array_map(static fn($constantString) => $constantString->getValue() === '' ? new ErrorType() : $scope->filterByTruthyValue(new Identical($expr->name, new String_($constantString->getValue())))->getType(new Expr\StaticPropertyFetch($expr->class, new VarLikeIdentifier($constantString->getValue()))), $nameType->getConstantStrings())); } return new MixedType(); } private function propertyFetchType(MutatingScope $scope, Type $fetchedOnType, string $propertyName, StaticPropertyFetch $propertyFetch): ?Type { $propertyReflection = $scope->getStaticPropertyReflection($fetchedOnType, $propertyName); if ($propertyReflection === null) { return null; } if ($scope->isInExpressionAssign($propertyFetch)) { return $propertyReflection->getWritableType(); } return $propertyReflection->getReadableType(); } } */ #[AutowiredService] final class TernaryHandler implements ExprHandler { private NodeScopeResolver $nodeScopeResolver; public function __construct(NodeScopeResolver $nodeScopeResolver) { $this->nodeScopeResolver = $nodeScopeResolver; } public function supports(Expr $expr): bool { return $expr instanceof Ternary; } public function resolveType(MutatingScope $scope, Expr $expr): Type { $condResult = $this->nodeScopeResolver->processExprNode(new Stmt\Expression($expr->cond), $expr->cond, $scope, new ExpressionResultStorage(), new NoopNodeCallback(), ExpressionContext::createDeep()); if ($expr->if === null) { $conditionType = $scope->getType($expr->cond); $booleanConditionType = $conditionType->toBoolean(); if ($booleanConditionType->isTrue()->yes()) { return $condResult->getTruthyScope()->getType($expr->cond); } if ($booleanConditionType->isFalse()->yes()) { return $condResult->getFalseyScope()->getType($expr->else); } return TypeCombinator::union(TypeCombinator::removeFalsey($condResult->getTruthyScope()->getType($expr->cond)), $condResult->getFalseyScope()->getType($expr->else)); } $booleanConditionType = $scope->getType($expr->cond)->toBoolean(); if ($booleanConditionType->isTrue()->yes()) { return $condResult->getTruthyScope()->getType($expr->if); } if ($booleanConditionType->isFalse()->yes()) { return $condResult->getFalseyScope()->getType($expr->else); } return TypeCombinator::union($condResult->getTruthyScope()->getType($expr->if), $condResult->getFalseyScope()->getType($expr->else)); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $ternaryCondResult = $nodeScopeResolver->processExprNode($stmt, $expr->cond, $scope, $storage, $nodeCallback, $context->enterDeep()); $throwPoints = $ternaryCondResult->getThrowPoints(); $impurePoints = $ternaryCondResult->getImpurePoints(); $ifTrueScope = $ternaryCondResult->getTruthyScope(); $ifFalseScope = $ternaryCondResult->getFalseyScope(); $ifTrueType = null; if ($expr->if === null) { $elseResult = $nodeScopeResolver->processExprNode($stmt, $expr->else, $ifFalseScope, $storage, $nodeCallback, $context); $throwPoints = array_merge($throwPoints, $elseResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $elseResult->getImpurePoints()); $ifFalseScope = $elseResult->getScope(); } else { $ifResult = $nodeScopeResolver->processExprNode($stmt, $expr->if, $ifTrueScope, $storage, $nodeCallback, $context); $throwPoints = array_merge($throwPoints, $ifResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $ifResult->getImpurePoints()); $ifTrueScope = $ifResult->getScope(); $ifTrueType = $ifTrueScope->getType($expr->if); $elseResult = $nodeScopeResolver->processExprNode($stmt, $expr->else, $ifFalseScope, $storage, $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 ExpressionResult($finalScope, $ternaryCondResult->hasYield(), $ternaryCondResult->isAlwaysTerminating(), $throwPoints, $impurePoints, static fn(): MutatingScope => $finalScope->filterByTruthyValue($expr), static fn(): MutatingScope => $finalScope->filterByFalseyValue($expr)); } } */ #[AutowiredService] final class ThrowHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof Throw_; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, ExpressionContext::createDeep()); return new ExpressionResult($scope, \false, \true, array_merge($exprResult->getThrowPoints(), [InternalThrowPoint::createExplicit($scope, $scope->getType($expr->expr), $expr, \false)]), $exprResult->getImpurePoints()); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return new NonAcceptingNeverType(); } } */ #[AutowiredService] final class UnaryMinusHandler implements ExprHandler { private InitializerExprTypeResolver $initializerExprTypeResolver; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; } public function supports(Expr $expr): bool { return $expr instanceof UnaryMinus; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context->enterDeep()); return new ExpressionResult($exprResult->getScope(), $exprResult->hasYield(), $exprResult->isAlwaysTerminating(), $exprResult->getThrowPoints(), $exprResult->getImpurePoints()); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $this->initializerExprTypeResolver->getUnaryMinusType($expr->expr, static fn(Expr $expr): Type => $scope->getType($expr)); } } */ #[AutowiredService] final class UnaryPlusHandler implements ExprHandler { private InitializerExprTypeResolver $initializerExprTypeResolver; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; } public function supports(Expr $expr): bool { return $expr instanceof UnaryPlus; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context->enterDeep()); return new ExpressionResult($exprResult->getScope(), $exprResult->hasYield(), $exprResult->isAlwaysTerminating(), $exprResult->getThrowPoints(), $exprResult->getImpurePoints()); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $this->initializerExprTypeResolver->getUnaryPlusType($expr->expr, static fn(Expr $expr): Type => $scope->getType($expr)); } } */ #[AutowiredService] final class VariableHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof Variable; } public function resolveType(MutatingScope $scope, Expr $expr): Type { if (is_string($expr->name)) { if ($scope->hasVariableType($expr->name)->no()) { return new ErrorType(); } return $scope->getVariableType($expr->name); } $nameType = $scope->getType($expr->name); if (count($nameType->getConstantStrings()) > 0) { $types = []; foreach ($nameType->getConstantStrings() as $constantString) { $variableScope = $scope->filterByTruthyValue(new Identical($expr->name, new String_($constantString->getValue()))); if ($variableScope->hasVariableType($constantString->getValue())->no()) { $types[] = new ErrorType(); continue; } $types[] = $variableScope->getVariableType($constantString->getValue()); } return TypeCombinator::union(...$types); } return new MixedType(); } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $hasYield = \false; $throwPoints = []; $impurePoints = []; $isAlwaysTerminating = \false; if (is_string($expr->name)) { if (in_array($expr->name, Scope::SUPERGLOBAL_VARIABLES, \true)) { $impurePoints[] = new ImpurePoint($scope, $expr, 'superglobal', 'access to superglobal variable', \true); } } else { $nameResult = $nodeScopeResolver->processExprNode($stmt, $expr->name, $scope, $storage, $nodeCallback, $context->enterDeep()); $hasYield = $nameResult->hasYield(); $throwPoints = $nameResult->getThrowPoints(); $impurePoints = $nameResult->getImpurePoints(); $isAlwaysTerminating = $nameResult->isAlwaysTerminating(); $scope = $nameResult->getScope(); } return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints, static fn(): MutatingScope => $scope->filterByTruthyValue($expr), static fn(): MutatingScope => $scope->filterByFalseyValue($expr)); } } */ #[AutowiredService] final class AlwaysRememberedExprHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof AlwaysRememberedExpr; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $innerExpr = $expr->getExpr(); $innerResult = $nodeScopeResolver->processExprNode($stmt, $innerExpr, $scope, $storage, $nodeCallback, $context); $scope = $innerResult->getScope(); return new ExpressionResult($scope, $innerResult->hasYield(), $innerResult->isAlwaysTerminating(), $innerResult->getThrowPoints(), $innerResult->getImpurePoints(), static fn(): MutatingScope => $scope->filterByTruthyValue($innerExpr), static fn(): MutatingScope => $scope->filterByFalseyValue($innerExpr)); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $scope->nativeTypesPromoted ? $expr->getNativeExprType() : $expr->getExprType(); } } */ #[AutowiredService] final class ExistingArrayDimFetchHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof ExistingArrayDimFetch; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { // because this is a virtual node handler, the caller will only be interested in the type // we don't need to process the inner expr return new ExpressionResult($scope, \false, \false, [], []); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $scope->getType(new Expr\ArrayDimFetch($expr->getVar(), $expr->getDim())); } } */ #[AutowiredService] final class FunctionCallableNodeHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof FunctionCallableNode; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $throwPoints = []; $impurePoints = []; $hasYield = \false; $isAlwaysTerminating = \false; if ($expr->getName() instanceof Expr) { $nameResult = $nodeScopeResolver->processExprNode($stmt, $expr->getName(), $scope, $storage, $nodeCallback, ExpressionContext::createDeep()); $scope = $nameResult->getScope(); $hasYield = $nameResult->hasYield(); $throwPoints = $nameResult->getThrowPoints(); $impurePoints = $nameResult->getImpurePoints(); $isAlwaysTerminating = $nameResult->isAlwaysTerminating(); } return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints); } public function resolveType(MutatingScope $scope, Expr $expr): Type { // in practice the type of the first-class callable is resolved // by FirstClassCallableFuncCallHandler return new MixedType(); } } */ #[AutowiredService] final class GetIterableKeyTypeExprHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof GetIterableKeyTypeExpr; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { // because this is a virtual node handler, the caller will only be interested in the type // we don't need to process the inner expr return new ExpressionResult($scope, \false, \false, [], []); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $scope->getIterableKeyType($scope->getType($expr->getExpr())); } } */ #[AutowiredService] final class GetIterableValueTypeExprHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof GetIterableValueTypeExpr; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { // because this is a virtual node handler, the caller will only be interested in the type // we don't need to process the inner expr return new ExpressionResult($scope, \false, \false, [], []); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $scope->getIterableValueType($scope->getType($expr->getExpr())); } } */ #[AutowiredService] final class GetOffsetValueTypeExprHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof GetOffsetValueTypeExpr; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { // because this is a virtual node handler, the caller will only be interested in the type // we don't need to process the inner expr return new ExpressionResult($scope, \false, \false, [], []); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $scope->getType($expr->getVar())->getOffsetValueType($scope->getType($expr->getDim())); } } */ #[AutowiredService] final class InstantiationCallableNodeHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof InstantiationCallableNode; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $throwPoints = []; $impurePoints = []; $hasYield = \false; $isAlwaysTerminating = \false; if ($expr->getClass() instanceof Expr) { $classResult = $nodeScopeResolver->processExprNode($stmt, $expr->getClass(), $scope, $storage, $nodeCallback, ExpressionContext::createDeep()); $scope = $classResult->getScope(); $hasYield = $classResult->hasYield(); $throwPoints = $classResult->getThrowPoints(); $impurePoints = $classResult->getImpurePoints(); $isAlwaysTerminating = $classResult->isAlwaysTerminating(); } return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints); } public function resolveType(MutatingScope $scope, Expr $expr): Type { // in practice the type of the first-class callable is resolved // by FirstClassCallableNewHandler return new MixedType(); } } */ #[AutowiredService] final class MethodCallableNodeHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof MethodCallableNode; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $varResult = $nodeScopeResolver->processExprNode($stmt, $expr->getVar(), $scope, $storage, $nodeCallback, ExpressionContext::createDeep()); $scope = $varResult->getScope(); $hasYield = $varResult->hasYield(); $throwPoints = $varResult->getThrowPoints(); $impurePoints = $varResult->getImpurePoints(); $isAlwaysTerminating = \false; if ($expr->getName() instanceof Expr) { $nameResult = $nodeScopeResolver->processExprNode($stmt, $expr->getName(), $scope, $storage, $nodeCallback, ExpressionContext::createDeep()); $scope = $nameResult->getScope(); $hasYield = $hasYield || $nameResult->hasYield(); $throwPoints = array_merge($throwPoints, $nameResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $nameResult->getImpurePoints()); $isAlwaysTerminating = $nameResult->isAlwaysTerminating(); } return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints); } public function resolveType(MutatingScope $scope, Expr $expr): Type { // in practice the type of the first-class callable is resolved // by FirstClassCallableMethodCallHandler return new MixedType(); } } */ #[AutowiredService] final class NativeTypeExprHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof NativeTypeExpr; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { // because this is a virtual node handler, the caller will only be interested in the type // we don't need to process the inner expr return new ExpressionResult($scope, \false, \false, [], []); } public function resolveType(MutatingScope $scope, Expr $expr): Type { if ($scope->nativeTypesPromoted) { return $expr->getNativeType(); } return $expr->getPhpDocType(); } } */ #[AutowiredService] final class OriginalPropertyTypeExprHandler implements ExprHandler { private PropertyReflectionFinder $propertyReflectionFinder; public function __construct(PropertyReflectionFinder $propertyReflectionFinder) { $this->propertyReflectionFinder = $propertyReflectionFinder; } public function supports(Expr $expr): bool { return $expr instanceof OriginalPropertyTypeExpr; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { // because this is a virtual node handler, the caller will only be interested in the type // we don't need to process the inner expr return new ExpressionResult($scope, \false, \false, [], []); } public function resolveType(MutatingScope $scope, Expr $expr): Type { $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($expr->getPropertyFetch(), $scope); if ($propertyReflection === null) { return new ErrorType(); } return $propertyReflection->getReadableType(); } } */ #[AutowiredService] final class SetExistingOffsetValueTypeExprHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof SetExistingOffsetValueTypeExpr; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { // because this is a virtual node handler, the caller will only be interested in the type // we don't need to process the inner expr return new ExpressionResult($scope, \false, \false, [], []); } public function resolveType(MutatingScope $scope, Expr $expr): Type { $varNode = $expr->getVar(); $varType = $scope->getType($varNode); if ($varNode instanceof OriginalPropertyTypeExpr) { $currentPropertyType = $scope->getType($varNode->getPropertyFetch()); if ($varType instanceof UnionType) { $varType = $varType->filterTypes(static fn(Type $innerType) => !$innerType->isSuperTypeOf($currentPropertyType)->no()); } } return $varType->setExistingOffsetValueType($scope->getType($expr->getDim()), $scope->getType($expr->getValue())); } } */ #[AutowiredService] final class SetOffsetValueTypeExprHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof SetOffsetValueTypeExpr; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { // because this is a virtual node handler, the caller will only be interested in the type // we don't need to process the inner expr return new ExpressionResult($scope, \false, \false, [], []); } public function resolveType(MutatingScope $scope, Expr $expr): Type { $varNode = $expr->getVar(); $varType = $scope->getType($varNode); if ($varNode instanceof OriginalPropertyTypeExpr) { $currentPropertyType = $scope->getType($varNode->getPropertyFetch()); if ($varType instanceof UnionType) { $varType = $varType->filterTypes(static fn(Type $innerType) => !$innerType->isSuperTypeOf($currentPropertyType)->no()); } } return $varType->setOffsetValueType($expr->getDim() !== null ? $scope->getType($expr->getDim()) : null, $scope->getType($expr->getValue())); } } */ #[AutowiredService] final class StaticMethodCallableNodeHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof StaticMethodCallableNode; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $throwPoints = []; $impurePoints = []; $hasYield = \false; $isAlwaysTerminating = \false; if ($expr->getClass() instanceof Expr) { $classResult = $nodeScopeResolver->processExprNode($stmt, $expr->getClass(), $scope, $storage, $nodeCallback, ExpressionContext::createDeep()); $scope = $classResult->getScope(); $hasYield = $classResult->hasYield(); $throwPoints = $classResult->getThrowPoints(); $impurePoints = $classResult->getImpurePoints(); $isAlwaysTerminating = $classResult->isAlwaysTerminating(); } if ($expr->getName() instanceof Expr) { $nameResult = $nodeScopeResolver->processExprNode($stmt, $expr->getName(), $scope, $storage, $nodeCallback, ExpressionContext::createDeep()); $scope = $nameResult->getScope(); $hasYield = $hasYield || $nameResult->hasYield(); $throwPoints = array_merge($throwPoints, $nameResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $nameResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $nameResult->isAlwaysTerminating(); } return new ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints); } public function resolveType(MutatingScope $scope, Expr $expr): Type { // in practice the type of the first-class callable is resolved // by FirstClassCallableStaticCallHandler return new MixedType(); } } */ #[AutowiredService] final class TypeExprHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof TypeExpr; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { // because this is a virtual node handler, the caller will only be interested in the type // we don't need to process the inner expr return new ExpressionResult($scope, \false, \false, [], []); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $expr->getExprType(); } } */ #[AutowiredService] final class UnsetOffsetExprHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof UnsetOffsetExpr; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { // because this is a virtual node handler, the caller will only be interested in the type // we don't need to process the inner expr return new ExpressionResult($scope, \false, \false, [], []); } public function resolveType(MutatingScope $scope, Expr $expr): Type { return $scope->getType($expr->getVar())->unsetOffset($scope->getType($expr->getDim())); } } */ #[AutowiredService] final class YieldFromHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof YieldFrom; } public function resolveType(MutatingScope $scope, Expr $expr): Type { $yieldFromType = $scope->getType($expr->expr); $generatorReturnType = $yieldFromType->getTemplateType(Generator::class, 'TReturn'); if ($generatorReturnType instanceof ErrorType) { return new MixedType(); } return $generatorReturnType; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $exprResult = $nodeScopeResolver->processExprNode($stmt, $expr->expr, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $exprResult->getScope(); return new ExpressionResult($scope, \true, $exprResult->isAlwaysTerminating(), array_merge($exprResult->getThrowPoints(), [InternalThrowPoint::createImplicit($scope, $expr)]), array_merge($exprResult->getImpurePoints(), [new ImpurePoint($scope, $expr, 'yieldFrom', 'yield from', \true)])); } } */ #[AutowiredService] final class YieldHandler implements ExprHandler { public function supports(Expr $expr): bool { return $expr instanceof Yield_; } public function resolveType(MutatingScope $scope, Expr $expr): Type { $functionReflection = $scope->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; } public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Expr $expr, MutatingScope $scope, ExpressionResultStorage $storage, callable $nodeCallback, ExpressionContext $context): ExpressionResult { $throwPoints = [InternalThrowPoint::createImplicit($scope, $expr)]; $impurePoints = [new ImpurePoint($scope, $expr, 'yield', 'yield', \true)]; $isAlwaysTerminating = \false; if ($expr->key !== null) { $keyResult = $nodeScopeResolver->processExprNode($stmt, $expr->key, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $keyResult->getScope(); $throwPoints = $keyResult->getThrowPoints(); $impurePoints = array_merge($impurePoints, $keyResult->getImpurePoints()); $isAlwaysTerminating = $keyResult->isAlwaysTerminating(); } if ($expr->value !== null) { $valueResult = $nodeScopeResolver->processExprNode($stmt, $expr->value, $scope, $storage, $nodeCallback, $context->enterDeep()); $scope = $valueResult->getScope(); $throwPoints = array_merge($throwPoints, $valueResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $valueResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $valueResult->isAlwaysTerminating(); } return new ExpressionResult($scope, \true, $isAlwaysTerminating, $throwPoints, $impurePoints); } } isDeep = $isDeep; $this->inAssignRightSideVariableName = $inAssignRightSideVariableName; $this->inAssignRightSideExpr = $inAssignRightSideExpr; } public static function createTopLevel(): self { return new self(\false, null, null); } public static function createDeep(): self { return new self(\true, null, null); } public function enterDeep(): self { if ($this->isDeep) { return $this; } return new self(\true, $this->inAssignRightSideVariableName, $this->inAssignRightSideExpr); } public function isDeep(): bool { return $this->isDeep; } public function enterRightSideAssign(string $variableName, Expr $expr): self { return new self($this->isDeep, $variableName, $expr); } public function getInAssignRightSideVariableName(): ?string { return $this->inAssignRightSideVariableName; } public function getInAssignRightSideExpr(): ?Expr { return $this->inAssignRightSideExpr; } } scope = $scope; $this->hasYield = $hasYield; $this->isAlwaysTerminating = $isAlwaysTerminating; $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 InternalThrowPoint[] */ 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; } public function isAlwaysTerminating(): bool { return $this->isAlwaysTerminating; } } */ private SplObjectStorage $scopes; /** @var array, request: BeforeScopeForExprRequest}> */ public array $pendingFibers = []; /** @var list> */ public array $parkedFibers = []; public function __construct() { $this->scopes = new SplObjectStorage(); } public function duplicate(): self { $new = new self(); $new->scopes->addAll($this->scopes); return $new; } public function storeBeforeScope(Expr $expr, \PHPStan\Analyser\Scope $scope): void { $this->scopes[$expr] = $scope; } public function findBeforeScope(Expr $expr): ?\PHPStan\Analyser\Scope { return $this->scopes[$expr] ?? 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 equalTypes(self $other): bool { if ($this === $other) { return \true; } return $this->type === $other->type || $this->type->equals($other->type); } public function equals(self $other): bool { if ($this === $other) { return \true; } if (!$this->certainty->equals($other->certainty)) { return \false; } return $this->type === $other->type || $this->type->equals($other->type); } public function and(self $other): self { if ($this->type === $other->type || $this->type->equals($other->type)) { if ($this->certainty->and($other->certainty)->yes()) { return $this; } if ($this->certainty->maybe()) { return $this; } return $other; } return new self($this->expr, TypeCombinator::union($this->type, $other->type), $this->certainty->and($other->certainty)); } public function getExpr(): Expr { return $this->expr; } public function getType(): Type { return $this->type; } public function getCertainty(): TrinaryLogic { return $this->certainty; } } expr = $expr; $this->scope = $scope; } } toFiberScope()); return; } if (count($storage->parkedFibers) > 0) { $fiber = array_pop($storage->parkedFibers); $request = $fiber->resume([$nodeCallback, $node, $scope]); } else { $fiber = new Fiber(static function () use ($node, $scope, $nodeCallback) { while (\true) { // @phpstan-ignore while.alwaysTrue $nodeCallback($node, $scope->toFiberScope()); [$nodeCallback, $node, $scope] = Fiber::suspend(new \PHPStan\Analyser\Fiber\ParkFiberRequest()); } }); $request = $fiber->start(); } $this->runFiberForNodeCallback($storage, $fiber, $request); } public function storeBeforeScope(ExpressionResultStorage $storage, Expr $expr, Scope $beforeScope): void { $storage->storeBeforeScope($expr, $beforeScope); $this->processPendingFibersForRequestedExpr($storage, $expr, $beforeScope); } /** * @param Fiber $fiber * @param \PHPStan\Analyser\Fiber\BeforeScopeForExprRequest|\PHPStan\Analyser\Fiber\ParkFiberRequest|null $request */ private function runFiberForNodeCallback(ExpressionResultStorage $storage, Fiber $fiber, $request): void { while (!$fiber->isTerminated()) { if ($request instanceof \PHPStan\Analyser\Fiber\BeforeScopeForExprRequest) { $beforeScope = $storage->findBeforeScope($request->expr); if ($beforeScope !== null) { $request = $fiber->resume($beforeScope); continue; } $storage->pendingFibers[] = ['fiber' => $fiber, 'request' => $request]; return; } if ($request instanceof \PHPStan\Analyser\Fiber\ParkFiberRequest) { $storage->parkedFibers[] = $fiber; return; } throw new ShouldNotHappenException('Unknown fiber suspension: ' . get_debug_type($request)); } if ($request !== null) { throw new ShouldNotHappenException('Fiber terminated but we did not handle its request ' . get_debug_type($request)); } } protected function processPendingFibers(ExpressionResultStorage $storage): void { start: foreach ($storage->pendingFibers as $key => $pending) { $request = $pending['request']; $beforeScope = $storage->findBeforeScope($request->expr); if ($beforeScope !== null) { throw new ShouldNotHappenException('Pending fibers at the end should be about synthetic nodes'); } unset($storage->pendingFibers[$key]); $fiber = $pending['fiber']; $request = $fiber->resume($request->scope); $this->runFiberForNodeCallback($storage, $fiber, $request); // Break and restart the loop since the array may have been modified goto start; } } private function processPendingFibersForRequestedExpr(ExpressionResultStorage $storage, Expr $expr, Scope $result): void { start: foreach ($storage->pendingFibers as $key => $pending) { $request = $pending['request']; if ($request->expr !== $expr) { continue; } unset($storage->pendingFibers[$key]); $fiber = $pending['fiber']; $request = $fiber->resume($result); $this->runFiberForNodeCallback($storage, $fiber, $request); // Break and restart the loop since the array may have been modified goto start; } } } mutatingScope !== null) { return $this->mutatingScope; } return $this->mutatingScope = $this->scopeFactory->toMutatingFactory()->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $this->expressionTypes, $this->nativeExpressionTypes, $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->getAnonymousFunctionReflection(), $this->isInFirstLevelStatement(), $this->currentlyAssignedExpressions, $this->currentlyAllowedUndefinedExpressions, $this->inFunctionCallsStack, $this->afterExtractCall, $this->getParentScope(), $this->nativeTypesPromoted); } /** @api */ public function getType(Expr $node): Type { /** @var Scope $beforeScope */ $beforeScope = Fiber::suspend(new \PHPStan\Analyser\Fiber\BeforeScopeForExprRequest($node, $this)); $scope = $this->preprocessScope($beforeScope->toMutatingScope()); return $scope->getType($node); } public function getScopeType(Expr $expr): Type { return $this->toMutatingScope()->getType($expr); } public function getScopeNativeType(Expr $expr): Type { return $this->toMutatingScope()->getNativeType($expr); } /** @api */ public function getNativeType(Expr $expr): Type { /** @var Scope $beforeScope */ $beforeScope = Fiber::suspend(new \PHPStan\Analyser\Fiber\BeforeScopeForExprRequest($expr, $this)); $scope = $this->preprocessScope($beforeScope->toMutatingScope()); return $scope->getNativeType($expr); } public function getKeepVoidType(Expr $node): Type { /** @var Scope $beforeScope */ $beforeScope = Fiber::suspend(new \PHPStan\Analyser\Fiber\BeforeScopeForExprRequest($node, $this)); $scope = $this->preprocessScope($beforeScope->toMutatingScope()); return $scope->getKeepVoidType($node); } public function filterByTruthyValue(Expr $expr): self { /** @var self $scope */ $scope = parent::filterByTruthyValue($expr); $scope->truthyValueExprs = $this->truthyValueExprs; $scope->truthyValueExprs[] = $expr; return $scope; } public function filterByFalseyValue(Expr $expr): self { /** @var self $scope */ $scope = parent::filterByTruthyValue($expr); $scope->falseyValueExprs = $this->falseyValueExprs; $scope->falseyValueExprs[] = $expr; return $scope; } private function preprocessScope(MutatingScope $scope): Scope { if ($this->nativeTypesPromoted) { $scope = $scope->doNotTreatPhpDocTypesAsCertain(); } foreach ($this->truthyValueExprs as $expr) { $scope = $scope->filterByTruthyValue($expr); } foreach ($this->falseyValueExprs as $expr) { $scope = $scope->filterByFalseyValue($expr); } return $scope; } /** * @param MethodReflection|FunctionReflection|null $reflection */ public function pushInFunctionCall($reflection, ?ParameterReflection $parameter, bool $rememberTypes): self { /** @var self $scope */ $scope = parent::pushInFunctionCall($reflection, $parameter, $rememberTypes); $scope->truthyValueExprs = $this->truthyValueExprs; $scope->falseyValueExprs = $this->falseyValueExprs; return $scope; } public function popInFunctionCall(): self { $stack = $this->inFunctionCallsStack; array_pop($stack); /** @var self $scope */ $scope = parent::popInFunctionCall(); $scope->truthyValueExprs = $this->truthyValueExprs; $scope->falseyValueExprs = $this->falseyValueExprs; return $scope; } public function getParentScope(): ?MutatingScope { $parent = parent::getParentScope(); if ($parent === null) { return null; } return $parent->toFiberScope(); } } */ private array $allPhpErrors = []; /** @var array */ private array $filteredPhpErrors = []; public function __construct( \PHPStan\Analyser\ScopeFactory $scopeFactory, #[AutowiredParameter('@' . \PHPStan\Analyser\NodeScopeResolver::class)] \PHPStan\Analyser\NodeScopeResolver $nodeScopeResolver, #[AutowiredParameter('@defaultAnalysisParser')] Parser $parser, DependencyResolver $dependencyResolver, \PHPStan\Analyser\IgnoreErrorExtensionProvider $ignoreErrorExtensionProvider, \PHPStan\Analyser\RuleErrorTransformer $ruleErrorTransformer, \PHPStan\Analyser\LocalIgnoresProcessor $localIgnoresProcessor, #[AutowiredParameter] bool $reportIgnoresWithoutComments ) { $this->scopeFactory = $scopeFactory; $this->nodeScopeResolver = $nodeScopeResolver; $this->parser = $parser; $this->dependencyResolver = $dependencyResolver; $this->ignoreErrorExtensionProvider = $ignoreErrorExtensionProvider; $this->ruleErrorTransformer = $ruleErrorTransformer; $this->localIgnoresProcessor = $localIgnoresProcessor; $this->reportIgnoresWithoutComments = $reportIgnoresWithoutComments; } /** * @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 $processedFiles */ $processedFiles = []; /** @var list $locallyIgnoredErrors */ $locallyIgnoredErrors = []; /** @var CollectorData $fileCollectedData */ $fileCollectedData = []; $fileDependencies = []; $usedTraitFileDependencies = []; $exportedNodes = []; $linesToIgnore = []; $unmatchedLineIgnores = []; if (is_file($file)) { try { $this->collectErrors($analysedFiles); $parserNodes = $this->parser->parseFile($file); $processedFiles[] = $file; $nodeCallback = new \PHPStan\Analyser\FileAnalyserCallback($file, $analysedFiles, $ruleRegistry, $collectorRegistry, $outerNodeCallback, $parserNodes, $this->ignoreErrorExtensionProvider->getExtensions(), $this->parser, $this->dependencyResolver, $this->ruleErrorTransformer, $processedFiles); $scope = $this->scopeFactory->create(\PHPStan\Analyser\ScopeContext::create($file), $nodeCallback); $nodeCallback(new FileNode($parserNodes), $scope); $this->nodeScopeResolver->processNodes($parserNodes, $scope, $nodeCallback); $fileErrors = $nodeCallback->getFileErrors(); $fileCollectedData = $nodeCallback->getFileCollectedData(); $fileDependencies = $nodeCallback->getFileDependencies(); $usedTraitFileDependencies = $nodeCallback->getUsedTraitFileDependencies(); $exportedNodes = $nodeCallback->getExportedNodes(); $linesToIgnore = $nodeCallback->getLinesToIgnore(); $unmatchedLineIgnores = $nodeCallback->getUnmatchedLineIgnores(); $temporaryFileErrors = $nodeCallback->getTemporaryFileErrors(); $processedFiles = $nodeCallback->getProcessedFiles(); if ($this->reportIgnoresWithoutComments) { foreach ($linesToIgnore as $ignoredFile => $lines) { foreach ($lines as $line => $identifiers) { if ($identifiers === null) { $fileErrors[] = (new \PHPStan\Analyser\Error('Ignoring all errors on a line is not allowed.', $ignoredFile, $line, \false, $ignoredFile, null, 'Use @phpstan-ignore with an identifier and a comment (in parentheses).'))->withIdentifier('ignore.allLineErrors'); unset($linesToIgnore[$ignoredFile][$line]); unset($unmatchedLineIgnores[$ignoredFile][$line]); continue; } foreach ($identifiers as $identifier) { if ($identifier['comment'] !== null) { continue; } $fileErrors[] = (new \PHPStan\Analyser\Error(sprintf('Ignore with identifier %s has no comment.', $identifier['name']), $ignoredFile, $line, \false, $ignoredFile, null, 'Explain why this ignore is necessary in parentheses after the identifier.'))->withIdentifier('ignore.noComment'); unset($linesToIgnore[$ignoredFile][$line]); unset($unmatchedLineIgnores[$ignoredFile][$line]); } } } } $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, array_values($this->filteredPhpErrors), array_values($this->allPhpErrors), $locallyIgnoredErrors, $fileCollectedData, array_values(array_unique($fileDependencies)), array_values(array_unique($usedTraitFileDependencies)), $exportedNodes, $linesToIgnore, $unmatchedLineIgnores, $processedFiles); } /** * @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); $errorSignature = hash('sha256', sprintf('%s:%s::%s', $errfile, $errline, $errorMessage)); $this->allPhpErrors[$errorSignature] = (new \PHPStan\Analyser\Error($errorMessage, $errfile, $errline, \false))->withIdentifier('phpstan.php'); if ($errno === E_DEPRECATED) { return \true; } if (!isset($analysedFiles[$errfile])) { return \true; } $this->filteredPhpErrors[$errorSignature] = (new \PHPStan\Analyser\Error($errorMessage, $errfile, $errline, $errno === E_USER_DEPRECATED))->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_DEPRECATED: return 'Deprecated'; 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_USER_DEPRECATED: return 'Deprecated (E_USER_DEPRECATED)'; case E_STRICT: return 'Strict error (E_STRICT)'; } return 'Unknown PHP error'; } } */ private array $analysedFiles; private RuleRegistry $ruleRegistry; private CollectorRegistry $collectorRegistry; /** * @var callable(Node $node, Scope $scope): void|null */ private $outerNodeCallback; /** * @var Node\Stmt[] */ private array $parserNodes; /** * @var IgnoreErrorExtension[] */ private array $ignoreErrorExtensions; private Parser $parser; private DependencyResolver $dependencyResolver; private \PHPStan\Analyser\RuleErrorTransformer $ruleErrorTransformer; /** * @var list */ private array $processedFiles; /** @var list */ private array $fileErrors = []; /** @var CollectorData */ private array $fileCollectedData = []; /** @var array */ private array $fileDependencies = []; /** @var array */ private array $usedTraitFileDependencies = []; /** @var list */ private array $exportedNodes = []; /** @var list */ private array $temporaryFileErrors = []; /** @var LinesToIgnore */ private array $linesToIgnore; /** @var LinesToIgnore */ private array $unmatchedLineIgnores; /** * @param array $analysedFiles * @param callable(Node $node, Scope $scope): void|null $outerNodeCallback * @param Node\Stmt[] $parserNodes * @param IgnoreErrorExtension[] $ignoreErrorExtensions * @param list $processedFiles */ public function __construct(string $file, array $analysedFiles, RuleRegistry $ruleRegistry, CollectorRegistry $collectorRegistry, $outerNodeCallback, array $parserNodes, array $ignoreErrorExtensions, Parser $parser, DependencyResolver $dependencyResolver, \PHPStan\Analyser\RuleErrorTransformer $ruleErrorTransformer, array $processedFiles) { $this->file = $file; $this->analysedFiles = $analysedFiles; $this->ruleRegistry = $ruleRegistry; $this->collectorRegistry = $collectorRegistry; $this->outerNodeCallback = $outerNodeCallback; $this->parserNodes = $parserNodes; $this->ignoreErrorExtensions = $ignoreErrorExtensions; $this->parser = $parser; $this->dependencyResolver = $dependencyResolver; $this->ruleErrorTransformer = $ruleErrorTransformer; $this->processedFiles = $processedFiles; $this->linesToIgnore = $this->unmatchedLineIgnores = [$file => $this->getLinesToIgnoreFromTokens($parserNodes)]; } public function __invoke(Node $node, \PHPStan\Analyser\Scope $scope): void { $parserNodes = $this->parserNodes; /** @var Scope&NodeCallbackInvoker $scope */ if ($node instanceof Node\Stmt\Trait_) { foreach (array_keys($this->linesToIgnore[$this->file] ?? []) as $lineToIgnore) { if ($lineToIgnore < $node->getStartLine() || $lineToIgnore > $node->getEndLine()) { continue; } unset($this->unmatchedLineIgnores[$this->file][$lineToIgnore]); } } if ($node instanceof InTraitNode) { $traitNode = $node->getOriginalNode(); $fileDescription = $scope->getFileDescription(); $this->linesToIgnore[$fileDescription] ??= []; $this->linesToIgnore[$fileDescription] += $this->getLinesToIgnoreFromTokens([$traitNode]); $traitFileName = $node->getTraitReflection()->getFileName(); if ($traitFileName !== null) { $this->processedFiles[] = $traitFileName; } } if ($scope->isInTrait()) { $traitReflection = $scope->getTraitReflection(); if ($traitReflection->getFileName() !== null) { $traitFilePath = $traitReflection->getFileName(); $parserNodes = $this->parser->parseFile($traitFilePath); } } if ($this->outerNodeCallback !== null) { ($this->outerNodeCallback)($node, $scope); } $uniquedAnalysedCodeExceptionMessages = []; $nodeType = get_class($node); foreach ($this->ruleRegistry->getRules($nodeType) as $rule) { try { $ruleErrors = $rule->processNode($node, $scope); } catch (AnalysedCodeException $e) { if (isset($uniquedAnalysedCodeExceptionMessages[$e->getMessage()])) { continue; } $uniquedAnalysedCodeExceptionMessages[$e->getMessage()] = \true; $this->fileErrors[] = (new \PHPStan\Analyser\Error($e->getMessage(), $this->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) { $this->fileErrors[] = (new \PHPStan\Analyser\Error(sprintf('Reflection error: %s not found.', $e->getIdentifier()->getName()), $this->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) { $this->fileErrors[] = (new \PHPStan\Analyser\Error(sprintf('Reflection error: %s', $e->getMessage()), $this->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) { $error = $this->ruleErrorTransformer->transform($ruleError, $scope, $parserNodes, $node); if ($error->canBeIgnored()) { foreach ($this->ignoreErrorExtensions as $ignoreErrorExtension) { if ($ignoreErrorExtension->shouldIgnore($error, $node, $scope)) { continue 2; } } } $this->temporaryFileErrors[] = $error; } } foreach ($this->collectorRegistry->getCollectors($nodeType) as $collector) { try { $collectedData = $collector->processNode($node, $scope); } catch (AnalysedCodeException $e) { if (isset($uniquedAnalysedCodeExceptionMessages[$e->getMessage()])) { continue; } $uniquedAnalysedCodeExceptionMessages[$e->getMessage()] = \true; $this->fileErrors[] = (new \PHPStan\Analyser\Error($e->getMessage(), $this->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) { $this->fileErrors[] = (new \PHPStan\Analyser\Error(sprintf('Reflection error: %s not found.', $e->getIdentifier()->getName()), $this->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) { $this->fileErrors[] = (new \PHPStan\Analyser\Error(sprintf('Reflection error: %s', $e->getMessage()), $this->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; } $this->fileCollectedData[$scope->getFile()][get_class($collector)][] = $collectedData; } try { $dependencies = $this->dependencyResolver->resolveDependencies($node, $scope); foreach ($dependencies->getFileDependencies($scope->getFile(), $this->analysedFiles) as $dependentFile) { $this->fileDependencies[] = $dependentFile; } if ($dependencies->getExportedNode() !== null) { $this->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(), $this->analysedFiles) as $dependentFile) { $this->usedTraitFileDependencies[] = $dependentFile; } } /** * @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', []); } /** * @return list */ public function getFileErrors(): array { return $this->fileErrors; } /** * @return CollectorData */ public function getFileCollectedData(): array { return $this->fileCollectedData; } /** * @return array */ public function getFileDependencies(): array { return $this->fileDependencies; } /** * @return array */ public function getUsedTraitFileDependencies(): array { return $this->usedTraitFileDependencies; } /** * @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; } /** * @return list */ public function getTemporaryFileErrors(): array { return $this->temporaryFileErrors; } /** * @return list */ public function getProcessedFiles(): array { return $this->processedFiles; } } |null>> * @phpstan-import-type CollectorData from CollectedData */ final class FileAnalyserResult { /** * @var list */ private array $errors; /** * @var list */ private array $filteredPhpErrors; /** * @var list */ private array $allPhpErrors; /** * @var list */ private array $locallyIgnoredErrors; /** * @var CollectorData */ private array $collectedData; /** * @var list */ private array $dependencies; /** * @var list */ private array $usedTraitDependencies; /** * @var list */ private array $exportedNodes; /** * @var LinesToIgnore */ private array $linesToIgnore; /** * @var LinesToIgnore */ private array $unmatchedLineIgnores; /** * @var list */ private array $processedFiles; /** * @param list $errors * @param list $filteredPhpErrors * @param list $allPhpErrors * @param list $locallyIgnoredErrors * @param CollectorData $collectedData * @param list $dependencies * @param list $usedTraitDependencies * @param list $exportedNodes * @param LinesToIgnore $linesToIgnore * @param LinesToIgnore $unmatchedLineIgnores * @param list $processedFiles */ public function __construct(array $errors, array $filteredPhpErrors, array $allPhpErrors, array $locallyIgnoredErrors, array $collectedData, array $dependencies, array $usedTraitDependencies, array $exportedNodes, array $linesToIgnore, array $unmatchedLineIgnores, array $processedFiles) { $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; $this->processedFiles = $processedFiles; } /** * @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 CollectorData */ 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; } /** * @return list */ public function getProcessedFiles(): array { return $this->processedFiles; } } */ private array $collectorErrors; /** * @var list */ private array $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; } } originalHash = $originalHash; $this->diff = $diff; } /** * @param mixed[] $properties */ public static function __set_state(array $properties): self { return new self($properties['originalHash'], $properties['diff']); } } '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; private ?string $regexp = null; /** * @return list */ public function tokenize(string $input): array { $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; } } , path?: string, paths?: list}|string $ignoredError */ public static function getIgnoredErrorLabel($ignoredError): string { if (is_array($ignoredError) && !isset($ignoredError['message']) && isset($ignoredError['rawMessage'])) { return 'Ignored error'; } return 'Ignored error pattern'; } /** * @param mixed[]|string $ignoredError * @return string Representation of the ignored error */ public static function stringifyPattern($ignoredError): string { if (!is_array($ignoredError)) { return $ignoredError; } $message = ''; if (isset($ignoredError['message'])) { $message = $ignoredError['message']; } elseif (isset($ignoredError['rawMessage'])) { $message = '"' . $ignoredError['rawMessage'] . '"'; } if (isset($ignoredError['identifier'])) { if ($message === '') { $message = $ignoredError['identifier']; } else { $message = sprintf('%s (%s)', $message, $ignoredError['identifier']); } } elseif (isset($ignoredError['identifiers'])) { $identifierList = implode(', ', $ignoredError['identifiers']); if ($message === '') { $message = $identifierList; } else { $message = sprintf('%s (%s)', $message, $identifierList); } } if ($message === '') { throw new ShouldNotHappenException(); } // ignore by path if (isset($ignoredError['path'])) { return sprintf('%s in path %s', $message, $ignoredError['path']); } elseif (isset($ignoredError['paths'])) { if (count($ignoredError['paths']) === 1) { return sprintf('%s in path %s', $message, implode(', ', $ignoredError['paths'])); } return sprintf('%s in paths: %s', $message, implode(', ', $ignoredError['paths'])); } return $message; } /** * @return bool To ignore or not to ignore? */ public static function shouldIgnore(FileHelper $fileHelper, Error $error, ?string $ignoredErrorPattern, ?string $ignoredErrorMessage, ?string $identifier, ?string $path): bool { if ($identifier !== null) { if ($error->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 ($ignoredErrorMessage !== null) { if ($error->getMessage() !== $ignoredErrorMessage) { return \false; } } if ($path !== null) { $fileExcluder = new FileExcluder($fileHelper, [$path]); $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['rawMessage']) && !isset($ignoreError['rawMessages']) && !isset($ignoreError['identifier']) && !isset($ignoreError['identifiers'])) { $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; } } elseif (isset($ignoreError['rawMessages'])) { foreach ($ignoreError['rawMessages'] as $rawMessage) { $expandedIgnoreError = $ignoreError; unset($expandedIgnoreError['rawMessages']); $expandedIgnoreError['rawMessage'] = $rawMessage; $expandedIgnoreErrors[] = $expandedIgnoreError; } } elseif (isset($ignoreError['identifiers'])) { foreach ($ignoreError['identifiers'] as $identifier) { $expandedIgnoreError = $ignoreError; unset($expandedIgnoreError['identifiers']); $expandedIgnoreError['identifier'] = $identifier; $expandedIgnoreErrors[] = $expandedIgnoreError; } } else { $expandedIgnoreErrors[] = $ignoreError; } } else { $expandedIgnoreErrors[] = $ignoreError; } } $uniquedExpandedIgnoreErrors = []; foreach ($expandedIgnoreErrors as $ignoreError) { if (!isset($ignoreError['message']) && !isset($ignoreError['rawMessage']) && !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['rawMessage'])) { $key = sprintf("%s\n%s", $key, $ignoreError['rawMessage']); } 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; } $reportUnmatched = (bool) ($uniquedExpandedIgnoreErrors[$key]['reportUnmatched'] ?? $this->reportUnmatchedIgnoredErrors); if (!$reportUnmatched) { $reportUnmatched = $ignoreError['reportUnmatched'] ?? $this->reportUnmatchedIgnoredErrors; } $uniquedExpandedIgnoreErrors[$key] = ['message' => $ignoreError['message'] ?? null, 'rawMessage' => $ignoreError['rawMessage'] ?? null, 'path' => $ignoreError['path'], 'identifier' => $ignoreError['identifier'] ?? null, 'count' => ($uniquedExpandedIgnoreErrors[$key]['count'] ?? 1) + ($ignoreError['count'] ?? 1), 'reportUnmatched' => $reportUnmatched]; } $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['rawMessage']) && !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); } } */ private array $notIgnoredErrors; /** * @var list */ private array $ignoredErrors; /** * @var list */ private array $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; } } */ private array $errors; /** * @var array> */ private array $otherIgnoreErrors; /** * @var array>> */ private array $ignoreErrorsByFile; /** * @var (string|mixed[])[] */ private array $ignoreErrors; private bool $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 list $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, null); if ($shouldBeIgnored) { unset($unmatchedIgnoredErrors[$i]); } } else if (isset($ignore['path'])) { $shouldBeIgnored = \PHPStan\Analyser\Ignore\IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore['message'] ?? null, $ignore['rawMessage'] ?? 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['rawMessage'] ?? 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['rawMessage'] ?? 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('%s %s is expected to occur %d %s, but occurred %d %s.', \PHPStan\Analyser\Ignore\IgnoredError::getIgnoredErrorLabel($unmatchedIgnoredError), \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'], $unmatchedIgnoredError['realCount']) && (isset($unmatchedIgnoredError['realPath']) || !$onlyFiles)) { if ($unmatchedIgnoredError['realCount'] < $unmatchedIgnoredError['count']) { $errors[] = (new Error(sprintf('%s %s is expected to occur %d %s, but occurred only %d %s.', \PHPStan\Analyser\Ignore\IgnoredError::getIgnoredErrorLabel($unmatchedIgnoredError), \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; } if ($onlyFiles) { continue; } $errors[] = (new Error(sprintf('%s %s was not matched in reported errors.', \PHPStan\Analyser\Ignore\IgnoredError::getIgnoredErrorLabel($unmatchedIgnoredError), \PHPStan\Analyser\Ignore\IgnoredError::stringifyPattern($unmatchedIgnoredError)), $unmatchedIgnoredError['realPath'], \null, \false))->withIdentifier('ignore.unmatched'); } elseif (!$onlyFiles) { $stringErrors[] = sprintf('%s %s was not matched in reported errors.', \PHPStan\Analyser\Ignore\IgnoredError::getIgnoredErrorLabel($unmatchedIgnoredError), \PHPStan\Analyser\Ignore\IgnoredError::stringifyPattern($unmatchedIgnoredError)); } } } return new \PHPStan\Analyser\Ignore\IgnoredErrorHelperProcessedResult($errors, $ignoredErrors, $stringErrors); } } container = $container; } /** * @return IgnoreErrorExtension[] */ public function getExtensions(): array { return $this->container->getServicesByTag(\PHPStan\Analyser\IgnoreErrorExtension::EXTENSION_TAG); } } 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; } } */ private array $uses; private ?string $className; private ?string $functionName; /** * @var array */ private array $templatePhpDocNodes; private ?self $parent; /** * @var array */ private array $typeAliasesMap; private bool $bypassTypeAliases; /** * @var array */ private array $constUses; private ?string $typeAliasClassName; /** * @var array{string, string, string, string|null, string|null}|null */ private ?array $traitData; /** * @api * @param non-empty-string|null $namespace * @param array $uses alias(string) => fullName(string) * @param array $templatePhpDocNodes * @param array $constUses alias(string) => fullName(string) * @param array $typeAliasesMap * @param array{string, string, string, string|null, string|null}|null $traitData */ public function __construct(?string $namespace, array $uses, ?string $className = null, ?string $functionName = null, array $templatePhpDocNodes = [], ?self $parent = null, array $typeAliasesMap = [], bool $bypassTypeAliases = \false, array $constUses = [], ?string $typeAliasClassName = null, ?array $traitData = null) { $this->namespace = $namespace; $this->uses = $uses; $this->className = $className; $this->functionName = $functionName; $this->templatePhpDocNodes = $templatePhpDocNodes; $this->parent = $parent; $this->typeAliasesMap = $typeAliasesMap; $this->bypassTypeAliases = $bypassTypeAliases; $this->constUses = $constUses; $this->typeAliasClassName = $typeAliasClassName; $this->traitData = $traitData; } /** * @return non-empty-string|null */ public function getNamespace(): ?string { return $this->namespace; } /** * @return array */ public function getUses(): array { return $this->uses; } /** * @return array */ public function getConstUses(): array { return $this->constUses; } public function getClassName(): ?string { return $this->className; } public function getFunctionName(): ?string { return $this->functionName; } /** * @return array */ public function getTemplatePhpDocNodes(): array { return $this->templatePhpDocNodes; } public function withTraitData(string $fileName, string $className, string $traitName, ?string $lookForTraitName, ?string $docComment): self { return new self($this->namespace, $this->uses, $this->className, $this->functionName, $this->templatePhpDocNodes, $this->parent, $this->typeAliasesMap, $this->bypassTypeAliases, $this->constUses, $this->typeAliasClassName, [$fileName, $className, $traitName, $lookForTraitName, $docComment]); } /** * @param string[] $namesToUnset */ public function unsetTemplatePhpDocNodes(array $namesToUnset): self { $templatePhpDocNodes = $this->templatePhpDocNodes; foreach ($namesToUnset as $name) { unset($templatePhpDocNodes[$name]); } return new self($this->namespace, $this->uses, $this->className, $this->functionName, $templatePhpDocNodes, $this->parent, $this->typeAliasesMap, $this->bypassTypeAliases, $this->constUses, $this->typeAliasClassName, $this->traitData); } /** * @return array{string, string, string, string|null, string|null}|null */ public function getTraitData(): ?array { return $this->traitData; } public function getParent(): ?self { return $this->parent; } /** * @return array */ public function getTypeAliasesMap(): array { return $this->typeAliasesMap; } public function shouldBypassTypeAliases(): bool { return $this->bypassTypeAliases; } public function getClassNameForTypeAlias(): ?string { return $this->typeAliasClassName; } /** * @param array $properties */ public static function __set_state(array $properties): self { return new self($properties['namespace'], $properties['uses'], $properties['className'], $properties['functionName'], $properties['templatePhpDocNodes'], $properties['parent'], $properties['typeAliasesMap'], $properties['bypassTypeAliases'], $properties['constUses'], $properties['typeAliasClassName'], $properties['traitData']); } } statement = $statement; $this->result = $result; } public function toPublic(): \PHPStan\Analyser\EndStatementResult { return new \PHPStan\Analyser\EndStatementResult($this->statement, $this->result->toPublic()); } public function getStatement(): Stmt { return $this->statement; } public function getResult(): \PHPStan\Analyser\InternalStatementResult { return $this->result; } } */ final class InternalError implements JsonSerializable { private string $message; private string $contextDescription; /** * @var Trace */ private array $trace; private ?string $traceAsString; private bool $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 fn(array $trace) => ['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] #[Override] public function jsonSerialize() { return ['message' => $this->message, 'contextDescription' => $this->contextDescription, 'trace' => $this->trace, 'traceAsString' => $this->traceAsString, 'shouldReportBug' => $this->shouldReportBug]; } } $expressionTypes * @param array $nativeExpressionTypes * @param array $conditionalExpressions * @param list $inClosureBindScopeClasses * @param array $currentlyAssignedExpressions * @param array $currentlyAllowedUndefinedExpressions * @param list $inFunctionCallsStack * @param \PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection|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 = [], ?ClosureType $anonymousFunctionReflection = null, bool $inFirstLevelStatement = \true, array $currentlyAssignedExpressions = [], array $currentlyAllowedUndefinedExpressions = [], array $inFunctionCallsStack = [], bool $afterExtractCall = \false, ?\PHPStan\Analyser\MutatingScope $parentScope = null, bool $nativeTypesPromoted = \false): \PHPStan\Analyser\MutatingScope; public function toFiberFactory(): self; public function toMutatingFactory(): self; } statement = $statement; $this->scope = $scope; } public function toPublic(): \PHPStan\Analyser\StatementExitPoint { return new \PHPStan\Analyser\StatementExitPoint($this->statement, $this->scope); } public function getStatement(): Stmt { return $this->statement; } public function getScope(): \PHPStan\Analyser\MutatingScope { return $this->scope; } } scope = $scope; $this->hasYield = $hasYield; $this->isAlwaysTerminating = $isAlwaysTerminating; $this->exitPoints = $exitPoints; $this->throwPoints = $throwPoints; $this->impurePoints = $impurePoints; $this->endStatements = $endStatements; } public function toPublic(): \PHPStan\Analyser\StatementResult { return new \PHPStan\Analyser\StatementResult($this->scope, $this->hasYield, $this->isAlwaysTerminating, array_map(static fn($exitPoint) => $exitPoint->toPublic(), $this->exitPoints), array_map(static fn($throwPoint) => $throwPoint->toPublic(), $this->throwPoints), $this->impurePoints, array_map(static fn($endStatement) => $endStatement->toPublic(), $this->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 Int_) { 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 InternalStatementExitPoint[] */ public function getExitPoints(): array { return $this->exitPoints; } /** * @param class-string|class-string $stmtClass * @return list */ 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 Int_) { $exitPoints[] = $exitPoint; continue; } $value = $value->value; if ($value !== 1) { continue; } $exitPoints[] = $exitPoint; } return $exitPoints; } /** * @return list */ 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 Int_) { continue; } $value = $statement->num->value; if ($value === 1) { continue; } $newNode = null; if ($value > 2) { $newNode = new Int_($value - 1); } if ($statement instanceof Stmt\Continue_) { $newStatement = new Stmt\Continue_($newNode); } else { $newStatement = new Stmt\Break_($newNode); } $exitPoints[] = new \PHPStan\Analyser\InternalStatementExitPoint($newStatement, $exitPoint->getScope()); } return $exitPoints; } /** * @return InternalThrowPoint[] */ 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 InternalEndStatementResult[] */ public function getEndStatements(): array { return $this->endStatements; } } scope = $scope; $this->type = $type; $this->node = $node; $this->explicit = $explicit; $this->canContainAnyThrowable = $canContainAnyThrowable; } public function toPublic(): \PHPStan\Analyser\ThrowPoint { if ($this->explicit) { return \PHPStan\Analyser\ThrowPoint::createExplicit($this->scope, $this->type, $this->node, $this->canContainAnyThrowable); } return \PHPStan\Analyser\ThrowPoint::createImplicit($this->scope, $this->node); } /** * @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 static function createFromPublic(\PHPStan\Analyser\ThrowPoint $throwPoint, \PHPStan\Analyser\MutatingScope $scope): self { return new self($scope, $throwPoint->getType(), $throwPoint->getNode(), $throwPoint->isExplicit(), $throwPoint->canContainAnyThrowable()); } 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); } } container = $container; $this->nodeCallback = $nodeCallback; $this->fiber = $fiber; $this->phpVersion = $this->container->getParameter('phpVersion'); $this->currentSimpleVersionParser = $this->container->getService('currentPhpVersionSimpleParser'); } /** * @param \PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection|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 = [], ?ClosureType $anonymousFunctionReflection = null, bool $inFirstLevelStatement = \true, array $currentlyAssignedExpressions = [], array $currentlyAllowedUndefinedExpressions = [], array $inFunctionCallsStack = [], bool $afterExtractCall = \false, ?\PHPStan\Analyser\MutatingScope $parentScope = null, bool $nativeTypesPromoted = \false): \PHPStan\Analyser\MutatingScope { $className = \PHPStan\Analyser\MutatingScope::class; if ($this->fiber) { $className = FiberScope::class; } $this->reflectionProvider ??= $this->container->getByType(ReflectionProvider::class); $this->initializerExprTypeResolver ??= $this->container->getByType(InitializerExprTypeResolver::class); $this->expressionTypeResolverExtensionRegistry ??= $this->container->getByType(ExpressionTypeResolverExtensionRegistryProvider::class)->getRegistry(); $this->exprPrinter ??= $this->container->getByType(ExprPrinter::class); $this->typeSpecifier ??= $this->container->getByType(\PHPStan\Analyser\TypeSpecifier::class); $this->propertyReflectionFinder ??= $this->container->getByType(PropertyReflectionFinder::class); $this->constantResolver ??= $this->container->getByType(\PHPStan\Analyser\ConstantResolver::class); $this->phpVersionType ??= $this->container->getByType(PhpVersion::class); $this->attributeReflectionFactory ??= $this->container->getByType(AttributeReflectionFactory::class); return new $className($this->container, $this, $this->reflectionProvider, $this->initializerExprTypeResolver, $this->expressionTypeResolverExtensionRegistry, $this->exprPrinter, $this->typeSpecifier, $this->propertyReflectionFinder, $this->currentSimpleVersionParser, $this->constantResolver, $context, $this->phpVersionType, $this->attributeReflectionFactory, $this->phpVersion, $this->nodeCallback, $declareStrictTypes, $function, $namespace, $expressionTypes, $nativeExpressionTypes, $conditionalExpressions, $inClosureBindScopeClasses, $anonymousFunctionReflection, $inFirstLevelStatement, $currentlyAssignedExpressions, $currentlyAllowedUndefinedExpressions, $inFunctionCallsStack, $afterExtractCall, $parentScope, $nativeTypesPromoted); } public function toFiberFactory(): \PHPStan\Analyser\InternalScopeFactory { return new self($this->container, $this->nodeCallback, \true); } public function toMutatingFactory(): \PHPStan\Analyser\InternalScopeFactory { return new self($this->container, $this->nodeCallback, \false); } } $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['name'] !== $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['name'] !== $unmatchedIgnoredIdentifier['name']) { 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 array $fileErrors; /** * @var list */ private array $locallyIgnoredErrors; /** * @var LinesToIgnore */ private array $linesToIgnore; /** * @var LinesToIgnore */ private array $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; } } */ public array $expressionTypes; /** * @var array */ protected array $nativeExpressionTypes; /** * @var array */ protected array $conditionalExpressions; /** * @var list */ protected array $inClosureBindScopeClasses; private ?ClosureType $anonymousFunctionReflection; private bool $inFirstLevelStatement; /** * @var array */ protected array $currentlyAssignedExpressions; /** * @var array */ protected array $currentlyAllowedUndefinedExpressions; /** * @var list */ public array $inFunctionCallsStack; protected bool $afterExtractCall; private ?self $parentScope; public bool $nativeTypesPromoted; public const KEEP_VOID_ATTRIBUTE_NAME = 'keepVoid'; private const CONTAINS_SUPER_GLOBAL_ATTRIBUTE_NAME = 'containsSuperGlobal'; private const COMPLEX_UNION_TYPE_MEMBER_LIMIT = 8; /** @var Type[] */ private array $resolvedTypes = []; /** @var array */ private array $truthyScopes = []; /** @var array */ private array $falseyScopes = []; private ?self $fiberScope = null; /** @var non-empty-string|null */ private ?string $namespace; private ?self $scopeOutOfFirstLevelStatement = null; private ?self $scopeWithPromotedNativeTypes = null; /** * @param int|array{min: int, max: int}|null $configPhpVersion * @param callable(Node $node, Scope $scope): void|null $nodeCallback * @param array $expressionTypes * @param array $conditionalExpressions * @param list $inClosureBindScopeClasses * @param array $currentlyAssignedExpressions * @param array $currentlyAllowedUndefinedExpressions * @param array $nativeExpressionTypes * @param list $inFunctionCallsStack * @param \PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection|null $function */ public function __construct(Container $container, \PHPStan\Analyser\InternalScopeFactory $scopeFactory, ReflectionProvider $reflectionProvider, InitializerExprTypeResolver $initializerExprTypeResolver, ExpressionTypeResolverExtensionRegistry $expressionTypeResolverExtensionRegistry, ExprPrinter $exprPrinter, \PHPStan\Analyser\TypeSpecifier $typeSpecifier, PropertyReflectionFinder $propertyReflectionFinder, Parser $parser, \PHPStan\Analyser\ConstantResolver $constantResolver, \PHPStan\Analyser\ScopeContext $context, PhpVersion $phpVersion, AttributeReflectionFactory $attributeReflectionFactory, $configPhpVersion, $nodeCallback = null, bool $declareStrictTypes = \false, $function = null, ?string $namespace = null, array $expressionTypes = [], array $nativeExpressionTypes = [], array $conditionalExpressions = [], array $inClosureBindScopeClasses = [], ?ClosureType $anonymousFunctionReflection = null, bool $inFirstLevelStatement = \true, array $currentlyAssignedExpressions = [], array $currentlyAllowedUndefinedExpressions = [], array $inFunctionCallsStack = [], bool $afterExtractCall = \false, ?self $parentScope = null, bool $nativeTypesPromoted = \false) { $this->container = $container; $this->scopeFactory = $scopeFactory; $this->reflectionProvider = $reflectionProvider; $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->expressionTypeResolverExtensionRegistry = $expressionTypeResolverExtensionRegistry; $this->exprPrinter = $exprPrinter; $this->typeSpecifier = $typeSpecifier; $this->propertyReflectionFinder = $propertyReflectionFinder; $this->parser = $parser; $this->constantResolver = $constantResolver; $this->context = $context; $this->phpVersion = $phpVersion; $this->attributeReflectionFactory = $attributeReflectionFactory; $this->configPhpVersion = $configPhpVersion; $this->nodeCallback = $nodeCallback; $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; if ($namespace === '') { $namespace = null; } $this->namespace = $namespace; } public function toFiberScope(): self { if (PHP_VERSION_ID < 80100) { throw new ShouldNotHappenException('Cannot create FiberScope below PHP 8.1'); } if ($this->fiberScope !== null) { return $this->fiberScope; } return $this->fiberScope = $this->scopeFactory->toFiberFactory()->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, $this->inFunctionCallsStack, $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); } public function toMutatingScope(): self { return $this; } /** @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); } /** * @param array $currentExpressionTypes * @return array */ private function rememberConstructorExpressions(array $currentExpressionTypes): array { $expressionTypes = []; foreach ($currentExpressionTypes as $exprString => $expressionTypeHolder) { $expr = $expressionTypeHolder->getExpr(); if ($expr instanceof FuncCall) { if (!$expr->name instanceof Name || !in_array($expr->name->name, ['class_exists', 'function_exists'], \true)) { continue; } } elseif ($expr instanceof PropertyFetch) { if (!$this->isReadonlyPropertyFetch($expr, \true)) { continue; } } elseif (!$expr instanceof ConstFetch && !$expr instanceof PropertyInitializationExpr) { continue; } $expressionTypes[$exprString] = $expressionTypeHolder; } if (array_key_exists('$this', $currentExpressionTypes)) { $expressionTypes['$this'] = $currentExpressionTypes['$this']; } return $expressionTypes; } public function rememberConstructorScope(): self { return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), null, $this->getNamespace(), $this->rememberConstructorExpressions($this->expressionTypes), $this->rememberConstructorExpressions($this->nativeExpressionTypes), $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->inFirstLevelStatement, [], [], $this->inFunctionCallsStack, $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); } private function isReadonlyPropertyFetch(PropertyFetch $expr, bool $allowOnlyOnThis): bool { if (!$this->phpVersion->supportsReadOnlyProperties()) { return \false; } while ($expr instanceof PropertyFetch) { if ($expr->var instanceof Variable) { if ($allowOnlyOnThis && (!$expr->name instanceof Node\Identifier || !is_string($expr->var->name) || $expr->var->name !== 'this')) { return \false; } } elseif (!$expr->var instanceof PropertyFetch) { return \false; } $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($expr, $this); if ($propertyReflection === null) { return \false; } $nativePropertyReflection = $propertyReflection->getNativeReflection(); if ($nativePropertyReflection === null || !$nativePropertyReflection->isReadOnly()) { return \false; } $expr = $expr->var; } return \true; } /** @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(): ?self { 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 { $changed = \false; $expressionTypes = $this->expressionTypes; $nativeExpressionTypes = $this->nativeExpressionTypes; 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]); unset($nativeExpressionTypes[$exprString]); $changed = \true; continue 2; } } if (!$changed) { return $this; } return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $expressionTypes, $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; $nativeExpressionTypes = $this->nativeExpressionTypes; $errorStringFunction = '\openssl_error_string()'; if (!array_key_exists($errorStringFunction, $expressionTypes) && !array_key_exists($errorStringFunction, $nativeExpressionTypes)) { return $this; } $changed = \false; 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[$errorStringFunction]); unset($nativeExpressionTypes[$errorStringFunction]); $changed = \true; } if (!$changed) { return $this; } return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $expressionTypes, $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 { $hasVariableType = $this->hasVariableType($variableName); if ($hasVariableType->maybe()) { if ($variableName === 'argc') { return StaticTypeFactory::argc(); } if ($variableName === 'argv') { return StaticTypeFactory::argv(); } if ($this->canAnyVariableExist()) { return new MixedType(); } } if ($hasVariableType->no()) { throw new \PHPStan\Analyser\UndefinedVariableException($this, $variableName); } $varExprString = '$' . $variableName; if (!array_key_exists($varExprString, $this->expressionTypes)) { if ($this->isGlobalVariable($variableName)) { return new ArrayType(new BenevolentUnionType([new IntegerType(), new StringType()]), new MixedType(\true)); } return new MixedType(); } return $this->expressionTypes[$varExprString]->getType(); } /** * @api * @return list */ 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 list */ 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; } /** * @return list */ public function findPossiblyImpureCallDescriptions(Expr $expr): array { $nodeFinder = new NodeFinder(); $callExprDescriptions = []; $foundCallExprMatch = \false; $matchedCallExprKeys = []; foreach ($this->expressionTypes as $holder) { $holderExpr = $holder->getExpr(); if (!$holderExpr instanceof PossiblyImpureCallExpr) { continue; } $callExprKey = $this->getNodeKey($holderExpr->callExpr); $found = $nodeFinder->findFirst([$expr], function (Node $node) use ($callExprKey): bool { if (!$node instanceof Expr) { return \false; } return $this->getNodeKey($node) === $callExprKey; }); if ($found === null) { continue; } $foundCallExprMatch = \true; $matchedCallExprKeys[$callExprKey] = \true; // Only show the tip when the scope's type for the call expression // differs from the declared return type, meaning control flow // narrowing affected the type (the cached value was narrowed). assert($found instanceof Expr); $scopeType = $this->getType($found); $declaredReturnType = $holder->getType(); if ($declaredReturnType->isSuperTypeOf($scopeType)->yes() && $scopeType->isSuperTypeOf($declaredReturnType)->yes()) { continue; } $callExprDescriptions[] = $holderExpr->getCallDescription(); } // If the first pass found a callExpr in the error expression but // filtered it out (return type wasn't narrowed), the error is // explained by the return type alone - skip the fallback. if ($foundCallExprMatch && count($callExprDescriptions) === 0) { return []; } // Second pass: match by impactedExpr for cases where a maybe-impure method // on an object didn't invalidate it, but a different method's return // value was narrowed on that object. // Skip when the expression itself is a direct method/static call - // those are passed by ImpossibleCheckType rules where the error is // about the call's arguments, not about object state. if (!($expr instanceof Expr\MethodCall || $expr instanceof Expr\StaticCall)) { $impactedExprDescriptions = []; foreach ($this->expressionTypes as $holder) { $holderExpr = $holder->getExpr(); if (!$holderExpr instanceof PossiblyImpureCallExpr) { continue; } $impactedExprKey = $this->getNodeKey($holderExpr->impactedExpr); // Skip if impactedExpr is the same as callExpr (function calls) if ($impactedExprKey === $this->getNodeKey($holderExpr->callExpr)) { continue; } // Skip if this entry's callExpr was already matched in the first pass $callExprKey = $this->getNodeKey($holderExpr->callExpr); if (isset($matchedCallExprKeys[$callExprKey])) { continue; } $found = $nodeFinder->findFirst([$expr], function (Node $node) use ($impactedExprKey): bool { if (!$node instanceof Expr) { return \false; } return $this->getNodeKey($node) === $impactedExprKey; }); if ($found === null) { continue; } $impactedExprDescriptions[] = $holderExpr->getCallDescription(); } // Prefer impactedExpr matches (intermediate calls that could have // invalidated the object) over callExpr matches if (count($impactedExprDescriptions) > 0) { return array_values(array_unique($impactedExprDescriptions)); } } if (count($callExprDescriptions) > 0) { return array_values(array_unique($callExprDescriptions)); } return []; } 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 ($this->getGlobalConstantType($name) !== null) { 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(): ?ClosureType { 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 { $key = $this->getNodeKey($node); if (!array_key_exists($key, $this->resolvedTypes)) { $this->resolvedTypes[$key] = TypeUtils::resolveLateResolvableTypes($this->resolveType($key, $node)); } return $this->resolvedTypes[$key]; } public function getScopeType(Expr $expr): Type { return $this->getType($expr); } public function getScopeNativeType(Expr $expr): Type { return $this->getNativeType($expr); } public function getNodeKey(Expr $node): string { // perf optimize for the most common path if ($node instanceof Variable && !$node->name instanceof Expr) { return '$' . $node->name; } $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; } public function getClosureScopeCacheKey(): string { $parts = []; foreach ($this->expressionTypes as $exprString => $expressionTypeHolder) { if ($expressionTypeHolder->getExpr() instanceof VirtualNode) { continue; } $parts[] = sprintf('%s::%s', $exprString, $expressionTypeHolder->getType()->describe(VerbosityLevel::cache())); } $parts[] = '---'; $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 Variable && !$node instanceof Expr\Closure && !$node instanceof Expr\ArrowFunction && $this->hasExpressionType($node)->yes()) { return $this->expressionTypes[$exprString]->getType(); } /** @var ExprHandler $exprHandler */ foreach ($this->container->getServicesByTag(\PHPStan\Analyser\ExprHandler::EXTENSION_TAG) as $exprHandler) { if (!$exprHandler->supports($node)) { continue; } return $exprHandler->resolveType($this, $node); } return new MixedType(); } /** * @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; } if ($propertyReflection->hasNativeType() && !$propertyReflection->isVirtual()->yes()) { if (!$this->hasExpressionType($expr)->yes()) { $nativeReflection = $propertyReflection->getNativeReflection(); if ($nativeReflection === null || !$nativeReflection->isPromoted() || !$nativeReflection->isReadOnly() && !$nativeReflection->isHooked()) { 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) { 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; } $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; } /** @api */ public function getNativeType(Expr $expr): Type { return $this->promoteNativeTypes()->getType($expr); } public function getKeepVoidType(Expr $node): Type { if (!$node instanceof Match_ && (!$node instanceof FuncCall && !$node instanceof MethodCall && !$node instanceof Expr\NullsafeMethodCall && !$node instanceof Expr\StaticCall || $node->isFirstClassCallable())) { return $this->getType($node); } $originalType = $this->getType($node); if (!TypeCombinator::containsNull($originalType)) { return $originalType; } $clonedNode = clone $node; $clonedNode->setAttribute(self::KEEP_VOID_ATTRIBUTE_NAME, \true); return $this->getType($clonedNode); } 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); } /** @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); } /** * @api * @param mixed $value */ public function getTypeFromValue($value): Type { return ConstantTypeHelper::getTypeFromValue($value); } /** @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, bool $rememberTypes): self { $stack = $this->inFunctionCallsStack; $stack[] = [$reflection, $parameter]; $functionScope = $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); if ($rememberTypes) { $functionScope->resolvedTypes = $this->resolvedTypes; } return $functionScope; } public function popInFunctionCall(): self { $stack = $this->inFunctionCallsStack; array_pop($stack); $parentScope = $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); $parentScope->resolvedTypes = $this->resolvedTypes; return $parentScope; } /** @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 fn($values) => $values[0], $this->inFunctionCallsStack), static fn($reflection) => $reflection !== null)); } public function getFunctionCallStackWithParameters(): array { return array_values(array_filter($this->inFunctionCallsStack, static fn($item) => $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, ?ResolvedPhpDocBlock $resolvedPhpDocBlock = null): self { if (!$this->isInClass()) { throw new ShouldNotHappenException(); } return $this->enterFunctionLike(new PhpMethodFromParserNodeReflection($this->getClassReflection(), $classMethod, null, $this->getFile(), $templateTypeMap, $this->getRealParameterTypes($classMethod), array_map(fn(Type $type): Type => $this->transformStaticType(TemplateTypeHelper::toArgument($type)), $phpDocParameterTypes), $this->getRealParameterDefaultValues($classMethod), $this->getParameterAttributes($classMethod), $this->transformStaticType($this->getFunctionType($classMethod->returnType, \false, \false)), $phpDocReturnType !== null ? $this->transformStaticType(TemplateTypeHelper::toArgument($phpDocReturnType)) : null, $throwType !== null ? $this->transformStaticType(TemplateTypeHelper::toArgument($throwType)) : null, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal, $isPure, $acceptsNamedArguments, $asserts ?? Assertions::createEmpty(), $selfOutType, $phpDocComment, $resolvedPhpDocBlock, array_map(fn(Type $type): Type => $this->transformStaticType(TemplateTypeHelper::toArgument($type)), $parameterOutTypes), $immediatelyInvokedCallableParameters, array_map(fn(Type $type): Type => $this->transformStaticType(TemplateTypeHelper::toArgument($type)), $phpDocClosureThisTypeParameters), $isConstructor, $this->attributeReflectionFactory->fromAttrGroups($classMethod->attrGroups, InitializerExprContext::fromStubParameter($this->getClassReflection()->getName(), $this->getFile(), $classMethod))), !$classMethod->isStatic()); } /** * @param Type[] $phpDocParameterTypes * @param \PhpParser\Node\Identifier|\PhpParser\Node\Name|\PhpParser\Node\ComplexType|null $nativePropertyTypeNode */ public function enterPropertyHook(Node\PropertyHook $hook, string $propertyName, $nativePropertyTypeNode, ?Type $phpDocPropertyType, array $phpDocParameterTypes, ?Type $throwType, ?string $deprecatedDescription, bool $isDeprecated, ?string $phpDocComment, ?ResolvedPhpDocBlock $resolvedPhpDocBlock = null): self { if (!$this->isInClass()) { throw new ShouldNotHappenException(); } $phpDocParameterTypes = array_map(fn(Type $type): Type => $this->transformStaticType(TemplateTypeHelper::toArgument($type)), $phpDocParameterTypes); $hookName = $hook->name->toLowerString(); if ($hookName === 'set') { if ($hook->params === []) { $hook = clone $hook; $hook->params = [new Node\Param(new Variable('value'), \null, $nativePropertyTypeNode)]; } $firstParam = $hook->params[0] ?? null; if ($firstParam !== null && $phpDocPropertyType !== null && $firstParam->var instanceof Variable && is_string($firstParam->var->name)) { $valueParamPhpDocType = $phpDocParameterTypes[$firstParam->var->name] ?? null; if ($valueParamPhpDocType === null) { $phpDocParameterTypes[$firstParam->var->name] = $this->transformStaticType(TemplateTypeHelper::toArgument($phpDocPropertyType)); } } $realReturnType = new VoidType(); $phpDocReturnType = null; } elseif ($hookName === 'get') { $realReturnType = $this->getFunctionType($nativePropertyTypeNode, \false, \false); $phpDocReturnType = $phpDocPropertyType !== null ? $this->transformStaticType(TemplateTypeHelper::toArgument($phpDocPropertyType)) : null; } else { throw new ShouldNotHappenException(); } $realParameterTypes = $this->getRealParameterTypes($hook); return $this->enterFunctionLike(new PhpMethodFromParserNodeReflection($this->getClassReflection(), $hook, $propertyName, $this->getFile(), TemplateTypeMap::createEmpty(), $realParameterTypes, $phpDocParameterTypes, [], $this->getParameterAttributes($hook), $realReturnType, $phpDocReturnType, $throwType !== null ? $this->transformStaticType(TemplateTypeHelper::toArgument($throwType)) : null, $deprecatedDescription, $isDeprecated, \false, \false, \false, \true, Assertions::createEmpty(), null, $phpDocComment, $resolvedPhpDocBlock, [], [], [], \false, $this->attributeReflectionFactory->fromAttrGroups($hook->attrGroups, InitializerExprContext::fromStubParameter($this->getClassReflection()->getName(), $this->getFile(), $hook))), \true); } private function transformStaticType(Type $type): Type { return TypeTraverser::map($type, new TransformStaticTypeTraverser($this)); } /** * @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; } /** * @return array> * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\PropertyHook $functionLike */ private function getParameterAttributes($functionLike): array { $parameterAttributes = []; $className = null; if ($this->isInClass()) { $className = $this->getClassReflection()->getName(); } foreach ($functionLike->getParams() as $parameter) { if (!$parameter->var instanceof Variable || !is_string($parameter->var->name)) { throw new ShouldNotHappenException(); } $parameterAttributes[$parameter->var->name] = $this->attributeReflectionFactory->fromAttrGroups($parameter->attrGroups, InitializerExprContext::fromStubParameter($className, $this->getFile(), $functionLike)); } return $parameterAttributes; } /** * @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 $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 fn(Type $type): Type => TemplateTypeHelper::toArgument($type), $phpDocParameterTypes), $this->getRealParameterDefaultValues($function), $this->getParameterAttributes($function), $this->getFunctionType($function->returnType, $function->returnType === null, \false), $phpDocReturnType !== null ? TemplateTypeHelper::toArgument($phpDocReturnType) : null, $throwType, $deprecatedDescription, $isDeprecated, $isInternal, $isPure, $acceptsNamedArguments, $asserts ?? Assertions::createEmpty(), $phpDocComment, array_map(static fn(Type $type): Type => TemplateTypeHelper::toArgument($type), $parameterOutTypes), $immediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters, $this->attributeReflectionFactory->fromAttrGroups($function->attrGroups, InitializerExprContext::fromStubParameter(null, $this->getFile(), $function))), \false); } private function enterFunctionLike(PhpFunctionFromParserNodeReflection $functionReflection, bool $preserveConstructorScope): self { $parametersByName = []; $functionParameters = $functionReflection->getParameters(); foreach ($functionParameters as $parameter) { $parametersByName[$parameter->getName()] = $parameter; } $expressionTypes = []; $nativeExpressionTypes = []; $conditionalTypes = []; if ($preserveConstructorScope) { $expressionTypes = $this->expressionTypes; $nativeExpressionTypes = $this->nativeExpressionTypes; } foreach ($functionParameters 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()))], \PHPStan\Analyser\ExpressionTypeHolder::createYes(new Variable($parameter->getName()), $ifType)); $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()))], \PHPStan\Analyser\ExpressionTypeHolder::createYes(new Variable($parameter->getName()), $elseType)); $conditionalTypes['$' . $parameter->getName()][$holder->getKey()] = $holder; } } $paramExprString = '$' . $parameter->getName(); if ($parameter->isVariadic()) { if (!$this->getPhpVersion()->supportsNamedArguments()->no() && $functionReflection->acceptsNamedArguments()->yes()) { $parameterType = new ArrayType(new UnionType([new IntegerType(), new StringType()]), $parameterType); } else { $parameterType = new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $parameterType), new AccessoryArrayListType()]); } } $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->getPhpVersion()->supportsNamedArguments()->no() && $functionReflection->acceptsNamedArguments()->yes()) { $nativeParameterType = new ArrayType(new UnionType([new IntegerType(), new StringType()]), $nativeParameterType); } else { $nativeParameterType = new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $nativeParameterType), new AccessoryArrayListType()]); } } $nativeExpressionTypes[$paramExprString] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($parameterNode, $nativeParameterType); $nativeExpressionTypes[$parameterOriginalValueExprString] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($parameterOriginalValueExpr, $nativeParameterType); } 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()) { foreach ($restoreThisScope->expressionTypes as $exprString => $expressionTypeHolder) { if (!str_starts_with($exprString, '$this')) { continue; } $expressionTypes[$exprString] = $expressionTypeHolder; } foreach ($restoreThisScope->nativeExpressionTypes as $exprString => $expressionTypeHolder) { if (!str_starts_with($exprString, '$this')) { 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): self { $anonymousFunctionReflection = $this->resolveType('__phpstanClosure', $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->conditionalExpressions, $scope->inClosureBindScopeClasses, $anonymousFunctionReflection, \true, [], [], $this->inFunctionCallsStack, \false, $this, $this->nativeTypesPromoted); } /** * @param ParameterReflection[]|null $callableParameters */ public function enterAnonymousFunctionWithoutReflection(Expr\Closure $closure, ?array $callableParameters): 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) { $parameterType = self::intersectButNotNever($parameterType, $this->getCallableParameterType($parameter, $callableParameters, $i)); } $holder = \PHPStan\Analyser\ExpressionTypeHolder::createYes($parameter->var, $parameterType); $expressionTypes[$paramExprString] = $holder; $nativeTypes[$paramExprString] = $holder; } $nonRefVariableNames = []; $useVariableNames = []; foreach ($closure->uses as $use) { if (!is_string($use->var->name)) { throw new ShouldNotHappenException(); } $variableName = $use->var->name; $paramExprString = '$' . $use->var->name; $useVariableNames[$paramExprString] = \true; 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); } $nonStaticExpressions = $this->invalidateStaticExpressions($this->expressionTypes); foreach ($nonStaticExpressions 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 (!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)); if ($this->phpVersion->supportsReadOnlyProperties()) { foreach ($nonStaticExpressions as $exprString => $typeHolder) { $expr = $typeHolder->getExpr(); if (!$expr instanceof PropertyFetch) { continue; } if (!$this->isReadonlyPropertyFetch($expr, \true)) { continue; } $expressionTypes[$exprString] = $typeHolder; } } } $filteredConditionalExpressions = []; foreach ($this->conditionalExpressions as $conditionalExprString => $holders) { if (!array_key_exists($conditionalExprString, $useVariableNames)) { continue; } $filteredHolders = []; foreach ($holders as $holder) { foreach (array_keys($holder->getConditionExpressionTypeHolders()) as $holderExprString) { if (!array_key_exists($holderExprString, $useVariableNames)) { continue 2; } } $filteredHolders[] = $holder; } if ($filteredHolders === []) { continue; } $filteredConditionalExpressions[$conditionalExprString] = $filteredHolders; } return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), array_merge($this->getConstantTypes(), $expressionTypes), array_merge($this->getNativeConstantTypes(), $nativeTypes), $filteredConditionalExpressions, $this->inClosureBindScopeClasses, new ClosureType(), \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 fn($node) => $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): self { $anonymousFunctionReflection = $this->resolveType('__phpStanArrowFn', $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 */ public function enterArrowFunctionWithoutReflection(Expr\ArrowFunction $arrowFunction, ?array $callableParameters): self { $arrowFunctionScope = $this; foreach ($arrowFunction->params as $i => $parameter) { $isNullable = $this->isParameterValueNullable($parameter); $parameterType = $this->getFunctionType($parameter->type, $isNullable, $parameter->variadic); if ($callableParameters !== null) { $parameterType = self::intersectButNotNever($parameterType, $this->getCallableParameterType($parameter, $callableParameters, $i)); } if (!$parameter->var instanceof Variable || !is_string($parameter->var->name)) { throw new ShouldNotHappenException(); } $arrowFunctionScope = $arrowFunctionScope->assignVariable($parameter->var->name, $parameterType, $parameterType, TrinaryLogic::createYes()); } 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 ClosureType(), \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 ($isVariadic) { if (!$this->getPhpVersion()->supportsNamedArguments()->no()) { return new ArrayType(new UnionType([new IntegerType(), new StringType()]), $this->getFunctionType($type, $isNullable, \false)); } return new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $this->getFunctionType($type, $isNullable, \false)), new AccessoryArrayListType()]); } return $this->initializerExprTypeResolver->getFunctionType($type, $isNullable, \false, InitializerExprContext::fromScope($this)); } /** * @param ParameterReflection[] $callableParameters */ private function getCallableParameterType(Node\Param $parameter, array $callableParameters, int $index): Type { if ($parameter->variadic) { return $this->buildVariadicArrayTypeFromCallableParameters($callableParameters, $index); } if (isset($callableParameters[$index])) { return $callableParameters[$index]->getType(); } if (count($callableParameters) === 0) { return new MixedType(); } $lastParameter = array_last($callableParameters); if ($lastParameter->isVariadic()) { return $lastParameter->getType(); } return new MixedType(); } /** * @param array $callableParameters */ private function buildVariadicArrayTypeFromCallableParameters(array $callableParameters, int $startIndex): Type { $elementTypes = []; $callableParametersCount = count($callableParameters); for ($j = $startIndex; $j < $callableParametersCount; $j++) { $elementTypes[] = $callableParameters[$j]->getType(); if ($callableParameters[$j]->isVariadic()) { break; } } if ($elementTypes === [] && $callableParametersCount > 0) { $lastParameter = array_last($callableParameters); if ($lastParameter->isVariadic()) { $elementTypes[] = $lastParameter->getType(); } } if ($elementTypes === []) { return new MixedType(); } $elementType = TypeCombinator::union(...$elementTypes); if (!$this->getPhpVersion()->supportsNamedArguments()->no()) { return new ArrayType(new UnionType([new IntegerType(), new StringType()]), $elementType); } return new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $elementType), new AccessoryArrayListType()]); } public 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, Type $condType, Type $condNativeType): self { if ($expr->cond instanceof Variable) { return $this; } if ($expr->cond instanceof AlwaysRememberedExpr) { $cond = $expr->cond->expr; } else { $cond = $expr->cond; } if ($cond instanceof Scalar) { return $this; } $type = $condType; $nativeType = $condNativeType; $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, bool $valueByRef): self { $iterateeType = $originalScope->getType($iteratee); $nativeIterateeType = $originalScope->getNativeType($iteratee); $valueType = $originalScope->getIterableValueType($iterateeType); $nativeValueType = $originalScope->getIterableValueType($nativeIterateeType); $scope = $this->assignVariable($valueName, $valueType, $nativeValueType, TrinaryLogic::createYes()); // Track the original foreach value so narrowings applied to the value // variable (e.g. is_string($type)) can later be projected back onto the // corresponding array dim fetch without being confused by a reassignment // ($type = 'foo' invalidates this expression, same as OriginalForeachKeyExpr). $scope = $scope->assignExpression(new OriginalForeachValueExpr($valueName), $valueType, $nativeValueType); if ($valueByRef && $iterateeType->isArray()->yes() && $iterateeType->isConstantArray()->no()) { $scope = $scope->assignExpression(new IntertwinedVariableByReferenceWithExpr($valueName, $iteratee, new SetExistingOffsetValueTypeExpr($iteratee, new GetIterableKeyTypeExpr($iteratee), new Variable($valueName))), $valueType, $nativeValueType); } if ($keyName !== null) { $scope = $scope->enterForeachKey($originalScope, $iteratee, $keyName); if ($valueByRef && $iterateeType->isArray()->yes() && $iterateeType->isConstantArray()->no()) { $scope = $scope->assignExpression(new IntertwinedVariableByReferenceWithExpr($valueName, new Expr\ArrayDimFetch($iteratee, new Variable($keyName)), new Variable($valueName)), $valueType, $nativeValueType); } } return $scope; } public function enterForeachKey(self $originalScope, Expr $iteratee, string $keyName): self { $iterateeType = $originalScope->getType($iteratee); $nativeIterateeType = $originalScope->getNativeType($iteratee); $keyType = $originalScope->getIterableKeyType($iterateeType); $nativeKeyType = $originalScope->getIterableKeyType($nativeIterateeType); $scope = $this->assignVariable($keyName, $keyType, $nativeKeyType, TrinaryLogic::createYes()); $originalForeachKeyExpr = new OriginalForeachKeyExpr($keyName); $scope = $scope->assignExpression($originalForeachKeyExpr, $keyType, $nativeKeyType); if ($iterateeType->isArray()->yes()) { $scope = $scope->assignExpression(new Expr\ArrayDimFetch($iteratee, new Variable($keyName)), $originalScope->getIterableValueType($iterateeType), $originalScope->getIterableValueType($nativeIterateeType)); } return $scope; } 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)), TrinaryLogic::createYes()); } 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 { if (count($this->currentlyAssignedExpressions) === 0) { return \false; } $exprString = $this->getNodeKey($expr); return array_key_exists($exprString, $this->currentlyAssignedExpressions); } public function setAllowedUndefinedExpression(Expr $expr): self { if ($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 { if (count($this->currentlyAllowedUndefinedExpressions) === 0) { return \false; } $exprString = $this->getNodeKey($expr); return array_key_exists($exprString, $this->currentlyAllowedUndefinedExpressions); } /** * @param list $intertwinedPropagatedFrom */ public function assignVariable(string $variableName, Type $type, Type $nativeType, TrinaryLogic $certainty, array $intertwinedPropagatedFrom = []): self { $node = new Variable($variableName); $scope = $this->assignExpression($node, $type, $nativeType); 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); } foreach ($scope->expressionTypes as $exprString => $expressionType) { if (!$expressionType->getExpr() instanceof IntertwinedVariableByReferenceWithExpr) { continue; } if (!$expressionType->getCertainty()->yes()) { continue; } if ($expressionType->getExpr()->getVariableName() !== $variableName) { continue; } $assignedExpr = $expressionType->getExpr()->getAssignedExpr(); if ($assignedExpr instanceof Expr\ArrayDimFetch && !$this->isDimFetchPathReachable($scope, $assignedExpr)) { unset($scope->expressionTypes[$exprString]); unset($scope->nativeExpressionTypes[$exprString]); continue; } $has = $scope->hasExpressionType($expressionType->getExpr()->getExpr()); if ($expressionType->getExpr()->getExpr() instanceof Variable && is_string($expressionType->getExpr()->getExpr()->name) && !$has->no()) { $targetVarName = $expressionType->getExpr()->getExpr()->name; if (in_array($targetVarName, $intertwinedPropagatedFrom, \true)) { continue; } $scope = $scope->assignVariable($targetVarName, $scope->getType($expressionType->getExpr()->getAssignedExpr()), $scope->getNativeType($expressionType->getExpr()->getAssignedExpr()), $has, array_merge($intertwinedPropagatedFrom, [$variableName])); } else { $targetRootVar = $this->getIntertwinedRefRootVariableName($expressionType->getExpr()->getExpr()); if ($targetRootVar !== null && in_array($targetRootVar, $intertwinedPropagatedFrom, \true)) { continue; } $scope = $scope->assignExpression($expressionType->getExpr()->getExpr(), $scope->getType($expressionType->getExpr()->getAssignedExpr()), $scope->getNativeType($expressionType->getExpr()->getAssignedExpr())); } } return $scope; } private function isDimFetchPathReachable(self $scope, Expr\ArrayDimFetch $dimFetch): bool { if ($dimFetch->dim === null) { return \false; } if (!$dimFetch->var instanceof Expr\ArrayDimFetch) { return \true; } $varType = $scope->getType($dimFetch->var); $dimType = $scope->getType($dimFetch->dim); if (!$varType->hasOffsetValueType($dimType)->yes()) { return \false; } return $this->isDimFetchPathReachable($scope, $dimFetch->var); } private 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): self { if ($expr instanceof Scalar) { return $this; } 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 && !$expr->dim instanceof Expr\PreInc && !$expr->dim instanceof Expr\PreDec && !$expr->dim instanceof Expr\PostDec && !$expr->dim instanceof Expr\PostInc) { $dimType = $scope->getType($expr->dim)->toArrayKey(); if ($dimType->isInteger()->yes() || $dimType->isString()->yes()) { $exprVarType = $scope->getType($expr->var); $isArray = $exprVarType->isArray(); if (!$exprVarType instanceof MixedType && !$isArray->no()) { $varType = $exprVarType; if (!$isArray->yes()) { if ($dimType->isInteger()->yes()) { $varType = TypeCombinator::intersect($exprVarType, StaticTypeFactory::intOffsetAccessibleType()); } else { $varType = TypeCombinator::intersect($exprVarType, StaticTypeFactory::generalOffsetAccessibleType()); } } if ($dimType instanceof ConstantIntegerType || $dimType instanceof ConstantStringType) { if (!$this->isComplexUnionType($varType)) { $varType = TypeCombinator::intersect($varType, new HasOffsetValueType($dimType, $type)); } } $scope = $scope->specifyExpressionType($expr->var, $varType, $scope->getNativeType($expr->var), $certainty); } } } if ($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): self { $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, TrinaryLogic::createYes()); } public function assignInitializedProperty(Type $fetchedOnType, string $propertyName): self { if (!$this->isInClass()) { return $this; } if (TypeUtils::findThisType($fetchedOnType) === null) { return $this; } $propertyReflection = $this->getInstancePropertyReflection($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, ?ClassReflection $invalidatingClass = null): 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, $exprString, $requireMoreCharacters, $invalidatingClass)) { continue; } unset($expressionTypes[$exprString]); unset($nativeExpressionTypes[$exprString]); $invalidated = \true; } $newConditionalExpressions = []; foreach ($this->conditionalExpressions as $conditionalExprString => $holders) { if (count($holders) === 0) { continue; } $firstExpr = $holders[array_key_first($holders)]->getTypeHolder()->getExpr(); if ($this->shouldInvalidateExpression($exprStringToInvalidate, $expressionToInvalidate, $firstExpr, $this->getNodeKey($firstExpr), $requireMoreCharacters, $invalidatingClass)) { $invalidated = \true; continue; } $filteredHolders = []; foreach ($holders as $key => $holder) { $shouldKeep = \true; $conditionalTypeHolders = $holder->getConditionExpressionTypeHolders(); foreach ($conditionalTypeHolders as $conditionalTypeHolderExprString => $conditionalTypeHolder) { if ($this->shouldInvalidateExpression($exprStringToInvalidate, $expressionToInvalidate, $conditionalTypeHolder->getExpr(), $conditionalTypeHolderExprString, \false, $invalidatingClass)) { $invalidated = \true; $shouldKeep = \false; break; } } if (!$shouldKeep) { continue; } $filteredHolders[$key] = $holder; } if (count($filteredHolders) <= 0) { continue; } $newConditionalExpressions[$conditionalExprString] = $filteredHolders; } 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 getIntertwinedRefRootVariableName(Expr $expr): ?string { if ($expr instanceof Variable && is_string($expr->name)) { return $expr->name; } if ($expr instanceof Expr\ArrayDimFetch) { return $this->getIntertwinedRefRootVariableName($expr->var); } return null; } private function shouldInvalidateExpression(string $exprStringToInvalidate, Expr $exprToInvalidate, Expr $expr, string $exprString, bool $requireMoreCharacters = \false, ?ClassReflection $invalidatingClass = null): bool { if ($expr instanceof IntertwinedVariableByReferenceWithExpr && $exprToInvalidate instanceof Variable && is_string($exprToInvalidate->name) && ($expr->getVariableName() === $exprToInvalidate->name || $this->getIntertwinedRefRootVariableName($expr->getExpr()) === $exprToInvalidate->name || $this->getIntertwinedRefRootVariableName($expr->getAssignedExpr()) === $exprToInvalidate->name)) { return \false; } if ($requireMoreCharacters && $exprStringToInvalidate === $exprString) { return \false; } // Variables will not contain traversable expressions. skip the NodeFinder overhead if ($expr instanceof Variable && is_string($expr->name) && !$requireMoreCharacters) { return $exprStringToInvalidate === $exprString; } $nodeFinder = new NodeFinder(); $expressionToInvalidateClass = get_class($exprToInvalidate); $found = $nodeFinder->findFirst([$expr], function (Node $node) use ($expressionToInvalidateClass, $exprStringToInvalidate): bool { if ($exprStringToInvalidate === '$this' && $node instanceof Name && (in_array($node->toLowerString(), ['self', 'static', 'parent'], \true) || $this->getClassReflection() !== null && $this->getClassReflection()->is($this->resolveName($node)))) { return \true; } if (!$node instanceof $expressionToInvalidateClass) { return \false; } $nodeString = $this->getNodeKey($node); return $nodeString === $exprStringToInvalidate; }); if ($found === null) { return \false; } if ($expr instanceof PropertyFetch && $requireMoreCharacters && $this->isReadonlyPropertyFetch($expr, \false)) { return \false; } if ($invalidatingClass !== null && $requireMoreCharacters && $this->isPrivatePropertyOfDifferentClass($expr, $invalidatingClass)) { return \false; } return \true; } private function isPrivatePropertyOfDifferentClass(Expr $expr, ClassReflection $invalidatingClass): bool { if ($expr instanceof Expr\StaticPropertyFetch || $expr instanceof PropertyFetch) { $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($expr, $this); if ($propertyReflection === null) { return \false; } if (!$propertyReflection->isPrivate()) { return \false; } return $propertyReflection->getDeclaringClass()->getName() !== $invalidatingClass->getName(); } return \false; } private function invalidateMethodsOnExpression(Expr $expressionToInvalidate): self { $exprStringToInvalidate = null; $expressionTypes = $this->expressionTypes; $nativeExpressionTypes = $this->nativeExpressionTypes; $invalidated = \false; foreach ($expressionTypes as $exprString => $exprTypeHolder) { $expr = $exprTypeHolder->getExpr(); if (!$expr instanceof MethodCall) { continue; } $exprStringToInvalidate ??= $this->getNodeKey($expressionToInvalidate); if ($this->getNodeKey($expr->var) !== $exprStringToInvalidate) { 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); } /** * Returns true when the type is a large union with intersection * members that carry HasOffsetValueType — a sign of combinatorial * growth from successive array|object offset access patterns. * Operating on such types is expensive and should be skipped. */ private function isComplexUnionType(Type $type): bool { if (!$type instanceof UnionType) { return \false; } $types = $type->getTypes(); if (count($types) <= self::COMPLEX_UNION_TYPE_MEMBER_LIMIT) { return \false; } foreach ($types as $member) { if (!$member instanceof IntersectionType) { continue; } foreach ($member->getTypes() as $innerType) { if ($innerType instanceof HasOffsetValueType) { return \true; } } } return \false; } public function addTypeToExpression(Expr $expr, Type $type): self { $originalExprType = $this->getType($expr); if ($this->isComplexUnionType($originalExprType)) { return $this; } $nativeType = $this->getNativeType($expr); if ($originalExprType->equals($nativeType)) { $newType = TypeCombinator::intersect($type, $originalExprType); return $this->specifyExpressionType($expr, $newType, $newType, TrinaryLogic::createYes()); } return $this->specifyExpressionType($expr, TypeCombinator::intersect($type, $originalExprType), TypeCombinator::intersect($type, $nativeType), TrinaryLogic::createYes()); } public function removeTypeFromExpression(Expr $expr, Type $typeToRemove): self { if ($typeToRemove instanceof NeverType) { return $this; } $exprType = $this->getType($expr); if ($exprType instanceof NeverType) { return $this; } if ($this->isComplexUnionType($exprType)) { return $this; } return $this->specifyExpressionType($expr, TypeCombinator::remove($exprType, $typeToRemove), TypeCombinator::remove($this->getNativeType($expr), $typeToRemove), TrinaryLogic::createYes()); } /** * @api */ public function filterByTruthyValue(Expr $expr): self { $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 */ public function filterByFalseyValue(Expr $expr): self { $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[$typeSpecification['exprString']] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($expr, $scope->getScopeType($expr)); } $conditions = []; $prevSpecifiedCount = -1; while (count($specifiedExpressions) !== $prevSpecifiedCount) { $prevSpecifiedCount = count($specifiedExpressions); foreach ($scope->conditionalExpressions as $conditionalExprString => $conditionalExpressions) { if (array_key_exists($conditionalExprString, $conditions)) { continue; } // Pass 1: Prefer exact matches foreach ($conditionalExpressions as $conditionalExpression) { foreach ($conditionalExpression->getConditionExpressionTypeHolders() as $holderExprString => $conditionalTypeHolder) { if (!array_key_exists($holderExprString, $specifiedExpressions) || !$conditionalTypeHolder->equals($specifiedExpressions[$holderExprString])) { continue 2; } } $conditions[$conditionalExprString][] = $conditionalExpression; $specifiedExpressions[$conditionalExprString] = $conditionalExpression->getTypeHolder(); } if (array_key_exists($conditionalExprString, $conditions)) { continue; } // Pass 2: Supertype match. Only runs when Pass 1 found no exact match for this expression. foreach ($conditionalExpressions as $conditionalExpression) { if ($conditionalExpression->getTypeHolder()->getCertainty()->no()) { continue; } foreach ($conditionalExpression->getConditionExpressionTypeHolders() as $holderExprString => $conditionalTypeHolder) { if (!array_key_exists($holderExprString, $specifiedExpressions) || !$conditionalTypeHolder->getCertainty()->equals($specifiedExpressions[$holderExprString]->getCertainty()) || !$conditionalTypeHolder->getType()->isSuperTypeOf($specifiedExpressions[$holderExprString]->getType())->yes()) { continue 2; } } $conditions[$conditionalExprString][] = $conditionalExpression; $specifiedExpressions[$conditionalExprString] = $conditionalExpression->getTypeHolder(); } } } foreach ($conditions as $conditionalExprString => $expressions) { $certainty = TrinaryLogic::lazyExtremeIdentity($expressions, static fn(\PHPStan\Analyser\ConditionalExpressionHolder $holder) => $holder->getTypeHolder()->getCertainty()); if ($certainty->no()) { unset($scope->expressionTypes[$conditionalExprString]); } else if (array_key_exists($conditionalExprString, $scope->expressionTypes)) { $type = $expressions[0]->getTypeHolder()->getType(); for ($i = 1, $count = count($expressions); $i < $count; $i++) { $type = TypeCombinator::intersect($type, $expressions[$i]->getTypeHolder()->getType()); } $scope->expressionTypes[$conditionalExprString] = new \PHPStan\Analyser\ExpressionTypeHolder($scope->expressionTypes[$conditionalExprString]->getExpr(), TypeCombinator::intersect($scope->expressionTypes[$conditionalExprString]->getType(), $type), TrinaryLogic::maxMin($scope->expressionTypes[$conditionalExprString]->getCertainty(), $certainty)); } else { $scope->expressionTypes[$conditionalExprString] = $expressions[0]->getTypeHolder(); } } return $scope->scopeFactory->create($scope->context, $scope->isDeclareStrictTypes(), $scope->getFunction(), $scope->getNamespace(), $scope->expressionTypes, $scope->nativeExpressionTypes, $this->mergeConditionalExpressions($specifiedTypes->getNewConditionalExpressionHolders(), $scope->conditionalExpressions), $scope->inClosureBindScopeClasses, $scope->anonymousFunctionReflection, $scope->inFirstLevelStatement, $scope->currentlyAssignedExpressions, $scope->currentlyAllowedUndefinedExpressions, $scope->inFunctionCallsStack, $scope->afterExtractCall, $scope->parentScope, $scope->nativeTypesPromoted); } /** * @return array */ public function getConditionalExpressions(): array { return $this->conditionalExpressions; } /** * @param ConditionalExpressionHolder[] $conditionalExpressionHolders */ public function addConditionalExpressions(string $exprString, array $conditionalExpressionHolders): self { $conditionalExpressions = $this->conditionalExpressions; // Merge rather than overwrite: multiple independent holders can target the same // expression (e.g. `$xIsA = $x instanceof A && $y instanceof A` stores a holder // for `$x` keyed on `$xIsA`; later `$yIsA = $y instanceof A && $x instanceof A` // stores another holder for the same target `$x` keyed on `$yIsA`). Replacing // the existing entry here would throw away the earlier binding, breaking // narrowing inside later `if ($xIsA) { … }` inside `if ($xIsA || $yIsA)`. // Holder keys (`getKey()`) disambiguate identical entries so we still dedupe. $existing = $conditionalExpressions[$exprString] ?? []; foreach ($conditionalExpressionHolders as $holder) { $existing[$holder->getKey()] = $holder; } $conditionalExpressions[$exprString] = $existing; 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, bool $preserveVacuousConditionals = \false): self { if ($otherScope === null || $this === $otherScope) { return $this; } $ourExpressionTypes = $this->expressionTypes; $theirExpressionTypes = $otherScope->expressionTypes; $mergedExpressionTypes = $this->mergeVariableHolders($ourExpressionTypes, $theirExpressionTypes); $conditionalExpressions = $this->intersectConditionalExpressions($otherScope->conditionalExpressions); if ($preserveVacuousConditionals) { $conditionalExpressions = $this->preserveVacuousConditionalExpressions($conditionalExpressions, $this->conditionalExpressions, $theirExpressionTypes); $conditionalExpressions = $this->preserveVacuousConditionalExpressions($conditionalExpressions, $otherScope->conditionalExpressions, $ourExpressionTypes); } $conditionalExpressions = $this->createConditionalExpressions($conditionalExpressions, $ourExpressionTypes, $theirExpressionTypes, $mergedExpressionTypes); $conditionalExpressions = $this->createConditionalExpressions($conditionalExpressions, $theirExpressionTypes, $ourExpressionTypes, $mergedExpressionTypes); $filter = static function (\PHPStan\Analyser\ExpressionTypeHolder $expressionTypeHolder) { if ($expressionTypeHolder->getCertainty()->yes()) { return \true; } $expr = $expressionTypeHolder->getExpr(); return $expr instanceof Variable || $expr instanceof FuncCall || $expr instanceof VirtualNode; }; $mergedExpressionTypes = array_filter($mergedExpressionTypes, $filter); $ourNativeExpressionTypes = $this->nativeExpressionTypes; $theirNativeExpressionTypes = $otherScope->nativeExpressionTypes; $mergedNativeExpressionTypes = []; foreach ($ourNativeExpressionTypes as $exprString => $expressionTypeHolder) { if (!array_key_exists($exprString, $theirNativeExpressionTypes)) { continue; } if (!array_key_exists($exprString, $ourExpressionTypes)) { continue; } if (!array_key_exists($exprString, $theirExpressionTypes)) { continue; } if (!$expressionTypeHolder->equals($ourExpressionTypes[$exprString])) { continue; } if (!$theirNativeExpressionTypes[$exprString]->equals($theirExpressionTypes[$exprString])) { continue; } if (!array_key_exists($exprString, $mergedExpressionTypes)) { continue; } $mergedNativeExpressionTypes[$exprString] = $mergedExpressionTypes[$exprString]; unset($ourNativeExpressionTypes[$exprString]); unset($theirNativeExpressionTypes[$exprString]); } return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $mergedExpressionTypes, array_merge($mergedNativeExpressionTypes, array_filter($this->mergeVariableHolders($ourNativeExpressionTypes, $theirNativeExpressionTypes), $filter)), $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]; $intersectedHolders = []; foreach ($holders as $key => $holder) { if (!array_key_exists($key, $otherHolders)) { continue; } $intersectedHolders[$key] = $holder; } if (count($intersectedHolders) === 0) { continue; } $newConditionalExpressions[$exprString] = $intersectedHolders; } return $newConditionalExpressions; } /** * @param array $currentConditionalExpressions * @param array $sourceConditionalExpressions * @param array $otherExpressionTypes * @return array */ private function preserveVacuousConditionalExpressions(array $currentConditionalExpressions, array $sourceConditionalExpressions, array $otherExpressionTypes): array { foreach ($sourceConditionalExpressions as $exprString => $holders) { foreach ($holders as $key => $holder) { if (isset($currentConditionalExpressions[$exprString][$key])) { continue; } $typeHolder = $holder->getTypeHolder(); if ($typeHolder->getCertainty()->no() && !$typeHolder->getExpr() instanceof Variable) { continue; } foreach ($holder->getConditionExpressionTypeHolders() as $guardExprString => $guardTypeHolder) { if (!array_key_exists($guardExprString, $otherExpressionTypes)) { continue; } $otherType = $otherExpressionTypes[$guardExprString]->getType(); $guardType = $guardTypeHolder->getType(); if ($otherType->isSuperTypeOf($guardType)->no()) { $currentConditionalExpressions[$exprString][$key] = $holder; break; } } } } return $currentConditionalExpressions; } /** * @param array $newConditionalExpressions * @param array $existingConditionalExpressions * @return array */ private function mergeConditionalExpressions(array $newConditionalExpressions, array $existingConditionalExpressions): array { $result = $existingConditionalExpressions; foreach ($newConditionalExpressions as $exprString => $holders) { if (!array_key_exists($exprString, $result)) { $result[$exprString] = $holders; } else { $result[$exprString] = array_merge($result[$exprString], $holders); } } return $result; } /** * @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]->equalTypes($holder)) { continue; } if (array_key_exists($exprString, $newVariableTypes) && !$newVariableTypes[$exprString]->getCertainty()->equals($holder->getCertainty()) && $newVariableTypes[$exprString]->equalTypes($holder)) { continue; } unset($newVariableTypes[$exprString]); } $typeGuards = []; foreach ($newVariableTypes as $exprString => $holder) { if ($holder->getExpr() instanceof VirtualNode) { continue; } if (!array_key_exists($exprString, $mergedExpressionTypes)) { continue; } if (!$holder->getCertainty()->yes()) { continue; } if (array_key_exists($exprString, $theirExpressionTypes) && !$theirExpressionTypes[$exprString]->getCertainty()->yes()) { continue; } if ($mergedExpressionTypes[$exprString]->equalTypes($holder)) { continue; } $typeGuards[$exprString] = $holder; } if (count($typeGuards) === 0) { return $conditionalExpressions; } foreach ($newVariableTypes as $exprString => $holder) { if ($holder->getExpr() instanceof VirtualNode) { continue; } if (array_key_exists($exprString, $mergedExpressionTypes) && $mergedExpressionTypes[$exprString]->equals($holder)) { continue; } $variableTypeGuards = $typeGuards; unset($variableTypeGuards[$exprString]); if (count($variableTypeGuards) === 0) { continue; } foreach ($variableTypeGuards as $guardExprString => $guardHolder) { if (array_key_exists($guardExprString, $theirExpressionTypes) && $theirExpressionTypes[$guardExprString]->getCertainty()->yes() && (array_key_exists($exprString, $theirExpressionTypes) && $theirExpressionTypes[$exprString]->getCertainty()->yes() && !$guardHolder->getType()->isSuperTypeOf($theirExpressionTypes[$guardExprString]->getType())->no() || $guardHolder->getType()->isSuperTypeOf($theirExpressionTypes[$guardExprString]->getType())->yes())) { continue; } $conditionalExpression = new \PHPStan\Analyser\ConditionalExpressionHolder([$guardExprString => $guardHolder], $holder); $conditionalExpressions[$exprString][$conditionalExpression->getKey()] = $conditionalExpression; } } foreach ($mergedExpressionTypes as $exprString => $mergedExprTypeHolder) { if (array_key_exists($exprString, $ourExpressionTypes)) { continue; } foreach ($typeGuards as $guardExprString => $guardHolder) { $conditionalExpression = new \PHPStan\Analyser\ConditionalExpressionHolder([$guardExprString => $guardHolder], 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 = []; $globalVariableCallback = fn(Node $node) => $node instanceof Variable && is_string($node->name) && $this->isGlobalVariable($node->name); $nodeFinder = new NodeFinder(); foreach ($ourVariableTypeHolders as $exprString => $variableTypeHolder) { if (isset($theirVariableTypeHolders[$exprString])) { if ($variableTypeHolder === $theirVariableTypeHolders[$exprString]) { $intersectedVariableTypeHolders[$exprString] = $variableTypeHolder; continue; } $intersectedVariableTypeHolders[$exprString] = $variableTypeHolder->and($theirVariableTypeHolders[$exprString]); } else { $expr = $variableTypeHolder->getExpr(); $containsSuperGlobal = $expr->getAttribute(self::CONTAINS_SUPER_GLOBAL_ATTRIBUTE_NAME); if ($containsSuperGlobal === null) { $containsSuperGlobal = $nodeFinder->findFirst($expr, $globalVariableCallback) !== null; $expr->setAttribute(self::CONTAINS_SUPER_GLOBAL_ATTRIBUTE_NAME, $containsSuperGlobal); } if ($containsSuperGlobal === \true) { continue; } $intersectedVariableTypeHolders[$exprString] = \PHPStan\Analyser\ExpressionTypeHolder::createMaybe($expr, $variableTypeHolder->getType()); } } foreach ($theirVariableTypeHolders as $exprString => $variableTypeHolder) { if (isset($intersectedVariableTypeHolders[$exprString])) { continue; } $expr = $variableTypeHolder->getExpr(); $containsSuperGlobal = $expr->getAttribute(self::CONTAINS_SUPER_GLOBAL_ATTRIBUTE_NAME); if ($containsSuperGlobal === null) { $containsSuperGlobal = $nodeFinder->findFirst($expr, $globalVariableCallback) !== null; $expr->setAttribute(self::CONTAINS_SUPER_GLOBAL_ATTRIBUTE_NAME, $containsSuperGlobal); } if ($containsSuperGlobal === \true) { continue; } $intersectedVariableTypeHolders[$exprString] = \PHPStan\Analyser\ExpressionTypeHolder::createMaybe($expr, $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->intersectConditionalExpressions($finallyScope->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]->equalTypes($variableTypeHolder)) { $ourVariableTypeHolders[$exprString] = $variableTypeHolder; continue; } if (isset($originalVariableTypeHolders[$exprString])) { continue; } $ourVariableTypeHolders[$exprString] = $variableTypeHolder; } return $ourVariableTypeHolders; } /** * @param Node\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 = $this->generalizeType($variableType, $prevVariableType, 0); } } $holder = \PHPStan\Analyser\ExpressionTypeHolder::createYes($use->var, $variableType); $expressionTypes[$variableExprString] = $holder; $nativeExpressionTypes[$variableExprString] = $holder; } 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->intersectConditionalExpressions($finalScope->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 { uksort($variableTypeHolders, static fn(string $exprA, string $exprB): int => strlen($exprA) <=> strlen($exprB)); $generalizedExpressions = []; $newVariableTypeHolders = []; foreach ($variableTypeHolders as $variableExprString => $variableTypeHolder) { foreach ($generalizedExpressions as $generalizedExprString => $generalizedExpr) { if (!$this->shouldInvalidateExpression($generalizedExprString, $generalizedExpr, $variableTypeHolder->getExpr(), $variableExprString)) { continue; } continue 2; } if (!isset($otherVariableTypeHolders[$variableExprString])) { $newVariableTypeHolders[$variableExprString] = $variableTypeHolder; continue; } $generalizedType = $this->generalizeType($variableTypeHolder->getType(), $otherVariableTypeHolders[$variableExprString]->getType(), 0); if (!$generalizedType->equals($variableTypeHolder->getType())) { $generalizedExpressions[$variableExprString] = $variableTypeHolder->getExpr(); } $newVariableTypeHolders[$variableExprString] = new \PHPStan\Analyser\ExpressionTypeHolder($variableTypeHolder->getExpr(), $generalizedType, $variableTypeHolder->getCertainty()); } return $newVariableTypeHolders; } private 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($this->phpVersion)->isSuperTypeOf($constantArraysB->getArraySize())->yes()) { $resultArrayBuilder = ConstantArrayTypeBuilder::createEmpty(); foreach (TypeUtils::flattenTypes($constantArraysA->getIterableKeyType()) as $keyType) { $resultArrayBuilder->setOffsetValueType($keyType, $this->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($this->generalizeType($constantArraysA->getIterableKeyType(), $constantArraysB->getIterableKeyType(), $depth + 1)), TypeCombinator::union($this->generalizeType($constantArraysA->getIterableValueType(), $constantArraysB->getIterableValueType(), $depth + 1))); $accessories = []; if ($constantArraysA->isIterableAtLeastOnce()->yes() && $constantArraysB->isIterableAtLeastOnce()->yes() && $constantArraysA->getArraySize()->getGreaterOrEqualType($this->phpVersion)->isSuperTypeOf($constantArraysB->getArraySize())->yes()) { $accessories[] = new NonEmptyArrayType(); } if ($constantArraysA->isList()->yes() && $constantArraysB->isList()->yes()) { $accessories[] = new AccessoryArrayListType(); } if (count($accessories) === 0) { $resultTypes[] = $resultType; } else { $resultTypes[] = TypeCombinator::intersect($resultType, ...$accessories); } } } } 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($this->generalizeType($generalArraysA->getIterableKeyType(), $generalArraysB->getIterableKeyType(), $depth + 1)), TypeCombinator::union($this->generalizeType($aValueType, $bValueType, $depth + 1))); $accessories = []; if ($generalArraysA->isIterableAtLeastOnce()->yes() && $generalArraysB->isIterableAtLeastOnce()->yes()) { $accessories[] = new NonEmptyArrayType(); } if ($generalArraysA->isList()->yes() && $generalArraysB->isList()->yes()) { $accessories[] = new AccessoryArrayListType(); } if ($generalArraysA->isOversizedArray()->yes() && $generalArraysB->isOversizedArray()->yes()) { $accessories[] = new OversizedArrayType(); } if (count($accessories) === 0) { $resultTypes[] = $resultType; } else { $resultTypes[] = TypeCombinator::intersect($resultType, ...$accessories); } } } 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(); } $newMin = $min; $newMax = $max; foreach ($constantIntegers['b'] as $int) { if ($int->getValue() > $newMax) { $newMax = $int->getValue(); } if ($int->getValue() >= $newMin) { continue; } $newMin = $int->getValue(); } if ($newMax > $max && $newMin < $min) { $resultTypes[] = IntegerRangeType::fromInterval($newMin, $newMax); } elseif ($newMax > $max) { $resultTypes[] = IntegerRangeType::fromInterval($min, null); } elseif ($newMin < $min) { $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; } $newMin = $min; $newMax = $max; 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 > $newMax) { $newMax = $rangeMax; } if ($rangeMin >= $newMin) { continue; } $newMin = $rangeMin; } $gotGreater = $newMax > $max; $gotSmaller = $newMin < $min; if ($min === PHP_INT_MIN) { $min = null; } if ($max === PHP_INT_MAX) { $max = null; } if ($newMin === PHP_INT_MIN) { $newMin = null; } if ($newMax === PHP_INT_MAX) { $newMax = null; } if ($gotGreater && $gotSmaller) { $resultTypes[] = IntegerRangeType::fromInterval($newMin, $newMax); } 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 fn(Type $type): Type => $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::toBenevolentUnion($type)->getArrays(); while (count($arrays) > 0) { $temp = $type->getIterableValueType(); $type = $temp; $arrays = TypeUtils::toBenevolentUnion($type)->getArrays(); $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->equalTypes($otherVariableTypeHolders[$variableExprString])) { return \false; } } return \true; } /** * @api * @deprecated Use canReadProperty() or canWriteProperty() */ public function canAccessProperty(PropertyReflection $propertyReflection): bool { return $this->canAccessClassMember($propertyReflection); } /** @api */ public function canReadProperty(ExtendedPropertyReflection $propertyReflection): bool { return $this->canAccessClassMember($propertyReflection); } /** @api */ public function canWriteProperty(ExtendedPropertyReflection $propertyReflection): bool { if (!$propertyReflection->isPrivateSet() && !$propertyReflection->isProtectedSet()) { return $this->canAccessClassMember($propertyReflection); } if (!$this->phpVersion->supportsAsymmetricVisibility()) { return $this->canAccessClassMember($propertyReflection); } $propertyDeclaringClass = $propertyReflection->getDeclaringClass(); $canAccessClassMember = static function (ClassReflection $classReflection) use ($propertyReflection, $propertyDeclaringClass) { if ($propertyReflection->isPrivateSet()) { return $classReflection->getName() === $propertyDeclaringClass->getName(); } // protected set if ($classReflection->getName() === $propertyDeclaringClass->getName() || $classReflection->isSubclassOfClass($propertyDeclaringClass->removeFinalKeywordOverride())) { return \true; } return $propertyReflection->getDeclaringClass()->isSubclassOfClass($classReflection); }; 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; } /** @api */ public function canCallMethod(MethodReflection $methodReflection): bool { if ($this->canAccessClassMember($methodReflection)) { return \true; } return $this->canAccessClassMember($methodReflection->getPrototype()); } /** @api */ public function canAccessConstant(ClassConstantReflection $constantReflection): bool { return $this->canAccessClassMember($constantReflection); } private function canAccessClassMember(ClassMemberReflection $classMemberReflection): bool { if ($classMemberReflection->isPublic()) { return \true; } $classMemberDeclaringClass = $classMemberReflection->getDeclaringClass(); $canAccessClassMember = static function (ClassReflection $classReflection) use ($classMemberReflection, $classMemberDeclaringClass) { if ($classMemberReflection->isPrivate()) { return $classReflection->getName() === $classMemberDeclaringClass->getName(); } // protected if ($classReflection->getName() === $classMemberDeclaringClass->getName() || $classReflection->isSubclassOfClass($classMemberDeclaringClass->removeFinalKeywordOverride())) { return \true; } return $classMemberReflection->getDeclaringClass()->isSubclassOfClass($classReflection); }; 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 (array_keys($this->currentlyAssignedExpressions) as $exprString) { $descriptions[sprintf('currently assigned %s', $exprString)] = 'true'; } foreach (array_keys($this->currentlyAllowedUndefinedExpressions) as $exprString) { $descriptions[sprintf('currently allowed undefined %s', $exprString)] = 'true'; } 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; } public function filterTypeWithMethod(Type $typeWithMethod, string $methodName): ?Type { if ($typeWithMethod instanceof UnionType) { $typeWithMethod = $typeWithMethod->filterTypes(static fn(Type $innerType) => $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); } public function getNakedMethod(Type $typeWithMethod, string $methodName): ?ExtendedMethodReflection { $type = $this->filterTypeWithMethod($typeWithMethod, $methodName); if ($type === null) { return null; } return $type->getUnresolvedMethodPrototype($methodName, $this)->getNakedMethod(); } /** * @api * @deprecated Use getInstancePropertyReflection or getStaticPropertyReflection instead */ public function getPropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection { if ($typeWithProperty instanceof UnionType) { $typeWithProperty = $typeWithProperty->filterTypes(static fn(Type $innerType) => $innerType->hasProperty($propertyName)->yes()); } if (!$typeWithProperty->hasProperty($propertyName)->yes()) { return null; } return $typeWithProperty->getProperty($propertyName, $this); } /** @api */ public function getInstancePropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection { if ($typeWithProperty instanceof UnionType) { $typeWithProperty = $typeWithProperty->filterTypes(static fn(Type $innerType) => $innerType->hasInstanceProperty($propertyName)->yes()); } if (!$typeWithProperty->hasInstanceProperty($propertyName)->yes()) { return null; } return $typeWithProperty->getInstanceProperty($propertyName, $this); } /** @api */ public function getStaticPropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection { if ($typeWithProperty instanceof UnionType) { $typeWithProperty = $typeWithProperty->filterTypes(static fn(Type $innerType) => $innerType->hasStaticProperty($propertyName)->yes()); } if (!$typeWithProperty->hasStaticProperty($propertyName)->yes()) { return null; } return $typeWithProperty->getStaticProperty($propertyName, $this); } public function getConstantReflection(Type $typeWithConstant, string $constantName): ?ClassConstantReflection { if ($typeWithConstant instanceof UnionType) { $typeWithConstant = $typeWithConstant->filterTypes(static fn(Type $innerType) => $innerType->hasConstant($constantName)->yes()); } if (!$typeWithConstant->hasConstant($constantName)->yes()) { return null; } return $typeWithConstant->getConstant($constantName); } public function getConstantExplicitTypeFromConfig(string $constantName, Type $constantType): Type { return $this->constantResolver->resolveConstantType($constantName, $constantType); } /** * @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; } private function getGlobalConstantType(Name $name): ?Type { $fetches = []; if (!$name->isFullyQualified() && $this->getNamespace() !== null) { $fetches[] = new ConstFetch(new FullyQualified([$this->getNamespace(), $name->toString()])); } $fetches[] = new ConstFetch(new FullyQualified($name->toString())); $fetches[] = new ConstFetch($name); foreach ($fetches as $constFetch) { if ($this->hasExpressionType($constFetch)->yes()) { return $this->getType($constFetch); } } return null; } /** * @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 fn(Type $innerType) => $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 fn(Type $innerType) => $innerType->isIterable()->yes()); if (!$filtered instanceof NeverType) { $iteratee = $filtered; } } return $iteratee->getIterableValueType(); } public function getPhpVersion(): PhpVersions { $constType = $this->getGlobalConstantType(new Name('PHP_VERSION_ID')); $isOverallPhpVersionRange = \false; if ($constType instanceof IntegerRangeType && $constType->getMin() === \PHPStan\Analyser\ConstantResolver::PHP_MIN_ANALYZABLE_VERSION_ID && ($constType->getMax() === null || $constType->getMax() === PhpVersionFactory::MAX_PHP_VERSION)) { $isOverallPhpVersionRange = \true; } if ($constType !== null && !$isOverallPhpVersionRange) { return new PhpVersions($constType); } if (is_array($this->configPhpVersion)) { return new PhpVersions(IntegerRangeType::fromInterval($this->configPhpVersion['min'], $this->configPhpVersion['max'])); } return new PhpVersions(new ConstantIntegerType($this->phpVersion->getVersionId())); } public function invokeNodeCallback(Node $node): void { $nodeCallback = $this->nodeCallback; if ($nodeCallback === null) { throw new ShouldNotHappenException('Node callback is not present in this scope'); } $nodeCallback($node, $this); } } */ private array $uses; private ?string $className; private ?string $functionName; /** * @var array */ private array $templateTags; /** * @var array */ private array $typeAliasesMap; private bool $bypassTypeAliases; /** * @var array */ private array $constUses; private ?string $typeAliasClassName; private TemplateTypeMap $templateTypeMap; /** * @api * @param non-empty-string|null $namespace * @param array $uses alias(string) => fullName(string) * @param array $constUses alias(string) => fullName(string) * @param array $templateTags * @param array $typeAliasesMap */ public function __construct(?string $namespace, array $uses, ?string $className = null, ?string $functionName = null, ?TemplateTypeMap $templateTypeMap = null, array $templateTags = [], array $typeAliasesMap = [], bool $bypassTypeAliases = \false, array $constUses = [], ?string $typeAliasClassName = null) { $this->namespace = $namespace; $this->uses = $uses; $this->className = $className; $this->functionName = $functionName; $this->templateTags = $templateTags; $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; } /** * @return array */ public function getTemplateTags(): array { return $this->templateTags; } public function resolveTemplateTypeName(string $name): ?Type { return $this->templateTypeMap->getType($name); } /** * @param array $templateTags */ public function withTemplateTypeMap(TemplateTypeMap $map, array $templateTags): 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())), $templateTags, $this->typeAliasesMap, $this->bypassTypeAliases, $this->constUses); } public function withoutNamespaceAndUses(): self { return new self(null, [], $this->className, $this->functionName, $this->templateTypeMap, $this->templateTags, $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->templateTags, $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->templateTags, $this->typeAliasesMap, $this->bypassTypeAliases, $this->constUses); } public function bypassTypeAliases(): self { return new self($this->namespace, $this->uses, $this->className, $this->functionName, $this->templateTypeMap, $this->templateTags, $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); } } invokeNodeCallback(new New_(new Name($className), $args))` * * And PHPStan will call all the registered rules for New_, checking as if the instantiation * is actually in the code. * * @api */ interface NodeCallbackInvoker { public function invokeNodeCallback(Node $node): void; } */ private array $earlyTerminatingFunctionCalls; /** * @readonly */ private bool $implicitThrows; /** * @readonly */ private bool $treatPhpDocTypesAsCertain; /** * @readonly */ private ImplicitToStringCallHelper $implicitToStringCallHelper; private const LOOP_SCOPE_ITERATIONS = 3; private const GENERALIZE_AFTER_ITERATION = 1; private const FOREACH_UNROLL_LIMIT = 16; private const FOREACH_UNROLL_NESTED_LIMIT = 16; /** @var array filePath(string) => bool(true) */ private array $analysedFiles = []; /** @var array */ private array $earlyTerminatingMethodNames; /** @var array */ private array $calledMethodStack = []; /** @var array */ private array $calledMethodResults = []; /** * @param string[][] $earlyTerminatingMethodCalls className(string) => methods(string[]) * @param array $earlyTerminatingFunctionCalls */ public function __construct( Container $container, ReflectionProvider $reflectionProvider, InitializerExprTypeResolver $initializerExprTypeResolver, #[AutowiredParameter('@nodeScopeResolverReflector')] Reflector $reflector, ClassReflectionFactory $classReflectionFactory, ParameterOutTypeExtensionProvider $parameterOutTypeExtensionProvider, #[AutowiredParameter('@defaultAnalysisParser')] Parser $parser, FileTypeMapper $fileTypeMapper, PhpDocInheritanceResolver $phpDocInheritanceResolver, FileHelper $fileHelper, \PHPStan\Analyser\TypeSpecifier $typeSpecifier, ReadWritePropertiesExtensionProvider $readWritePropertiesExtensionProvider, ParameterClosureThisExtensionProvider $parameterClosureThisExtensionProvider, ParameterClosureTypeExtensionProvider $parameterClosureTypeExtensionProvider, \PHPStan\Analyser\ScopeFactory $scopeFactory, DeepNodeCloner $deepNodeCloner, #[AutowiredParameter] bool $polluteScopeWithLoopInitialAssignments, #[AutowiredParameter] bool $polluteScopeWithAlwaysIterableForeach, #[AutowiredParameter] bool $polluteScopeWithBlock, #[AutowiredParameter] array $earlyTerminatingMethodCalls, #[AutowiredParameter] array $earlyTerminatingFunctionCalls, #[AutowiredParameter('%exceptions.implicitThrows%')] bool $implicitThrows, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, ImplicitToStringCallHelper $implicitToStringCallHelper ) { $this->container = $container; $this->reflectionProvider = $reflectionProvider; $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->reflector = $reflector; $this->classReflectionFactory = $classReflectionFactory; $this->parameterOutTypeExtensionProvider = $parameterOutTypeExtensionProvider; $this->parser = $parser; $this->fileTypeMapper = $fileTypeMapper; $this->phpDocInheritanceResolver = $phpDocInheritanceResolver; $this->fileHelper = $fileHelper; $this->typeSpecifier = $typeSpecifier; $this->readWritePropertiesExtensionProvider = $readWritePropertiesExtensionProvider; $this->parameterClosureThisExtensionProvider = $parameterClosureThisExtensionProvider; $this->parameterClosureTypeExtensionProvider = $parameterClosureTypeExtensionProvider; $this->scopeFactory = $scopeFactory; $this->deepNodeCloner = $deepNodeCloner; $this->polluteScopeWithLoopInitialAssignments = $polluteScopeWithLoopInitialAssignments; $this->polluteScopeWithAlwaysIterableForeach = $polluteScopeWithAlwaysIterableForeach; $this->polluteScopeWithBlock = $polluteScopeWithBlock; $this->earlyTerminatingMethodCalls = $earlyTerminatingMethodCalls; $this->earlyTerminatingFunctionCalls = $earlyTerminatingFunctionCalls; $this->implicitThrows = $implicitThrows; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->implicitToStringCallHelper = $implicitToStringCallHelper; $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 { $expressionResultStorage = new \PHPStan\Analyser\ExpressionResultStorage(); $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, $expressionResultStorage, $nodeCallback, \PHPStan\Analyser\StatementContext::createTopLevel()); $scope = $statementResult->getScope(); if ($alreadyTerminated || !$statementResult->isAlwaysTerminating()) { continue; } $alreadyTerminated = \true; $nextStmts = $this->getNextUnreachableStatements(array_slice($nodes, $i + 1), \true); $this->processUnreachableStatement($nextStmts, $scope, $expressionResultStorage, $nodeCallback); } $this->processPendingFibers($expressionResultStorage); } public function storeBeforeScope(\PHPStan\Analyser\ExpressionResultStorage $storage, Expr $expr, \PHPStan\Analyser\Scope $beforeScope): void { } protected function processPendingFibers(\PHPStan\Analyser\ExpressionResultStorage $storage): void { } /** * @param Node\Stmt[] $nextStmts * @param callable(Node $node, Scope $scope): void $nodeCallback */ private function processUnreachableStatement(array $nextStmts, \PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\ExpressionResultStorage $storage, callable $nodeCallback): void { if ($nextStmts === []) { return; } $unreachableStatement = null; $nextStatements = []; foreach ($nextStmts as $key => $nextStmt) { if ($key === 0) { $unreachableStatement = $nextStmt; continue; } $nextStatements[] = $nextStmt; } if (!$unreachableStatement instanceof Node\Stmt) { return; } $this->callNodeCallback($nodeCallback, new UnreachableStatementNode($unreachableStatement, $nextStatements), $scope, $storage); } /** * @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): \PHPStan\Analyser\StatementResult { $storage = new \PHPStan\Analyser\ExpressionResultStorage(); return $this->processStmtNodesInternal($parentNode, $stmts, $scope, $storage, $nodeCallback, $context)->toPublic(); } /** * @param Node\Stmt[] $stmts * @param callable(Node $node, Scope $scope): void $nodeCallback */ private function processStmtNodesInternal(Node $parentNode, array $stmts, \PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\ExpressionResultStorage $storage, callable $nodeCallback, \PHPStan\Analyser\StatementContext $context): \PHPStan\Analyser\InternalStatementResult { $statementResult = $this->processStmtNodesInternalWithoutFlushingPendingFibers($parentNode, $stmts, $scope, $storage, $nodeCallback, $context); $this->processPendingFibers($storage); return $statementResult; } /** * @param Node\Stmt[] $stmts * @param callable(Node $node, Scope $scope): void $nodeCallback */ private function processStmtNodesInternalWithoutFlushingPendingFibers(Node $parentNode, array $stmts, \PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\ExpressionResultStorage $storage, callable $nodeCallback, \PHPStan\Analyser\StatementContext $context): \PHPStan\Analyser\InternalStatementResult { $exitPoints = []; $throwPoints = []; $impurePoints = []; $alreadyTerminated = \false; $hasYield = \false; $stmtCount = count($stmts); $shouldCheckLastStatement = $parentNode instanceof Node\Stmt\Function_ || $parentNode instanceof Node\Stmt\ClassMethod || $parentNode instanceof PropertyHookStatementNode || $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, $storage, $nodeCallback, $context); $scope = $statementResult->getScope(); $hasYield = $hasYield || $statementResult->hasYield(); if ($shouldCheckLastStatement && $isLast) { $endStatements = $statementResult->getEndStatements(); if (count($endStatements) > 0) { foreach ($endStatements as $endStatement) { $endStatementResult = $endStatement->getResult(); $this->callNodeCallback($nodeCallback, new ExecutionEndNode($endStatement->getStatement(), (new \PHPStan\Analyser\InternalStatementResult($endStatementResult->getScope(), $hasYield, $endStatementResult->isAlwaysTerminating(), $endStatementResult->getExitPoints(), $endStatementResult->getThrowPoints(), $endStatementResult->getImpurePoints()))->toPublic(), $parentNode->getReturnType() !== null), $endStatementResult->getScope(), $storage); } } else { $this->callNodeCallback($nodeCallback, new ExecutionEndNode($stmt, (new \PHPStan\Analyser\InternalStatementResult($scope, $hasYield, $statementResult->isAlwaysTerminating(), $statementResult->getExitPoints(), $statementResult->getThrowPoints(), $statementResult->getImpurePoints()))->toPublic(), $parentNode->getReturnType() !== null), $scope, $storage); } } $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; $nextStmts = $this->getNextUnreachableStatements(array_slice($stmts, $i + 1), $parentNode instanceof Node\Stmt\Namespace_); $this->processUnreachableStatement($nextStmts, $scope, $storage, $nodeCallback); } $statementResult = new \PHPStan\Analyser\InternalStatementResult($scope, $hasYield, $alreadyTerminated, $exitPoints, $throwPoints, $impurePoints); if ($stmtCount === 0 && $shouldCheckLastStatement) { $returnTypeNode = $parentNode->getReturnType(); if ($parentNode instanceof Expr\Closure) { $parentNode = new Node\Stmt\Expression($parentNode, $parentNode->getAttributes()); } $this->callNodeCallback($nodeCallback, new ExecutionEndNode($parentNode, $statementResult->toPublic(), $returnTypeNode !== null), $scope, $storage); } return $statementResult; } /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ public function processStmtNode(Node\Stmt $stmt, \PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\ExpressionResultStorage $storage, callable $nodeCallback, \PHPStan\Analyser\StatementContext $context): \PHPStan\Analyser\InternalStatementResult { $overridingThrowPoints = null; if (!$stmt instanceof Static_ && !$stmt instanceof Node\Stmt\Global_ && !$stmt instanceof Node\Stmt\Property && !$stmt instanceof Node\Stmt\ClassConst && !$stmt instanceof Node\Stmt\Const_ && !$stmt instanceof Node\Stmt\ClassLike && !$stmt instanceof Node\Stmt\Function_ && !$stmt instanceof Node\Stmt\ClassMethod) { if (!$stmt instanceof Foreach_) { $scope = $this->processStmtVarAnnotation($scope, $storage, $stmt, null, $nodeCallback); } $overridingThrowPoints = $this->getOverridingThrowPoints($stmt, $scope); } 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\InternalStatementResult($scope, \false, \false, [], [], []); } if ($methodReflection instanceof PhpMethodReflection) { $declaringTrait = $methodReflection->getDeclaringTrait(); if ($declaringTrait === null || $declaringTrait->getName() !== $scope->getTraitReflection()->getName()) { return new \PHPStan\Analyser\InternalStatementResult($scope, \false, \false, [], [], []); } } } } $stmtScope = $scope; if ($stmt instanceof Node\Stmt\Expression && $stmt->expr instanceof Expr\Throw_) { $stmtScope = $this->processStmtVarAnnotation($scope, $storage, $stmt, $stmt->expr->expr, $nodeCallback); } if ($stmt instanceof Return_) { $stmtScope = $this->processStmtVarAnnotation($scope, $storage, $stmt, $stmt->expr, $nodeCallback); } $this->callNodeCallback($nodeCallback, $stmt, $stmtScope, $storage); if ($stmt instanceof Node\Stmt\Declare_) { $hasYield = \false; $throwPoints = []; $impurePoints = []; $alwaysTerminating = \false; $exitPoints = []; foreach ($stmt->declares as $declare) { $this->callNodeCallback($nodeCallback, $declare, $scope, $storage); $this->callNodeCallback($nodeCallback, $declare->value, $scope, $storage); if ($declare->key->name !== 'strict_types' || !$declare->value instanceof Node\Scalar\Int_ || $declare->value->value !== 1) { continue; } $scope = $scope->enterDeclareStrictTypes(); } if ($stmt->stmts !== null) { $result = $this->processStmtNodesInternal($stmt, $stmt->stmts, $scope, $storage, $nodeCallback, $context); $scope = $result->getScope(); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $alwaysTerminating = $result->isAlwaysTerminating(); $exitPoints = $result->getExitPoints(); } return new \PHPStan\Analyser\InternalStatementResult($scope, $hasYield, $alwaysTerminating, $exitPoints, $throwPoints, $impurePoints); } elseif ($stmt instanceof Node\Stmt\Function_) { $hasYield = \false; $throwPoints = []; $impurePoints = []; $this->processAttributeGroups($stmt, $stmt->attrGroups, $scope, $storage, $nodeCallback); [$templateTypeMap, $phpDocParameterTypes, $phpDocImmediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters, $phpDocReturnType, $phpDocThrowType, $deprecatedDescription, $isDeprecated, $isInternal, , $isPure, $acceptsNamedArguments, , $phpDocComment, $asserts, , $phpDocParameterOutTypes] = $this->getPhpDocs($scope, $stmt); foreach ($stmt->params as $param) { $this->processParamNode($stmt, $param, $scope, $storage, $nodeCallback); } if ($stmt->returnType !== null) { $this->callNodeCallback($nodeCallback, $stmt->returnType, $scope, $storage); } if (!$isDeprecated) { [$isDeprecated, $deprecatedDescription] = $this->getDeprecatedAttribute($scope, $stmt); } $functionScope = $scope->enterFunction($stmt, $templateTypeMap, $phpDocParameterTypes, $phpDocReturnType, $phpDocThrowType, $deprecatedDescription, $isDeprecated, $isInternal, $isPure, $acceptsNamedArguments, $asserts, $phpDocComment, $phpDocParameterOutTypes, $phpDocImmediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters); $functionReflection = $functionScope->getFunction(); if (!$functionReflection instanceof PhpFunctionFromParserNodeReflection) { throw new ShouldNotHappenException(); } $this->callNodeCallback($nodeCallback, new InFunctionNode($functionReflection, $stmt), $functionScope, $storage); $gatheredReturnStatements = []; $gatheredYieldStatements = []; $executionEnds = []; $functionImpurePoints = []; $statementResult = $this->processStmtNodesInternal($stmt, $stmt->stmts, $functionScope, $storage, 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())->toPublic(); $this->callNodeCallback($nodeCallback, new FunctionReturnStatementsNode($stmt, $gatheredReturnStatements, $gatheredYieldStatements, $statementResult, $executionEnds, array_merge($statementResult->getImpurePoints(), $functionImpurePoints), $functionReflection), $functionScope, $storage); if (!$scope->isInAnonymousFunction()) { $this->processPendingFibers($storage); } } elseif ($stmt instanceof Node\Stmt\ClassMethod) { $hasYield = \false; $throwPoints = []; $impurePoints = []; $this->processAttributeGroups($stmt, $stmt->attrGroups, $scope, $storage, $nodeCallback); [$templateTypeMap, $phpDocParameterTypes, $phpDocImmediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters, $phpDocReturnType, $phpDocThrowType, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal, $isPure, $acceptsNamedArguments, $isReadOnly, $phpDocComment, $asserts, $selfOutType, $phpDocParameterOutTypes] = $this->getPhpDocs($scope, $stmt); foreach ($stmt->params as $param) { $this->processParamNode($stmt, $param, $scope, $storage, $nodeCallback); } if ($stmt->returnType !== null) { $this->callNodeCallback($nodeCallback, $stmt->returnType, $scope, $storage); } if (!$isDeprecated) { [$isDeprecated, $deprecatedDescription] = $this->getDeprecatedAttribute($scope, $stmt); } $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(); } $classReflection = $scope->getClassReflection(); if ($isConstructor) { foreach ($stmt->params as $param) { if ($param->flags === 0 && $param->hooks === []) { continue; } if (!$param->var instanceof Variable || !is_string($param->var->name) || $param->var->name === '') { throw new ShouldNotHappenException(); } $phpDoc = null; if ($param->getDocComment() !== null) { $phpDoc = $param->getDocComment()->getText(); } $this->callNodeCallback($nodeCallback, new ClassPropertyNode($param->var->name, $param->flags, $param->type !== null ? ParserNodeTypeToPHPStanType::resolve($param->type, $classReflection) : null, null, $phpDoc, $phpDocParameterTypes[$param->var->name] ?? null, \true, $isFromTrait, $param, $isReadOnly, $scope->isInTrait(), $classReflection->isReadOnly(), \false, $classReflection), $methodScope, $storage); $this->processPropertyHooks($stmt, $param->type, $phpDocParameterTypes[$param->var->name] ?? null, $param->var->name, $param->hooks, $scope, $storage, $nodeCallback); $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(); } $this->callNodeCallback($nodeCallback, new InClassMethodNode($classReflection, $methodReflection, $stmt), $methodScope, $storage); } if ($stmt->stmts !== null) { $gatheredReturnStatements = []; $gatheredYieldStatements = []; $executionEnds = []; $methodImpurePoints = []; $statementResult = $this->processStmtNodesInternal($stmt, $stmt->stmts, $methodScope, $storage, 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())->toPublic(); $methodReflection = $methodScope->getFunction(); if (!$methodReflection instanceof PhpMethodFromParserNodeReflection) { throw new ShouldNotHappenException(); } $this->callNodeCallback($nodeCallback, new MethodReturnStatementsNode($stmt, $gatheredReturnStatements, $gatheredYieldStatements, $statementResult, $executionEnds, array_merge($statementResult->getImpurePoints(), $methodImpurePoints), $classReflection, $methodReflection), $methodScope, $storage); if ($isConstructor) { $finalScope = null; foreach ($executionEnds as $executionEnd) { if ($executionEnd->getStatementResult()->isAlwaysTerminating()) { continue; } $endScope = $executionEnd->getStatementResult()->getScope(); if ($finalScope === null) { $finalScope = $endScope; continue; } $finalScope = $finalScope->mergeWith($endScope); } foreach ($gatheredReturnStatements as $statement) { if ($finalScope === null) { $finalScope = $statement->getScope()->toMutatingScope(); continue; } $finalScope = $finalScope->mergeWith($statement->getScope()->toMutatingScope()); } if ($finalScope !== null) { $scope = $finalScope->rememberConstructorScope(); } } } if (!$scope->getClassReflection()->isAnonymous() && !$scope->isInAnonymousFunction()) { $this->processPendingFibers($storage); } } elseif ($stmt instanceof Echo_) { $hasYield = \false; $throwPoints = []; $impurePoints = []; $isAlwaysTerminating = \false; foreach ($stmt->exprs as $echoExpr) { $result = $this->processExprNode($stmt, $echoExpr, $scope, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $toStringResult = $this->implicitToStringCallHelper->processImplicitToStringCall($echoExpr, $scope); $throwPoints = array_merge($throwPoints, $toStringResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $toStringResult->getImpurePoints()); $scope = $result->getScope(); $hasYield = $hasYield || $result->hasYield(); $isAlwaysTerminating = $isAlwaysTerminating || $result->isAlwaysTerminating(); } $throwPoints = $overridingThrowPoints ?? $throwPoints; $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $stmt, 'echo', 'echo', \true); return new \PHPStan\Analyser\InternalStatementResult($scope, $hasYield, $isAlwaysTerminating, [], $throwPoints, $impurePoints); } elseif ($stmt instanceof Return_) { if ($stmt->expr !== null) { $result = $this->processExprNode($stmt, $stmt->expr, $stmtScope, $storage, $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\InternalStatementResult($scope, $hasYield, \true, [new \PHPStan\Analyser\InternalStatementExitPoint($stmt, $scope)], $overridingThrowPoints ?? $throwPoints, $impurePoints); } elseif ($stmt instanceof Continue_ || $stmt instanceof Break_) { if ($stmt->num !== null) { $result = $this->processExprNode($stmt, $stmt->num, $scope, $storage, $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\InternalStatementResult($scope, $hasYield, \true, [new \PHPStan\Analyser\InternalStatementExitPoint($stmt, $scope)], $overridingThrowPoints ?? $throwPoints, $impurePoints); } elseif ($stmt instanceof Node\Stmt\Expression) { if ($stmt->expr instanceof Expr\Throw_) { $scope = $stmtScope; } $earlyTerminationExpr = $this->findEarlyTerminatingExpr($stmt->expr, $scope); $hasAssign = \false; $currentScope = $scope; $result = $this->processExprNode($stmt, $stmt->expr, $scope, $storage, static function (Node $node, \PHPStan\Analyser\Scope $scope) use ($nodeCallback, $currentScope, &$hasAssign): void { if (($node instanceof VariableAssignNode || $node instanceof PropertyAssignNode) && $scope->getAnonymousFunctionReflection() === $currentScope->getAnonymousFunctionReflection() && $scope->getFunction() === $currentScope->getFunction()) { $hasAssign = \true; } $nodeCallback($node, $scope); }, \PHPStan\Analyser\ExpressionContext::createTopLevel()); $throwPoints = array_filter($result->getThrowPoints(), static fn($throwPoint) => $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) { $this->callNodeCallback($nodeCallback, new NoopExpressionNode($stmt->expr, $hasAssign), $scope, $storage); } $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(); $isAlwaysTerminating = $result->isAlwaysTerminating(); if ($earlyTerminationExpr !== null) { return new \PHPStan\Analyser\InternalStatementResult($scope, $hasYield, \true, [new \PHPStan\Analyser\InternalStatementExitPoint($stmt, $scope)], $overridingThrowPoints ?? $throwPoints, $impurePoints); } return new \PHPStan\Analyser\InternalStatementResult($scope, $hasYield, $isAlwaysTerminating, [], $overridingThrowPoints ?? $throwPoints, $impurePoints); } elseif ($stmt instanceof Node\Stmt\Namespace_) { if ($stmt->name !== null) { $scope = $scope->enterNamespace($stmt->name->toString()); } else { $scope = $scope->enterNamespace(''); } $scope = $this->processStmtNodesInternal($stmt, $stmt->stmts, $scope, $storage, $nodeCallback, $context)->getScope(); $hasYield = \false; $throwPoints = []; $impurePoints = []; } elseif ($stmt instanceof Node\Stmt\Trait_) { return new \PHPStan\Analyser\InternalStatementResult($scope, \false, \false, [], [], []); } elseif ($stmt instanceof Node\Stmt\ClassLike) { if (!$context->isTopLevel()) { return new \PHPStan\Analyser\InternalStatementResult($scope, \false, \false, [], [], []); } $hasYield = \false; $throwPoints = []; $impurePoints = []; if (isset($stmt->namespacedName)) { $classReflection = $this->getCurrentClassReflection($stmt, $stmt->namespacedName->toString(), $scope); $classScope = $scope->enterClass($classReflection); $this->callNodeCallback($nodeCallback, new InClassNode($stmt, $classReflection), $classScope, $storage); } 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); $this->callNodeCallback($nodeCallback, new InClassNode($stmt, $classReflection), $classScope, $storage); } else { throw new ShouldNotHappenException(); } $classStatementsGatherer = new ClassStatementsGatherer($classReflection, $nodeCallback); $this->processAttributeGroups($stmt, $stmt->attrGroups, $classScope, $storage, $classStatementsGatherer); $classLikeStatements = $stmt->stmts; // analyze static methods first; constructor next; instance methods and property hooks last so we can carry over the scope usort($classLikeStatements, static function ($a, $b) { if ($a instanceof Node\Stmt\Property) { return 1; } if ($b instanceof Node\Stmt\Property) { return -1; } if (!$a instanceof Node\Stmt\ClassMethod || !$b instanceof Node\Stmt\ClassMethod) { return 0; } return [!$a->isStatic(), $a->name->toLowerString() !== '__construct'] <=> [!$b->isStatic(), $b->name->toLowerString() !== '__construct']; }); $this->processStmtNodesInternal($stmt, $classLikeStatements, $classScope, $storage, $classStatementsGatherer, $context); $this->callNodeCallback($nodeCallback, new ClassPropertiesNode($stmt, $this->readWritePropertiesExtensionProvider, $classStatementsGatherer->getProperties(), $classStatementsGatherer->getPropertyUsages(), $classStatementsGatherer->getMethodCalls(), $classStatementsGatherer->getReturnStatementsNodes(), $classStatementsGatherer->getPropertyAssigns(), $classReflection), $classScope, $storage); $this->callNodeCallback($nodeCallback, new ClassMethodsNode($stmt, $classStatementsGatherer->getMethods(), $classStatementsGatherer->getMethodCalls(), $classReflection), $classScope, $storage); $this->callNodeCallback($nodeCallback, new ClassConstantsNode($stmt, $classStatementsGatherer->getConstants(), $classStatementsGatherer->getConstantFetches(), $classReflection), $classScope, $storage); $classReflection->evictPrivateSymbols(); $this->calledMethodResults = []; } elseif ($stmt instanceof Node\Stmt\Property) { $hasYield = \false; $throwPoints = []; $impurePoints = []; $this->processAttributeGroups($stmt, $stmt->attrGroups, $scope, $storage, $nodeCallback); $nativePropertyType = $stmt->type !== null ? ParserNodeTypeToPHPStanType::resolve($stmt->type, $scope->getClassReflection()) : null; [, , , , , , , , , , , , $isReadOnly, $docComment, , , , $varTags, $isAllowedPrivateMutation] = $this->getPhpDocs($scope, $stmt); $phpDocType = null; if (isset($varTags[0]) && count($varTags) === 1) { $phpDocType = $varTags[0]->getType(); } foreach ($stmt->props as $prop) { $this->callNodeCallback($nodeCallback, $prop, $scope, $storage); if ($prop->default !== null) { $this->processExprNode($stmt, $prop->default, $scope, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); } if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } $propertyName = $prop->name->toString(); if ($phpDocType === null) { if (isset($varTags[$propertyName])) { $phpDocType = $varTags[$propertyName]->getType(); } } $propStmt = clone $stmt; $propStmt->setAttributes($prop->getAttributes()); $propStmt->setAttribute('originalPropertyStmt', $stmt); $this->callNodeCallback($nodeCallback, new ClassPropertyNode($propertyName, $stmt->flags, $nativePropertyType, $prop->default, $docComment, $phpDocType, \false, \false, $propStmt, $isReadOnly, $scope->isInTrait(), $scope->getClassReflection()->isReadOnly(), $isAllowedPrivateMutation, $scope->getClassReflection()), $scope, $storage); } if (count($stmt->hooks) > 0) { if (!isset($propertyName)) { throw new ShouldNotHappenException('Property name should be known when analysing hooks.'); } $this->processPropertyHooks($stmt, $stmt->type, $phpDocType, $propertyName, $stmt->hooks, $scope, $storage, $nodeCallback); } if ($stmt->type !== null) { $this->callNodeCallback($nodeCallback, $stmt->type, $scope, $storage); } } 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, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $exitPoints = []; $throwPoints = $overridingThrowPoints ?? $condResult->getThrowPoints(); $impurePoints = $condResult->getImpurePoints(); $endStatements = []; $finalScope = null; $alwaysTerminating = \true; $hasYield = $condResult->hasYield(); $branchScopeStatementResult = $this->processStmtNodesInternal($stmt, $stmt->stmts, $condResult->getTruthyScope(), $storage, $nodeCallback, $context); if (!$conditionType->isTrue()->no()) { $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\InternalEndStatementResult($stmt->stmts[count($stmt->stmts) - 1], $branchScopeStatementResult); } else { $endStatements[] = new \PHPStan\Analyser\InternalEndStatementResult($stmt, $branchScopeStatementResult); } $hasYield = $branchScopeStatementResult->hasYield() || $hasYield; } $scope = $condResult->getFalseyScope(); $lastElseIfConditionIsTrue = \false; $condScope = $scope; foreach ($stmt->elseifs as $elseif) { $this->callNodeCallback($nodeCallback, $elseif, $scope, $storage); $elseIfConditionType = ($this->treatPhpDocTypesAsCertain ? $condScope->getType($elseif->cond) : $scope->getNativeType($elseif->cond))->toBoolean(); $condResult = $this->processExprNode($stmt, $elseif->cond, $condScope, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $throwPoints = array_merge($throwPoints, $condResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $condResult->getImpurePoints()); $condScope = $condResult->getScope(); $branchScopeStatementResult = $this->processStmtNodesInternal($elseif, $elseif->stmts, $condResult->getTruthyScope(), $storage, $nodeCallback, $context); if (!$ifAlwaysTrue && !$lastElseIfConditionIsTrue && !$elseIfConditionType->isTrue()->no()) { $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, \true); $alwaysTerminating = $alwaysTerminating && $branchScopeStatementResult->isAlwaysTerminating(); if (count($branchScopeStatementResult->getEndStatements()) > 0) { $endStatements = array_merge($endStatements, $branchScopeStatementResult->getEndStatements()); } elseif (count($elseif->stmts) > 0) { $endStatements[] = new \PHPStan\Analyser\InternalEndStatementResult($elseif->stmts[count($elseif->stmts) - 1], $branchScopeStatementResult); } else { $endStatements[] = new \PHPStan\Analyser\InternalEndStatementResult($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, \true); $alwaysTerminating = \false; } } else { $this->callNodeCallback($nodeCallback, $stmt->else, $scope, $storage); $branchScopeStatementResult = $this->processStmtNodesInternal($stmt->else, $stmt->else->stmts, $scope, $storage, $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, \true); $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\InternalEndStatementResult($stmt->else->stmts[count($stmt->else->stmts) - 1], $branchScopeStatementResult); } else { $endStatements[] = new \PHPStan\Analyser\InternalEndStatementResult($stmt->else, $branchScopeStatementResult); } $hasYield = $hasYield || $branchScopeStatementResult->hasYield(); } } if ($finalScope === null) { $finalScope = $scope; } if ($stmt->else === null && !$ifAlwaysTrue && !$lastElseIfConditionIsTrue) { $endStatements[] = new \PHPStan\Analyser\InternalEndStatementResult($stmt, new \PHPStan\Analyser\InternalStatementResult($finalScope, $hasYield, $alwaysTerminating, $exitPoints, $throwPoints, $impurePoints)); } return new \PHPStan\Analyser\InternalStatementResult($finalScope, $hasYield, $alwaysTerminating, $exitPoints, $throwPoints, $impurePoints, $endStatements); } elseif ($stmt instanceof Node\Stmt\TraitUse) { $hasYield = \false; $throwPoints = []; $impurePoints = []; $traitStorage = $storage->duplicate(); $traitStorage->pendingFibers = []; $this->processTraitUse($stmt, $scope, $traitStorage, $nodeCallback); $this->processPendingFibers($traitStorage); } elseif ($stmt instanceof Foreach_) { if ($stmt->expr instanceof Variable && is_string($stmt->expr->name)) { $scope = $this->processVarAnnotation($scope, [$stmt->expr->name], $stmt); } $condResult = $this->processExprNode($stmt, $stmt->expr, $scope, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $throwPoints = $overridingThrowPoints ?? $condResult->getThrowPoints(); $impurePoints = $condResult->getImpurePoints(); $scope = $condResult->getScope(); $arrayComparisonExpr = new BinaryOp\NotIdentical($stmt->expr, new Array_([])); $this->callNodeCallback($nodeCallback, new InForeachNode($stmt), $scope, $storage); $originalScope = $scope; $bodyScope = $scope; if ($stmt->keyVar instanceof Variable) { $this->callNodeCallback($nodeCallback, new VariableAssignNode($stmt->keyVar, new GetIterableKeyTypeExpr($stmt->expr)), $originalScope, $storage); } if ($stmt->valueVar instanceof Variable) { $this->callNodeCallback($nodeCallback, new VariableAssignNode($stmt->valueVar, new GetIterableValueTypeExpr($stmt->expr)), $originalScope, $storage); } elseif ($stmt->valueVar instanceof List_) { $virtualAssign = new Assign($stmt->valueVar, new GetIterableValueTypeExpr($stmt->expr)); $virtualAssign->setAttributes($stmt->valueVar->getAttributes()); $this->callNodeCallback($nodeCallback, $virtualAssign, $scope, $storage); } $originalStorage = $storage; $unrolledEndScope = null; if ($context->isTopLevel()) { $storage = $originalStorage->duplicate(); $originalScope = $this->polluteScopeWithAlwaysIterableForeach ? $scope->filterByTruthyValue($arrayComparisonExpr) : $scope; $unrolledResult = $this->tryProcessUnrolledConstantArrayForeach($stmt, $originalScope, $originalStorage, $context); if ($unrolledResult !== null) { $bodyScope = $unrolledResult['bodyScope']; $unrolledEndScope = $unrolledResult['endScope']; } else { $bodyScope = $this->enterForeach($originalScope, $storage, $originalScope, $stmt, $nodeCallback); $count = 0; do { $prevScope = $bodyScope; $bodyScope = $bodyScope->mergeWith($this->polluteScopeWithAlwaysIterableForeach ? $scope->filterByTruthyValue($arrayComparisonExpr) : $scope); $storage = $originalStorage->duplicate(); $bodyScope = $this->enterForeach($bodyScope, $storage, $originalScope, $stmt, $nodeCallback); $bodyScopeResult = $this->processStmtNodesInternal($stmt, $stmt->stmts, $bodyScope, $storage, new \PHPStan\Analyser\NoopNodeCallback(), $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); $storage = $originalStorage; $bodyScope = $this->enterForeach($bodyScope, $storage, $originalScope, $stmt, $nodeCallback); $finalScopeResult = $this->processStmtNodesInternal($stmt, $stmt->stmts, $bodyScope, $storage, $nodeCallback, $context)->filterOutLoopExitPoints(); $finalScope = $finalScopeResult->getScope(); $scopesWithIterableValueType = []; $originalKeyVarExpr = null; $continueExitPointHasUnoriginalKeyType = \false; if ($stmt->keyVar instanceof Variable && is_string($stmt->keyVar->name)) { $originalKeyVarExpr = new OriginalForeachKeyExpr($stmt->keyVar->name); if ($finalScope->hasExpressionType($originalKeyVarExpr)->yes()) { $scopesWithIterableValueType[] = $finalScope; } else { $continueExitPointHasUnoriginalKeyType = \true; } } foreach ($finalScopeResult->getExitPointsByType(Continue_::class) as $continueExitPoint) { $continueScope = $continueExitPoint->getScope(); $finalScope = $continueScope->mergeWith($finalScope); if ($originalKeyVarExpr === null || !$continueScope->hasExpressionType($originalKeyVarExpr)->yes()) { $continueExitPointHasUnoriginalKeyType = \true; continue; } $scopesWithIterableValueType[] = $continueScope; } $breakExitPoints = $finalScopeResult->getExitPointsByType(Break_::class); foreach ($breakExitPoints as $breakExitPoint) { $finalScope = $breakExitPoint->getScope()->mergeWith($finalScope); } if ($unrolledEndScope !== null) { $finalScope = $unrolledEndScope; } $exprType = $scope->getType($stmt->expr); $hasExpr = $scope->hasExpressionType($stmt->expr); if (count($breakExitPoints) === 0 && count($scopesWithIterableValueType) > 0 && !$continueExitPointHasUnoriginalKeyType && $stmt->keyVar !== null && (!$hasExpr->no() || !$stmt->expr instanceof Variable) && $exprType->isArray()->yes() && $exprType->isConstantArray()->no()) { $arrayExprDimFetch = new ArrayDimFetch($stmt->expr, $stmt->keyVar); $originalValueExpr = null; if ($stmt->valueVar instanceof Variable && is_string($stmt->valueVar->name)) { $originalValueExpr = new OriginalForeachValueExpr($stmt->valueVar->name); } $arrayDimFetchLoopTypes = []; $keyLoopTypes = []; foreach ($scopesWithIterableValueType as $scopeWithIterableValueType) { $dimFetchType = $scopeWithIterableValueType->getType($arrayExprDimFetch); // Condition-based narrowings like `is_string($type)` apply to the value // variable but not automatically to the array dim fetch, even though the // two describe the same element for a given iteration. If the value var // hasn't been reassigned (OriginalForeachValueExpr still tracked) we use // the narrowed value-var type in place of the broader dim fetch type so // the loop's final array rewrite below picks up the sharper element type. if ($originalValueExpr !== null && $scopeWithIterableValueType->hasExpressionType($originalValueExpr)->yes()) { $valueVarType = $scopeWithIterableValueType->getType($stmt->valueVar); if ($dimFetchType->isSuperTypeOf($valueVarType)->yes()) { $dimFetchType = $valueVarType; } } $arrayDimFetchLoopTypes[] = $dimFetchType; $keyLoopTypes[] = $scopeWithIterableValueType->getType($stmt->keyVar); } $arrayDimFetchLoopType = TypeCombinator::union(...$arrayDimFetchLoopTypes); $keyLoopType = TypeCombinator::union(...$keyLoopTypes); $arrayDimFetchLoopNativeTypes = []; $keyLoopNativeTypes = []; foreach ($scopesWithIterableValueType as $scopeWithIterableValueType) { $dimFetchNativeType = $scopeWithIterableValueType->getNativeType($arrayExprDimFetch); if ($originalValueExpr !== null && $scopeWithIterableValueType->hasExpressionType($originalValueExpr)->yes()) { $valueVarNativeType = $scopeWithIterableValueType->getNativeType($stmt->valueVar); if ($dimFetchNativeType->isSuperTypeOf($valueVarNativeType)->yes()) { $dimFetchNativeType = $valueVarNativeType; } } $arrayDimFetchLoopNativeTypes[] = $dimFetchNativeType; $keyLoopNativeTypes[] = $scopeWithIterableValueType->getType($stmt->keyVar); } $arrayDimFetchLoopNativeType = TypeCombinator::union(...$arrayDimFetchLoopNativeTypes); $keyLoopNativeType = TypeCombinator::union(...$keyLoopNativeTypes); $valueTypeChanged = !$arrayDimFetchLoopType->equals($exprType->getIterableValueType()); $keyTypeChanged = !$keyLoopType->equals($exprType->getIterableKeyType()); if ($valueTypeChanged || $keyTypeChanged) { $newExprType = $exprType; if ($valueTypeChanged) { $newExprType = $newExprType->mapValueType(static fn(Type $type): Type => $arrayDimFetchLoopType); } if ($keyTypeChanged) { $newExprType = $newExprType->mapKeyType(static fn(Type $type): Type => $keyLoopType); } $nativeExprType = $scope->getNativeType($stmt->expr); $newExprNativeType = $nativeExprType; if ($valueTypeChanged) { $newExprNativeType = $newExprNativeType->mapValueType(static fn(Type $type): Type => $arrayDimFetchLoopNativeType); } if ($keyTypeChanged) { $newExprNativeType = $newExprNativeType->mapKeyType(static fn(Type $type): Type => $keyLoopNativeType); } if ($stmt->expr instanceof Variable && is_string($stmt->expr->name)) { $finalScope = $finalScope->assignVariable($stmt->expr->name, $newExprType, $newExprNativeType, $hasExpr); } else { $finalScope = $finalScope->assignExpression($stmt->expr, $newExprType, $newExprNativeType); } } } $isIterableAtLeastOnce = $exprType->isIterableAtLeastOnce(); if ($isIterableAtLeastOnce->maybe() || $exprType->isIterable()->no()) { $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()); } $traversableThrowPoint = $this->getTraversableForeachThrowPoint($scope, $stmt->expr); if ($traversableThrowPoint !== null) { $throwPoints[] = $traversableThrowPoint; } if ($context->isTopLevel() && $stmt->byRef) { $finalScope = $finalScope->assignExpression(new ForeachValueByRefExpr($stmt->valueVar), new MixedType(), new MixedType()); } return new \PHPStan\Analyser\InternalStatementResult($finalScope, $finalScopeResult->hasYield() || $condResult->hasYield(), $isIterableAtLeastOnce->yes() && $finalScopeResult->isAlwaysTerminating(), $finalScopeResult->getExitPointsForOuterLoop(), $throwPoints, $impurePoints); } elseif ($stmt instanceof While_) { $originalStorage = $storage; $storage = $originalStorage->duplicate(); $condResult = $this->processExprNode($stmt, $stmt->cond, $scope, $storage, new \PHPStan\Analyser\NoopNodeCallback(), \PHPStan\Analyser\ExpressionContext::createDeep()); $beforeCondBooleanType = ($this->treatPhpDocTypesAsCertain ? $scope->getType($stmt->cond) : $scope->getNativeType($stmt->cond))->toBoolean(); $condScope = $condResult->getFalseyScope(); if (!$context->isTopLevel() && $beforeCondBooleanType->isFalse()->yes()) { if (!$this->polluteScopeWithLoopInitialAssignments) { $scope = $condScope->mergeWith($scope); } return new \PHPStan\Analyser\InternalStatementResult($scope, $condResult->hasYield(), \false, [], $condResult->getThrowPoints(), $condResult->getImpurePoints()); } $bodyScope = $condResult->getTruthyScope(); if ($context->isTopLevel()) { $count = 0; do { $prevScope = $bodyScope; $bodyScope = $bodyScope->mergeWith($scope); $storage = $originalStorage->duplicate(); $bodyScope = $this->processExprNode($stmt, $stmt->cond, $bodyScope, $storage, new \PHPStan\Analyser\NoopNodeCallback(), \PHPStan\Analyser\ExpressionContext::createDeep())->getTruthyScope(); $bodyScopeResult = $this->processStmtNodesInternal($stmt, $stmt->stmts, $bodyScope, $storage, new \PHPStan\Analyser\NoopNodeCallback(), $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; $storage = $originalStorage; $bodyScope = $this->processExprNode($stmt, $stmt->cond, $bodyScope, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep())->getTruthyScope(); $finalScopeResult = $this->processStmtNodesInternal($stmt, $stmt->stmts, $bodyScope, $storage, $nodeCallback, $context)->filterOutLoopExitPoints(); $finalScope = $finalScopeResult->getScope()->filterByFalseyValue($stmt->cond); $alwaysIterates = \false; $neverIterates = \false; if ($context->isTopLevel()) { $condBooleanType = ($this->treatPhpDocTypesAsCertain ? $bodyScopeMaybeRan->getType($stmt->cond) : $bodyScopeMaybeRan->getNativeType($stmt->cond))->toBoolean(); $alwaysIterates = $condBooleanType->isTrue()->yes(); $neverIterates = $condBooleanType->isFalse()->yes(); } if (!$alwaysIterates) { foreach ($finalScopeResult->getExitPointsByType(Continue_::class) as $continueExitPoint) { $finalScope = $finalScope->mergeWith($continueExitPoint->getScope()); } } $breakExitPoints = $finalScopeResult->getExitPointsByType(Break_::class); if (count($breakExitPoints) > 0) { $breakScope = $alwaysIterates ? null : $finalScope; foreach ($breakExitPoints as $breakExitPoint) { $breakScope = $breakScope === null ? $breakExitPoint->getScope() : $breakScope->mergeWith($breakExitPoint->getScope()); } $finalScope = $breakScope; } $isIterableAtLeastOnce = $beforeCondBooleanType->isTrue()->yes(); $this->callNodeCallback($nodeCallback, new BreaklessWhileLoopNode($stmt, $finalScopeResult->toPublic()->getExitPoints(), $finalScopeResult->hasYield()), $bodyScopeMaybeRan, $storage); if ($alwaysIterates) { $isAlwaysTerminating = count($finalScopeResult->getExitPointsByType(Break_::class)) === 0; } elseif ($isIterableAtLeastOnce) { $isAlwaysTerminating = $finalScopeResult->isAlwaysTerminating(); } else { $isAlwaysTerminating = \false; } 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\InternalStatementResult($finalScope, $finalScopeResult->hasYield() || $condResult->hasYield(), $isAlwaysTerminating, $finalScopeResult->getExitPointsForOuterLoop(), $throwPoints, $impurePoints); } elseif ($stmt instanceof Do_) { $finalScope = null; $bodyScope = $scope; $count = 0; $hasYield = \false; $throwPoints = []; $impurePoints = []; $originalStorage = $storage; if ($context->isTopLevel()) { do { $prevScope = $bodyScope; $bodyScope = $bodyScope->mergeWith($scope); $storage = $originalStorage->duplicate(); $bodyScopeResult = $this->processStmtNodesInternal($stmt, $stmt->stmts, $bodyScope, $storage, new \PHPStan\Analyser\NoopNodeCallback(), $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, $storage, new \PHPStan\Analyser\NoopNodeCallback(), \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); } $storage = $originalStorage; $bodyScopeResult = $this->processStmtNodesInternal($stmt, $stmt->stmts, $bodyScope, $storage, $nodeCallback, $context)->filterOutLoopExitPoints(); $bodyScope = $bodyScopeResult->getScope(); foreach ($bodyScopeResult->getExitPointsByType(Continue_::class) as $continueExitPoint) { $bodyScope = $bodyScope->mergeWith($continueExitPoint->getScope()); } $alwaysIterates = \false; if ($context->isTopLevel()) { $condBooleanType = ($this->treatPhpDocTypesAsCertain ? $bodyScope->getType($stmt->cond) : $bodyScope->getNativeType($stmt->cond))->toBoolean(); $alwaysIterates = $condBooleanType->isTrue()->yes(); } $this->callNodeCallback($nodeCallback, new DoWhileLoopConditionNode($stmt->cond, $bodyScopeResult->toPublic()->getExitPoints(), $bodyScopeResult->hasYield()), $bodyScope, $storage); 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, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $hasYield = $condResult->hasYield(); $throwPoints = $condResult->getThrowPoints(); $impurePoints = $condResult->getImpurePoints(); $finalScope = $condResult->getFalseyScope(); } else { $this->processExprNode($stmt, $stmt->cond, $bodyScope, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); } $breakExitPoints = $bodyScopeResult->getExitPointsByType(Break_::class); if (count($breakExitPoints) > 0) { $breakScope = $alwaysIterates ? null : $finalScope; foreach ($breakExitPoints as $breakExitPoint) { $breakScope = $breakScope === null ? $breakExitPoint->getScope() : $breakScope->mergeWith($breakExitPoint->getScope()); } $finalScope = $breakScope; } return new \PHPStan\Analyser\InternalStatementResult($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, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createTopLevel()); $initScope = $initResult->getScope(); $hasYield = $hasYield || $initResult->hasYield(); $throwPoints = array_merge($throwPoints, $initResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $initResult->getImpurePoints()); } $originalStorage = $storage; $bodyScope = $initScope; $isIterableAtLeastOnce = TrinaryLogic::createYes(); $lastCondExpr = array_last($stmt->cond) ?? null; if (count($stmt->cond) > 0) { $storage = $originalStorage->duplicate(); foreach ($stmt->cond as $condExpr) { $condResult = $this->processExprNode($stmt, $condExpr, $bodyScope, $storage, new \PHPStan\Analyser\NoopNodeCallback(), \PHPStan\Analyser\ExpressionContext::createDeep()); $initScope = $condResult->getScope(); $condResultScope = $condResult->getScope(); // only the last condition expression is relevant whether the loop continues // see https://www.php.net/manual/en/control-structures.for.php 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; $storage = $originalStorage->duplicate(); $bodyScope = $bodyScope->mergeWith($initScope); if ($lastCondExpr !== null) { $bodyScope = $this->processExprNode($stmt, $lastCondExpr, $bodyScope, $storage, new \PHPStan\Analyser\NoopNodeCallback(), \PHPStan\Analyser\ExpressionContext::createDeep())->getTruthyScope(); } $bodyScopeResult = $this->processStmtNodesInternal($stmt, $stmt->stmts, $bodyScope, $storage, new \PHPStan\Analyser\NoopNodeCallback(), $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, $storage, new \PHPStan\Analyser\NoopNodeCallback(), \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); } $storage = $originalStorage; $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, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep())->getTruthyScope(); $bodyScope = $this->inferForLoopExpressions($stmt, $lastCondExpr, $bodyScope); } $finalScopeResult = $this->processStmtNodesInternal($stmt, $stmt->stmts, $bodyScope, $storage, $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, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createTopLevel())->getScope(); } $finalScope = $finalScope->generalizeWith($loopScope); if ($lastCondExpr !== null) { $finalScope = $finalScope->filterByFalseyValue($lastCondExpr); } $breakExitPoints = $finalScopeResult->getExitPointsByType(Break_::class); if (count($breakExitPoints) > 0) { $breakScope = $alwaysIterates->yes() ? null : $finalScope; foreach ($breakExitPoints as $breakExitPoint) { $breakScope = $breakScope === null ? $breakExitPoint->getScope() : $breakScope->mergeWith($breakExitPoint->getScope()); } $finalScope = $breakScope; } 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\InternalStatementResult($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, $storage, $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, $storage, $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->processStmtNodesInternal($caseNode, $caseNode->stmts, $branchScope, $storage, $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 = $scopeForBranches->mergeWith($finalScope); } return new \PHPStan\Analyser\InternalStatementResult($finalScope, $hasYield, $alwaysTerminating, $exitPointsForOuterLoop, $throwPoints, $impurePoints); } elseif ($stmt instanceof TryCatch) { $branchScopeResult = $this->processStmtNodesInternal($stmt, $stmt->stmts, $scope, $storage, $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->toPublic(); if ($exitPoint->getStatement() instanceof Node\Stmt\Expression && $exitPoint->getStatement()->expr instanceof Expr\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) { $this->callNodeCallback($nodeCallback, $catchNode, $scope, $storage); $originalCatchTypes = []; $catchTypes = []; foreach ($catchNode->types as $catchNodeType) { $catchType = new ObjectType($catchNodeType->toString()); $originalCatchTypes[] = $catchType; $catchTypes[] = TypeCombinator::remove($catchType, $pastCatchTypes); } $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 Expr\Throw_ && !($throwNode instanceof Node\Stmt\Expression && $throwNode->expr instanceof Expr\Throw_)) { $onlyExplicitIsThrow = \false; } $matchingThrowPoints[$throwPointIndex] = $throwPoint; } } } // implicit only if (count($matchingThrowPoints) === 0 || $onlyExplicitIsThrow) { foreach ($throwPoints as $throwPointIndex => $throwPoint) { if ($throwPoint->isExplicit()) { continue; } foreach ($catchTypes as $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 foreach ($matchingCatchTypes as $catchTypeIndex => $matched) { if ($matched) { continue; } $this->callNodeCallback($nodeCallback, new CatchWithUnthrownExceptionNode($catchNode, $catchTypes[$catchTypeIndex], $originalCatchTypes[$catchTypeIndex]), $scope, $storage); } if (count($matchingThrowPoints) === 0) { 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; $this->callNodeCallback($nodeCallback, new VariableAssignNode($catchNode->var, new TypeExpr($catchType)), $scope, $storage); } $catchScopeResult = $this->processStmtNodesInternal($catchNode, $catchNode->stmts, $catchScope->enterCatchType($catchType, $variableName), $storage, $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->toPublic(); if ($exitPoint->getStatement() instanceof Node\Stmt\Expression && $exitPoint->getStatement()->expr instanceof Expr\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) { $originalFinallyScope = $finallyScope; $finallyResult = $this->processStmtNodesInternal($stmt->finally, $stmt->finally->stmts, $finallyScope, $storage, $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 && $finallyResult->isAlwaysTerminating()) { $this->callNodeCallback($nodeCallback, new FinallyExitPointsNode($finallyResult->toPublic()->getExitPoints(), $finallyExitPoints), $scope, $storage); } $exitPoints = array_merge($exitPoints, $finallyResult->getExitPoints()); } return new \PHPStan\Analyser\InternalStatementResult($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, $storage, $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) { $varType = $scope->getType($var->var); if (!$varType->isArray()->yes() && !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->no()) { $throwPoints = array_merge($throwPoints, $this->processExprNode($stmt, new MethodCall(new TypeExpr($varType), 'offsetUnset'), $scope, $storage, new \PHPStan\Analyser\NoopNodeCallback(), \PHPStan\Analyser\ExpressionContext::createDeep())->getThrowPoints()); } $clonedVar = $this->deepNodeCloner->cloneNode($var->var); $traverser = new NodeTraverser(); $traverser->addVisitor(new class extends NodeVisitorAbstract { #[Override] 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->processVirtualAssign($scope, $storage, $stmt, $clonedVar, new UnsetOffsetExpr($var->var, $var->dim), $nodeCallback)->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); } $scope = $scope->invalidateExpression(new ForeachValueByRefExpr($var)); } } elseif ($stmt instanceof Node\Stmt\Use_) { $hasYield = \false; $throwPoints = []; $impurePoints = []; foreach ($stmt->uses as $use) { $this->callNodeCallback($nodeCallback, $use, $scope, $storage); } } 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, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $impurePoints = array_merge($impurePoints, $varResult->getImpurePoints()); $scope = $this->lookForUnsetAllowedUndefinedExpressions($scope, $var); if (!is_string($var->name)) { continue; } $varType = $this->getGlobalVariableType($var->name); $scope = $scope->assignVariable($var->name, $varType, $varType, TrinaryLogic::createYes()); $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, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $impurePoints = array_merge($impurePoints, $defaultExprResult->getImpurePoints()); } $scope = $scope->enterExpressionAssign($var->var); $varResult = $this->processExprNode($stmt, $var->var, $scope, $storage, $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(), TrinaryLogic::createYes()); $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) { $this->callNodeCallback($nodeCallback, $const, $scope, $storage); $constResult = $this->processExprNode($stmt, $const->value, $scope, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $impurePoints = array_merge($impurePoints, $constResult->getImpurePoints()); if ($const->namespacedName !== null) { $constantName = new Name\FullyQualified($const->namespacedName->toString()); } else { $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, $storage, $nodeCallback); foreach ($stmt->consts as $const) { $this->callNodeCallback($nodeCallback, $const, $scope, $storage); $constResult = $this->processExprNode($stmt, $const->value, $scope, $storage, $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, $storage, $nodeCallback); $impurePoints = []; if ($stmt->expr !== null) { $exprResult = $this->processExprNode($stmt, $stmt->expr, $scope, $storage, $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\Block) { $result = $this->processStmtNodesInternal($stmt, $stmt->stmts, $scope, $storage, $nodeCallback, $context); if ($this->polluteScopeWithBlock) { return $result; } return new \PHPStan\Analyser\InternalStatementResult($scope->mergeWith($result->getScope()), $result->hasYield(), $result->isAlwaysTerminating(), $result->getExitPoints(), $result->getThrowPoints(), $result->getImpurePoints(), $result->getEndStatements()); } 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) { $this->callNodeCallback($nodeCallback, $use, $scope, $storage); } $impurePoints = []; } else { $hasYield = \false; $throwPoints = $overridingThrowPoints ?? []; $impurePoints = []; } return new \PHPStan\Analyser\InternalStatementResult($scope, $hasYield, \false, [], $throwPoints, $impurePoints); } /** * @return array{bool, string|null} * @param \PhpParser\Node\Stmt\Function_|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\PropertyHook $stmt */ private function getDeprecatedAttribute(\PHPStan\Analyser\Scope $scope, $stmt): array { $initializerExprContext = InitializerExprContext::fromStubParameter($scope->isInClass() ? $scope->getClassReflection()->getName() : null, $scope->getFile(), $stmt); $isDeprecated = \false; $deprecatedDescription = null; $deprecatedDescriptionType = null; foreach ($stmt->attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { if ($attr->name->toString() !== 'Deprecated') { continue; } $isDeprecated = \true; $arguments = $attr->args; foreach ($arguments as $i => $arg) { $argName = $arg->name; if ($argName === null) { if ($i !== 0) { continue; } $deprecatedDescriptionType = $this->initializerExprTypeResolver->getType($arg->value, $initializerExprContext); break; } if ($argName->toString() !== 'message') { continue; } $deprecatedDescriptionType = $this->initializerExprTypeResolver->getType($arg->value, $initializerExprContext); break; } } } if ($deprecatedDescriptionType !== null) { $constantStrings = $deprecatedDescriptionType->getConstantStrings(); if (count($constantStrings) === 1) { $deprecatedDescription = $constantStrings[0]->getValue(); } } return [$isDeprecated, $deprecatedDescription]; } /** * @return InternalThrowPoint[]|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\InternalThrowPoint::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 $this->classReflectionFactory->create($betterReflectionClass->getName(), $betterReflectionClass instanceof ReflectionEnum && PHP_VERSION_ID >= 80000 ? new $enumAdapter($betterReflectionClass) : new ReflectionClass($betterReflectionClass), null, null, null, sprintf('%s:%d', $scope->getFile(), $stmt->getStartLine())); } public function lookForSetAllowedUndefinedExpressions(\PHPStan\Analyser\MutatingScope $scope, Expr $expr): \PHPStan\Analyser\MutatingScope { return $this->lookForExpressionCallback($scope, $expr, static fn(\PHPStan\Analyser\MutatingScope $scope, Expr $expr): \PHPStan\Analyser\MutatingScope => $scope->setAllowedUndefinedExpression($expr)); } public function lookForUnsetAllowedUndefinedExpressions(\PHPStan\Analyser\MutatingScope $scope, Expr $expr): \PHPStan\Analyser\MutatingScope { return $this->lookForExpressionCallback($scope, $expr, static fn(\PHPStan\Analyser\MutatingScope $scope, Expr $expr): \PHPStan\Analyser\MutatingScope => $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 List_) { foreach ($expr->items as $item) { if ($item === null) { continue; } $scope = $this->lookForExpressionCallback($scope, $item->value, $callback); } } 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, \PHPStan\Analyser\ExpressionResultStorage $storage, callable $nodeCallback, \PHPStan\Analyser\ExpressionContext $context): \PHPStan\Analyser\ExpressionResult { $this->storeBeforeScope($storage, $expr, $scope); 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, $storage, $nodeCallback, $context); } $this->callNodeCallbackWithExpression($nodeCallback, $expr, $scope, $storage, $context); /** @var ExprHandler $exprHandler */ foreach ($this->container->getServicesByTag(\PHPStan\Analyser\ExprHandler::EXTENSION_TAG) as $exprHandler) { if (!$exprHandler->supports($expr)) { continue; } return $exprHandler->processExpr($this, $stmt, $expr, $scope, $storage, $nodeCallback, $context); } if ($expr instanceof List_) { // only in assign and foreach, processed elsewhere return new \PHPStan\Analyser\ExpressionResult($scope, \false, \false, [], []); } return new \PHPStan\Analyser\ExpressionResult($scope, \false, \false, [], [], static fn(): \PHPStan\Analyser\MutatingScope => $scope->filterByTruthyValue($expr), static fn(): \PHPStan\Analyser\MutatingScope => $scope->filterByFalseyValue($expr)); } /** * @param 'get'|'set' $hookName * @return InternalThrowPoint[] */ public function getThrowPointsFromPropertyHook(\PHPStan\Analyser\MutatingScope $scope, PropertyFetch $propertyFetch, PhpPropertyReflection $propertyReflection, string $hookName): array { $scopeFunction = $scope->getFunction(); if ($scopeFunction instanceof PhpMethodFromParserNodeReflection && $scopeFunction->isPropertyHook() && $propertyFetch->var instanceof Variable && $propertyFetch->var->name === 'this' && $propertyFetch->name instanceof Identifier && $propertyFetch->name->toString() === $scopeFunction->getHookedPropertyName()) { return []; } $declaringClass = $propertyReflection->getDeclaringClass(); if (!$propertyReflection->hasHook($hookName)) { if ($propertyReflection->isPrivate() || $propertyReflection->isFinal()->yes() || $declaringClass->isFinal()) { return []; } if ($this->implicitThrows) { return [\PHPStan\Analyser\InternalThrowPoint::createImplicit($scope, $propertyFetch)]; } return []; } $getHook = $propertyReflection->getHook($hookName); $throwType = $getHook->getThrowType(); if ($throwType !== null) { if (!$throwType->isVoid()->yes()) { return [\PHPStan\Analyser\InternalThrowPoint::createExplicit($scope, $throwType, $propertyFetch, \true)]; } } elseif ($this->implicitThrows) { return [\PHPStan\Analyser\InternalThrowPoint::createImplicit($scope, $propertyFetch)]; } return []; } /** * @return string[] */ public function getAssignedVariables(Expr $expr): array { if ($expr instanceof Expr\Variable) { if (is_string($expr->name)) { return [$expr->name]; } return []; } if ($expr instanceof Expr\List_) { $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 */ public function callNodeCallbackWithExpression(callable $nodeCallback, Expr $expr, \PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\ExpressionResultStorage $storage, \PHPStan\Analyser\ExpressionContext $context): void { if ($context->isDeep()) { $scope = $scope->exitFirstLevelStatements(); } $this->callNodeCallback($nodeCallback, $expr, $scope, $storage); } /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ public function callNodeCallback(callable $nodeCallback, Node $node, \PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\ExpressionResultStorage $storage): void { $nodeCallback($node, $scope); } /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ public function processClosureNode(Node\Stmt $stmt, Expr\Closure $expr, \PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\ExpressionResultStorage $storage, callable $nodeCallback, \PHPStan\Analyser\ExpressionContext $context, ?Type $passedToType): \PHPStan\Analyser\ProcessClosureResult { foreach ($expr->params as $param) { $this->processParamNode($stmt, $param, $scope, $storage, $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(); $inAssignRightSideExpr = $context->getInAssignRightSideExpr(); if ($inAssignRightSideVariableName === $use->var->name && $inAssignRightSideExpr !== null) { $inAssignRightSideType = $scope->getType($inAssignRightSideExpr); 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); } } $inAssignRightSideNativeType = $scope->getNativeType($inAssignRightSideExpr); 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, TrinaryLogic::createYes()); } } $this->processExprNode($stmt, $use->var, $useScope, $storage, $nodeCallback, $context); if (!$use->byRef) { continue; } $useScope = $useScope->exitExpressionAssign($use->var); } if ($expr->returnType !== null) { $this->callNodeCallback($nodeCallback, $expr->returnType, $scope, $storage); } $closureScope = $scope->enterAnonymousFunction($expr, $callableParameters); $closureScope = $closureScope->processClosureScope($scope, null, $byRefUses); $closureType = $closureScope->getAnonymousFunctionReflection(); if (!$closureType instanceof ClosureType) { throw new ShouldNotHappenException(); } $this->callNodeCallback($nodeCallback, new InClosureNode($closureType, $expr), $closureScope, $storage); $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); $invalidateExpressions[] = new InvalidateExprNode($node->getPropertyFetch()); 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->processStmtNodesInternalWithoutFlushingPendingFibers($expr, $expr->stmts, $closureScope, $storage, $closureStmtsCallback, \PHPStan\Analyser\StatementContext::createTopLevel()); $publicStatementResult = $statementResult->toPublic(); $this->callNodeCallback($nodeCallback, new ClosureReturnStatementsNode($expr, $gatheredReturnStatements, $gatheredYieldStatements, $publicStatementResult, $executionEnds, array_merge($publicStatementResult->getImpurePoints(), $closureImpurePoints)), $closureScope, $storage); return new \PHPStan\Analyser\ProcessClosureResult($scope, $statementResult->getThrowPoints(), $statementResult->getImpurePoints(), $invalidateExpressions); } $originalStorage = $storage; $count = 0; $closureResultScope = null; do { $prevScope = $closureScope; $storage = $originalStorage->duplicate(); $intermediaryClosureScopeResult = $this->processStmtNodesInternalWithoutFlushingPendingFibers($expr, $expr->stmts, $closureScope, $storage, new \PHPStan\Analyser\NoopNodeCallback(), \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; } $storage = $originalStorage; $statementResult = $this->processStmtNodesInternalWithoutFlushingPendingFibers($expr, $expr->stmts, $closureScope, $storage, $closureStmtsCallback, \PHPStan\Analyser\StatementContext::createTopLevel()); $publicStatementResult = $statementResult->toPublic(); $this->callNodeCallback($nodeCallback, new ClosureReturnStatementsNode($expr, $gatheredReturnStatements, $gatheredYieldStatements, $publicStatementResult, $executionEnds, array_merge($publicStatementResult->getImpurePoints(), $closureImpurePoints)), $closureScope, $storage); return new \PHPStan\Analyser\ProcessClosureResult($scope, $statementResult->getThrowPoints(), $statementResult->getImpurePoints(), $invalidateExpressions, $closureResultScope, $byRefUses); } /** * @param InvalidateExprNode[] $invalidatedExpressions * @param string[] $uses */ public 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) { $result = $finder->findFirst([$invalidateExpression->getExpr()], static fn($node) => $node instanceof Variable && in_array($node->name, $uses, \true)); if ($result === null) { continue; } $requireMoreCharacters = $invalidateExpression->getExpr() instanceof Variable; $scope = $scope->invalidateExpression($invalidateExpression->getExpr(), $requireMoreCharacters); } return $scope; } /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ public function processArrowFunctionNode(Node\Stmt $stmt, Expr\ArrowFunction $expr, \PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\ExpressionResultStorage $storage, callable $nodeCallback, ?Type $passedToType): \PHPStan\Analyser\ExpressionResult { foreach ($expr->params as $param) { $this->processParamNode($stmt, $param, $scope, $storage, $nodeCallback); } if ($expr->returnType !== null) { $this->callNodeCallback($nodeCallback, $expr->returnType, $scope, $storage); } $arrowFunctionCallArgs = $expr->getAttribute(ArrowFunctionArgVisitor::ATTRIBUTE_NAME); $arrowFunctionScope = $scope->enterArrowFunction($expr, $this->createCallableParameters($scope, $expr, $arrowFunctionCallArgs, $passedToType)); $arrowFunctionType = $arrowFunctionScope->getAnonymousFunctionReflection(); if ($arrowFunctionType === null) { throw new ShouldNotHappenException(); } $this->callNodeCallback($nodeCallback, new InArrowFunctionNode($arrowFunctionType, $expr), $arrowFunctionScope, $storage); $exprResult = $this->processExprNode($stmt, $expr->expr, $arrowFunctionScope, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createTopLevel()); return new \PHPStan\Analyser\ExpressionResult($scope, \false, $exprResult->isAlwaysTerminating(), $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; } if ($callableParameter->isVariadic()) { $argTypes = []; for ($j = $index; $j < count($args); $j++) { $argTypes[] = $scope->getType($args[$j]->value); } $type = TypeCombinator::union(...$argTypes); } else { $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 = $passedToType->filterTypes(static fn(Type $innerType) => $innerType->isCallable()->yes()); if ($passedToType->isCallable()->no()) { return null; } } $acceptors = $passedToType->getCallableParametersAcceptors($scope); foreach ($acceptors as $acceptor) { if ($callableParameters === null) { $callableParameters = array_map(static fn(ParameterReflection $callableParameter) => 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, \PHPStan\Analyser\ExpressionResultStorage $storage, callable $nodeCallback): void { $this->processAttributeGroups($stmt, $param->attrGroups, $scope, $storage, $nodeCallback); $this->callNodeCallback($nodeCallback, $param, $scope, $storage); if ($param->type !== null) { $this->callNodeCallback($nodeCallback, $param->type, $scope, $storage); } if ($param->default === null) { return; } $this->processExprNode($stmt, $param->default, $scope, $storage, $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, \PHPStan\Analyser\ExpressionResultStorage $storage, callable $nodeCallback): void { foreach ($attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { $className = $scope->resolveName($attr->name); if ($this->reflectionProvider->hasClass($className)) { $classReflection = $this->reflectionProvider->getClass($className); if ($classReflection->hasConstructor()) { $constructorReflection = $classReflection->getConstructor(); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $attr->args, $constructorReflection->getVariants(), $constructorReflection->getNamedArgumentsVariants()); $expr = new New_($attr->name, $attr->args); $expr = \PHPStan\Analyser\ArgumentsNormalizer::reorderNewArguments($parametersAcceptor, $expr) ?? $expr; $this->processArgs($stmt, $constructorReflection, null, $parametersAcceptor, $expr, $scope, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $this->callNodeCallback($nodeCallback, $attr, $scope, $storage); continue; } } foreach ($attr->args as $arg) { $this->processExprNode($stmt, $arg->value, $scope, $storage, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $this->callNodeCallback($nodeCallback, $arg, $scope, $storage); } $this->callNodeCallback($nodeCallback, $attr, $scope, $storage); } $this->callNodeCallback($nodeCallback, $attrGroup, $scope, $storage); } } /** * @param Node\PropertyHook[] $hooks * @param callable(Node $node, Scope $scope): void $nodeCallback * @param \PhpParser\Node\Identifier|\PhpParser\Node\Name|\PhpParser\Node\ComplexType|null $nativeTypeNode */ private function processPropertyHooks(Node\Stmt $stmt, $nativeTypeNode, ?Type $phpDocType, string $propertyName, array $hooks, \PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\ExpressionResultStorage $storage, callable $nodeCallback): void { if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } $classReflection = $scope->getClassReflection(); foreach ($hooks as $hook) { $this->callNodeCallback($nodeCallback, $hook, $scope, $storage); $this->processAttributeGroups($stmt, $hook->attrGroups, $scope, $storage, $nodeCallback); [, $phpDocParameterTypes, , , , $phpDocThrowType, , , , , , , , $phpDocComment, , , , , , $resolvedPhpDoc] = $this->getPhpDocs($scope, $hook); foreach ($hook->params as $param) { $this->processParamNode($stmt, $param, $scope, $storage, $nodeCallback); } [$isDeprecated, $deprecatedDescription] = $this->getDeprecatedAttribute($scope, $hook); $hookScope = $scope->enterPropertyHook($hook, $propertyName, $nativeTypeNode, $phpDocType, $phpDocParameterTypes, $phpDocThrowType, $deprecatedDescription, $isDeprecated, $phpDocComment, $resolvedPhpDoc); $hookReflection = $hookScope->getFunction(); if (!$hookReflection instanceof PhpMethodFromParserNodeReflection) { throw new ShouldNotHappenException(); } if (!$classReflection->hasNativeProperty($propertyName)) { throw new ShouldNotHappenException(); } $propertyReflection = $classReflection->getNativeProperty($propertyName); $this->callNodeCallback($nodeCallback, new InPropertyHookNode($classReflection, $hookReflection, $propertyReflection, $hook), $hookScope, $storage); $stmts = $hook->getStmts(); if ($stmts === null) { return; } if ($hook->body instanceof Expr) { // enrich attributes of nodes in short hook body statements $traverser = new NodeTraverser(new LineAttributesVisitor($hook->body->getStartLine(), $hook->body->getEndLine())); $traverser->traverse($stmts); } $gatheredReturnStatements = []; $executionEnds = []; $methodImpurePoints = []; $statementResult = $this->processStmtNodesInternal(new PropertyHookStatementNode($hook), $stmts, $hookScope, $storage, static function (Node $node, \PHPStan\Analyser\Scope $scope) use ($nodeCallback, $hookScope, &$gatheredReturnStatements, &$executionEnds, &$hookImpurePoints): void { $nodeCallback($node, $scope); if ($scope->getFunction() !== $hookScope->getFunction()) { return; } if ($scope->isInAnonymousFunction()) { return; } if ($node instanceof PropertyAssignNode) { $hookImpurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $node, 'propertyAssign', 'property assignment', \true); return; } if ($node instanceof ExecutionEndNode) { $executionEnds[] = $node; return; } if (!$node instanceof Return_) { return; } $gatheredReturnStatements[] = new ReturnStatement($scope, $node); }, \PHPStan\Analyser\StatementContext::createTopLevel())->toPublic(); $this->callNodeCallback($nodeCallback, new PropertyHookReturnStatementsNode($hook, $gatheredReturnStatements, $statementResult, $executionEnds, array_merge($statementResult->getImpurePoints(), $methodImpurePoints), $classReflection, $hookReflection, $propertyReflection), $hookScope, $storage); } } /** * @param FunctionReflection|MethodReflection|null $calleeReflection */ private function resolveClosureThisType(?CallLike $call, $calleeReflection, ParameterReflection $parameter, \PHPStan\Analyser\MutatingScope $scope): ?Type { if ($call instanceof FuncCall && $calleeReflection instanceof FunctionReflection) { foreach ($this->parameterClosureThisExtensionProvider->getFunctionParameterClosureThisExtensions() as $extension) { if (!$extension->isFunctionSupported($calleeReflection, $parameter)) { continue; } $type = $extension->getClosureThisTypeFromFunctionCall($calleeReflection, $call, $parameter, $scope); if ($type !== null) { return $type; } } } elseif ($call instanceof StaticCall && $calleeReflection instanceof MethodReflection) { foreach ($this->parameterClosureThisExtensionProvider->getStaticMethodParameterClosureThisExtensions() as $extension) { if (!$extension->isStaticMethodSupported($calleeReflection, $parameter)) { continue; } $type = $extension->getClosureThisTypeFromStaticMethodCall($calleeReflection, $call, $parameter, $scope); if ($type !== null) { return $type; } } } elseif ($call instanceof MethodCall && $calleeReflection instanceof MethodReflection) { foreach ($this->parameterClosureThisExtensionProvider->getMethodParameterClosureThisExtensions() as $extension) { if (!$extension->isMethodSupported($calleeReflection, $parameter)) { continue; } $type = $extension->getClosureThisTypeFromMethodCall($calleeReflection, $call, $parameter, $scope); if ($type !== null) { return $type; } } } if ($parameter instanceof ExtendedParameterReflection) { return $parameter->getClosureThisType(); } return null; } /** * @param MethodReflection|FunctionReflection|null $calleeReflection * @param callable(Node $node, Scope $scope): void $nodeCallback */ public function processArgs(Node\Stmt $stmt, $calleeReflection, ?ExtendedMethodReflection $nakedMethodReflection, ?ParametersAcceptor $parametersAcceptor, CallLike $callLike, \PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\ExpressionResultStorage $storage, callable $nodeCallback, \PHPStan\Analyser\ExpressionContext $context, ?\PHPStan\Analyser\MutatingScope $closureBindScope = null): \PHPStan\Analyser\ExpressionResult { $args = $callLike->getArgs(); $parameters = null; if ($parametersAcceptor !== null) { $parameters = $parametersAcceptor->getParameters(); } $hasYield = \false; $throwPoints = []; $impurePoints = []; $isAlwaysTerminating = \false; /** @var list $deferredInvalidateExpressions */ $deferredInvalidateExpressions = []; /** @var ProcessClosureResult[] $deferredByRefClosureResults */ $deferredByRefClosureResults = []; foreach ($args as $i => $arg) { $assignByReference = \false; $parameter = null; $parameterType = null; $parameterNativeType = null; if ($parameters !== null) { $matchedParameter = null; if ($arg->name !== null) { foreach ($parameters as $p) { if ($p->getName() === $arg->name->toString()) { $matchedParameter = $p; break; } } } elseif (isset($parameters[$i])) { $matchedParameter = $parameters[$i]; } if ($matchedParameter !== null) { $assignByReference = $matchedParameter->passedByReference()->createsNewVariable(); $parameterType = $matchedParameter->getType(); if ($matchedParameter instanceof ExtendedParameterReflection) { $parameterNativeType = $matchedParameter->getNativeType(); } $parameter = $matchedParameter; } elseif (count($parameters) > 0 && $parametersAcceptor->isVariadic()) { $lastParameter = array_last($parameters); $assignByReference = $lastParameter->passedByReference()->createsNewVariable(); $parameterType = $lastParameter->getType(); if ($lastParameter instanceof ExtendedParameterReflection) { $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; } } $originalArg = $arg->getAttribute(\PHPStan\Analyser\ArgumentsNormalizer::ORIGINAL_ARG_ATTRIBUTE) ?? $arg; if ($calleeReflection !== null) { $rememberTypes = !$originalArg->value instanceof Expr\Closure && !$originalArg->value instanceof Expr\ArrowFunction; $scope = $scope->pushInFunctionCall($calleeReflection, $parameter, $rememberTypes); } $this->callNodeCallback($nodeCallback, $originalArg, $scope, $storage); $originalScope = $scope; $scopeToPass = $scope; if ($i === 0 && $closureBindScope !== null && ($arg->value instanceof Expr\Closure || $arg->value instanceof Expr\ArrowFunction)) { $scopeToPass = $closureBindScope; } if ($arg->value instanceof Expr\Closure) { $restoreThisScope = null; if ($closureBindScope === null && $parameter instanceof ExtendedParameterReflection && !$arg->value->static) { $closureThisType = $this->resolveClosureThisType($callLike, $calleeReflection, $parameter, $scopeToPass); if ($closureThisType !== null) { $restoreThisScope = $scopeToPass; $scopeToPass = $scopeToPass->assignVariable('this', $closureThisType, new ObjectWithoutClassType(), TrinaryLogic::createYes()); } } if ($parameter !== null) { $overwritingParameterType = $this->getParameterTypeFromParameterClosureTypeExtension($callLike, $calleeReflection, $parameter, $scopeToPass); if ($overwritingParameterType !== null) { $parameterType = $overwritingParameterType; } } $this->callNodeCallbackWithExpression($nodeCallback, $arg->value, $scopeToPass, $storage, $context); $closureResult = $this->processClosureNode($stmt, $arg->value, $scopeToPass, $storage, $nodeCallback, $context, $parameterType ?? null); if ($this->callCallbackImmediately($parameter, $parameterType, $calleeReflection)) { $throwPoints = array_merge($throwPoints, array_map(static fn(\PHPStan\Analyser\InternalThrowPoint $throwPoint) => $throwPoint->isExplicit() ? \PHPStan\Analyser\InternalThrowPoint::createExplicit($scope, $throwPoint->getType(), $arg->value, $throwPoint->canContainAnyThrowable()) : \PHPStan\Analyser\InternalThrowPoint::createImplicit($scope, $arg->value), $closureResult->getThrowPoints())); $impurePoints = array_merge($impurePoints, $closureResult->getImpurePoints()); } $this->storeBeforeScope($storage, $arg->value, $scopeToPass); $uses = []; foreach ($arg->value->uses as $use) { if (!is_string($use->var->name)) { continue; } $uses[] = $use->var->name; } $scope = $closureResult->getScope(); $deferredByRefClosureResults[] = $closureResult; $invalidateExpressions = $closureResult->getInvalidateExpressions(); if ($restoreThisScope !== null) { $nodeFinder = new NodeFinder(); $cb = static fn($expr) => $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); } if ($this->callCallbackImmediately($parameter, $parameterType, $calleeReflection)) { $deferredInvalidateExpressions[] = [$invalidateExpressions, $uses]; } } elseif ($arg->value instanceof Expr\ArrowFunction) { if ($closureBindScope === null && $parameter instanceof ExtendedParameterReflection && !$arg->value->static) { $closureThisType = $this->resolveClosureThisType($callLike, $calleeReflection, $parameter, $scopeToPass); if ($closureThisType !== null) { $scopeToPass = $scopeToPass->assignVariable('this', $closureThisType, new ObjectWithoutClassType(), TrinaryLogic::createYes()); } } if ($parameter !== null) { $overwritingParameterType = $this->getParameterTypeFromParameterClosureTypeExtension($callLike, $calleeReflection, $parameter, $scopeToPass); if ($overwritingParameterType !== null) { $parameterType = $overwritingParameterType; } } $this->callNodeCallbackWithExpression($nodeCallback, $arg->value, $scopeToPass, $storage, $context); $arrowFunctionResult = $this->processArrowFunctionNode($stmt, $arg->value, $scopeToPass, $storage, $nodeCallback, $parameterType ?? null); if ($this->callCallbackImmediately($parameter, $parameterType, $calleeReflection)) { $throwPoints = array_merge($throwPoints, array_map(static fn(\PHPStan\Analyser\InternalThrowPoint $throwPoint) => $throwPoint->isExplicit() ? \PHPStan\Analyser\InternalThrowPoint::createExplicit($scope, $throwPoint->getType(), $arg->value, $throwPoint->canContainAnyThrowable()) : \PHPStan\Analyser\InternalThrowPoint::createImplicit($scope, $arg->value), $arrowFunctionResult->getThrowPoints())); $impurePoints = array_merge($impurePoints, $arrowFunctionResult->getImpurePoints()); } $this->storeBeforeScope($storage, $arg->value, $scopeToPass); } else { $exprType = $scope->getType($arg->value); $enterExpressionAssignForByRef = $assignByReference && $arg->value instanceof ArrayDimFetch && $arg->value->dim === null; if ($enterExpressionAssignForByRef) { $scopeToPass = $scopeToPass->enterExpressionAssign($arg->value); } $exprResult = $this->processExprNode($stmt, $arg->value, $scopeToPass, $storage, $nodeCallback, $context->enterDeep()); $throwPoints = array_merge($throwPoints, $exprResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $exprResult->getImpurePoints()); $isAlwaysTerminating = $isAlwaysTerminating || $exprResult->isAlwaysTerminating(); $scope = $exprResult->getScope(); if ($enterExpressionAssignForByRef) { $scope = $scope->exitExpressionAssign($arg->value); } $hasYield = $hasYield || $exprResult->hasYield(); if ($exprType->isCallable()->yes()) { $acceptors = $exprType->getCallableParametersAcceptors($scope); if (count($acceptors) === 1) { if ($this->callCallbackImmediately($parameter, $parameterType, $calleeReflection)) { $deferredInvalidateExpressions[] = [$acceptors[0]->getInvalidateExpressions(), $acceptors[0]->getUsedVariables()]; $callableThrowPoints = array_map(static fn(SimpleThrowPoint $throwPoint) => $throwPoint->isExplicit() ? \PHPStan\Analyser\InternalThrowPoint::createExplicit($scope, $throwPoint->getType(), $arg->value, $throwPoint->canContainAnyThrowable()) : \PHPStan\Analyser\InternalThrowPoint::createImplicit($scope, $arg->value), $acceptors[0]->getThrowPoints()); if (!$this->implicitThrows) { $callableThrowPoints = array_values(array_filter($callableThrowPoints, static fn(\PHPStan\Analyser\InternalThrowPoint $throwPoint) => $throwPoint->isExplicit())); } $throwPoints = array_merge($throwPoints, $callableThrowPoints); $impurePoints = array_merge($impurePoints, array_map(static fn(SimpleImpurePoint $impurePoint) => 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 ($deferredInvalidateExpressions as [$invalidateExpressions, $uses]) { $scope = $this->processImmediatelyCalledCallable($scope, $invalidateExpressions, $uses); } foreach ($deferredByRefClosureResults as $deferredClosureResult) { $scope = $deferredClosureResult->applyByRefUseScope($scope); } if ($parameters !== null) { foreach ($args as $i => $arg) { $assignByReference = \false; $currentParameter = null; if (isset($parameters[$i])) { $currentParameter = $parameters[$i]; } elseif (count($parameters) > 0 && $parametersAcceptor->isVariadic()) { $currentParameter = array_last($parameters); } if ($currentParameter !== null) { $assignByReference = $currentParameter->passedByReference()->createsNewVariable(); } 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; } elseif ($currentParameter instanceof ExtendedParameterReflection && $currentParameter->getOutType() !== null) { $byRefType = $currentParameter->getOutType(); } elseif ($calleeReflection instanceof MethodReflection && !$calleeReflection->getDeclaringClass()->isBuiltin()) { $byRefType = $currentParameter->getType(); } elseif ($calleeReflection instanceof FunctionReflection && !$calleeReflection->isBuiltin()) { $byRefType = $currentParameter->getType(); } else { $byRefType = new MixedType(); } $scope = $this->processVirtualAssign($scope, $storage, $stmt, $argValue, new TypeExpr($byRefType), $nodeCallback)->getScope(); $scope = $this->lookForUnsetAllowedUndefinedExpressions($scope, $argValue); } } 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()) { $this->callNodeCallback($nodeCallback, new InvalidateExprNode($arg->value), $scope, $storage); $scope = $scope->invalidateExpression($arg->value, \true); } } elseif (!(new ResourceType())->isSuperTypeOf($argType)->no()) { $this->callNodeCallback($nodeCallback, new InvalidateExprNode($arg->value), $scope, $storage); $scope = $scope->invalidateExpression($arg->value, \true); } } } } // not storing this, it's scope after processing all args return new \PHPStan\Analyser\ExpressionResult($scope, $hasYield, $isAlwaysTerminating, $throwPoints, $impurePoints); } /** * @param MethodReflection|FunctionReflection|null $calleeReflection */ private function callCallbackImmediately(?ParameterReflection $parameter, ?Type $parameterType, $calleeReflection): bool { $parameterCallableType = null; if ($parameterType !== null && $calleeReflection instanceof FunctionReflection) { $parameterCallableType = TypeUtils::findCallableType($parameterType); } if ($parameter instanceof ExtendedParameterReflection) { $parameterCallImmediately = $parameter->isImmediatelyInvokedCallable(); if ($parameterCallImmediately->maybe()) { $callCallbackImmediately = $parameterCallableType !== null; } else { $callCallbackImmediately = $parameterCallImmediately->yes(); } } else { $callCallbackImmediately = $parameterCallableType !== null; } return $callCallbackImmediately; } /** * @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 New_ && $callLike->class instanceof Name) { $staticCall = new StaticCall($callLike->class, new Identifier('__construct'), $callLike->getArgs()); foreach ($this->parameterClosureTypeExtensionProvider->getStaticMethodParameterClosureTypeExtensions() as $staticMethodParameterClosureTypeExtension) { if ($staticMethodParameterClosureTypeExtension->isStaticMethodSupported($calleeReflection, $parameter)) { return $staticMethodParameterClosureTypeExtension->getTypeFromStaticMethodCall($calleeReflection, $staticCall, $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 */ public function processVirtualAssign(\PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\ExpressionResultStorage $storage, Node\Stmt $stmt, Expr $var, Expr $assignedExpr, callable $nodeCallback): \PHPStan\Analyser\ExpressionResult { return $this->container->getByType(AssignHandler::class)->processAssignVar($this, $scope, $storage, $stmt, $var, $assignedExpr, new \PHPStan\Analyser\VirtualAssignNodeCallback($nodeCallback), \PHPStan\Analyser\ExpressionContext::createDeep(), static fn(\PHPStan\Analyser\MutatingScope $scope): \PHPStan\Analyser\ExpressionResult => new \PHPStan\Analyser\ExpressionResult($scope, \false, \false, [], []), \false); } /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ public function processStmtVarAnnotation(\PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\ExpressionResultStorage $storage, 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())) { $this->callNodeCallback($nodeCallback, new VarTagChangedExpressionTypeNode($varTag, $variableNode), $scope, $storage); } $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())) { $this->callNodeCallback($nodeCallback, new VarTagChangedExpressionTypeNode($varTag, $defaultExpr), $scope, $storage); } $scope = $scope->assignExpression($defaultExpr, $varTag->getType(), new MixedType()); } return $scope; } /** * @param array $variableNames */ public 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(), TrinaryLogic::createYes()); } if (count($variableNames) === 1 && count($varTags) === 1 && isset($varTags[0])) { $variableType = $varTags[0]->getType(); $changed = \true; $scope = $scope->assignVariable($variableNames[0], $variableType, new MixedType(), TrinaryLogic::createYes()); } return $scope; } /** * @return array{bodyScope: MutatingScope, endScope: MutatingScope}|null */ private function tryProcessUnrolledConstantArrayForeach(Foreach_ $stmt, \PHPStan\Analyser\MutatingScope $originalScope, \PHPStan\Analyser\ExpressionResultStorage $originalStorage, \PHPStan\Analyser\StatementContext $context): ?array { if ($stmt->byRef) { return null; } if (!($stmt->valueVar instanceof Variable && is_string($stmt->valueVar->name))) { return null; } if ($stmt->keyVar !== null && !($stmt->keyVar instanceof Variable && is_string($stmt->keyVar->name))) { return null; } $iterateeType = $originalScope->getType($stmt->expr); if (!$iterateeType->isConstantArray()->yes()) { return null; } $constantArrays = $iterateeType->getConstantArrays(); if (count($constantArrays) === 0) { return null; } $totalKeys = 0; foreach ($constantArrays as $constantArray) { $totalKeys += count($constantArray->getKeyTypes()); } if ($totalKeys === 0 || $totalKeys > self::FOREACH_UNROLL_LIMIT) { return null; } if ($context->getForeachUnrollFactor() * $totalKeys > self::FOREACH_UNROLL_NESTED_LIMIT) { return null; } $nativeIterateeType = $originalScope->getNativeType($stmt->expr); $nativeConstantArrays = $nativeIterateeType->getConstantArrays(); $matchedNativeArrays = count($nativeConstantArrays) === count($constantArrays) ? $nativeConstantArrays : null; $valueVarName = $stmt->valueVar->name; $keyVarName = $stmt->keyVar instanceof Variable ? $stmt->keyVar->name : null; $allBodyScopes = []; $allChainScopes = []; $allBreakScopes = []; $bodyContext = $context->enterUnrolledForeach($totalKeys); foreach ($constantArrays as $arrayIndex => $constantArray) { $keyTypes = $constantArray->getKeyTypes(); $valueTypes = $constantArray->getValueTypes(); if (count($keyTypes) === 0) { continue; } $nativeConstantArray = $matchedNativeArrays !== null ? $matchedNativeArrays[$arrayIndex] : null; $optionalKeys = array_fill_keys($constantArray->getOptionalKeys(), \true); $chainScope = $originalScope; $entryScopes = []; foreach ($keyTypes as $i => $keyType) { $valueType = $valueTypes[$i]; $isOptional = isset($optionalKeys[$i]); $nativeKeyType = $nativeConstantArray !== null && isset($nativeConstantArray->getKeyTypes()[$i]) ? $nativeConstantArray->getKeyTypes()[$i] : $keyType; $nativeValueType = $nativeConstantArray !== null && isset($nativeConstantArray->getValueTypes()[$i]) ? $nativeConstantArray->getValueTypes()[$i] : $valueType; $iterScope = $chainScope->assignVariable($valueVarName, $valueType, $nativeValueType, TrinaryLogic::createYes()); $iterScope = $iterScope->assignExpression(new OriginalForeachValueExpr($valueVarName), $valueType, $nativeValueType); if ($keyVarName !== null) { $iterScope = $iterScope->assignVariable($keyVarName, $keyType, $nativeKeyType, TrinaryLogic::createYes()); $iterScope = $iterScope->assignExpression(new OriginalForeachKeyExpr($keyVarName), $keyType, $nativeKeyType); $iterScope = $iterScope->assignExpression(new ArrayDimFetch($stmt->expr, $stmt->keyVar), $valueType, $nativeValueType); } $entryScopes[] = $iterScope; $iterStorage = $originalStorage->duplicate(); $bodyResult = $this->processStmtNodesInternal($stmt, $stmt->stmts, $iterScope, $iterStorage, new \PHPStan\Analyser\NoopNodeCallback(), $bodyContext)->filterOutLoopExitPoints(); $iterEndScope = $bodyResult->getScope(); foreach ($bodyResult->getExitPointsByType(Continue_::class) as $continueExitPoint) { $iterEndScope = $iterEndScope->mergeWith($continueExitPoint->getScope()); } foreach ($bodyResult->getExitPointsByType(Break_::class) as $breakExitPoint) { $allBreakScopes[] = $breakExitPoint->getScope(); } if ($isOptional) { $chainScope = $iterEndScope->mergeWith($chainScope); } else { $chainScope = $iterEndScope; } } $arrayBodyScope = $entryScopes[0]; for ($i = 1, $c = count($entryScopes); $i < $c; $i++) { $arrayBodyScope = $arrayBodyScope->mergeWith($entryScopes[$i]); } if (count($entryScopes) === 1) { $arrayBodyScope = $arrayBodyScope->mergeWith($chainScope); } $allBodyScopes[] = $arrayBodyScope; $allChainScopes[] = $chainScope; } if ($allBodyScopes === []) { return null; } $bodyScope = $allBodyScopes[0]; for ($i = 1, $c = count($allBodyScopes); $i < $c; $i++) { $bodyScope = $bodyScope->mergeWith($allBodyScopes[$i]); } $endScope = $allChainScopes[0]; for ($i = 1, $c = count($allChainScopes); $i < $c; $i++) { $endScope = $endScope->mergeWith($allChainScopes[$i]); } foreach ($allBreakScopes as $breakScope) { $endScope = $endScope->mergeWith($breakScope); } return ['bodyScope' => $bodyScope, 'endScope' => $endScope]; } private function getTraversableForeachThrowPoint(\PHPStan\Analyser\MutatingScope $scope, Expr $iteratee): ?\PHPStan\Analyser\InternalThrowPoint { $exprType = $scope->getType($iteratee); $traversableType = new ObjectType(Traversable::class); if ($traversableType->isSuperTypeOf($exprType)->no()) { return null; } $traversablePart = TypeCombinator::intersect($exprType, $traversableType); $iteratorAggregateType = new ObjectType(IteratorAggregate::class); if ($iteratorAggregateType->isSuperTypeOf($traversablePart)->yes() && $traversablePart->hasMethod('getIterator')->yes()) { $method = $traversablePart->getMethod('getIterator', $scope); $throwType = $method->getThrowType(); if ($throwType !== null) { if ($throwType->isVoid()->yes()) { return null; } return \PHPStan\Analyser\InternalThrowPoint::createExplicit($scope, $throwType, $iteratee, \true); } if (!$this->implicitThrows) { return null; } } return \PHPStan\Analyser\InternalThrowPoint::createImplicit($scope, $iteratee); } /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ private function enterForeach(\PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\ExpressionResultStorage $storage, \PHPStan\Analyser\MutatingScope $originalScope, Foreach_ $stmt, callable $nodeCallback): \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 = $stmt->keyVar instanceof Variable ? $stmt->keyVar->name : null; $scope = $scope->enterForeach($originalScope, $stmt->expr, $stmt->valueVar->name, $keyVarName, $stmt->byRef); $vars = [$stmt->valueVar->name]; if ($keyVarName !== null) { $vars[] = $keyVarName; } } else { $scope = $this->processVirtualAssign($scope, $storage, $stmt, $stmt->valueVar, new GetIterableValueTypeExpr($stmt->expr), $nodeCallback)->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->processVirtualAssign($scope, $storage, $stmt, $stmt->keyVar, new GetIterableKeyTypeExpr($stmt->expr), $nodeCallback)->getScope(); $vars = array_merge($vars, $this->getAssignedVariables($stmt->keyVar)); } if ($stmt->valueVar instanceof List_) { $scope = $this->addDestructureTaggedUnionConditionalHolders($scope, $originalScope->getIterableValueType($iterateeType), $stmt->valueVar); } } $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]; $keyExpressionTypeHolder = \PHPStan\Analyser\ExpressionTypeHolder::createYes(new Variable($stmt->keyVar->name), $keyType); $holder = new \PHPStan\Analyser\ConditionalExpressionHolder(['$' . $stmt->keyVar->name => $keyExpressionTypeHolder], \PHPStan\Analyser\ExpressionTypeHolder::createYes($stmt->valueVar, $valueType)); $valueConditionalHolders[$holder->getKey()] = $holder; $arrayDimFetchHolder = new \PHPStan\Analyser\ConditionalExpressionHolder(['$' . $stmt->keyVar->name => $keyExpressionTypeHolder], \PHPStan\Analyser\ExpressionTypeHolder::createYes(new ArrayDimFetch($stmt->expr, $stmt->keyVar), $valueType)); $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); } } if ($stmt->expr instanceof FuncCall && $stmt->expr->name instanceof Name && !$stmt->expr->isFirstClassCallable() && $stmt->expr->name->toLowerString() === 'array_keys' && $stmt->valueVar instanceof Variable) { $args = $stmt->expr->getArgs(); if (count($args) >= 1) { $arrayArg = $args[0]->value; $scope = $scope->assignExpression(new ArrayDimFetch($arrayArg, $stmt->valueVar), $scope->getType($arrayArg)->getIterableValueType(), $scope->getNativeType($arrayArg)->getIterableValueType()); } } return $this->processVarAnnotation($scope, $vars, $stmt); } /** * When destructuring an iterable whose value type is a tagged union of * constant arrays — e.g. `array` — the * variants describe a relationship between the destructured variables that * a per-variable narrowing would normally lose: knowing `$x === null` should * imply `$y === int`, but `foreach ($a as [$x, $y])` assigns `$x` and `$y` * independently, so each ends up as the union (`int|null`) and the link is * dropped. * * Recover the link by storing conditional-expression holders on each * destructured variable: for every variant, "when this variable matches the * variant's value at its position, the other variables match the variant's * values at their positions". A later `if ($x === null)` then fires the * matching holder and narrows `$y` accordingly. * * Only handles flat positional / keyed destructure patterns (List_) where * each item's target is a plain Variable; nested destructure is left for * the regular per-variable type tracking. */ private function addDestructureTaggedUnionConditionalHolders(\PHPStan\Analyser\MutatingScope $scope, Type $iterableValueType, List_ $list): \PHPStan\Analyser\MutatingScope { $constantArrays = $iterableValueType->getConstantArrays(); if (count($constantArrays) < 2) { return $scope; } // Collect each list item's array-key value and target variable. $items = []; foreach ($list->items as $position => $item) { if ($item === null) { continue; } if (!$item->value instanceof Variable || !is_string($item->value->name)) { return $scope; } if ($item->key === null) { $keyValue = $position; } elseif ($item->key instanceof Node\Scalar\String_) { $keyValue = $item->key->value; } elseif ($item->key instanceof Node\Scalar\Int_) { $keyValue = $item->key->value; } else { return $scope; } $items[] = ['key' => $keyValue, 'name' => $item->value->name]; } if (count($items) < 2) { return $scope; } // For every variant, every item must have a matching key with a single // value type at it; otherwise the variants don't all describe the same // destructure shape and we can't form a sound holder set. $variantValuesByItem = []; foreach ($items as $itemIdx => $itemInfo) { $variantValuesByItem[$itemIdx] = []; foreach ($constantArrays as $variantIdx => $variant) { $keyType = is_int($itemInfo['key']) ? new ConstantIntegerType($itemInfo['key']) : new ConstantStringType($itemInfo['key']); if (!$variant->hasOffsetValueType($keyType)->yes()) { return $scope; } $variantValuesByItem[$itemIdx][$variantIdx] = $variant->getOffsetValueType($keyType); } } // For each item × variant, build a holder: "when item is variant's value // at this position, the *other* items are the variant's values at their // positions". Skip the variant if the condition value is too wide to be // a useful discriminator (i.e. equal to the union of all the variant // values at this position — narrowing it back wouldn't pick a variant). foreach ($items as $itemIdx => $itemInfo) { $exprString = '$' . $itemInfo['name']; $variantConditionTypes = $variantValuesByItem[$itemIdx]; $itemUnionType = TypeCombinator::union(...array_values($variantConditionTypes)); $holders = []; foreach (array_keys($constantArrays) as $variantIdx) { $conditionType = $variantConditionTypes[$variantIdx]; if ($conditionType->equals($itemUnionType)) { continue; } $conditions = [$exprString => \PHPStan\Analyser\ExpressionTypeHolder::createYes(new Variable($itemInfo['name']), $conditionType)]; foreach ($items as $otherIdx => $otherInfo) { if ($otherIdx === $itemIdx) { continue; } $otherType = $variantValuesByItem[$otherIdx][$variantIdx]; $holder = new \PHPStan\Analyser\ConditionalExpressionHolder($conditions, \PHPStan\Analyser\ExpressionTypeHolder::createYes(new Variable($otherInfo['name']), $otherType)); $holders['$' . $otherInfo['name']][$holder->getKey()] = $holder; } } foreach ($holders as $targetExprString => $targetHolders) { $scope = $scope->addConditionalExpressions($targetExprString, $targetHolders); } } return $scope; } /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ private function processTraitUse(Node\Stmt\TraitUse $node, \PHPStan\Analyser\MutatingScope $classScope, \PHPStan\Analyser\ExpressionResultStorage $storage, 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, $storage, $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, \PHPStan\Analyser\ExpressionResultStorage $storage, 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 & ~Modifiers::VISIBILITY_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); $this->callNodeCallback($nodeCallback, new InTraitNode($node, $traitReflection, $scope->getClassReflection()), $traitScope, $storage); $this->processStmtNodesInternal($node, $stmts, $traitScope, $storage, $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, $storage, $adaptations, $nodeCallback); } } elseif (is_array($node)) { foreach ($node as $subNode) { $this->processNodesForTraitUse($subNode, $traitReflection, $scope, $storage, $adaptations, $nodeCallback); } } } public 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])) { unset($this->calledMethodStack[$stackName]); return null; } $parserNodes = $this->parser->parseFile($fileName); $returnStatement = null; $this->processNodesForCalledMethod($parserNodes, new \PHPStan\Analyser\ExpressionResultStorage(), $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\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, \PHPStan\Analyser\ExpressionResultStorage $storage, string $fileName, MethodReflection $methodReflection, callable $nodeCallback): void { if ($node instanceof Node) { $declaringClass = $methodReflection->getDeclaringClass(); if ($node instanceof Node\Stmt\Class_ && isset($node->namespacedName) && $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, $storage, $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, $storage, $fileName, $methodReflection, $nodeCallback); } } elseif (is_array($node)) { foreach ($node as $subNode) { $this->processNodesForCalledMethod($subNode, $storage, $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, ?ResolvedPhpDocBlock} * @param \PhpParser\Node\FunctionLike|\PhpParser\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()); $currentResolvedPhpDoc = null; if ($docComment !== null) { $currentResolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($file, $class, $trait, $node->name->name, $docComment); } $methodNameForInheritance = $node->getAttribute('originalTraitMethodName') ?? $node->name->name; $resolvedPhpDoc = $this->phpDocInheritanceResolver->resolvePhpDocForMethod($scope->getClassReflection(), $methodNameForInheritance, $currentResolvedPhpDoc, $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, '\\'); } elseif ($node instanceof Node\PropertyHook) { $propertyName = $node->getAttribute('propertyName'); if ($propertyName !== null) { $functionName = sprintf('$%s::%s', $propertyName, $node->name->toString()); } } 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(); $isReadOnly = $isReadOnly || $resolvedPhpDoc->isReadOnly(); $asserts = Assertions::createFromResolvedPhpDocBlock($resolvedPhpDoc); $selfOutType = $resolvedPhpDoc->getSelfOutTag() !== null ? $resolvedPhpDoc->getSelfOutTag()->getType() : null; $varTags = $resolvedPhpDoc->getVarTags(); } if ($acceptsNamedArguments && $scope->isInClass()) { $acceptsNamedArguments = $scope->getClassReflection()->acceptsNamedArguments(); } if ($isPure === null && $node instanceof Node\FunctionLike && $scope->isInClass()) { $classResolvedPhpDoc = $scope->getClassReflection()->getResolvedPhpDoc(); if ($classResolvedPhpDoc !== null && $classResolvedPhpDoc->areAllMethodsPure()) { if (strtolower($functionName ?? '') === '__construct' || ($phpDocReturnType === null || !$phpDocReturnType->isVoid()->yes()) && !$scope->getFunctionType($node->getReturnType(), \false, \false)->isVoid()->yes()) { $isPure = \true; } } elseif ($classResolvedPhpDoc !== null && $classResolvedPhpDoc->areAllMethodsImpure()) { $isPure = \false; } } return [$templateTypeMap, $phpDocParameterTypes, $phpDocImmediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters, $phpDocReturnType, $phpDocThrowType, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal, $isPure, $acceptsNamedArguments, $isReadOnly, $docComment, $asserts, $selfOutType, $phpDocParameterOutTypes, $varTags, $isAllowedPrivateMutation, $resolvedPhpDoc]; } 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; } if ($phpDocReturnType instanceof UnionType) { $types = []; foreach ($phpDocReturnType->getTypes() as $innerType) { if (!$nativeReturnType->isSuperTypeOf($innerType)->yes()) { continue; } $types[] = $innerType; } if (count($types) === 0) { return null; } return TypeCombinator::union(...$types); } return null; } /** * @param array $nodes * @return list */ private function getNextUnreachableStatements(array $nodes, bool $earlyBinding): array { $stmts = []; $isPassedUnreachableStatement = \false; foreach ($nodes as $node) { if ($earlyBinding && ($node instanceof Node\Stmt\Function_ || $node instanceof Node\Stmt\ClassLike || $node instanceof Node\Stmt\HaltCompiler)) { continue; } if ($isPassedUnreachableStatement && $node instanceof Node\Stmt) { $stmts[] = $node; continue; } if ($node instanceof Node\Stmt\Nop || $node instanceof Node\Stmt\InlineHTML) { continue; } if (!$node instanceof Node\Stmt) { continue; } $stmts[] = $node; $isPassedUnreachableStatement = \true; } return $stmts; } private function inferForLoopExpressions(For_ $stmt, Expr $lastCondExpr, \PHPStan\Analyser\MutatingScope $bodyScope): \PHPStan\Analyser\MutatingScope { // infer $items[$i] type from for ($i = 0; $i < count($items); $i++) {...} if (count($stmt->init) === 1 && $stmt->init[0] instanceof Assign && $stmt->init[0]->var instanceof Variable && $stmt->init[0]->expr instanceof Node\Scalar\Int_ && $stmt->init[0]->expr->value === 0 && count($stmt->loop) === 1 && ($stmt->loop[0] instanceof Expr\PreInc || $stmt->loop[0] instanceof Expr\PostInc) && $stmt->loop[0]->var instanceof Variable) { // $i < count($items) if ($lastCondExpr instanceof BinaryOp\Smaller && $lastCondExpr->left instanceof Variable && $lastCondExpr->right instanceof FuncCall && $lastCondExpr->right->name instanceof Name && !$lastCondExpr->right->isFirstClassCallable() && in_array($lastCondExpr->right->name->toLowerString(), ['count', 'sizeof'], \true) && count($lastCondExpr->right->getArgs()) > 0 && $lastCondExpr->right->getArgs()[0]->value instanceof Variable && is_string($stmt->init[0]->var->name) && $stmt->init[0]->var->name === $stmt->loop[0]->var->name && $stmt->init[0]->var->name === $lastCondExpr->left->name) { $arrayArg = $lastCondExpr->right->getArgs()[0]->value; $arrayType = $bodyScope->getType($arrayArg); if ($arrayType->isList()->yes()) { $bodyScope = $bodyScope->assignExpression(new ArrayDimFetch($lastCondExpr->right->getArgs()[0]->value, $lastCondExpr->left), $arrayType->getIterableValueType(), $bodyScope->getNativeType($arrayArg)->getIterableValueType()); } } // count($items) > $i if ($lastCondExpr instanceof BinaryOp\Greater && $lastCondExpr->right instanceof Variable && $lastCondExpr->left instanceof FuncCall && $lastCondExpr->left->name instanceof Name && !$lastCondExpr->left->isFirstClassCallable() && in_array($lastCondExpr->left->name->toLowerString(), ['count', 'sizeof'], \true) && count($lastCondExpr->left->getArgs()) > 0 && $lastCondExpr->left->getArgs()[0]->value instanceof Variable && is_string($stmt->init[0]->var->name) && $stmt->init[0]->var->name === $stmt->loop[0]->var->name && $stmt->init[0]->var->name === $lastCondExpr->right->name) { $arrayArg = $lastCondExpr->left->getArgs()[0]->value; $arrayType = $bodyScope->getType($arrayArg); if ($arrayType->isList()->yes()) { $bodyScope = $bodyScope->assignExpression(new ArrayDimFetch($lastCondExpr->left->getArgs()[0]->value, $lastCondExpr->right), $arrayType->getIterableValueType(), $bodyScope->getNativeType($arrayArg)->getIterableValueType()); } } } return $bodyScope; } private function getGlobalVariableType(string $variableName): Type { if ($variableName === 'argc') { return StaticTypeFactory::argc(); } if ($variableName === 'argv') { return StaticTypeFactory::argv(); } return new MixedType(); } } 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; } } isPublic(); } public function canReadProperty(ExtendedPropertyReflection $propertyReflection): bool { return $propertyReflection->isPublic(); } public function canWriteProperty(ExtendedPropertyReflection $propertyReflection): bool { return $propertyReflection->isPublic() && !$propertyReflection->isProtectedSet() && !$propertyReflection->isPrivateSet(); } public function canCallMethod(MethodReflection $methodReflection): bool { return $methodReflection->isPublic(); } public function canAccessConstant(ClassConstantReflection $constantReflection): bool { return $constantReflection->isPublic(); } } scope = $scope; $this->throwPoints = $throwPoints; $this->impurePoints = $impurePoints; $this->invalidateExpressions = $invalidateExpressions; $this->byRefClosureResultScope = $byRefClosureResultScope; $this->byRefUses = $byRefUses; } public function getScope(): \PHPStan\Analyser\MutatingScope { return $this->scope; } public function applyByRefUseScope(\PHPStan\Analyser\MutatingScope $scope): \PHPStan\Analyser\MutatingScope { if ($this->byRefClosureResultScope === null) { return $scope; } return $scope->processClosureScope($this->byRefClosureResultScope, null, $this->byRefUses); } /** * @return InternalThrowPoint[] */ 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; } } > */ private array $errors; /** * @var array> */ private array $locallyIgnoredErrors; /** * @var array */ private array $linesToIgnore; /** * @var array */ private array $unmatchedLineIgnores; /** * @var CollectorData */ private array $collectedData; /** * @var array> */ private array $dependencies; /** * @var array> */ private array $usedTraitDependencies; /** * @var array> */ private array $exportedNodes; /** * @var array */ private array $projectExtensionFiles; /** * @var array */ private array $currentFileHashes; /** * @param string[] $filesToAnalyse * @param mixed[] $meta * @param array> $errors * @param array> $locallyIgnoredErrors * @param array $linesToIgnore * @param array $unmatchedLineIgnores * @param CollectorData $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 CollectorData */ 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; } } cacheFilePath = $cacheFilePath; } public function clear(): string { $dir = dirname($this->cacheFilePath); if (!is_file($this->cacheFilePath)) { return $dir; } @unlink($this->cacheFilePath); return $dir; } } */ private array $fileReplacements; private bool $checkDependenciesOfProjectExtensionFiles; /** * @var list> */ private array $parametersNotInvalidatingCache; private int $skipResultCacheIfOlderThanDays; private const CACHE_VERSION = 'v12-linesToIgnore'; /** @var array */ private array $fileHashes = []; /** @var array */ private array $alreadyProcessed = []; /** * @param string[] $analysedPaths * @param string[] $analysedPathsFromConfig * @param string[] $composerAutoloaderProjectPaths * @param string[] $bootstrapFiles * @param string[] $scanFiles * @param string[] $scanDirectories * @param list> $parametersNotInvalidatingCache * @param array $fileReplacements */ public function __construct( Container $container, ExportedNodeFetcher $exportedNodeFetcher, #[AutowiredParameter('@fileFinderScan')] FileFinder $scanFileFinder, StubFilesProvider $stubFilesProvider, FileHelper $fileHelper, #[AutowiredParameter('%resultCachePath%')] string $cacheFilePath, #[AutowiredParameter] array $analysedPaths, #[AutowiredParameter] array $analysedPathsFromConfig, #[AutowiredParameter] array $composerAutoloaderProjectPaths, #[AutowiredParameter] string $usedLevel, #[AutowiredParameter] ?string $cliAutoloadFile, #[AutowiredParameter] array $bootstrapFiles, #[AutowiredParameter] array $scanFiles, #[AutowiredParameter] array $scanDirectories, array $fileReplacements, #[AutowiredParameter('%resultCacheChecksProjectExtensionFilesDependencies%')] bool $checkDependenciesOfProjectExtensionFiles, #[AutowiredParameter] array $parametersNotInvalidatingCache, #[AutowiredParameter('%resultCacheSkipIfOlderThanDays%')] int $skipResultCacheIfOlderThanDays ) { $this->container = $container; $this->exportedNodeFetcher = $exportedNodeFetcher; $this->scanFileFinder = $scanFileFinder; $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; $this->parametersNotInvalidatingCache = $parametersNotInvalidatingCache; $this->skipResultCacheIfOlderThanDays = $skipResultCacheIfOlderThanDays; } /** * @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); } $daysOldForSkip = $this->skipResultCacheIfOlderThanDays; if (time() - $data['lastFullAnalysisTime'] >= 60 * 60 * 24 * $daysOldForSkip) { if ($output->isVeryVerbose()) { $output->writeLineFormatted(sprintf("Result cache not used because it's more than %d days since last full analysis.", $daysOldForSkip)); } // run full analysis if the result cache is older than X 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 (array_keys($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 %.1f seconds', $elapsed) : ''; $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 => $fileExportedNodeAgain) { $cachedExportedNode = $cachedFileExportedNodes[$i]; if (!$cachedExportedNode->equals($fileExportedNodeAgain)) { 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 = $analyserResult->getCollectedData(); $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; } } return new \PHPStan\Analyser\ResultCache\ResultCacheProcessResult(new AnalyserResult($flatErrors, $analyserResult->getFilteredPhpErrors(), $analyserResult->getAllPhpErrors(), $flatLocallyIgnoredErrors, $linesToIgnore, $unmatchedLineIgnores, $internalErrors, $collectedDataByFile, $dependencies, $usedTraitDependencies, $exportedNodes, $analyserResult->hasReachedInternalErrorsCountLimit(), $analyserResult->getPeakMemoryUsageBytes(), $analyserResult->getProcessedFiles()), $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 CollectorData $freshCollectedDataByFile * @return CollectorData */ 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 ($collectedData as &$collectedDataPerFile) { ksort($collectedDataPerFile); } 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) { try { // does not use static reflection to reduce file-parsing $classReflection = new ReflectionClass($class); /** @phpstan-ignore argument.type */ } catch (ReflectionException $e) { continue; } $fileName = $classReflection->getFileName(); if ($fileName === \false) { 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 fn(string $extension): bool => $extension !== 'xdebug' && $extension !== 'blackfire')); sort($extensions); if ($projectConfigArray !== null) { foreach ($this->parametersNotInvalidatingCache as $parameterPath) { $pathAsArray = is_array($parameterPath) ? $parameterPath : explode('.', $parameterPath); ArrayHelper::unsetKeyAtPath($projectConfigArray, $pathAsArray); } ksort($projectConfigArray); } $fnsr = getenv('PHPSTAN_FNSR', \true); return ['cacheVersion' => self::CACHE_VERSION, 'phpstanVersion' => ComposerHelper::getPhpStanVersion(), 'fnsr' => $fnsr, 'metaExtensions' => $this->getMetaFromPhpStanExtensions(), '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 = hash_file('sha256', $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; if (!is_array($installed)) { throw new ShouldNotHappenException(); } $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; } /** * @return array * @throws ShouldNotHappenException */ private function getMetaFromPhpStanExtensions(): array { $meta = []; /** @var ResultCacheMetaExtension $extension */ foreach ($this->container->getServicesByTag(\PHPStan\Analyser\ResultCache\ResultCacheMetaExtension::EXTENSION_TAG) as $extension) { if (array_key_exists($extension->getKey(), $meta)) { throw new ShouldNotHappenException(sprintf('Duplicate ResultCacheMetaExtension with key "%s" found.', $extension->getKey())); } $meta[$extension->getKey()] = $extension->getHash(); } ksort($meta); return $meta; } } $fileReplacements */ public function create(array $fileReplacements): \PHPStan\Analyser\ResultCache\ResultCacheManager; } analyserResult = $analyserResult; $this->saved = $saved; } public function getAnalyserResult(): AnalyserResult { return $this->analyserResult; } public function isSaved(): bool { return $this->saved; } } initializerExprTypeResolver = $initializerExprTypeResolver; $this->propertyReflectionFinder = $propertyReflectionFinder; } /** * @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 (($expr->left instanceof Node\Expr\PropertyFetch || $expr->left instanceof Node\Expr\StaticPropertyFetch) && $rightType->isNull()->yes()) { $foundPropertyReflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($expr->left, $scope); foreach ($foundPropertyReflections as $foundPropertyReflection) { if ($foundPropertyReflection->isNative() && !$foundPropertyReflection->hasNativeType()) { return new TypeResult(new BooleanType(), []); } } } if (($expr->right instanceof Node\Expr\PropertyFetch || $expr->right instanceof Node\Expr\StaticPropertyFetch) && $leftType->isNull()->yes()) { $foundPropertyReflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($expr->right, $scope); foreach ($foundPropertyReflections as $foundPropertyReflection) { if ($foundPropertyReflection->isNative() && !$foundPropertyReflection->hasNativeType()) { 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(), []); } } parser = $parser; $this->differ = new Differ(new UnifiedDiffOutputBuilder('', \true)); } /** * @param Node\Stmt[] $fileNodes */ public function transform(RuleError $ruleError, \PHPStan\Analyser\Scope $scope, array $fileNodes, Node $node): \PHPStan\Analyser\Error { $line = $node->getStartLine(); $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 ($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; } $fixedErrorDiff = null; if ($ruleError instanceof FixableNodeRuleError) { if ($ruleError->getOriginalNode() instanceof VirtualNode) { throw new ShouldNotHappenException('Cannot fix virtual node'); } $fixingFile = $filePath; if ($traitFilePath !== null) { $fixingFile = $traitFilePath; } $oldCode = FileReader::read($fixingFile); $this->parser->parse($oldCode); $hash = hash('sha256', $oldCode); $oldTokens = $this->parser->getTokens(); $indentTraverser = new NodeTraverser(); $indentDetector = new PhpPrinterIndentationDetectorVisitor(new TokenStream($oldTokens, PhpPrinter::TAB_WIDTH)); $indentTraverser->addVisitor($indentDetector); $indentTraverser->traverse($fileNodes); $cloningTraverser = new NodeTraverser(); $cloningTraverser->addVisitor(new CloningVisitor()); /** @var Stmt[] $newStmts */ $newStmts = $cloningTraverser->traverse($fileNodes); $traverser = new NodeTraverser(); $visitor = new ReplacingNodeVisitor($ruleError->getOriginalNode(), $ruleError->getNewNodeCallable()); $traverser->addVisitor($visitor); /** @var Stmt[] $newStmts */ $newStmts = $traverser->traverse($newStmts); if ($visitor->isFound()) { if (str_contains($indentDetector->indentCharacter, "\t")) { $indent = "\t"; } else { $indent = str_repeat($indentDetector->indentCharacter, $indentDetector->indentSize); } $printer = new PhpPrinter(['indent' => $indent]); $newCode = $printer->printFormatPreserving($newStmts, $fileNodes, $oldTokens); if ($oldCode !== $newCode) { $fixedErrorDiff = new \PHPStan\Analyser\FixedErrorDiff($hash, $this->differ->diff($oldCode, $newCode)); } } } return new \PHPStan\Analyser\Error($ruleError->getMessage(), $fileName, $line, $canBeIgnored, $filePath, $traitFilePath, $tip, $node->getStartLine(), get_class($node), $identifier, $metadata, $fixedErrorDiff); } } getTraitReflection() */ public function isInTrait(): bool; /** * Returns the trait itself, not the class using the trait. * Use getClassReflection() for the using class. */ 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; /** * True at the top level of a file or after extract() — contexts where * arbitrary variables may exist. */ public function canAnyVariableExist(): bool; /** @return array */ public function getDefinedVariables(): array; /** * Variables with TrinaryLogic::Maybe certainty — defined in some code paths but not others. * * @return array */ public function getMaybeDefinedVariables(): array; public function hasConstant(Name $name): bool; /** * @deprecated Use getInstancePropertyReflection or getStaticPropertyReflection instead */ public function getPropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection; public function getInstancePropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection; public function getStaticPropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection; public function getMethodReflection(Type $typeWithMethod, string $methodName): ?ExtendedMethodReflection; public function getConstantReflection(Type $typeWithConstant, string $constantName): ?ClassConstantReflection; public function getConstantExplicitTypeFromConfig(string $constantName, Type $constantType): Type; public function getIterableKeyType(Type $iteratee): Type; public function getIterableValueType(Type $iteratee): Type; /** * @phpstan-assert-if-true !null $this->getAnonymousFunctionReflection() * @phpstan-assert-if-true !null $this->getAnonymousFunctionReturnType() */ public function isInAnonymousFunction(): bool; public function getAnonymousFunctionReflection(): ?ClosureType; public function getAnonymousFunctionReturnType(): ?Type; /** * Returns the PHPDoc-enhanced type. Use getNativeType() for native types only. */ public function getType(Expr $node): Type; /** * Returns only what PHP's native type system knows, ignoring PHPDoc. */ public function getNativeType(Expr $expr): Type; /** * Like getType(), but preserves void for function/method calls * (normally getType() replaces void with null). */ public function getKeepVoidType(Expr $node): Type; /** * Unlike getType() which may defer evaluation, this uses the scope's * current state immediately. */ public function getScopeType(Expr $expr): Type; public function getScopeNativeType(Expr $expr): Type; /** * Resolves a Name AST node to a fully qualified class name string. * * Handles special names: `self` and `static` resolve to the current class, * `parent` resolves to the parent class. Other names are returned as-is * (they should already be fully qualified by the PHP parser's name resolver). * * Inside a Closure::bind() context, `self`/`static` resolve to the bound class. * * @return non-empty-string */ public function resolveName(Name $name): string; /** * Resolves a Name AST node to a TypeWithClassName. * * Unlike resolveName() which returns a plain string, this returns a proper * Type object that preserves late-static-binding information: * - `static` returns a StaticType (preserves LSB in subclasses) * - `self` returns a ThisType when inside the same class hierarchy * - Other names return an ObjectType */ public function resolveTypeByName(Name $name): TypeWithClassName; /** * Returns the PHPStan Type representing a given PHP value. * * Converts runtime PHP values to their corresponding constant types: * integers become ConstantIntegerType, strings become ConstantStringType, * arrays become ConstantArrayType (if small enough), etc. * * @param mixed $value */ public function getTypeFromValue($value): Type; /** * Returns whether an expression has a tracked type in this scope. * * Returns TrinaryLogic::Yes if the expression's type is definitely known, * TrinaryLogic::Maybe if it might be known, and TrinaryLogic::No if there * is no type information for it. * * This checks the scope's expression type map without computing the type * (unlike getType() which always computes a type). */ public function hasExpressionType(Expr $node): TrinaryLogic; /** * Returns whether the given class name is being checked inside a * class_exists(), interface_exists(), or trait_exists() call. * * When true, rules should suppress "class not found" errors because * the code is explicitly checking for the class's existence. */ public function isInClassExists(string $className): bool; /** * Returns whether the given function name is being checked inside a * function_exists() call. * * When true, rules should suppress "function not found" errors because * the code is explicitly checking for the function's existence. */ public function isInFunctionExists(string $functionName): bool; /** * Returns whether the current analysis context is inside a Closure::bind() * or Closure::bindTo() call. * * When true, the closure's $this and self/static may refer to a different * class than the one where the closure was defined. */ public function isInClosureBind(): bool; /** * Returns the stack of function/method calls that are currently being analysed. * * When analysing arguments of a function call, this returns the chain of * enclosing calls. Used by extensions that need to know the calling context, * such as type-specifying extensions for functions like class_exists(). * * @return list */ public function getFunctionCallStack(): array; /** * Like getFunctionCallStack(), but also includes the parameter being passed to. * * Each entry is a tuple of the function/method reflection and the parameter * reflection for the argument position being analysed (or null if unknown). * * @return list */ public function getFunctionCallStackWithParameters(): array; /** * Returns whether a function parameter has a default value of null. * * Checks the parameter's default value AST node to determine if * `= null` was specified. Used by function definition checks. */ public function isParameterValueNullable(Param $parameter): bool; /** * Resolves a type AST node (from a parameter/return type declaration) to a Type. * * Handles named types, identifier types (int, string, etc.), union types, * intersection types, and nullable types. The $isNullable flag adds null * to the type, and $isVariadic wraps the type in an array. * * @param Node\Name|Node\Identifier|Node\ComplexType|null $type */ public function getFunctionType($type, bool $isNullable, bool $isVariadic): Type; /** * Returns whether the given expression is currently being assigned to. * * Returns true during the analysis of the right-hand side of an assignment * to this expression. For example, when analysing `$a = expr`, this returns * true for the $a variable during the analysis of `expr`. * * Used to prevent infinite recursion when resolving types during assignment. */ public function isInExpressionAssign(Expr $expr): bool; /** * Returns whether accessing the given expression in an undefined state is allowed. * * Returns true when the expression is on the left-hand side of an assignment * or in similar contexts where it's valid for the expression to be undefined * (e.g. `$a['key'] = value` where $a['key'] doesn't need to exist yet). */ public function isUndefinedExpressionAllowed(Expr $expr): bool; /** * Returns a new Scope with types narrowed by assuming the expression is truthy. * * Given an expression like `$x instanceof Foo`, returns a scope where * $x is known to be of type Foo. This is the scope used inside the * if-branch of `if ($x instanceof Foo)`. * * Uses the TypeSpecifier internally to determine type narrowing. */ public function filterByTruthyValue(Expr $expr): self; /** * Returns a new Scope with types narrowed by assuming the expression is falsy. * * The opposite of filterByTruthyValue(). Given `$x instanceof Foo`, returns * a scope where $x is known NOT to be of type Foo. This is the scope used * in the else-branch of `if ($x instanceof Foo)`. */ public function filterByFalseyValue(Expr $expr): self; /** * Returns whether the current statement is a "first-level" statement. * * A first-level statement is one that is directly inside a function/method * body, not nested inside control structures like if/else, loops, or * try/catch. Used to determine whether certain checks should be more * or less strict. */ public function isInFirstLevelStatement(): bool; /** * Returns the PHP version(s) being analysed against. * * Returns a PhpVersions object that can represent a range of PHP versions * (when the exact version is not known). Use its methods like * supportsEnums(), supportsReadonlyProperties(), etc. to check for * version-specific features. */ public function getPhpVersion(): PhpVersions; /** @internal */ public function toMutatingScope(): \PHPStan\Analyser\MutatingScope; } 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; } } internalScopeFactoryFactory = $internalScopeFactoryFactory; } /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ public function create(\PHPStan\Analyser\ScopeContext $context, ?callable $nodeCallback = null): \PHPStan\Analyser\MutatingScope { return $this->internalScopeFactoryFactory->create($nodeCallback)->create($context); } } */ private array $sureTypes; /** * @var array */ private array $sureNotTypes; private bool $overwrite = \false; /** @var array */ private array $newConditionalExpressionHolders = []; private ?Expr $rootExpr = null; /** * @api * @param array $sureTypes * @param array $sureNotTypes */ public function __construct(array $sureTypes = [], array $sureNotTypes = []) { $this->sureTypes = $sureTypes; $this->sureNotTypes = $sureNotTypes; } /** * Normally, $sureTypes in truthy context are used to intersect with the pre-existing type. * And $sureNotTypes are used to remove type from the pre-existing type. * * Example: By default, non-empty-string intersected with '' (ConstantStringType) will lead to NeverType. * Because it's not possible to narrow non-empty-string to an empty string. * * In rare cases, a type-specifying extension might want to overwrite the pre-existing types * without taking the pre-existing types into consideration. * * In that case it should also call setAlwaysOverwriteTypes() on * the returned object. * * ! Only do this if you're certain. Otherwise, this is a source of common bugs. ! * * @api */ public function setAlwaysOverwriteTypes(): self { $self = new self($this->sureTypes, $this->sureNotTypes); $self->overwrite = \true; $self->newConditionalExpressionHolders = $this->newConditionalExpressionHolders; $self->rootExpr = $this->rootExpr; return $self; } /** * @api */ public function setRootExpr(?Expr $rootExpr): self { $self = new self($this->sureTypes, $this->sureNotTypes); $self->overwrite = $this->overwrite; $self->newConditionalExpressionHolders = $this->newConditionalExpressionHolders; $self->rootExpr = $rootExpr; return $self; } /** * @param array $newConditionalExpressionHolders */ public function setNewConditionalExpressionHolders(array $newConditionalExpressionHolders): self { $self = new self($this->sureTypes, $this->sureNotTypes); $self->overwrite = $this->overwrite; $self->newConditionalExpressionHolders = $newConditionalExpressionHolders; $self->rootExpr = $this->rootExpr; return $self; } /** * @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; } public function removeExpr(string $exprString): self { $sureTypes = $this->sureTypes; $sureNotTypes = $this->sureNotTypes; unset($sureTypes[$exprString]); unset($sureNotTypes[$exprString]); $self = new self($sureTypes, $sureNotTypes); $self->overwrite = $this->overwrite; $self->newConditionalExpressionHolders = $this->newConditionalExpressionHolders; $self->rootExpr = $this->rootExpr; return $self; } /** @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])]; } $result = new self($sureTypeUnion, $sureNotTypeUnion); if ($this->overwrite && $other->overwrite) { $result = $result->setAlwaysOverwriteTypes(); } return $result->setRootExpr($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])]; } $result = new self($sureTypeUnion, $sureNotTypeUnion); if ($this->overwrite || $other->overwrite) { $result = $result->setAlwaysOverwriteTypes(); } $conditionalExpressionHolders = $this->newConditionalExpressionHolders; foreach ($other->newConditionalExpressionHolders as $exprString => $holders) { if (!array_key_exists($exprString, $conditionalExpressionHolders)) { $conditionalExpressionHolders[$exprString] = $holders; } else { $conditionalExpressionHolders[$exprString] = array_merge($conditionalExpressionHolders[$exprString], $holders); } } $result->newConditionalExpressionHolders = $conditionalExpressionHolders; return $result->setRootExpr($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); } $result = new self($sureTypes, []); if ($this->overwrite) { $result = $result->setAlwaysOverwriteTypes(); } return $result->setRootExpr($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; } } isTopLevel = $isTopLevel; $this->foreachUnrollFactor = $foreachUnrollFactor; } /** * @api */ public static function createTopLevel(): self { return new self(\true); } /** * @api */ public static function createDeep(): self { return new self(\false); } public function isTopLevel(): bool { return $this->isTopLevel; } public function getForeachUnrollFactor(): int { return $this->foreachUnrollFactor; } public function enterDeep(): self { if ($this->isTopLevel) { return new self(\false, $this->foreachUnrollFactor); } return $this; } public function enterUnrolledForeach(int $totalKeys): self { return new self($this->isTopLevel, $this->foreachUnrollFactor * $totalKeys); } } statement = $statement; $this->scope = $scope; } public function getStatement(): Stmt { return $this->statement; } public function getScope(): \PHPStan\Analyser\Scope { return $this->scope; } } 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\Scope { 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 Int_) { 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 list */ 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 Int_) { $exitPoints[] = $exitPoint; continue; } $value = $value->value; if ($value !== 1) { continue; } $exitPoints[] = $exitPoint; } return $exitPoints; } /** * @return list */ 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 Int_) { continue; } $value = $statement->num->value; if ($value === 1) { continue; } $newNode = null; if ($value > 2) { $newNode = new Int_($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; } } 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\Scope $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\Scope $scope, Node $node): self { return new self($scope, new ObjectType(Throwable::class), $node, \false, \true); } public function getScope(): \PHPStan\Analyser\Scope { 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); } } getClassReflection(), $type->getSubtractedType()); } return $type; } } */ private array $classTemplateTypes; /** * @param array $classTemplateTypes */ public function __construct(array $classTemplateTypes) { $this->classTemplateTypes = $classTemplateTypes; } /** * @param callable(Type): Type $traverse */ public function traverse(Type $type, callable $traverse): Type { if ($type instanceof TemplateType && array_key_exists($type->getName(), $this->classTemplateTypes)) { $classTemplateType = $this->classTemplateTypes[$type->getName()]; if ($classTemplateType instanceof TemplateType && $classTemplateType->getScope()->equals($type->getScope())) { unset($this->classTemplateTypes[$type->getName()]); } return $type; } return $traverse($type); } /** * @return array */ public function getClassTemplateTypes(): array { return $this->classTemplateTypes; } } resolvedTemplateTypeMap = $resolvedTemplateTypeMap; } /** * @param callable(Type): Type $traverse */ public function traverse(Type $type, callable $traverse): Type { if ($type instanceof TemplateType && !$type->isArgument()) { $newType = $this->resolvedTemplateTypeMap->getType($type->getName()); if ($newType === null || $newType instanceof ErrorType) { return $type->getDefault() ?? $type->getBound(); } return TemplateTypeHelper::generalizeInferredTemplateType($type, $newType); } return $traverse($type); } } scope = $scope; } /** * @param callable(Type): Type $traverse */ public function traverse(Type $type, callable $traverse): Type { if (!$this->scope->isInClass()) { return $type; } if ($type instanceof StaticType) { $classReflection = $this->scope->getClassReflection(); $changedType = $type->changeBaseClass($classReflection); if ($classReflection->isFinal() && !$type instanceof ThisType) { $changedType = $changedType->getStaticObjectType(); } return $traverse($changedType); } return $traverse($type); } } isVoid()->yes()) { return new NullType(); } return $type; } } exprPrinter = $exprPrinter; $this->reflectionProvider = $reflectionProvider; $this->phpVersion = $phpVersion; $this->functionTypeSpecifyingExtensions = $functionTypeSpecifyingExtensions; $this->methodTypeSpecifyingExtensions = $methodTypeSpecifyingExtensions; $this->staticMethodTypeSpecifyingExtensions = $staticMethodTypeSpecifyingExtensions; $this->rememberPossiblyImpureFunctionValues = $rememberPossiblyImpureFunctionValues; } /** * @api */ public function specifyTypesInCondition(\PHPStan\Analyser\Scope $scope, Expr $expr, \PHPStan\Analyser\TypeSpecifierContext $context): \PHPStan\Analyser\SpecifiedTypes { if ($expr instanceof Expr\CallLike && $expr->isFirstClassCallable()) { return (new \PHPStan\Analyser\SpecifiedTypes([], []))->setRootExpr($expr); } 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, $scope)->setRootExpr($expr); } $result = $scope->getType($expr->class)->toObjectTypeForInstanceofCheck(); $type = $result->type; $uncertainty = $result->uncertainty; if (!$type->isSuperTypeOf(new MixedType())->yes()) { if ($context->true()) { $type = TypeCombinator::intersect($type, new ObjectWithoutClassType()); return $this->create($exprNode, $type, $context, $scope)->setRootExpr($expr); } elseif ($context->false() && !$uncertainty) { $exprType = $scope->getType($expr->expr); if (!$type->isSuperTypeOf($exprType)->yes()) { return $this->create($exprNode, $type, $context, $scope)->setRootExpr($expr); } } } if ($context->true()) { return $this->create($exprNode, new ObjectWithoutClassType(), $context, $scope)->setRootExpr($exprNode); } } elseif ($expr instanceof Node\Expr\BinaryOp\Identical) { return $this->resolveIdentical($expr, $scope, $context); } 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)->setRootExpr($expr); } elseif ($expr instanceof Expr\Cast\Bool_) { return $this->specifyTypesInCondition($scope, new Node\Expr\BinaryOp\Equal($expr->expr, new ConstFetch(new Name\FullyQualified('true'))), $context)->setRootExpr($expr); } elseif ($expr instanceof Expr\Cast\String_) { return $this->specifyTypesInCondition($scope, new Node\Expr\BinaryOp\NotEqual($expr->expr, new Node\Scalar\String_('')), $context)->setRootExpr($expr); } elseif ($expr instanceof Expr\Cast\Int_) { return $this->specifyTypesInCondition($scope, new Node\Expr\BinaryOp\NotEqual($expr->expr, new Node\Scalar\Int_(0)), $context)->setRootExpr($expr); } elseif ($expr instanceof Expr\Cast\Double) { return $this->specifyTypesInCondition($scope, new Node\Expr\BinaryOp\NotEqual($expr->expr, new Node\Scalar\Float_(0.0)), $context)->setRootExpr($expr); } elseif ($expr instanceof Node\Expr\BinaryOp\Equal) { return $this->resolveEqual($expr, $scope, $context); } 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)->setRootExpr($expr); } elseif ($expr instanceof Node\Expr\BinaryOp\Smaller || $expr instanceof Node\Expr\BinaryOp\SmallerOrEqual) { if ($expr->left instanceof FuncCall && $expr->left->name instanceof Name && !$expr->left->isFirstClassCallable() && in_array(strtolower((string) $expr->left->name), ['count', 'sizeof', 'strlen', 'mb_strlen', 'preg_match'], \true) && count($expr->left->getArgs()) >= 1 && (!$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)->setRootExpr($expr); } $orEqual = $expr instanceof Node\Expr\BinaryOp\SmallerOrEqual; $offset = $orEqual ? 0 : 1; $leftType = $scope->getType($expr->left); $result = (new \PHPStan\Analyser\SpecifiedTypes([], []))->setRootExpr($expr); if (!$context->null() && $expr->right instanceof FuncCall && $expr->right->name instanceof Name && !$expr->right->isFirstClassCallable() && in_array(strtolower((string) $expr->right->name), ['count', 'sizeof'], \true) && count($expr->right->getArgs()) >= 1 && $leftType->isInteger()->yes()) { $argType = $scope->getType($expr->right->getArgs()[0]->value); $sizeType = null; if ($leftType instanceof ConstantIntegerType) { if ($orEqual) { $sizeType = IntegerRangeType::createAllGreaterThanOrEqualTo($leftType->getValue()); } else { $sizeType = IntegerRangeType::createAllGreaterThan($leftType->getValue()); } } elseif ($leftType instanceof IntegerRangeType) { if ($context->falsey() && $leftType->getMax() !== null) { if ($orEqual) { $sizeType = IntegerRangeType::createAllGreaterThanOrEqualTo($leftType->getMax()); } else { $sizeType = IntegerRangeType::createAllGreaterThan($leftType->getMax()); } } elseif ($context->truthy() && $leftType->getMin() !== null) { if ($orEqual) { $sizeType = IntegerRangeType::createAllGreaterThanOrEqualTo($leftType->getMin()); } else { $sizeType = IntegerRangeType::createAllGreaterThan($leftType->getMin()); } } } else { $sizeType = $leftType; } if ($sizeType !== null) { $specifiedTypes = $this->specifyTypesForCountFuncCall($expr->right, $argType, $sizeType, $context, $scope, $expr); if ($specifiedTypes !== null) { $result = $result->unionWith($specifiedTypes); } } 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, $scope)->setRootExpr($expr); } } if ($argType->isArray()->yes()) { $newType = new NonEmptyArrayType(); if ($context->true() && $argType->isList()->yes()) { $newType = TypeCombinator::intersect($newType, new AccessoryArrayListType()); } $result = $result->unionWith($this->create($expr->right->getArgs()[0]->value, $newType, $context, $scope)->setRootExpr($expr)); } } // infer $list[$index] after $index < count($list) if ($context->true() && !$orEqual && !$leftType instanceof ConstantIntegerType && $argType->isList()->yes() && IntegerRangeType::fromInterval(0, null)->isSuperTypeOf($leftType)->yes()) { $arrayArg = $expr->right->getArgs()[0]->value; $dimFetch = new ArrayDimFetch($arrayArg, $expr->left); $result = $result->unionWith($this->create($dimFetch, $argType->getIterableValueType(), \PHPStan\Analyser\TypeSpecifierContext::createTrue(), $scope)->setRootExpr($expr)); } } // infer $list[$index] after $zeroOrMore < count($list) - N // infer $list[$index] after $zeroOrMore <= count($list) - N if ($context->true() && $expr->right instanceof Expr\BinaryOp\Minus && $expr->right->left instanceof FuncCall && $expr->right->left->name instanceof Name && !$expr->right->left->isFirstClassCallable() && in_array(strtolower((string) $expr->right->left->name), ['count', 'sizeof'], \true) && count($expr->right->left->getArgs()) >= 1 && !$leftType instanceof ConstantIntegerType && $leftType->isInteger()->yes() && IntegerRangeType::fromInterval(0, null)->isSuperTypeOf($leftType)->yes()) { $countArgType = $scope->getType($expr->right->left->getArgs()[0]->value); $subtractedType = $scope->getType($expr->right->right); if ($countArgType->isList()->yes() && $this->isNormalCountCall($expr->right->left, $countArgType, $scope)->yes() && IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($subtractedType)->yes()) { $arrayArg = $expr->right->left->getArgs()[0]->value; $dimFetch = new ArrayDimFetch($arrayArg, $expr->left); $result = $result->unionWith($this->create($dimFetch, $countArgType->getIterableValueType(), \PHPStan\Analyser\TypeSpecifierContext::createTrue(), $scope)->setRootExpr($expr)); } } if (!$context->null() && $expr->right instanceof FuncCall && $expr->right->name instanceof Name && !$expr->right->isFirstClassCallable() && in_array(strtolower((string) $expr->right->name), ['preg_match'], \true) && count($expr->right->getArgs()) >= 3 && (IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($leftType)->yes() || $expr instanceof Expr\BinaryOp\Smaller && IntegerRangeType::fromInterval(0, null)->isSuperTypeOf($leftType)->yes())) { // 0 < preg_match or 1 <= preg_match becomes 1 === preg_match $newExpr = new Expr\BinaryOp\Identical($expr->right, new Node\Scalar\Int_(1)); return $this->specifyTypesInCondition($scope, $newExpr, $context)->setRootExpr($expr); } if (!$context->null() && $expr->right instanceof FuncCall && $expr->right->name instanceof Name && !$expr->right->isFirstClassCallable() && in_array(strtolower((string) $expr->right->name), ['strlen', 'mb_strlen'], \true) && count($expr->right->getArgs()) === 1 && $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, $scope)->setRootExpr($expr)); } } } if ($leftType instanceof ConstantIntegerType) { if ($expr->right instanceof Expr\PostInc) { $result = $result->unionWith($this->createRangeTypes($expr, $expr->right->var, IntegerRangeType::fromInterval($leftType->getValue(), null, $offset + 1), $context)); } elseif ($expr->right instanceof Expr\PostDec) { $result = $result->unionWith($this->createRangeTypes($expr, $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($expr, $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($expr, $expr->left->var, IntegerRangeType::fromInterval(null, $rightType->getValue(), -$offset + 1), $context)); } elseif ($expr->left instanceof Expr\PostDec) { $result = $result->unionWith($this->createRangeTypes($expr, $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($expr, $expr->left->var, IntegerRangeType::fromInterval(null, $rightType->getValue(), -$offset), $context)); } } if ($context->true()) { if (!$expr->left instanceof Node\Scalar && !($expr->left instanceof Expr\UnaryMinus && $expr->left->expr instanceof Node\Scalar)) { $result = $result->unionWith($this->create($expr->left, $orEqual ? $rightType->getSmallerOrEqualType($this->phpVersion) : $rightType->getSmallerType($this->phpVersion), \PHPStan\Analyser\TypeSpecifierContext::createTruthy(), $scope)->setRootExpr($expr)); } if (!$expr->right instanceof Node\Scalar && !($expr->right instanceof Expr\UnaryMinus && $expr->right->expr instanceof Node\Scalar)) { $result = $result->unionWith($this->create($expr->right, $orEqual ? $leftType->getGreaterOrEqualType($this->phpVersion) : $leftType->getGreaterType($this->phpVersion), \PHPStan\Analyser\TypeSpecifierContext::createTruthy(), $scope)->setRootExpr($expr)); } } elseif ($context->false()) { if (!$expr->left instanceof Node\Scalar && !($expr->left instanceof Expr\UnaryMinus && $expr->left->expr instanceof Node\Scalar)) { $result = $result->unionWith($this->create($expr->left, $orEqual ? $rightType->getGreaterType($this->phpVersion) : $rightType->getGreaterOrEqualType($this->phpVersion), \PHPStan\Analyser\TypeSpecifierContext::createTruthy(), $scope)->setRootExpr($expr)); } if (!$expr->right instanceof Node\Scalar && !($expr->right instanceof Expr\UnaryMinus && $expr->right->expr instanceof Node\Scalar)) { $result = $result->unionWith($this->create($expr->right, $orEqual ? $leftType->getSmallerType($this->phpVersion) : $leftType->getSmallerOrEqualType($this->phpVersion), \PHPStan\Analyser\TypeSpecifierContext::createTruthy(), $scope)->setRootExpr($expr)); } } return $result; } elseif ($expr instanceof Node\Expr\BinaryOp\Greater) { return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Smaller($expr->right, $expr->left), $context)->setRootExpr($expr); } elseif ($expr instanceof Node\Expr\BinaryOp\GreaterOrEqual) { return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\SmallerOrEqual($expr->right, $expr->left), $context)->setRootExpr($expr); } elseif ($expr instanceof FuncCall && $expr->name instanceof Name) { if ($this->reflectionProvider->hasFunction($expr->name, $scope)) { // lazy create parametersAcceptor, as creation can be expensive $parametersAcceptor = null; $functionReflection = $this->reflectionProvider->getFunction($expr->name, $scope); $normalizedExpr = $expr; $args = $expr->getArgs(); if (count($args) > 0) { $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $args, $functionReflection->getVariants(), $functionReflection->getNamedArgumentsVariants()); $normalizedExpr = \PHPStan\Analyser\ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $expr) ?? $expr; } foreach ($this->getFunctionTypeSpecifyingExtensions() as $extension) { if (!$extension->isFunctionSupported($functionReflection, $normalizedExpr, $context)) { continue; } return $extension->specifyTypes($functionReflection, $normalizedExpr, $scope, $context); } if (count($args) > 0) { $specifiedTypes = $this->specifyTypesFromConditionalReturnType($context, $expr, $parametersAcceptor, $scope); if ($specifiedTypes !== null) { return $specifiedTypes; } } $assertions = $functionReflection->getAsserts(); if ($assertions->getAll() !== []) { $parametersAcceptor ??= ParametersAcceptorSelector::selectFromArgs($scope, $args, $functionReflection->getVariants(), $functionReflection->getNamedArgumentsVariants()); $asserts = $assertions->mapTypes(static fn(Type $type) => TemplateTypeHelper::resolveTemplateTypes($type, $parametersAcceptor->getResolvedTemplateTypeMap(), $parametersAcceptor instanceof ExtendedParametersAcceptor ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createInvariant())); $specifiedTypes = $this->specifyTypesFromAsserts($context, $expr, $asserts, $parametersAcceptor, $scope); if ($specifiedTypes !== null) { return $specifiedTypes; } } } return $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope); } elseif ($expr instanceof FuncCall) { $specifiedTypes = $this->specifyTypesFromCallableCall($context, $expr, $scope); if ($specifiedTypes !== null) { return $specifiedTypes; } return $this->handleDefaultTruthyOrFalseyContext($context, $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) { // lazy create parametersAcceptor, as creation can be expensive $parametersAcceptor = null; $normalizedExpr = $expr; $args = $expr->getArgs(); if (count($args) > 0) { $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $args, $methodReflection->getVariants(), $methodReflection->getNamedArgumentsVariants()); $normalizedExpr = \PHPStan\Analyser\ArgumentsNormalizer::reorderMethodArguments($parametersAcceptor, $expr) ?? $expr; } $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, $normalizedExpr, $context)) { continue; } return $extension->specifyTypes($methodReflection, $normalizedExpr, $scope, $context); } } if (count($args) > 0) { $specifiedTypes = $this->specifyTypesFromConditionalReturnType($context, $expr, $parametersAcceptor, $scope); if ($specifiedTypes !== null) { return $specifiedTypes; } } $assertions = $methodReflection->getAsserts(); if ($assertions->getAll() !== []) { $parametersAcceptor ??= ParametersAcceptorSelector::selectFromArgs($scope, $args, $methodReflection->getVariants(), $methodReflection->getNamedArgumentsVariants()); $asserts = $assertions->mapTypes(static fn(Type $type) => TemplateTypeHelper::resolveTemplateTypes($type, $parametersAcceptor->getResolvedTemplateTypeMap(), $parametersAcceptor instanceof ExtendedParametersAcceptor ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createInvariant())); $specifiedTypes = $this->specifyTypesFromAsserts($context, $expr, $asserts, $parametersAcceptor, $scope); if ($specifiedTypes !== null) { return $specifiedTypes; } } } return $this->handleDefaultTruthyOrFalseyContext($context, $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) { // lazy create parametersAcceptor, as creation can be expensive $parametersAcceptor = null; $normalizedExpr = $expr; $args = $expr->getArgs(); if (count($args) > 0) { $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $args, $staticMethodReflection->getVariants(), $staticMethodReflection->getNamedArgumentsVariants()); $normalizedExpr = \PHPStan\Analyser\ArgumentsNormalizer::reorderStaticCallArguments($parametersAcceptor, $expr) ?? $expr; } $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, $normalizedExpr, $context)) { continue; } return $extension->specifyTypes($staticMethodReflection, $normalizedExpr, $scope, $context); } } if (count($args) > 0) { $specifiedTypes = $this->specifyTypesFromConditionalReturnType($context, $expr, $parametersAcceptor, $scope); if ($specifiedTypes !== null) { return $specifiedTypes; } } $assertions = $staticMethodReflection->getAsserts(); if ($assertions->getAll() !== []) { $parametersAcceptor ??= ParametersAcceptorSelector::selectFromArgs($scope, $args, $staticMethodReflection->getVariants(), $staticMethodReflection->getNamedArgumentsVariants()); $asserts = $assertions->mapTypes(static fn(Type $type) => TemplateTypeHelper::resolveTemplateTypes($type, $parametersAcceptor->getResolvedTemplateTypeMap(), $parametersAcceptor instanceof ExtendedParametersAcceptor ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createInvariant())); $specifiedTypes = $this->specifyTypesFromAsserts($context, $expr, $asserts, $parametersAcceptor, $scope); if ($specifiedTypes !== null) { return $specifiedTypes; } } } return $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope); } elseif ($expr instanceof BooleanAnd || $expr instanceof LogicalAnd) { if (!$scope instanceof \PHPStan\Analyser\MutatingScope) { throw new ShouldNotHappenException(); } // For deep BooleanAnd chains in truthy context, flatten and // process all arms at once to avoid O(N²) recursive // filterByTruthyValue calls. if ($context->true() && BooleanAndHandler::getBooleanExpressionDepth($expr) > self::BOOLEAN_EXPRESSION_MAX_PROCESS_DEPTH) { return $this->specifyTypesForFlattenedBooleanAnd($scope, $expr, $context); } $leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context)->setRootExpr($expr); $rightScope = $scope->filterByTruthyValue($expr->left); $rightTypes = $this->specifyTypesInCondition($rightScope, $expr->right, $context)->setRootExpr($expr); if ($context->true()) { $types = $leftTypes->unionWith($rightTypes); } else { $leftNormalized = $leftTypes->normalize($scope); $rightNormalized = $rightTypes->normalize($rightScope); $types = $leftNormalized->intersectWith($rightNormalized); $types = $this->augmentDisjunctionTypes($scope, $rightScope, $leftNormalized, $rightNormalized, $expr->left, $expr->right, \false, $types); } if ($context->false()) { $leftTypesForHolders = $leftTypes; $rightTypesForHolders = $rightTypes; if ($context->truthy()) { if ($leftTypesForHolders->getSureTypes() === [] && $leftTypesForHolders->getSureNotTypes() === []) { $leftTypesForHolders = $this->specifyTypesInCondition($scope, $expr->left, \PHPStan\Analyser\TypeSpecifierContext::createFalsey())->setRootExpr($expr); } if ($rightTypesForHolders->getSureTypes() === [] && $rightTypesForHolders->getSureNotTypes() === []) { $rightTypesForHolders = $this->specifyTypesInCondition($rightScope, $expr->right, \PHPStan\Analyser\TypeSpecifierContext::createFalsey())->setRootExpr($expr); } } $result = new \PHPStan\Analyser\SpecifiedTypes($types->getSureTypes(), $types->getSureNotTypes()); if ($types->shouldOverwrite()) { $result = $result->setAlwaysOverwriteTypes(); } return $result->setNewConditionalExpressionHolders(array_merge($this->processBooleanNotSureConditionalTypes($scope, $leftTypesForHolders, $rightTypesForHolders, $rightScope), $this->processBooleanNotSureConditionalTypes($scope, $rightTypesForHolders, $leftTypesForHolders, $scope), $this->processBooleanSureConditionalTypes($scope, $leftTypesForHolders, $rightTypesForHolders, $rightScope), $this->processBooleanSureConditionalTypes($scope, $rightTypesForHolders, $leftTypesForHolders, $scope)))->setRootExpr($expr); } return $types; } elseif ($expr instanceof BooleanOr || $expr instanceof LogicalOr) { if (!$scope instanceof \PHPStan\Analyser\MutatingScope) { throw new ShouldNotHappenException(); } // For deep BooleanOr chains, flatten and process all arms at once // to avoid O(n^2) recursive filterByFalseyValue calls if (BooleanAndHandler::getBooleanExpressionDepth($expr) > self::BOOLEAN_EXPRESSION_MAX_PROCESS_DEPTH) { return $this->specifyTypesForFlattenedBooleanOr($scope, $expr, $context); } $leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context)->setRootExpr($expr); $rightScope = $scope->filterByFalseyValue($expr->left); $rightTypes = $this->specifyTypesInCondition($rightScope, $expr->right, $context)->setRootExpr($expr); if ($context->true()) { if ($scope->getType($expr->left)->toBoolean()->isFalse()->yes()) { $types = $rightTypes->normalize($rightScope); } elseif ($scope->getType($expr->left)->toBoolean()->isTrue()->yes() || $scope->getType($expr->right)->toBoolean()->isFalse()->yes()) { $types = $leftTypes->normalize($scope); } else { $leftNormalized = $leftTypes->normalize($scope); $rightNormalized = $rightTypes->normalize($rightScope); $types = $leftNormalized->intersectWith($rightNormalized); $types = $this->augmentBooleanOrTruthyWithConditionalHolders($scope, $rightScope, $expr, $types); $types = $this->augmentDisjunctionTypes($scope, $rightScope, $leftNormalized, $rightNormalized, $expr->left, $expr->right, \true, $types); } } else { $types = $leftTypes->unionWith($rightTypes); } if ($context->true()) { $result = new \PHPStan\Analyser\SpecifiedTypes($types->getSureTypes(), $types->getSureNotTypes()); if ($types->shouldOverwrite()) { $result = $result->setAlwaysOverwriteTypes(); } return $result->setNewConditionalExpressionHolders(array_merge($this->processBooleanNotSureConditionalTypes($scope, $leftTypes, $rightTypes, $rightScope), $this->processBooleanNotSureConditionalTypes($scope, $rightTypes, $leftTypes, $scope), $this->processBooleanSureConditionalTypes($scope, $leftTypes, $rightTypes, $rightScope), $this->processBooleanSureConditionalTypes($scope, $rightTypes, $leftTypes, $scope)))->setRootExpr($expr); } return $types; } elseif ($expr instanceof Node\Expr\BooleanNot && !$context->null()) { return $this->specifyTypesInCondition($scope, $expr->expr, $context->negate())->setRootExpr($expr); } elseif ($expr instanceof Node\Expr\Assign) { if (!$scope instanceof \PHPStan\Analyser\MutatingScope) { throw new ShouldNotHappenException(); } if ($context->null()) { $specifiedTypes = $this->specifyTypesInCondition($scope->exitFirstLevelStatements(), $expr->expr, $context)->setRootExpr($expr); $specifiedTypes = $specifiedTypes->removeExpr($this->exprPrinter->printExpr($expr->var)); } else { $specifiedTypes = $this->specifyTypesInCondition($scope->exitFirstLevelStatements(), $expr->var, $context)->setRootExpr($expr); } // infer $arr[$key] after $key = array_key_first/last($arr) if ($expr->expr instanceof FuncCall && $expr->expr->name instanceof Name && !$expr->expr->isFirstClassCallable() && in_array($expr->expr->name->toLowerString(), ['array_key_first', 'array_key_last'], \true) && count($expr->expr->getArgs()) >= 1) { $arrayArg = $expr->expr->getArgs()[0]->value; $arrayType = $scope->getType($arrayArg); if ($arrayType->isArray()->yes()) { if ($context->true()) { $specifiedTypes = $specifiedTypes->unionWith($this->create($arrayArg, new NonEmptyArrayType(), \PHPStan\Analyser\TypeSpecifierContext::createTrue(), $scope)); $isNonEmpty = \true; } else { $isNonEmpty = $arrayType->isIterableAtLeastOnce()->yes(); } if ($isNonEmpty) { $dimFetch = new ArrayDimFetch($arrayArg, $expr->var); $specifiedTypes = $specifiedTypes->unionWith($this->create($dimFetch, $arrayType->getIterableValueType(), \PHPStan\Analyser\TypeSpecifierContext::createTrue(), $scope)); } elseif ($expr->var instanceof Expr\Variable && is_string($expr->var->name)) { $keyType = $scope->getType($expr->expr); $nonNullKeyType = TypeCombinator::removeNull($keyType); if (!$nonNullKeyType instanceof NeverType) { $specifiedTypes = $specifiedTypes->unionWith($this->createArrayDimFetchConditionalExpressionHolder($expr->var, $arrayArg, $nonNullKeyType, $arrayType->getIterableValueType())); } } } } // infer $arr[$key] after $key = array_search($needle, $arr) or $key = array_find_key($arr, $callback) if ($expr->expr instanceof FuncCall && $expr->expr->name instanceof Name && !$expr->expr->isFirstClassCallable() && count($expr->expr->getArgs()) >= 2) { $funcName = $expr->expr->name->toLowerString(); $arrayArg = null; $sentinelType = null; $isStrictArraySearch = \false; if ($funcName === 'array_search') { $arrayArg = $expr->expr->getArgs()[1]->value; $sentinelType = new ConstantBooleanType(\false); $isStrictArraySearch = count($expr->expr->getArgs()) >= 3 && $scope->getType($expr->expr->getArgs()[2]->value)->isTrue()->yes(); } elseif ($funcName === 'array_find_key') { $arrayArg = $expr->expr->getArgs()[0]->value; $sentinelType = new NullType(); } if ($arrayArg !== null) { $arrayType = $scope->getType($arrayArg); if ($arrayType->isArray()->yes()) { if ($context->true()) { $specifiedTypes = $specifiedTypes->unionWith($this->create($arrayArg, new NonEmptyArrayType(), \PHPStan\Analyser\TypeSpecifierContext::createTrue(), $scope)); $dimFetch = new ArrayDimFetch($arrayArg, $expr->var); if ($isStrictArraySearch) { $needleType = $scope->getType($expr->expr->getArgs()[0]->value); $dimFetchType = TypeCombinator::intersect($needleType, $arrayType->getIterableValueType()); } else { $dimFetchType = $arrayType->getIterableValueType(); } $specifiedTypes = $specifiedTypes->unionWith($this->create($dimFetch, $dimFetchType, \PHPStan\Analyser\TypeSpecifierContext::createTrue(), $scope)); } elseif ($expr->var instanceof Expr\Variable && is_string($expr->var->name)) { $keyType = $scope->getType($expr->expr); $narrowedKeyType = TypeCombinator::remove($keyType, $sentinelType); if (!$narrowedKeyType instanceof NeverType) { if ($isStrictArraySearch) { $needleType = $scope->getType($expr->expr->getArgs()[0]->value); $dimFetchType = TypeCombinator::intersect($needleType, $arrayType->getIterableValueType()); } else { $dimFetchType = $arrayType->getIterableValueType(); } $specifiedTypes = $specifiedTypes->unionWith($this->createArrayDimFetchConditionalExpressionHolder($expr->var, $arrayArg, $narrowedKeyType, $dimFetchType)); } } } } } if ($context->null()) { // infer $arr[$key] after $key = array_rand($arr) if ($expr->expr instanceof FuncCall && $expr->expr->name instanceof Name && !$expr->expr->isFirstClassCallable() && in_array($expr->expr->name->toLowerString(), ['array_rand'], \true) && count($expr->expr->getArgs()) >= 1) { $numArg = null; $args = $expr->expr->getArgs(); $arrayArg = $args[0]->value; if (count($args) > 1) { $numArg = $args[1]->value; } $one = new ConstantIntegerType(1); $arrayType = $scope->getType($arrayArg); if ($arrayType->isArray()->yes() && $arrayType->isIterableAtLeastOnce()->yes() && ($numArg === null || $one->isSuperTypeOf($scope->getType($numArg))->yes())) { $dimFetch = new ArrayDimFetch($arrayArg, $expr->var); return $specifiedTypes->unionWith($this->create($dimFetch, $arrayType->getIterableValueType(), \PHPStan\Analyser\TypeSpecifierContext::createTrue(), $scope)); } } // infer $list[$count] after $count = count($list) - 1 if ($expr->expr instanceof Expr\BinaryOp\Minus && $expr->expr->left instanceof FuncCall && $expr->expr->left->name instanceof Name && !$expr->expr->left->isFirstClassCallable() && $expr->expr->right instanceof Node\Scalar\Int_ && $expr->expr->right->value === 1 && in_array($expr->expr->left->name->toLowerString(), ['count', 'sizeof'], \true) && count($expr->expr->left->getArgs()) >= 1) { $arrayArg = $expr->expr->left->getArgs()[0]->value; $arrayType = $scope->getType($arrayArg); if ($arrayType->isList()->yes() && $arrayType->isIterableAtLeastOnce()->yes()) { $dimFetch = new ArrayDimFetch($arrayArg, $expr->var); return $specifiedTypes->unionWith($this->create($dimFetch, $arrayType->getIterableValueType(), \PHPStan\Analyser\TypeSpecifierContext::createTrue(), $scope)); } } return $specifiedTypes; } return $specifiedTypes; } 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)->setRootExpr($expr); } $issetExpr = $expr->vars[0]; if (!$context->true()) { if (!$scope instanceof \PHPStan\Analyser\MutatingScope) { throw new ShouldNotHappenException(); } $isset = $scope->issetCheck($issetExpr, static fn() => \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(), $scope)->setRootExpr($expr); 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, $scope))->setRootExpr($expr); } if ($isNullable) { // reduces variable certainty to maybe return $exprType->unionWith($this->create(new IssetExpr($issetExpr), new NullType(), $context->negate(), $scope))->setRootExpr($expr); } // variable cannot exist in !isset() return $this->create(new IssetExpr($issetExpr), new NullType(), $context, $scope)->setRootExpr($expr); } if ($isNullable && $isset === \true) { return $exprType; } if ($issetExpr instanceof ArrayDimFetch && $issetExpr->dim !== null) { $varType = $scope->getType($issetExpr->var); if (!$varType instanceof MixedType) { $dimType = $scope->getType($issetExpr->dim); if ($dimType instanceof ConstantIntegerType || $dimType instanceof ConstantStringType) { $constantArrays = $varType->getConstantArrays(); $typesToRemove = []; foreach ($constantArrays as $constantArray) { $hasOffset = $constantArray->hasOffsetValueType($dimType); if (!$hasOffset->yes() || !$constantArray->getOffsetValueType($dimType)->isNull()->no()) { continue; } $typesToRemove[] = $constantArray; } if ($typesToRemove !== []) { $typeToRemove = TypeCombinator::union(...$typesToRemove); $result = $this->create($issetExpr->var, $typeToRemove, \PHPStan\Analyser\TypeSpecifierContext::createFalse(), $scope)->setRootExpr($expr); if ($scope->hasExpressionType($issetExpr->var)->maybe()) { $result = $result->unionWith($this->create(new IssetExpr($issetExpr->var), new NullType(), \PHPStan\Analyser\TypeSpecifierContext::createTruthy(), $scope)->setRootExpr($expr)); } return $result; } } } } 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([], []))->setRootExpr($expr); } } 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, $scope)->setRootExpr($expr)); } else { $varType = $scope->getType($var->var); $narrowedKey = AllowedArrayKeysTypes::narrowOffsetKeyType($varType, $dimType); if ($narrowedKey !== null) { $types = $types->unionWith($this->create($var->dim, $narrowedKey, $context, $scope)->setRootExpr($expr)); } if ($varType->isArray()->yes()) { $types = $types->unionWith($this->create($var->var, new NonEmptyArrayType(), $context, $scope)->setRootExpr($expr)); } } } 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(), $scope)->setRootExpr($expr)); } 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(), $scope)->setRootExpr($expr)); } $types = $types->unionWith($this->create($var, new NullType(), \PHPStan\Analyser\TypeSpecifierContext::createFalse(), $scope)->setRootExpr($expr)); } 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 fn() => \true); if ($isset !== \true) { return new \PHPStan\Analyser\SpecifiedTypes(); } return $this->create($expr->left, new NullType(), $context->negate(), $scope)->setRootExpr($expr); } if ((new ConstantBooleanType(\false))->isSuperTypeOf($scope->getType($expr->right)->toBoolean())->yes()) { return $this->create($expr->left, new NullType(), \PHPStan\Analyser\TypeSpecifierContext::createFalse(), $scope)->setRootExpr($expr); } } elseif ($expr instanceof Expr\Empty_) { if (!$scope instanceof \PHPStan\Analyser\MutatingScope) { throw new ShouldNotHappenException(); } $isset = $scope->issetCheck($expr->expr, static fn() => \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)->setRootExpr($expr); } elseif ($expr instanceof Expr\ErrorSuppress) { return $this->specifyTypesInCondition($scope, $expr->expr, $context)->setRootExpr($expr); } elseif ($expr instanceof Expr\Ternary && !$expr->cond instanceof Expr\Ternary && !$context->null()) { if ($expr->if !== null) { $conditionExpr = new BooleanOr(new BooleanAnd($expr->cond, $expr->if), new BooleanAnd(new Expr\BooleanNot($expr->cond), $expr->else)); } else { $conditionExpr = new BooleanOr($expr->cond, new BooleanAnd(new Expr\BooleanNot($expr->cond), $expr->else)); } return $this->specifyTypesInCondition($scope, $conditionExpr, $context)->setRootExpr($expr); } 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)->setRootExpr($expr); $nullSafeTypes = $this->handleDefaultTruthyOrFalseyContext($context, $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)->setRootExpr($expr); $nullSafeTypes = $this->handleDefaultTruthyOrFalseyContext($context, $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 fn(Type $type) => TemplateTypeHelper::resolveTemplateTypes($type, $parametersAcceptor->getResolvedTemplateTypeMap(), $parametersAcceptor instanceof ExtendedParametersAcceptor ? $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, $expr, $scope); } return (new \PHPStan\Analyser\SpecifiedTypes([], []))->setRootExpr($expr); } private function isNormalCountCall(FuncCall $countFuncCall, Type $typeToCount, \PHPStan\Analyser\Scope $scope): TrinaryLogic { if (count($countFuncCall->getArgs()) === 1) { return TrinaryLogic::createYes(); } $mode = $scope->getType($countFuncCall->getArgs()[1]->value); return (new ConstantIntegerType(COUNT_NORMAL))->isSuperTypeOf($mode)->result->or($typeToCount->getIterableValueType()->isArray()->negate()); } private function specifyTypesForCountFuncCall(FuncCall $countFuncCall, Type $type, Type $sizeType, \PHPStan\Analyser\TypeSpecifierContext $context, \PHPStan\Analyser\Scope $scope, Expr $rootExpr): ?\PHPStan\Analyser\SpecifiedTypes { $isConstantArray = $type->isConstantArray(); $isList = $type->isList(); $oneOrMore = IntegerRangeType::fromInterval(1, null); if (!$this->isNormalCountCall($countFuncCall, $type, $scope)->yes() || !$isConstantArray->yes() && !$isList->yes() || !$oneOrMore->isSuperTypeOf($sizeType)->yes() || $sizeType->isSuperTypeOf($type->getArraySize())->yes()) { return null; } if ($context->falsey() && $isConstantArray->yes()) { $remainingSize = TypeCombinator::remove($type->getArraySize(), $sizeType); if (!$remainingSize instanceof NeverType) { $negatedContext = $context->false() ? \PHPStan\Analyser\TypeSpecifierContext::createTrue() : \PHPStan\Analyser\TypeSpecifierContext::createTruthy(); $result = $this->specifyTypesForCountFuncCall($countFuncCall, $type, $remainingSize, $negatedContext, $scope, $rootExpr); if ($result !== null) { return $result; } } // Fallback: directly filter constant arrays by their exact sizes. // This avoids using TypeCombinator::remove() with falsey context, // which can incorrectly remove arrays whose count doesn't match // but whose shape is a subtype of the matched array. $keptTypes = []; foreach ($type->getConstantArrays() as $arrayType) { if ($sizeType->isSuperTypeOf($arrayType->getArraySize())->yes()) { continue; } $keptTypes[] = $arrayType; } if ($keptTypes !== []) { return $this->create($countFuncCall->getArgs()[0]->value, TypeCombinator::union(...$keptTypes), $context->negate(), $scope)->setRootExpr($rootExpr); } } $resultTypes = []; foreach ($type->getArrays() as $arrayType) { $isSizeSuperTypeOfArraySize = $sizeType->isSuperTypeOf($arrayType->getArraySize()); if ($isSizeSuperTypeOfArraySize->no()) { continue; } if ($context->falsey() && $isSizeSuperTypeOfArraySize->maybe()) { continue; } if ($sizeType instanceof ConstantIntegerType && $sizeType->getValue() < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT && $isList->yes() && $arrayType->getKeyType()->isSuperTypeOf(IntegerRangeType::fromInterval(0, $sizeType->getValue() - 1))->yes()) { // turn optional offsets non-optional $valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty(); for ($i = 0; $i < $sizeType->getValue(); $i++) { $offsetType = new ConstantIntegerType($i); $valueTypesBuilder->setOffsetValueType($offsetType, $arrayType->getOffsetValueType($offsetType)); } $resultTypes[] = $valueTypesBuilder->getArray(); continue; } if ($sizeType instanceof IntegerRangeType && $sizeType->getMin() !== null && $sizeType->getMin() < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT && $isList->yes() && $arrayType->getKeyType()->isSuperTypeOf(IntegerRangeType::fromInterval(0, ($sizeType->getMax() ?? $sizeType->getMin()) - 1))->yes()) { $builderData = []; // turn optional offsets non-optional for ($i = 0; $i < $sizeType->getMin(); $i++) { $offsetType = new ConstantIntegerType($i); $builderData[] = [$offsetType, $arrayType->getOffsetValueType($offsetType), \false]; } if ($sizeType->getMax() !== null) { if ($sizeType->getMax() - $sizeType->getMin() > ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT) { $resultTypes[] = $arrayType; continue; } for ($i = $sizeType->getMin(); $i < $sizeType->getMax(); $i++) { $offsetType = new ConstantIntegerType($i); $builderData[] = [$offsetType, $arrayType->getOffsetValueType($offsetType), \true]; } } elseif ($arrayType->isConstantArray()->yes()) { for ($i = $sizeType->getMin();; $i++) { $offsetType = new ConstantIntegerType($i); $hasOffset = $arrayType->hasOffsetValueType($offsetType); if ($hasOffset->no()) { break; } $builderData[] = [$offsetType, $arrayType->getOffsetValueType($offsetType), !$hasOffset->yes()]; } } else { $intersection = []; $intersection[] = $arrayType; $intersection[] = new NonEmptyArrayType(); $zero = new ConstantIntegerType(0); $i = 0; foreach ($builderData as [$offsetType, $valueType]) { // non-empty-list already implies the offset 0 if ($zero->isSuperTypeOf($offsetType)->yes()) { continue; } if ($i > self::MAX_ACCESSORIES_LIMIT) { break; } $intersection[] = new HasOffsetValueType($offsetType, $valueType); $i++; } $resultTypes[] = TypeCombinator::intersect(...$intersection); continue; } if (count($builderData) > ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT) { $resultTypes[] = $arrayType; continue; } $builder = ConstantArrayTypeBuilder::createEmpty(); foreach ($builderData as [$offsetType, $valueType, $optional]) { $builder->setOffsetValueType($offsetType, $valueType, $optional); } $builtArray = $builder->getArray(); if ($isList->yes() && !$builder->isList()) { $constantArrays = $builtArray->getConstantArrays(); if (count($constantArrays) === 1) { $builtArray = $constantArrays[0]->makeList(); } } $resultTypes[] = $builtArray; continue; } $resultTypes[] = TypeCombinator::intersect($arrayType, new NonEmptyArrayType()); } if ($context->truthy() && $isConstantArray->yes() && $isList->yes()) { $hasOptionalKeys = \false; foreach ($type->getConstantArrays() as $arrayType) { if ($arrayType->getOptionalKeys() !== []) { $hasOptionalKeys = \true; break; } } if (!$hasOptionalKeys) { $argExpr = $countFuncCall->getArgs()[0]->value; $argExprString = $this->exprPrinter->printExpr($argExpr); $sizeMin = null; $sizeMax = null; if ($sizeType instanceof ConstantIntegerType) { $sizeMin = $sizeType->getValue(); $sizeMax = $sizeType->getValue(); } elseif ($sizeType instanceof IntegerRangeType) { $sizeMin = $sizeType->getMin(); $sizeMax = $sizeType->getMax(); } $sureTypes = []; $sureNotTypes = []; if ($sizeMin !== null && $sizeMin >= 1) { $sureTypes[$argExprString] = [$argExpr, new HasOffsetValueType(new ConstantIntegerType($sizeMin - 1), new MixedType())]; } if ($sizeMax !== null) { $sureNotTypes[$argExprString] = [$argExpr, new HasOffsetValueType(new ConstantIntegerType($sizeMax), new MixedType())]; } if ($sureTypes !== [] || $sureNotTypes !== []) { return (new \PHPStan\Analyser\SpecifiedTypes($sureTypes, $sureNotTypes))->setRootExpr($rootExpr); } } } return $this->create($countFuncCall->getArgs()[0]->value, TypeCombinator::union(...$resultTypes), $context, $scope)->setRootExpr($rootExpr); } 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, $scope)->setRootExpr($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())->setRootExpr($rootExpr)); } if (!$context->null() && $constantType->isTrue()->yes()) { $types = $this->create($exprNode, $constantType, $context, $scope)->setRootExpr($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())->setRootExpr($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 && !$exprNode->isFirstClassCallable() && 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, $scope)->setRootExpr($rootExpr); $argType = $this->create($exprNode->getArgs()[0]->value, $type, $context, $scope)->setRootExpr($rootExpr); return $callType->unionWith($argType); } } if ($context->true() && $exprNode instanceof FuncCall && $exprNode->name instanceof Name && !$exprNode->isFirstClassCallable() && 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, $scope)->setRootExpr($rootExpr); } if ($argType->isObject()->yes()) { return $this->create($exprNode->getArgs()[0]->value, $objectType, $context, $scope)->setRootExpr($rootExpr); } return $this->create($exprNode->getArgs()[0]->value, TypeCombinator::union($objectType, $classStringType), $context, $scope)->setRootExpr($rootExpr); } if ($context->false() && $exprNode instanceof FuncCall && $exprNode->name instanceof Name && !$exprNode->isFirstClassCallable() && in_array(strtolower((string) $exprNode->name), ['trim', 'ltrim', 'rtrim', 'chop', 'mb_trim', 'mb_ltrim', 'mb_rtrim'], \true) && isset($exprNode->getArgs()[0]) && $constantStringValue === '') { $argValue = $exprNode->getArgs()[0]->value; $argType = $scope->getType($argValue); if ($argType->isString()->yes()) { return $this->create($argValue, new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]), $context->negate(), $scope)->setRootExpr($rootExpr); } } return null; } private function handleDefaultTruthyOrFalseyContext(\PHPStan\Analyser\TypeSpecifierContext $context, Expr $expr, \PHPStan\Analyser\Scope $scope): \PHPStan\Analyser\SpecifiedTypes { if ($context->null()) { return (new \PHPStan\Analyser\SpecifiedTypes([], []))->setRootExpr($expr); } if (!$context->truthy()) { $type = StaticTypeFactory::truthy(); return $this->create($expr, $type, \PHPStan\Analyser\TypeSpecifierContext::createFalse(), $scope)->setRootExpr($expr); } elseif (!$context->falsey()) { $type = StaticTypeFactory::falsey(); return $this->create($expr, $type, \PHPStan\Analyser\TypeSpecifierContext::createFalse(), $scope)->setRootExpr($expr); } return (new \PHPStan\Analyser\SpecifiedTypes([], []))->setRootExpr($expr); } 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; } $argumentExpr = null; $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; } if ($returnType->getParameterName() !== '$' . $paramName) { continue; } $argumentExpr = $arg->value; } if ($argumentExpr === null) { return null; } return $this->getConditionalSpecifiedTypes($returnType, $leftType, $rightType, $scope, $argumentExpr); } private function getConditionalSpecifiedTypes(ConditionalTypeForParameter $conditionalType, Type $leftType, Type $rightType, \PHPStan\Analyser\Scope $scope, Expr $argumentExpr): ?\PHPStan\Analyser\SpecifiedTypes { $targetType = $conditionalType->getTarget(); $ifType = $conditionalType->getIf(); $elseType = $conditionalType->getElse(); if (($argumentExpr instanceof Node\Scalar || $argumentExpr instanceof ConstFetch && in_array(strtolower($argumentExpr->name->toString()), ['true', 'false', 'null'], \true)) && ($ifType instanceof NeverType || $elseType instanceof NeverType)) { return null; } 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($argumentExpr, $targetType, $context, $scope); if ($targetType instanceof ConstantBooleanType) { if (!$targetType->getValue()) { $context = $context->negate(); } $specifiedTypes = $specifiedTypes->unionWith($this->specifyTypesInCondition($scope, $argumentExpr, $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 = array_last($parameters); $paramName = $lastParameter->getName(); } else { continue; } $argsMap[$paramName][] = $arg->value; } foreach ($parameters as $parameter) { $name = $parameter->getName(); $defaultValue = $parameter->getDefaultValue(); if (isset($argsMap[$name]) || $defaultValue === null) { continue; } $argsMap[$name][] = new TypeExpr($defaultValue); } 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)) { $type = $traverse($type); if ($type instanceof ConditionalTypeForParameter) { $argType = TypeCombinator::union(...array_map(static fn(Expr $expr) => $scope->getType($expr), $argsMap[substr($type->getParameterName(), 1)])); return $type->toConditional($argType); } return $type; } } 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(), $scope)->setRootExpr($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; } private function specifyTypesFromCallableCall(\PHPStan\Analyser\TypeSpecifierContext $context, FuncCall $call, \PHPStan\Analyser\Scope $scope): ?\PHPStan\Analyser\SpecifiedTypes { if (!$call->name instanceof Expr) { return null; } $calleeType = $scope->getType($call->name); $assertions = null; $parametersAcceptor = null; if ($calleeType->isCallable()->yes()) { $variants = $calleeType->getCallableParametersAcceptors($scope); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $call->getArgs(), $variants); if ($parametersAcceptor instanceof CallableParametersAcceptor) { $assertions = $parametersAcceptor->getAsserts(); } } if ($assertions === null || $assertions->getAll() === []) { return null; } $asserts = $assertions->mapTypes(static fn(Type $type) => TemplateTypeHelper::resolveTemplateTypes($type, $parametersAcceptor->getResolvedTemplateTypeMap(), $parametersAcceptor instanceof ExtendedParametersAcceptor ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createInvariant())); return $this->specifyTypesFromAsserts($context, $call, $asserts, $parametersAcceptor, $scope); } /** * For `if ($a || $b)` truthy, expressions narrowed by stored conditional * holders (e.g. `$a = $obj instanceof ClassA;` records "when `$a` is * truthy, `$obj` is `ClassA`") need to be projected into the OR-truthy * scope as the union of the per-arm narrowings. specifyTypesInCondition * for each arm only looks at the boolean variable itself, so the held * narrowing of `$obj` would otherwise be invisible until a later check * pins one of the booleans down. * * For each conditional-holder target $T: * - resolve $T's type in the left-truthy and right-truthy filtered scopes * - if both narrow $T strictly below the original, add `$T : leftT|rightT` * as a sure type to the OR-truthy result * * The asymmetric case (one arm narrows, the other doesn't) is intentionally * skipped: in the OR-truthy scope the arm that didn't narrow could still be * the truthy one, so the sound result is the original (unnarrowed) type. * @param \PhpParser\Node\Expr\BinaryOp\BooleanOr|\PhpParser\Node\Expr\BinaryOp\LogicalOr $expr */ private function augmentBooleanOrTruthyWithConditionalHolders(\PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\MutatingScope $rightScope, $expr, \PHPStan\Analyser\SpecifiedTypes $types): \PHPStan\Analyser\SpecifiedTypes { $leftTruthyScope = $scope->filterByTruthyValue($expr->left); $rightTruthyScope = $rightScope->filterByTruthyValue($expr->right); $seen = []; foreach ([$scope, $rightScope] as $sourceScope) { foreach ($sourceScope->getConditionalExpressions() as $exprString => $holders) { if (isset($seen[$exprString])) { continue; } if ($holders === []) { continue; } $seen[$exprString] = \true; $targetExpr = $holders[array_key_first($holders)]->getTypeHolder()->getExpr(); // Only project when the target stays Yes-defined in the original // scope and in both filtered branches. A sure type implicitly // raises certainty to Yes, which would wrongly upgrade Maybe-defined // variables — `if (empty($a['bar']))` for instance leaves `$a` // Maybe-defined because `empty()` tolerates undefined offsets. if (!$scope->hasExpressionType($targetExpr)->yes()) { continue; } if (!$leftTruthyScope->hasExpressionType($targetExpr)->yes()) { continue; } if (!$rightTruthyScope->hasExpressionType($targetExpr)->yes()) { continue; } $origType = $scope->getType($targetExpr); $leftType = $leftTruthyScope->getType($targetExpr); $rightType = $rightTruthyScope->getType($targetExpr); $leftNarrowed = !$leftType->equals($origType) && $origType->isSuperTypeOf($leftType)->yes(); $rightNarrowed = !$rightType->equals($origType) && $origType->isSuperTypeOf($rightType)->yes(); if (!$leftNarrowed || !$rightNarrowed) { continue; } $unionType = TypeCombinator::union($leftType, $rightType); if ($unionType->equals($origType)) { continue; } $types = $types->unionWith($this->create($targetExpr, $unionType, \PHPStan\Analyser\TypeSpecifierContext::createTrue(), $scope)); } } return $types; } private function augmentDisjunctionTypes(\PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\MutatingScope $rightScope, \PHPStan\Analyser\SpecifiedTypes $leftNormalized, \PHPStan\Analyser\SpecifiedTypes $rightNormalized, Expr $leftExpr, Expr $rightExpr, bool $truthy, \PHPStan\Analyser\SpecifiedTypes $types): \PHPStan\Analyser\SpecifiedTypes { $candidateExprs = []; foreach ($leftNormalized->getSureTypes() as $exprString => [$exprNode, $type]) { $candidateExprs[$exprString] = $exprNode; } foreach ($rightNormalized->getSureTypes() as $exprString => [$exprNode, $type]) { $candidateExprs[$exprString] = $exprNode; } $existingSureTypes = $types->getSureTypes(); $viableCandidates = []; foreach ($candidateExprs as $exprString => $targetExpr) { if (isset($existingSureTypes[$exprString])) { continue; } if (!$scope->hasExpressionType($targetExpr)->yes()) { continue; } $viableCandidates[$exprString] = $targetExpr; } if ($viableCandidates === []) { return $types; } if ($truthy) { $leftFilteredScope = $scope->filterByTruthyValue($leftExpr); $rightFilteredScope = $rightScope->filterByTruthyValue($rightExpr); } else { $leftFilteredScope = $scope->filterByFalseyValue($leftExpr); $rightFilteredScope = $rightScope->filterByFalseyValue($rightExpr); } foreach ($viableCandidates as $targetExpr) { if (!$leftFilteredScope->hasExpressionType($targetExpr)->yes()) { continue; } if (!$rightFilteredScope->hasExpressionType($targetExpr)->yes()) { continue; } $originalType = $scope->getType($targetExpr); $leftType = $leftFilteredScope->getType($targetExpr); $rightType = $rightFilteredScope->getType($targetExpr); if ($leftType->equals($originalType) || !$originalType->isSuperTypeOf($leftType)->yes()) { continue; } if ($rightType->equals($originalType) || !$originalType->isSuperTypeOf($rightType)->yes()) { continue; } $unionType = TypeCombinator::union($leftType, $rightType); if ($unionType->equals($originalType)) { continue; } $types = $types->unionWith($this->create($targetExpr, $unionType, \PHPStan\Analyser\TypeSpecifierContext::createTrue(), $scope)); } return $types; } /** * @return array */ private function processBooleanSureConditionalTypes(\PHPStan\Analyser\Scope $scope, \PHPStan\Analyser\SpecifiedTypes $leftTypes, \PHPStan\Analyser\SpecifiedTypes $rightTypes, \PHPStan\Analyser\Scope $rightScope): array { $conditionExpressionTypes = []; foreach ($leftTypes->getSureTypes() as $exprString => [$expr, $type]) { if (!$this->isTrackableExpression($expr)) { continue; } $scopeType = $scope->getType($expr); $conditionType = TypeCombinator::remove($scopeType, $type); if ($scopeType->equals($conditionType)) { continue; } $conditionExpressionTypes[$exprString] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($expr, $conditionType); } if (count($conditionExpressionTypes) > 0) { $holders = []; foreach ($rightTypes->getSureTypes() as $exprString => [$expr, $type]) { if (!$this->isTrackableExpression($expr)) { continue; } if (!isset($holders[$exprString])) { $holders[$exprString] = []; } $conditions = $conditionExpressionTypes; foreach (array_keys($conditions) as $conditionExprString) { if ($conditionExprString !== $exprString) { continue; } unset($conditions[$conditionExprString]); } if (count($conditions) === 0) { continue; } $targetScope = $expr instanceof Expr\Variable ? $scope : $rightScope; $holder = new \PHPStan\Analyser\ConditionalExpressionHolder($conditions, \PHPStan\Analyser\ExpressionTypeHolder::createYes($expr, TypeCombinator::intersect($targetScope->getType($expr), $type))); $holders[$exprString][$holder->getKey()] = $holder; } return $holders; } return []; } private function isTrackableExpression(Expr $expr): bool { if ($expr instanceof Expr\Variable) { return is_string($expr->name); } return $expr instanceof Expr\PropertyFetch || $expr instanceof Expr\ArrayDimFetch || $expr instanceof Expr\StaticPropertyFetch; } /** * Flatten a deep BooleanOr chain into leaf expressions and process them * without recursive filterByFalseyValue calls. This reduces O(n^2) to O(n) * for chains with many arms (e.g., 80+ === comparisons in ||). * @param \PhpParser\Node\Expr\BinaryOp\BooleanOr|\PhpParser\Node\Expr\BinaryOp\LogicalOr $expr */ private function specifyTypesForFlattenedBooleanOr(\PHPStan\Analyser\MutatingScope $scope, $expr, \PHPStan\Analyser\TypeSpecifierContext $context): \PHPStan\Analyser\SpecifiedTypes { // Collect all leaf expressions from the chain $arms = []; $current = $expr; while ($current instanceof BooleanOr || $current instanceof LogicalOr) { $arms[] = $current->right; $current = $current->left; } $arms[] = $current; // leftmost leaf $arms = array_reverse($arms); if ($context->false() || $context->falsey()) { // Falsey: all arms are false → union all SpecifiedTypes. // Collect per-expression types first, then build unions once // to avoid O(N²) from incremental TypeCombinator::union() growth. /** @var array}> $sureTypesPerExpr */ $sureTypesPerExpr = []; /** @var array}> $sureNotTypesPerExpr */ $sureNotTypesPerExpr = []; foreach ($arms as $arm) { $armTypes = $this->specifyTypesInCondition($scope, $arm, $context); foreach ($armTypes->getSureTypes() as $exprString => [$exprNode, $type]) { $sureTypesPerExpr[$exprString][0] = $exprNode; $sureTypesPerExpr[$exprString][1][] = $type; } foreach ($armTypes->getSureNotTypes() as $exprString => [$exprNode, $type]) { $sureNotTypesPerExpr[$exprString][0] = $exprNode; $sureNotTypesPerExpr[$exprString][1][] = $type; } } $sureTypes = []; foreach ($sureTypesPerExpr as $exprString => [$exprNode, $types]) { $sureTypes[$exprString] = [$exprNode, TypeCombinator::intersect(...$types)]; } $sureNotTypes = []; foreach ($sureNotTypesPerExpr as $exprString => [$exprNode, $types]) { $sureNotTypes[$exprString] = [$exprNode, TypeCombinator::union(...$types)]; } return (new \PHPStan\Analyser\SpecifiedTypes($sureTypes, $sureNotTypes))->setRootExpr($expr); } // Truthy: at least one arm is true → intersect all normalized SpecifiedTypes $armSpecifiedTypes = []; foreach ($arms as $arm) { $armTypes = $this->specifyTypesInCondition($scope, $arm, $context); $armSpecifiedTypes[] = $armTypes->normalize($scope); } $types = $armSpecifiedTypes[0]; for ($i = 1; $i < count($armSpecifiedTypes); $i++) { $types = $types->intersectWith($armSpecifiedTypes[$i]); } $result = new \PHPStan\Analyser\SpecifiedTypes($types->getSureTypes(), $types->getSureNotTypes()); if ($types->shouldOverwrite()) { $result = $result->setAlwaysOverwriteTypes(); } return $result->setRootExpr($expr); } /** * @param BooleanAnd|LogicalAnd $expr */ private function specifyTypesForFlattenedBooleanAnd(\PHPStan\Analyser\MutatingScope $scope, Expr $expr, \PHPStan\Analyser\TypeSpecifierContext $context): \PHPStan\Analyser\SpecifiedTypes { $arms = []; $current = $expr; while ($current instanceof BooleanAnd || $current instanceof LogicalAnd) { $arms[] = $current->right; $current = $current->left; } $arms[] = $current; $arms = array_reverse($arms); // Truthy: all arms are true → union all SpecifiedTypes. // Collect per-expression types first, then build unions once // to avoid O(N²) from incremental growth. /** @var array}> $sureTypesPerExpr */ $sureTypesPerExpr = []; /** @var array}> $sureNotTypesPerExpr */ $sureNotTypesPerExpr = []; foreach ($arms as $arm) { $armTypes = $this->specifyTypesInCondition($scope, $arm, $context); foreach ($armTypes->getSureTypes() as $exprString => [$exprNode, $type]) { $sureTypesPerExpr[$exprString][0] = $exprNode; $sureTypesPerExpr[$exprString][1][] = $type; } foreach ($armTypes->getSureNotTypes() as $exprString => [$exprNode, $type]) { $sureNotTypesPerExpr[$exprString][0] = $exprNode; $sureNotTypesPerExpr[$exprString][1][] = $type; } } $sureTypes = []; foreach ($sureTypesPerExpr as $exprString => [$exprNode, $types]) { $sureTypes[$exprString] = [$exprNode, TypeCombinator::union(...$types)]; } $sureNotTypes = []; foreach ($sureNotTypesPerExpr as $exprString => [$exprNode, $types]) { $sureNotTypes[$exprString] = [$exprNode, TypeCombinator::union(...$types)]; } return (new \PHPStan\Analyser\SpecifiedTypes($sureTypes, $sureNotTypes))->setRootExpr($expr); } /** * @return array */ private function processBooleanNotSureConditionalTypes(\PHPStan\Analyser\Scope $scope, \PHPStan\Analyser\SpecifiedTypes $leftTypes, \PHPStan\Analyser\SpecifiedTypes $rightTypes, \PHPStan\Analyser\Scope $rightScope): array { $conditionExpressionTypes = []; foreach ($leftTypes->getSureNotTypes() as $exprString => [$expr, $type]) { if (!$this->isTrackableExpression($expr)) { 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 (!$this->isTrackableExpression($expr)) { continue; } if (!isset($holders[$exprString])) { $holders[$exprString] = []; } $conditions = $conditionExpressionTypes; foreach (array_keys($conditions) as $conditionExprString) { if ($conditionExprString !== $exprString) { continue; } unset($conditions[$conditionExprString]); } if (count($conditions) === 0) { continue; } $targetScope = $expr instanceof Expr\Variable ? $scope : $rightScope; $holder = new \PHPStan\Analyser\ConditionalExpressionHolder($conditions, \PHPStan\Analyser\ExpressionTypeHolder::createYes($expr, TypeCombinator::remove($targetScope->getType($expr), $type))); $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) { return [$binaryOperation->right, $leftType, $rightType]; } elseif ($rightType instanceof ConstantScalarType && !$leftExpr instanceof ConstFetch) { return [$binaryOperation->left, $rightType, $leftType]; } return null; } /** * @api */ public function create(Expr $expr, Type $type, \PHPStan\Analyser\TypeSpecifierContext $context, \PHPStan\Analyser\Scope $scope): \PHPStan\Analyser\SpecifiedTypes { if ($expr instanceof Instanceof_ || $expr instanceof Expr\List_) { return (new \PHPStan\Analyser\SpecifiedTypes([], []))->setRootExpr($expr); } $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, $scope); if ($types === null) { $types = $newTypes; } else { $types = $types->unionWith($newTypes); } } return $types; } private function createArrayDimFetchConditionalExpressionHolder(Expr\Variable $keyVar, Expr $arrayArg, Type $narrowedKeyType, Type $dimFetchType): \PHPStan\Analyser\SpecifiedTypes { $dimFetch = new ArrayDimFetch($arrayArg, $keyVar); $dimFetchString = $this->exprPrinter->printExpr($dimFetch); $keyExprString = $this->exprPrinter->printExpr($keyVar); $holder = new \PHPStan\Analyser\ConditionalExpressionHolder([$keyExprString => \PHPStan\Analyser\ExpressionTypeHolder::createYes($keyVar, $narrowedKeyType)], \PHPStan\Analyser\ExpressionTypeHolder::createYes($dimFetch, $dimFetchType)); return (new \PHPStan\Analyser\SpecifiedTypes([], []))->setNewConditionalExpressionHolders([$dimFetchString => [$holder->getKey() => $holder]]); } private function createForExpr(Expr $expr, Type $type, \PHPStan\Analyser\TypeSpecifierContext $context, \PHPStan\Analyser\Scope $scope): \PHPStan\Analyser\SpecifiedTypes { 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 (!$context->null() && $expr instanceof Expr\BinaryOp\Coalesce) { if ($context->true() && $type->isSuperTypeOf($scope->getType($expr->right))->no() || $context->false() && $type->isSuperTypeOf($scope->getType($expr->right))->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([], []); } $functionReflection = $this->reflectionProvider->getFunction($expr->name, $scope); $hasSideEffects = $functionReflection->hasSideEffects(); if ($hasSideEffects->yes()) { return new \PHPStan\Analyser\SpecifiedTypes([], []); } if (!$this->rememberPossiblyImpureFunctionValues && !$hasSideEffects->no()) { return new \PHPStan\Analyser\SpecifiedTypes([], []); } } if ($expr instanceof FuncCall && !$expr->name instanceof Name) { $nameType = $scope->getType($expr->name); if ($nameType->isCallable()->yes()) { $isPure = null; foreach ($nameType->getCallableParametersAcceptors($scope) as $variant) { $variantIsPure = $variant->isPure(); $isPure = $isPure === null ? $variantIsPure : $isPure->and($variantIsPure); } if ($isPure !== null) { if ($isPure->no()) { return new \PHPStan\Analyser\SpecifiedTypes([], []); } if (!$this->rememberPossiblyImpureFunctionValues && !$isPure->yes()) { return new \PHPStan\Analyser\SpecifiedTypes([], []); } } } } if ($expr instanceof MethodCall && $expr->name instanceof Node\Identifier) { $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($originalExpr, $scope, $context, $type); } return new \PHPStan\Analyser\SpecifiedTypes([], []); } } if ($expr instanceof StaticCall && $expr->name instanceof Node\Identifier) { $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($originalExpr, $scope, $context, $type); } return new \PHPStan\Analyser\SpecifiedTypes([], []); } } $sureTypes = []; $sureNotTypes = []; if ($context->false()) { $exprString = $this->exprPrinter->printExpr($expr); $sureNotTypes[$exprString] = [$expr, $type]; if ($expr !== $originalExpr) { $originalExprString = $this->exprPrinter->printExpr($originalExpr); $sureNotTypes[$originalExprString] = [$originalExpr, $type]; } } elseif ($context->true()) { $exprString = $this->exprPrinter->printExpr($expr); $sureTypes[$exprString] = [$expr, $type]; if ($expr !== $originalExpr) { $originalExprString = $this->exprPrinter->printExpr($originalExpr); $sureTypes[$originalExprString] = [$originalExpr, $type]; } } $types = new \PHPStan\Analyser\SpecifiedTypes($sureTypes, $sureNotTypes); if (isset($containsNull) && !$containsNull) { return $this->createNullsafeTypes($originalExpr, $scope, $context, $type)->unionWith($types); } return $types; } private function createNullsafeTypes(Expr $expr, \PHPStan\Analyser\Scope $scope, \PHPStan\Analyser\TypeSpecifierContext $context, ?Type $type): \PHPStan\Analyser\SpecifiedTypes { if ($expr instanceof Expr\NullsafePropertyFetch) { if ($type !== null) { $propertyFetchTypes = $this->create(new PropertyFetch($expr->var, $expr->name), $type, $context, $scope); } else { $propertyFetchTypes = $this->create(new PropertyFetch($expr->var, $expr->name), new NullType(), \PHPStan\Analyser\TypeSpecifierContext::createFalse(), $scope); } return $propertyFetchTypes->unionWith($this->create($expr->var, new NullType(), \PHPStan\Analyser\TypeSpecifierContext::createFalse(), $scope)); } if ($expr instanceof Expr\NullsafeMethodCall) { if ($type !== null) { $methodCallTypes = $this->create(new MethodCall($expr->var, $expr->name, $expr->args), $type, $context, $scope); } else { $methodCallTypes = $this->create(new MethodCall($expr->var, $expr->name, $expr->args), new NullType(), \PHPStan\Analyser\TypeSpecifierContext::createFalse(), $scope); } return $methodCallTypes->unionWith($this->create($expr->var, new NullType(), \PHPStan\Analyser\TypeSpecifierContext::createFalse(), $scope)); } if ($expr instanceof Expr\PropertyFetch) { return $this->createNullsafeTypes($expr->var, $scope, $context, null); } if ($expr instanceof Expr\MethodCall) { return $this->createNullsafeTypes($expr->var, $scope, $context, null); } if ($expr instanceof Expr\ArrayDimFetch) { return $this->createNullsafeTypes($expr->var, $scope, $context, null); } if ($expr instanceof Expr\StaticPropertyFetch && $expr->class instanceof Expr) { return $this->createNullsafeTypes($expr->class, $scope, $context, null); } if ($expr instanceof Expr\StaticCall && $expr->class instanceof Expr) { return $this->createNullsafeTypes($expr->class, $scope, $context, null); } return new \PHPStan\Analyser\SpecifiedTypes([], []); } 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))->setRootExpr($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): \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, $scope)->setRootExpr($expr); } if (!$context->null() && $constantType->getValue() === \false) { return $this->specifyTypesInCondition($scope, $exprNode, $context->true() ? \PHPStan\Analyser\TypeSpecifierContext::createFalsey() : \PHPStan\Analyser\TypeSpecifierContext::createFalsey()->negate())->setRootExpr($expr); } if (!$context->null() && $constantType->getValue() === \true) { return $this->specifyTypesInCondition($scope, $exprNode, $context->true() ? \PHPStan\Analyser\TypeSpecifierContext::createTruthy() : \PHPStan\Analyser\TypeSpecifierContext::createTruthy()->negate())->setRootExpr($expr); } 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, $scope)->setRootExpr($expr); } 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, $scope)->setRootExpr($expr); } if ($exprNode instanceof FuncCall && $exprNode->name instanceof Name && !$exprNode->isFirstClassCallable() && 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)->setRootExpr($expr); } 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)->setRootExpr($expr); } if ($context->true() && $exprNode instanceof ClassConstFetch && $exprNode->name instanceof Node\Identifier && strtolower($exprNode->name->toString()) === 'class' && $constantType->isString()->yes()) { return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Identical($expr->left, $expr->right), $context)->setRootExpr($expr); } } $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)->setRootExpr($expr); } $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)->setRootExpr($expr); } if (!$context->null() && $rightType->isArray()->yes() && $leftType->isConstantArray()->yes() && $leftType->isIterableAtLeastOnce()->no()) { return $this->create($expr->right, new NonEmptyArrayType(), $context->negate(), $scope)->setRootExpr($expr); } if (!$context->null() && $leftType->isArray()->yes() && $rightType->isConstantArray()->yes() && $rightType->isIterableAtLeastOnce()->no()) { return $this->create($expr->left, new NonEmptyArrayType(), $context->negate(), $scope)->setRootExpr($expr); } 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)->setRootExpr($expr); } $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([], []))->setRootExpr($expr); } } $leftTypes = $this->create($expr->left, $leftType, $context, $scope)->setRootExpr($expr); $rightTypes = $this->create($expr->right, $rightType, $context, $scope)->setRootExpr($expr); 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): \PHPStan\Analyser\SpecifiedTypes { $leftExpr = $expr->left; $rightExpr = $expr->right; // Normalize to: fn() === expr if ($rightExpr instanceof FuncCall && !$leftExpr instanceof FuncCall) { $specifiedTypes = $this->resolveNormalizedIdentical(new Expr\BinaryOp\Identical($rightExpr, $leftExpr), $scope, $context); } else { $specifiedTypes = $this->resolveNormalizedIdentical(new Expr\BinaryOp\Identical($leftExpr, $rightExpr), $scope, $context); } // merge result of fn1() === fn2() and fn2() === fn1() if ($rightExpr instanceof FuncCall && $leftExpr instanceof FuncCall) { return $specifiedTypes->unionWith($this->resolveNormalizedIdentical(new Expr\BinaryOp\Identical($rightExpr, $leftExpr), $scope, $context)); } return $specifiedTypes; } private function resolveNormalizedIdentical(Expr\BinaryOp\Identical $expr, \PHPStan\Analyser\Scope $scope, \PHPStan\Analyser\TypeSpecifierContext $context): \PHPStan\Analyser\SpecifiedTypes { $leftExpr = $expr->left; $rightExpr = $expr->right; $unwrappedLeftExpr = $leftExpr; if ($leftExpr instanceof AlwaysRememberedExpr) { $unwrappedLeftExpr = $leftExpr->getExpr(); } $unwrappedRightExpr = $rightExpr; if ($rightExpr instanceof AlwaysRememberedExpr) { $unwrappedRightExpr = $rightExpr->getExpr(); } $rightType = $scope->getType($rightExpr); // (count($a) === $expr) if (!$context->null() && $unwrappedLeftExpr instanceof FuncCall && !$unwrappedLeftExpr->isFirstClassCallable() && count($unwrappedLeftExpr->getArgs()) >= 1 && $unwrappedLeftExpr->name instanceof Name && in_array(strtolower((string) $unwrappedLeftExpr->name), ['count', 'sizeof'], \true) && $rightType->isInteger()->yes()) { // count($a) === count($b) if ($context->true() && $unwrappedRightExpr instanceof FuncCall && $unwrappedRightExpr->name instanceof Name && !$unwrappedRightExpr->isFirstClassCallable() && in_array($unwrappedRightExpr->name->toLowerString(), ['count', 'sizeof'], \true) && count($unwrappedRightExpr->getArgs()) >= 1) { $argType = $scope->getType($unwrappedRightExpr->getArgs()[0]->value); $sizeType = $scope->getType($leftExpr); $specifiedTypes = $this->specifyTypesForCountFuncCall($unwrappedRightExpr, $argType, $sizeType, $context, $scope, $expr); if ($specifiedTypes !== null) { return $specifiedTypes; } $leftArrayType = $scope->getType($unwrappedLeftExpr->getArgs()[0]->value); $rightArrayType = $scope->getType($unwrappedRightExpr->getArgs()[0]->value); if ($leftArrayType->isArray()->yes() && $rightArrayType->isArray()->yes() && !$rightType->isConstantScalarValue()->yes() && ($leftArrayType->isIterableAtLeastOnce()->yes() || $rightArrayType->isIterableAtLeastOnce()->yes())) { $arrayTypes = $this->create($unwrappedLeftExpr->getArgs()[0]->value, new NonEmptyArrayType(), $context, $scope)->setRootExpr($expr); return $arrayTypes->unionWith($this->create($unwrappedRightExpr->getArgs()[0]->value, new NonEmptyArrayType(), $context, $scope)->setRootExpr($expr)); } } if (IntegerRangeType::fromInterval(null, -1)->isSuperTypeOf($rightType)->yes()) { return $this->create($unwrappedLeftExpr->getArgs()[0]->value, new NeverType(), $context, $scope)->setRootExpr($expr); } $argType = $scope->getType($unwrappedLeftExpr->getArgs()[0]->value); $isZero = (new ConstantIntegerType(0))->isSuperTypeOf($rightType); if ($isZero->yes()) { $funcTypes = $this->create($leftExpr, $rightType, $context, $scope)->setRootExpr($expr); 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, $scope)->setRootExpr($expr)); } $specifiedTypes = $this->specifyTypesForCountFuncCall($unwrappedLeftExpr, $argType, $rightType, $context, $scope, $expr); if ($specifiedTypes !== null) { if ($leftExpr !== $unwrappedLeftExpr) { $funcTypes = $this->create($leftExpr, $rightType, $context, $scope)->setRootExpr($expr); return $specifiedTypes->unionWith($funcTypes); } return $specifiedTypes; } if ($context->truthy() && $argType->isArray()->yes()) { $funcTypes = $this->create($leftExpr, $rightType, $context, $scope)->setRootExpr($expr); if (IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($rightType)->yes()) { return $funcTypes->unionWith($this->create($unwrappedLeftExpr->getArgs()[0]->value, new NonEmptyArrayType(), $context, $scope)->setRootExpr($expr)); } return $funcTypes; } } // strlen($a) === $b if (!$context->null() && $unwrappedLeftExpr instanceof FuncCall && $unwrappedLeftExpr->name instanceof Name && !$unwrappedLeftExpr->isFirstClassCallable() && in_array(strtolower((string) $unwrappedLeftExpr->name), ['strlen', 'mb_strlen'], \true) && count($unwrappedLeftExpr->getArgs()) === 1 && $rightType->isInteger()->yes()) { if (IntegerRangeType::fromInterval(null, -1)->isSuperTypeOf($rightType)->yes()) { return $this->create($unwrappedLeftExpr->getArgs()[0]->value, new NeverType(), $context, $scope)->setRootExpr($expr); } $isZero = (new ConstantIntegerType(0))->isSuperTypeOf($rightType); if ($isZero->yes()) { $funcTypes = $this->create($leftExpr, $rightType, $context, $scope)->setRootExpr($expr); return $funcTypes->unionWith($this->create($unwrappedLeftExpr->getArgs()[0]->value, new ConstantStringType(''), $context, $scope)->setRootExpr($expr)); } if ($context->truthy() && IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($rightType)->yes()) { $argType = $scope->getType($unwrappedLeftExpr->getArgs()[0]->value); if ($argType->isString()->yes()) { $funcTypes = $this->create($leftExpr, $rightType, $context, $scope)->setRootExpr($expr); $accessory = new AccessoryNonEmptyStringType(); if (IntegerRangeType::fromInterval(2, null)->isSuperTypeOf($rightType)->yes()) { $accessory = new AccessoryNonFalsyStringType(); } $valueTypes = $this->create($unwrappedLeftExpr->getArgs()[0]->value, $accessory, $context, $scope)->setRootExpr($expr); return $funcTypes->unionWith($valueTypes); } } } // array_key_first($a) !== null // array_key_last($a) !== null // array_find_key($a, $cb) !== null if ($unwrappedLeftExpr instanceof FuncCall && $unwrappedLeftExpr->name instanceof Name && !$unwrappedLeftExpr->isFirstClassCallable() && isset($unwrappedLeftExpr->getArgs()[0]) && $rightType->isNull()->yes()) { $funcName = $unwrappedLeftExpr->name->toLowerString(); $bothDirections = in_array($funcName, ['array_key_first', 'array_key_last'], \true); $notNullOnly = $funcName === 'array_find_key'; if ($bothDirections || $notNullOnly) { $args = $unwrappedLeftExpr->getArgs(); $argType = $scope->getType($args[0]->value); if ($argType->isArray()->yes()) { if ($bothDirections) { return $this->create($args[0]->value, new NonEmptyArrayType(), $context->negate(), $scope)->setRootExpr($expr); } if ($context->falsey()) { return $this->create($args[0]->value, new NonEmptyArrayType(), $context->negate(), $scope)->setRootExpr($expr); } } } } // 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)->setRootExpr($expr); } // get_class($a) === 'Foo' if ($context->true() && $unwrappedLeftExpr instanceof FuncCall && $unwrappedLeftExpr->name instanceof Name && !$unwrappedLeftExpr->isFirstClassCallable() && in_array(strtolower($unwrappedLeftExpr->name->toString()), ['get_class', 'get_debug_type'], \true) && isset($unwrappedLeftExpr->getArgs()[0])) { if ($rightType instanceof ConstantStringType && $this->reflectionProvider->hasClass($rightType->getValue())) { return $this->create($unwrappedLeftExpr->getArgs()[0]->value, new ObjectType($rightType->getValue(), \null, $this->reflectionProvider->getClass($rightType->getValue())->asFinal()), $context, $scope)->unionWith($this->create($leftExpr, $rightType, $context, $scope))->setRootExpr($expr); } if ($rightType->getClassStringObjectType()->isObject()->yes()) { return $this->create($unwrappedLeftExpr->getArgs()[0]->value, $rightType->getClassStringObjectType(), $context, $scope)->unionWith($this->create($leftExpr, $rightType, $context, $scope))->setRootExpr($expr); } } if ($context->truthy() && $unwrappedLeftExpr instanceof FuncCall && $unwrappedLeftExpr->name instanceof Name && !$unwrappedLeftExpr->isFirstClassCallable() && 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()) { $specifiedTypes = new \PHPStan\Analyser\SpecifiedTypes(); if (in_array(strtolower($unwrappedLeftExpr->name->toString()), ['strtolower', 'mb_strtolower'], \true)) { $specifiedTypes = $this->create($unwrappedRightExpr, TypeCombinator::intersect($rightType, new AccessoryLowercaseStringType()), $context, $scope)->setRootExpr($expr); } if (in_array(strtolower($unwrappedLeftExpr->name->toString()), ['strtoupper', 'mb_strtoupper'], \true)) { $specifiedTypes = $this->create($unwrappedRightExpr, TypeCombinator::intersect($rightType, new AccessoryUppercaseStringType()), $context, $scope)->setRootExpr($expr); } if ($rightType->isNonFalsyString()->yes()) { return $specifiedTypes->unionWith($this->create($unwrappedLeftExpr->getArgs()[0]->value, TypeCombinator::intersect($argType, new AccessoryNonFalsyStringType()), $context, $scope)->setRootExpr($expr)); } return $specifiedTypes->unionWith($this->create($unwrappedLeftExpr->getArgs()[0]->value, TypeCombinator::intersect($argType, new AccessoryNonEmptyStringType()), $context, $scope)->setRootExpr($expr)); } } if ($rightType->isString()->yes()) { $types = null; foreach ($rightType->getConstantStrings() as $constantString) { $specifiedType = $this->specifyTypesForConstantStringBinaryExpression($unwrappedLeftExpr, $constantString, $context, $scope, $expr); 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, $scope)->setRootExpr($expr)); } 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, $expr); if ($specifiedType !== null) { if ($exprNode !== $unwrappedExprNode) { $specifiedType = $specifiedType->unionWith($this->create($exprNode, $constantType, $context, $scope)->setRootExpr($expr)); } 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') { if ($this->reflectionProvider->hasClass($rightType->getValue())) { return $this->create($unwrappedLeftExpr->class, new ObjectType($rightType->getValue(), \null, $this->reflectionProvider->getClass($rightType->getValue())->asFinal()), $context, $scope)->unionWith($this->create($leftExpr, $rightType, $context, $scope))->setRootExpr($expr); } return $this->specifyTypesInCondition($scope, new Instanceof_($unwrappedLeftExpr->class, new Name($rightType->getValue())), $context)->unionWith($this->create($leftExpr, $rightType, $context, $scope))->setRootExpr($expr); } $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') { if ($this->reflectionProvider->hasClass($leftType->getValue())) { return $this->create($unwrappedRightExpr->class, new ObjectType($leftType->getValue(), \null, $this->reflectionProvider->getClass($leftType->getValue())->asFinal()), $context, $scope)->unionWith($this->create($rightExpr, $leftType, $context, $scope)->setRootExpr($expr)); } return $this->specifyTypesInCondition($scope, new Instanceof_($unwrappedRightExpr->class, new Name($leftType->getValue())), $context)->unionWith($this->create($rightExpr, $leftType, $context, $scope)->setRootExpr($expr)); } if ($context->false()) { $identicalType = $scope->getType($expr); if ($identicalType instanceof ConstantBooleanType) { $never = new NeverType(); $contextForTypes = $identicalType->getValue() ? $context->negate() : $context; if ($leftExpr instanceof AlwaysRememberedExpr) { $leftTypes = $this->create($unwrappedLeftExpr, $never, $contextForTypes, $scope)->setRootExpr($expr); } else { $leftTypes = $this->create($leftExpr, $never, $contextForTypes, $scope)->setRootExpr($expr); } if ($rightExpr instanceof AlwaysRememberedExpr) { $rightTypes = $this->create($unwrappedRightExpr, $never, $contextForTypes, $scope)->setRootExpr($expr); } else { $rightTypes = $this->create($rightExpr, $never, $contextForTypes, $scope)->setRootExpr($expr); } 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, $scope)->setRootExpr($expr); if ($rightExpr instanceof AlwaysRememberedExpr) { $types = $types->unionWith($this->create($unwrappedRightExpr, $leftType, $context, $scope))->setRootExpr($expr); } } if (count($rightType->getFiniteTypes()) === 1 || $context->true() && $rightType->isConstantValue()->yes() && !$leftType->equals($rightType) && $leftType->isSuperTypeOf($rightType)->yes()) { $leftTypes = $this->create($leftExpr, $rightType, $context, $scope)->setRootExpr($expr); if ($leftExpr instanceof AlwaysRememberedExpr) { $leftTypes = $leftTypes->unionWith($this->create($unwrappedLeftExpr, $rightType, $context, $scope))->setRootExpr($expr); } 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([], []))->setRootExpr($expr); } } if ($context->true()) { $leftTypes = $this->create($leftExpr, $rightType, $context, $scope)->setRootExpr($expr); $rightTypes = $this->create($rightExpr, $leftType, $context, $scope)->setRootExpr($expr); if ($leftExpr instanceof AlwaysRememberedExpr) { $leftTypes = $leftTypes->unionWith($this->create($unwrappedLeftExpr, $rightType, $context, $scope)->setRootExpr($expr)); } if ($rightExpr instanceof AlwaysRememberedExpr) { $rightTypes = $rightTypes->unionWith($this->create($unwrappedRightExpr, $leftType, $context, $scope)->setRootExpr($expr)); } return $leftTypes->unionWith($rightTypes); } elseif ($context->false()) { return $this->create($leftExpr, $leftType, $context, $scope)->setRootExpr($expr)->normalize($scope)->intersectWith($this->create($rightExpr, $rightType, $context, $scope)->setRootExpr($expr)->normalize($scope)); } return (new \PHPStan\Analyser\SpecifiedTypes([], []))->setRootExpr($expr); } } value = $value; } private static function create(?int $value): self { $key = $value ?? ''; self::$registry[$key] ??= new self($value); return self::$registry[$key]; } 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; } } container = $container; } public function create(): \PHPStan\Analyser\TypeSpecifier { $functionTypeSpecifying = $this->container->getServicesByTag(self::FUNCTION_TYPE_SPECIFYING_EXTENSION_TAG); $methodTypeSpecifying = $this->container->getServicesByTag(self::METHOD_TYPE_SPECIFYING_EXTENSION_TAG); $staticMethodTypeSpecifying = $this->container->getServicesByTag(self::STATIC_METHOD_TYPE_SPECIFYING_EXTENSION_TAG); $typeSpecifier = new \PHPStan\Analyser\TypeSpecifier($this->container->getByType(ExprPrinter::class), $this->container->getByType(ReflectionProvider::class), $this->container->getByType(PhpVersion::class), $functionTypeSpecifying, $methodTypeSpecifying, $staticMethodTypeSpecifying, $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), $functionTypeSpecifying, $methodTypeSpecifying, $staticMethodTypeSpecifying) as $extension) { if (!$extension instanceof \PHPStan\Analyser\TypeSpecifierAwareExtension) { continue; } $extension->setTypeSpecifier($typeSpecifier); } return $typeSpecifier; } } 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; } } originalNodeCallback = $originalNodeCallback; } public function __invoke(Node $node, \PHPStan\Analyser\Scope $scope): void { if (!$node instanceof PropertyAssignNode && !$node instanceof VariableAssignNode) { return; } ($this->originalNodeCallback)($node, $scope); } } fileHelper = $fileHelper; $this->relativePathHelper = $relativePathHelper; } /** * @return non-empty-string */ 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); } } 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'; } } 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'; } } storage = $storage; } /** * @param non-empty-string $key * * @return mixed|null */ public function load(string $key, string $variableKey) { return $this->storage->load($key, $variableKey); } /** * @param non-empty-string $key * * @param mixed $data */ public function save(string $key, string $variableKey, $data): void { $this->storage->save($key, $variableKey, $data); } } 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 ($variableKey, $filePath) { $cacheItem = @include $filePath; if (!$cacheItem instanceof \PHPStan\Cache\CacheItem) { return null; } if (!$cacheItem->isVariableKeyValid($variableKey)) { return null; } return $cacheItem->getData(); })($variableKey, $filePath); } /** * @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, "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]; } public function clearUnusedFiles(): void { if (!is_dir($this->directory)) { return; } $cachedClearedFile = $this->directory . '/cache-cleared'; if (is_file($cachedClearedFile)) { try { $cachedClearedContents = FileReader::read($cachedClearedFile); if ($cachedClearedContents === self::CACHED_CLEARED_VERSION) { return; } } catch (CouldNotReadFileException $e) { return; } } $iterator = new RecursiveDirectoryIterator($this->directory); $iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS); $files = new RecursiveIteratorIterator($iterator); $beginFunction = sprintf("getPathname(); $contents = FileReader::read($path); if (!str_starts_with($contents, $beginFunction) && !str_starts_with($contents, $beginMethod) && str_starts_with($contents, $beginNew)) { continue; } $emptyDirectoriesToCheck[dirname($path)] = \true; $emptyDirectoriesToCheck[dirname($path, 2)] = \true; @unlink($path); } catch (CouldNotReadFileException $e) { continue; } } uksort($emptyDirectoriesToCheck, static fn($a, $b) => strlen($b) - strlen($a)); foreach (array_keys($emptyDirectoriesToCheck) as $directory) { if (!$this->isDirectoryEmpty($directory)) { continue; } @rmdir($directory); } try { FileWriter::write($cachedClearedFile, self::CACHED_CLEARED_VERSION); } catch (CouldNotWriteFileException $e) { // pass } } private function isDirectoryEmpty(string $directory): bool { $handle = opendir($directory); if ($handle === \false) { return \false; } while (($entry = readdir($handle)) !== \false) { if ($entry !== '.' && $entry !== '..') { closedir($handle); return \false; } } closedir($handle); return \true; } } */ private array $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 { $this->storage[$key] = new \PHPStan\Cache\CacheItem($variableKey, $data); } } */ public function getClassPrefixes(): array; } >, list>> */ final class CollectedData implements JsonSerializable { /** * @var mixed */ private $data; private string $filePath; /** * @var class-string> */ private string $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] #[Override] 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']); } } */ public function getNodeType(): string; /** * @param TNodeType $node * @return TValue|null Collected data */ public function processNode(Node $node, Scope $scope); } 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; } } container = $container; } public function create(): \PHPStan\Collectors\Registry { return new \PHPStan\Collectors\Registry($this->container->getServicesByTag(self::COLLECTOR_TAG)); } } 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); $processedFiles = []; 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(), $intermediateAnalyserResult->getProcessedFiles()); } $processedFiles = $intermediateAnalyserResult->getProcessedFiles(); $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 = hash_file('sha256', $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, [], $this->mapCollectedData($collectedData), $defaultLevelUsed, $projectConfigFile, $savedResultCache, $memoryUsageBytes, $isResultCacheUsed, $changedProjectExtensionFilesOutsideOfAnalysedPaths, $processedFiles); } /** * @param CollectorData $collectedData * * @return list */ private function mapCollectedData(array $collectedData): array { $result = []; foreach ($collectedData as $file => $dataPerCollector) { foreach ($dataPerCollector as $collectorType => $rawData) { $result[] = new CollectedData($rawData, $file, $collectorType); } } return $result; } /** * @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 (int $step, array $processedFiles = []) use ($stdOutput, &$previousMemory, &$startTime, &$linesOfCode): void { if ($startTime === null) { throw new ShouldNotHappenException(); } $currentTotalMemory = memory_get_peak_usage(\true); $elapsedTime = microtime(\true) - $startTime; $linesOfCode = 0; foreach (array_unique($processedFiles) as $processedFile) { $handle = @fopen($processedFile, 'r'); if ($handle === \false) { continue; } while (!feof($handle)) { fgets($handle); $linesOfCode++; } fclose($handle); } $stdOutput->writeLineFormatted(sprintf('--- consumed %s, total %s, took %.2f s, %.3f LoC/s', BytesHelper::bytes($currentTotalMemory - $previousMemory), BytesHelper::bytes($currentTotalMemory), $elapsedTime, $linesOfCode / $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; } $newCollectedData = []; foreach ($analyserResult->getCollectedData() as $file => $data) { if ($file === $tmpFile) { $file = $insteadOfFile; } $newCollectedData[$file] = $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->switchTmpFileInLinesToIgnore($analyserResult->getLinesToIgnore(), $insteadOfFile, $tmpFile), $this->switchTmpFileInLinesToIgnore($analyserResult->getUnmatchedLineIgnores(), $insteadOfFile, $tmpFile), $analyserResult->getInternalErrors(), $newCollectedData, $dependencies, $usedTraitDependencies, $exportedNodes, $analyserResult->hasReachedInternalErrorsCountLimit(), $analyserResult->getPeakMemoryUsageBytes(), $analyserResult->getProcessedFiles()); } /** * @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 switchTmpFileInLinesToIgnore(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; $this->analysisStartTime = $analysisStartTime; parent::__construct(); } #[Override] 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'), 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, 'Fix auto-fixable errors (experimental)'), 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[] */ #[Override] public function getAliases(): array { return ['analyze']; } #[Override] protected function initialize(InputInterface $input, OutputInterface $output): void { if ((bool) $input->getOption('debug')) { $application = $this->getApplication(); if ($application === null) { return; } $application->setCatchExceptions(\false); return; } } #[Override] 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(self::OPTION_LEVEL); $allowXdebug = $input->getOption('xdebug'); $debugEnabled = (bool) $input->getOption('debug'); $pro = (bool) $input->getOption('watch') || (bool) $input->getOption('pro'); $fix = (bool) $input->getOption('fix'); $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, \true); } 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 ($pro) { $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); } if ($fix) { $inceptionResult->getStdOutput()->getStyle()->error('Editor mode options --tmp-file and --instead-of cannot be used with --fix.'); return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } } if ($fix) { if ($generateBaselineFile !== null) { $inceptionResult->getStdOutput()->getStyle()->error('Errors cannot be fixed when generating the baseline.'); return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } $inceptionResult->getErrorOutput()->getStyle()->note('The --fix CLI option no longer launches PHPStan Pro. Use --pro instead if you want to launch PHPStan Pro'); } $errorOutput = $inceptionResult->getErrorOutput(); $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 fn(string $name): string => 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) { $this->runDiagnoseExtensions($container, $inceptionResult->getErrorOutput()); $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 ($pro) { 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(); } if ($fix) { $inceptionResult->getErrorOutput()->writeLineFormatted('Analysing files...'); } 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(), $analysisResult->getProcessedFiles()); 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 fn(InternalError $internalError) => $internalError->getMessage(), $internalErrors), [], [], [], $analysisResult->isDefaultLevelUsed(), $analysisResult->getProjectConfigFile(), $analysisResult->isResultCacheSaved(), $analysisResult->getPeakMemoryUsageBytes(), $analysisResult->isResultCacheUsed(), $analysisResult->getChangedProjectExtensionFilesOutsideOfAnalysedPaths(), $analysisResult->getProcessedFiles()); $exitCode = $errorFormatter->formatErrors($analysisResult, $inceptionResult->getStdOutput()); $this->runDiagnoseExtensions($container, $inceptionResult->getErrorOutput(), $analysisResult->getProcessedFiles()); $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); } if ($fix) { $fixableErrors = []; foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { if ($fileSpecificError->getFixedErrorDiff() === null) { continue; } $fixableErrors[] = $fileSpecificError; } $fixableErrorsCount = count($fixableErrors); if ($fixableErrorsCount === 0) { $inceptionResult->getStdOutput()->getStyle()->error('No fixable errors found'); $exitCode = 1; } else { $skippedCount = 0; $diffsByFile = []; foreach ($fixableErrors as $fixableError) { $fixFile = $fixableError->getFilePath(); if ($fixableError->getTraitFilePath() !== null) { $fixFile = $fixableError->getTraitFilePath(); } if ($fixableError->getFixedErrorDiff() === null) { throw new ShouldNotHappenException(); } $diffsByFile[$fixFile][] = $fixableError->getFixedErrorDiff(); } $inceptionResult->getErrorOutput()->writeLineFormatted('Fixing errors...'); $errorOutput->getStyle()->progressStart($fixableErrorsCount); $patcher = $container->getByType(Patcher::class); foreach ($diffsByFile as $file => $diffs) { $diffsCount = count($diffs); try { $finalFileContents = $patcher->applyDiffs($file, $diffs); $errorOutput->getStyle()->progressAdvance($diffsCount); } catch (FileChangedException|MergeConflictException $e) { $skippedCount += $diffsCount; $errorOutput->getStyle()->progressAdvance($diffsCount); continue; } FileWriter::write($file, $finalFileContents); } $errorOutput->getStyle()->progressFinish(); if ($skippedCount > 0) { $inceptionResult->getStdOutput()->getStyle()->warning(sprintf('%d %s fixed, %d %s skipped', $fixableErrorsCount, $fixableErrorsCount === 1 ? 'error' : 'errors', $skippedCount, $skippedCount === 1 ? 'error' : 'errors')); } else { $inceptionResult->getStdOutput()->getStyle()->success(sprintf('%d %s fixed', $fixableErrorsCount, $fixableErrorsCount === 1 ? 'error' : 'errors')); } $exitCode = 0; } } else { if (AgentDetector::isRunningInAgent() && count($analysisResult->getFileSpecificErrors()) > 0) { $errorOutput->writeLineFormatted('Instructions for interpreting errors'); $errorOutput->writeLineFormatted('---------'); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted('Each error has an associated identifier, like `argument.type`'); $errorOutput->writeLineFormatted('or `return.missing`.'); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted('Each error identifier has documentation at URL https://phpstan.org/error-identifiers/'); $errorOutput->writeLineFormatted('This page contains code example, explanation why is this an error'); $errorOutput->writeLineFormatted('and instruction how to fix it.'); $errorOutput->writeLineFormatted('Before fixing the error, fetch the documentation page for its identifier.'); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted('The error usually indicates a real bug or incorrect type in the code. Fix the underlying cause, do not just make the error go away.'); $errorOutput->writeLineFormatted('Do not add `@phpstan-ignore` comments, `@phpstan-ignore-next-line` comments, or baseline entries to suppress the error.'); $errorOutput->writeLineFormatted('Do not use assert() or inline @var PHPDoc tag to override PHPStan\'s inferred type.'); $errorOutput->writeLineFormatted('Do not add type casts just to silence errors.'); $errorOutput->writeLineFormatted('Do not widen parameter or return types just to make the error go away.'); } $exitCode = $errorFormatter->formatErrors($analysisResult, $inceptionResult->getStdOutput()); } if ($exitCode === 0 && $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(''); return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); } } $this->runDiagnoseExtensions($container, $inceptionResult->getErrorOutput(), $analysisResult->getProcessedFiles()); 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); $rawMessageInBaseline = $inceptionResult->getContainer()->getParameter('featureToggles')['rawMessageInBaseline']; if ($baselineExtension === 'php') { $baselineErrorFormatter = new BaselinePhpErrorFormatter($baselinePathHelper, $rawMessageInBaseline); $baselineErrorFormatter->formatErrors($analysisResult, $baselineOutput); } else { $baselineErrorFormatter = new BaselineNeonErrorFormatter($baselinePathHelper, $rawMessageInBaseline); $existingBaselineContent = is_file($generateBaselineFile) ? FileReader::read($generateBaselineFile) : ''; $baselineErrorFormatter->formatErrors($analysisResult, $baselineOutput, $existingBaselineContent); } $stream = $streamOutput->getStream(); rewind($stream); $baselineContents = stream_get_contents($stream); 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, $input, $output, count($files), $_SERVER['argv'][0]); } /** * @param list $processedFiles */ private function runDiagnoseExtensions(Container $container, \PHPStan\Command\Output $errorOutput, array $processedFiles = []): 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, $processedFiles); /** @var DiagnoseExtension $extension */ foreach ($container->getServicesByTag(DiagnoseExtension::EXTENSION_TAG) as $extension) { $extension->print($errorOutput); } } } 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, list=): 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), []); } if (!$debug && $allowParallel && function_exists('proc_open')) { $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 ($mainScript !== null && $schedule->getNumberOfProcesses() > 0) { $loop = new StreamSelectLoop(); $result = null; $promise = $this->parallelAnalyser->analyse($loop, $schedule, $allAnalysedFiles, $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 fn(string $file): bool => $file !== $insteadOfFile)); if ($tmpFile !== null) { array_unshift($analysedFiles, $tmpFile); } return $analysedFiles; } } */ private array $notFileSpecificErrors; /** * @var list */ private array $internalErrors; /** * @var list */ private array $warnings; /** * @var list */ private array $collectedData; private bool $defaultLevelUsed; private ?string $projectConfigFile; private bool $savedResultCache; private int $peakMemoryUsageBytes; private bool $isResultCacheUsed; /** * @var array */ private array $changedProjectExtensionFilesOutsideOfAnalysedPaths; /** * @var list */ private array $processedFiles; /** @var list sorted by their file name, line number and message */ private array $fileSpecificErrors; /** * @param list $fileSpecificErrors * @param list $notFileSpecificErrors * @param list $internalErrors * @param list $warnings * @param list $collectedData * @param array $changedProjectExtensionFilesOutsideOfAnalysedPaths * @param list $processedFiles */ 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, array $processedFiles = []) { $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; $this->processedFiles = $processedFiles; usort($fileSpecificErrors, static fn(Error $a, Error $b): int => [$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; } /** * @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; } /** * @return list */ public function getProcessedFiles(): array { return $this->processedFiles; } /** * @api * @param list $fileSpecificErrors */ public function withFileSpecificErrors(array $fileSpecificErrors): self { return new self($fileSpecificErrors, $this->notFileSpecificErrors, $this->internalErrors, $this->warnings, $this->collectedData, $this->defaultLevelUsed, $this->projectConfigFile, $this->savedResultCache, $this->peakMemoryUsageBytes, $this->isResultCacheUsed, $this->changedProjectExtensionFilesOutsideOfAnalysedPaths, $this->processedFiles); } } $items Items ordered from oldest to newest (at least 2) * @return BinarySearchStep */ public static function getStep(array $items): \PHPStan\Command\Bisect\BinarySearchStep { $count = count($items); if ($count < 2) { throw new InvalidArgumentException('Binary search requires at least 2 items.'); } $mid = (int) (($count - 1) / 2); return new \PHPStan\Command\Bisect\BinarySearchStep($items[$mid], array_slice($items, $mid + 1), array_slice($items, 0, $mid + 1), (int) ceil(log($count, 2))); } } */ public array $ifGood; /** * @readonly * @var list */ public array $ifBad; /** * @readonly */ public int $stepsRemaining; /** * @param T $item Item to test * @param list $ifGood Remaining items to search if this item is good * @param list $ifBad Remaining items to search if this item is bad */ public function __construct($item, array $ifGood, array $ifBad, int $stepsRemaining) { $this->item = $item; $this->ifGood = $ifGood; $this->ifBad = $ifBad; $this->stepsRemaining = $stepsRemaining; } } setName(self::NAME)->setDescription('Binary search for the first bad PHPStan commit between two releases')->setDefinition([new InputArgument('paths', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'Paths with source code to run analysis on'), new InputOption('good', null, InputOption::VALUE_REQUIRED, 'Good (old) PHPStan release version (e.g. 2.1.0)'), new InputOption('bad', null, InputOption::VALUE_REQUIRED, 'Bad (new) PHPStan release version (e.g. 2.1.5)'), 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')]); } #[Override] protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); $good = $input->getOption('good'); if (!is_string($good)) { if (!$input->isInteractive()) { $io->error('Both --good and --bad release versions are required in non-interactive mode.'); return 1; } $good = $io->ask('Enter the good (working) PHPStan release version (e.g. 2.1.0)'); } $bad = $input->getOption('bad'); if (!is_string($bad)) { if (!$input->isInteractive()) { $io->error('Both --good and --bad release versions are required in non-interactive mode.'); return 1; } $bad = $io->ask('Enter the bad (broken) PHPStan release version (e.g. 2.1.5)'); } if (!is_string($good) || !is_string($bad)) { $io->error('Both good and bad release versions are required.'); return 1; } $token = $this->getGitHubToken(); if ($token === null) { $io->error(['GitHub token not found.', 'Please set the GITHUB_TOKEN or GH_TOKEN environment variable,', 'or add a GitHub OAuth token to ~/.composer/auth.json.']); return 1; } $client = (new HttpClientFactory())->createClient(['headers' => ['Authorization' => 'token ' . $token, 'Accept' => 'application/vnd.github.v3+json']]); $io->section(sprintf('Fetching commits between %s and %s...', $good, $bad)); try { $commits = $this->getCommitsBetween($client, $good, $bad); } catch (GuzzleException $e) { $io->error(sprintf('Failed to fetch commits from GitHub: %s', $e->getMessage())); return 1; } if (count($commits) === 0) { $io->error('No commits found between the specified releases.'); return 1; } $io->writeln(sprintf('Found %d commits between %s and %s.', count($commits), $good, $bad)); $rangeShas = []; foreach ($commits as $commit) { $rangeShas[$commit['sha']] = \true; } try { $checksumShas = $this->getPharChecksumCommitShas($client, $bad, $rangeShas); } catch (GuzzleException $e) { $io->error(sprintf('Failed to fetch .phar-checksum commits from GitHub: %s', $e->getMessage())); return 1; } $commits = array_values(array_filter($commits, static fn(array $commit): bool => isset($checksumShas[$commit['sha']]))); if (count($commits) === 0) { $io->error('No commits found that change phpstan.phar between the specified releases.'); return 1; } $io->writeln(sprintf('%d of them change phpstan.phar.', count($commits))); $tmpDir = sys_get_temp_dir() . '/phpstan-bisect'; @mkdir($tmpDir, 0777, \true); $analyseArgs = $this->buildAnalyseArgs($input); while (count($commits) > 1) { $step = BinarySearch::getStep($commits); $commit = $step->item; $sha = $commit['sha']; $shortSha = substr($sha, 0, 7); $message = $commit['commit']['message']; $firstLine = strtok($message, "\n") ?: $shortSha; $io->section(sprintf('Testing commit %s (%s) [~%d step%s left]', $shortSha, $firstLine, $step->stepsRemaining, $step->stepsRemaining === 1 ? '' : 's')); $pharPath = $tmpDir . '/phpstan-' . $shortSha . '.phar'; if (!is_file($pharPath)) { $io->writeln('Downloading phpstan.phar...'); try { $this->downloadPharForCommit($client, $sha, $pharPath, $output); } catch (GuzzleException $e) { $io->error(sprintf('Failed to download phpstan.phar: %s', $e->getMessage())); return 1; } } $io->writeln('Running analysis...'); $io->newLine(); $exitCode = $this->runAnalysis($pharPath, $analyseArgs); $io->newLine(); $io->writeln(sprintf('Analysis exited with code: %d', $exitCode)); if (!$input->isInteractive()) { $io->error('Cannot continue bisect in non-interactive mode.'); return 1; } $answer = $io->choice('Is this result good or bad?', ['good', 'bad']); $commits = $answer === 'good' ? $step->ifGood : $step->ifBad; } $badCommit = $commits[0]; $this->printResult($badCommit, $io); return 0; } public function getGitHubToken(?string $composerHome = null): ?string { $envToken = getenv('GITHUB_TOKEN'); if ($envToken !== \false && $envToken !== '') { return $envToken; } $ghToken = getenv('GH_TOKEN'); if ($ghToken !== \false && $ghToken !== '') { return $ghToken; } if ($composerHome === null) { $composerHome = getenv('COMPOSER_HOME'); if ($composerHome === \false) { $home = getenv('HOME'); if ($home === \false) { $home = getenv('USERPROFILE'); } if ($home === \false) { return null; } $composerHome = $home . '/.composer'; } } $authFile = $composerHome . '/auth.json'; if (!is_file($authFile)) { return null; } try { /** @var array{github-oauth?: array} $auth */ $auth = Json::decode(FileReader::read($authFile), Json::FORCE_ARRAY); return $auth['github-oauth']['github.com'] ?? null; } catch (Throwable $e) { return null; } } /** * @return list * @throws GuzzleException */ private function getCommitsBetween(Client $client, string $good, string $bad): array { $allCommits = []; $page = 1; $perPage = 100; while (\true) { $response = $client->get(sprintf('https://api.github.com/repos/%s/%s/compare/%s...%s?per_page=%d&page=%d', self::REPO_OWNER, self::REPO_NAME, urlencode($good), urlencode($bad), $perPage, $page)); /** @var array{commits: list, total_commits: int} $data */ $data = Json::decode($response->getBody()->getContents(), Json::FORCE_ARRAY); $commits = $data['commits']; $allCommits = array_merge($allCommits, $commits); if (count($commits) < $perPage || count($allCommits) >= $data['total_commits']) { break; } $page++; } return $allCommits; } /** * @param array $rangeShas * @return array * @throws GuzzleException */ private function getPharChecksumCommitShas(Client $client, string $bad, array $rangeShas): array { $checksumShas = []; $page = 1; $perPage = 100; while (\true) { $response = $client->get(sprintf('https://api.github.com/repos/%s/%s/commits?sha=%s&path=%s&per_page=%d&page=%d', self::REPO_OWNER, self::REPO_NAME, urlencode($bad), urlencode('.phar-checksum'), $perPage, $page)); /** @var list $commits */ $commits = Json::decode($response->getBody()->getContents(), Json::FORCE_ARRAY); if (count($commits) === 0) { break; } $foundOutOfRange = \false; foreach ($commits as $commit) { if (!isset($rangeShas[$commit['sha']])) { $foundOutOfRange = \true; break; } $checksumShas[$commit['sha']] = \true; } if ($foundOutOfRange || count($commits) < $perPage) { break; } $page++; } return $checksumShas; } /** * @throws GuzzleException */ private function downloadPharForCommit(Client $client, string $sha, string $pharPath, OutputInterface $output): void { $url = sprintf('https://raw.githubusercontent.com/%s/%s/%s/phpstan.phar', self::REPO_OWNER, self::REPO_NAME, $sha); $progressBar = new ProgressBar($output); $bytes = 0; $client->get($url, [RequestOptions::SINK => $pharPath, RequestOptions::TIMEOUT => 120, RequestOptions::PROGRESS => static function (int $downloadTotal, int $downloadedBytes) use ($progressBar, &$bytes): void { if ($downloadTotal === 0) { return; } if ($progressBar->getMaxSteps() === 0) { $progressBar->setFormat('file_download'); $progressBar->setMessage(sprintf('%.2f MB', $downloadTotal / 1000000), 'fileSize'); $progressBar->start($downloadTotal); } if ($downloadedBytes <= $bytes) { return; } $bytes = $downloadedBytes; $progressBar->setProgress($bytes); }]); $progressBar->finish(); $output->writeln(''); chmod($pharPath, 0755); } public function buildAnalyseArgs(InputInterface $input): string { $args = []; $config = $input->getOption('configuration'); if (is_string($config)) { $args[] = '-c ' . escapeshellarg($config); } $level = $input->getOption(\PHPStan\Command\AnalyseCommand::OPTION_LEVEL); if (is_string($level)) { $args[] = '-l ' . escapeshellarg($level); } $autoload = $input->getOption('autoload-file'); if (is_string($autoload)) { $args[] = '-a ' . escapeshellarg($autoload); } $memory = $input->getOption('memory-limit'); if (is_string($memory)) { $args[] = '--memory-limit=' . escapeshellarg($memory); } $args[] = '--no-progress'; $paths = $input->getArgument('paths'); if (is_array($paths)) { foreach ($paths as $path) { if (!is_string($path)) { continue; } $args[] = escapeshellarg($path); } } return implode(' ', $args); } private function runAnalysis(string $pharPath, string $analyseArgs): int { $command = sprintf('%s %s analyse %s', escapeshellarg(PHP_BINARY), escapeshellarg($pharPath), $analyseArgs); passthru($command, $exitCode); return $exitCode; } /** * @param array{sha: string, commit: array{message: string}} $commit */ private function printResult(array $commit, SymfonyStyle $io): void { $sha = $commit['sha']; $message = $commit['commit']['message']; $io->success('Found the first bad commit!'); $io->writeln(sprintf('Commit: %s', $sha)); $io->writeln(sprintf('URL: https://github.com/%s/%s/commit/%s', self::REPO_OWNER, self::REPO_NAME, $sha)); $io->newLine(); $io->writeln('Commit message:'); $io->writeln($message); if (preg_match_all('#https://github\.com/phpstan/phpstan-src/commit/[a-f0-9]+(?:\s+.*)?#', $message, $matches) < 1) { return; } $io->newLine(); $io->writeln('Related phpstan-src commits:'); foreach ($matches[0] as $line) { $io->writeln(sprintf(' %s', $line)); } } } composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; parent::__construct(); } #[Override] 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')]); } #[Override] 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; } } #[Override] 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, null, null, \true); } 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; $errorOutput = 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 fn(string $path): string => $currentWorkingDirectoryFileHelper->normalizePath($currentWorkingDirectoryFileHelper->absolutizePath($path)), $paths); $analysedPathsFromConfig = []; $containerFactory = new ContainerFactory($currentWorkingDirectory); if ($cleanupContainerCache) { $containerFactory->setJournalContainer(); } $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, ['[parameters][paths][]', '[parameters][tmpDir]']))->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 (MissingImplementedInterfaceInServiceWithTagException $e) { $errorOutput->writeLineFormatted('Invalid service:'); $errorOutput->writeLineFormatted($e->getMessage()); $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(''); } $suggestOptional = $e->getSuggestOptional(); if (count($suggestOptional) > 0) { $baselinePathHelper = null; if ($projectConfigFile !== null) { $baselinePathHelper = new ParentDirectoryRelativePathHelper(dirname($projectConfigFile)); } $errorOutput->writeLineFormatted('If the excluded path can sometimes exist, append (?)'); $errorOutput->writeLineFormatted('to its config entry to mark it as optional. Example:'); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted('parameters:'); $errorOutput->writeLineFormatted("\texcludePaths:"); foreach ($suggestOptional as $key => $suggestOptionalPaths) { $errorOutput->writeLineFormatted(sprintf("\t\t%s:", $key)); foreach ($suggestOptionalPaths as $suggestOptionalPath) { if ($baselinePathHelper === null) { $errorOutput->writeLineFormatted(sprintf("\t\t\t- %s (?)", $suggestOptionalPath)); continue; } $errorOutput->writeLineFormatted(sprintf("\t\t\t- %s (?)", $baselinePathHelper->getRelativePath($suggestOptionalPath))); } } $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) { $cacheStorage = $container->getService('cacheStorage'); if ($cacheStorage instanceof FileCacheStorage) { $cacheStorage->clearUnusedFiles(); } } /** @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(); } /** @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()); $files = array_values(array_filter($files, static fn(string $file) => !$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(); } } } composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; parent::__construct(); } #[Override] 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')]); } #[Override] 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; } } #[Override] 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, \false, null, null, \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; } } composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; parent::__construct(); } #[Override] 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')]); } #[Override] 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; } } #[Override] 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, \false, null, null, \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; } } relativePathHelper = $relativePathHelper; $this->useRawMessage = $useRawMessage; } 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; } ksort($fileErrors, SORT_STRING); $messageKey = $this->useRawMessage ? 'rawMessage' : 'message'; $errorsToOutput = []; foreach ($fileErrors as $file => $errors) { $fileErrorsByMessage = []; foreach ($errors as $error) { $errorMessage = $error->getMessage(); $identifier = $error->getIdentifier(); if (!isset($fileErrorsByMessage[$errorMessage])) { $fileErrorsByMessage[$errorMessage] = [1, $identifier !== null ? [$identifier => 1] : []]; continue; } $fileErrorsByMessage[$errorMessage][0]++; if ($identifier === null) { continue; } if (!isset($fileErrorsByMessage[$errorMessage][1][$identifier])) { $fileErrorsByMessage[$errorMessage][1][$identifier] = 1; continue; } $fileErrorsByMessage[$errorMessage][1][$identifier]++; } ksort($fileErrorsByMessage, SORT_STRING); foreach ($fileErrorsByMessage as $message => [$totalCount, $identifiers]) { if (!$this->useRawMessage) { $message = '#^' . preg_quote($message, '#') . '$#'; } ksort($identifiers, SORT_STRING); if (count($identifiers) > 0) { foreach ($identifiers as $identifier => $identifierCount) { $errorsToOutput[] = [$messageKey => Helpers::escape($message), 'identifier' => $identifier, 'count' => $identifierCount, 'path' => Helpers::escape($file)]; } } else { $errorsToOutput[] = [$messageKey => Helpers::escape($message), 'count' => $totalCount, '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; $this->useRawMessage = $useRawMessage; } 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(); $identifier = $error->getIdentifier(); if (!isset($fileErrorsByMessage[$errorMessage])) { $fileErrorsByMessage[$errorMessage] = [1, $identifier !== null ? [$identifier => 1] : []]; continue; } $fileErrorsByMessage[$errorMessage][0]++; if ($identifier === null) { continue; } if (!isset($fileErrorsByMessage[$errorMessage][1][$identifier])) { $fileErrorsByMessage[$errorMessage][1][$identifier] = 1; continue; } $fileErrorsByMessage[$errorMessage][1][$identifier]++; } ksort($fileErrorsByMessage, SORT_STRING); foreach ($fileErrorsByMessage as $message => [$totalCount, $identifiers]) { if ($this->useRawMessage) { $messageKey = 'rawMessage'; } else { $messageKey = 'message'; $message = '#^' . preg_quote($message, '#') . '$#'; } ksort($identifiers, SORT_STRING); if (count($identifiers) > 0) { foreach ($identifiers as $identifier => $identifierCount) { $php .= sprintf("\$ignoreErrors[] = [\n\t%s => %s,\n\t'identifier' => %s,\n\t'count' => %s,\n\t'path' => __DIR__ . %s,\n];\n", var_export($messageKey, \true), var_export(Helpers::escape($message), \true), var_export(Helpers::escape($identifier), \true), var_export($identifierCount, \true), var_export(Helpers::escape($file), \true)); } } else { $php .= sprintf("\$ignoreErrors[] = [\n\t%s => %s,\n\t'count' => %s,\n\t'path' => __DIR__ . %s,\n];\n", var_export($messageKey, \true), var_export(Helpers::escape($message), \true), var_export($totalCount, \true), var_export(Helpers::escape($file), \true)); } } } $php .= "\n"; $php .= 'return [\'parameters\' => [\'ignoreErrors\' => $ignoreErrors]];'; $php .= "\n"; $output->writeRaw($php); return 1; } } 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; } } 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; } } 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(); $message = $this->formatMessage($message); $line = sprintf('::error %s::%s', implode(',', $metas), $message); $output->writeRaw($line); $output->writeLineFormatted(''); } foreach ($analysisResult->getNotFileSpecificErrors() as $notFileSpecificError) { $notFileSpecificError = $this->formatMessage($notFileSpecificError); $line = sprintf('::error ::%s', $notFileSpecificError); $output->writeRaw($line); $output->writeLineFormatted(''); } foreach ($analysisResult->getWarnings() as $warning) { $warning = $this->formatMessage($warning); $warning = str_replace("\n", '%0A', $warning); $line = sprintf('::warning ::%s', $warning); $output->writeRaw($line); $output->writeLineFormatted(''); } return $analysisResult->hasErrors() ? 1 : 0; } private function formatMessage(string $message): string { // newlines need to be encoded // see https://github.com/actions/starter-workflows/issues/68#issuecomment-581479448 $message = str_replace("\n", '%0A', $message); return preg_replace('/(^|\s)@([a-zA-Z0-9_\-]+)(\s|$)/', '$1`@$2`$3', $message) ?? $message; } } relativePathHelper = $relativePathHelper; } public function formatErrors(AnalysisResult $analysisResult, Output $output): int { $errorsArray = []; foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { $error = [ 'description' => $fileSpecificError->getMessage(), // This field is intended to be shown in the GitLab code quality scan widget and mentioned in the GitLab docs. // However, due to a regression in GitLab, it is currently not shown - see https://gitlab.com/gitlab-org/gitlab/-/issues/578172. // There is no harm in having it here, and it allows users to work around the GitLab bug by post-processing the JSON file. // For example, they might prepend `check_name` to `description`, causing GitLab to show the error identifier as part of the message. // TODO: remove this comment once the GitLab bug is fixed 'check_name' => $fileSpecificError->getIdentifier(), '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' => new stdClass(), 'errors' => []]; $tipFormatter = new OutputFormatter(\false); foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { $file = $fileSpecificError->getFile(); if (!property_exists($errorsArray['files'], $file)) { $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; } 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'); } } getNotFileSpecificErrors() as $notFileSpecificError) { $output->writeRaw(sprintf('?:?:%s', $notFileSpecificError)); $output->writeLineFormatted(''); } $outputIdentifiers = $output->isVerbose() || AgentDetector::isRunningInAgent(); foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { $identifier = ''; if ($outputIdentifiers && $fileSpecificError->getIdentifier() !== null) { $identifier = sprintf(' [identifier=%s]', $fileSpecificError->getIdentifier()); } $output->writeRaw(sprintf('%s:%s:%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; $this->simpleRelativePathHelper = $simpleRelativePathHelper; $this->ciDetectedErrorFormatter = $ciDetectedErrorFormatter; $this->showTipsOfTheDay = $showTipsOfTheDay; $this->editorUrl = $editorUrl; $this->editorUrlTitle = $editorUrlTitle; $this->usedLevel = $usedLevel; $this->errorsBudget = $errorsBudget; if ($this->errorsBudget !== null) { return; } $forceShowAll = getenv(self::FORCE_SHOW_ALL_ERRORS); if (!in_array($forceShowAll, [\false, '0'], \true)) { return; } $this->errorsBudget = self::ERRORS_LIMIT; } /** @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, (int) AnalyseCommand::DEFAULT_LEVEL)); $output->writeLineFormatted(''); } } return 0; } /** @var array $fileErrors */ $fileErrors = []; foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { if (!isset($fileErrors[$fileSpecificError->getFile()])) { $fileErrors[$fileSpecificError->getFile()] = []; } $fileErrors[$fileSpecificError->getFile()][] = $fileSpecificError; } $errorsBudget = $this->errorsBudget; $printedErrors = 0; foreach ($fileErrors as $file => $errors) { $rows = []; foreach ($errors as $error) { $message = $error->getMessage(); $filePath = $error->getTraitFilePath() ?? $error->getFilePath(); if ($error->getIdentifier() !== null && in_array($error->getIdentifier(), ['phpstan.type', 'phpstan.nativeType', 'phpstan.variable', 'phpstan.dumpType', 'phpstan.unknownExpectation'], \true)) { $message = '' . OutputFormatter::escape($message) . ''; } if ($error->getIdentifier() !== null) { $message .= "\n"; $message .= '🪪 ' . $error->getIdentifier(); if (!$error->canBeIgnored()) { $message .= ' (non-ignorable)'; } } 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"; } $message = rtrim($message, "\n"); } else { $message .= '💡 ' . $tip; } } if (getenv('TERMINAL_EMULATOR') === 'JetBrains-JediTerm') { $title = $this->simpleRelativePathHelper->getRelativePath($filePath); $message .= sprintf("\nat %s:%d", $title, $error->getLine() ?? 0); } elseif (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]; } $printedErrors += count($rows); if ($errorsBudget !== null && $printedErrors > $errorsBudget) { $rows = array_slice($rows, 0, $errorsBudget - ($printedErrors - count($rows))); $style->table(['Line', $this->relativePathHelper->getRelativePath($file)], $rows); break; } $style->table(['Line', $this->relativePathHelper->getRelativePath($file)], $rows); } if (count($analysisResult->getNotFileSpecificErrors()) > 0) { $style->table(['', 'Error'], array_map(static fn(string $error): array => ['', OutputFormatter::escape($error)], $analysisResult->getNotFileSpecificErrors())); } $warningsCount = count($analysisResult->getWarnings()); if ($warningsCount > 0) { $style->table(['', 'Warning'], array_map(static fn(string $warning): array => ['', OutputFormatter::escape($warning)], $analysisResult->getWarnings())); } if ($errorsBudget !== null && $printedErrors > $errorsBudget) { $style->error(sprintf('Found %s+ errors', $errorsBudget)); $note = []; $note[] = sprintf('Result is limited to the first %d errors', $errorsBudget); if ($this->usedLevel !== CommandHelper::DEFAULT_LEVEL) { $note[] = '- Consider lowering the PHPStan level'; } $note[] = sprintf('- Pass %s=1 environment variable to show all errors', self::FORCE_SHOW_ALL_ERRORS); $note[] = '- Consider using PHPStan Pro for more comfortable error browsing'; $note[] = ' Learn more: https://phpstan.com'; $style->note(implode("\n", $note)); } else { $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; } } 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) { $message = $fileSpecificError->getMessage(); if ($fileSpecificError->getIdentifier() !== null && $fileSpecificError->canBeIgnored()) { $message .= sprintf(' (🪪 %s)', $fileSpecificError->getIdentifier()); } $result .= $this->createTeamcityLine('inspection', [ 'typeId' => 'phpstan', 'message' => $message, '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); } } 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 */ #[Override] 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 = Helper::width(Helper::removeDecoration($this->getFormatter(), $row[0])); if ($maxHeaderWidth !== 0 && $length <= $maxHeaderWidth) { continue; } $maxHeaderWidth = $length; } foreach ($headers as $i => $header) { $newHeader = []; foreach (explode("\n", $header) as $h) { $newHeader[] = sprintf('%s', $h); } $headers[$i] = implode("\n", $newHeader); } $table = $this->createTable(); // -5 because there are 5 padding spaces: One on each side of the table, one on each side of a cell and one between columns. $table->setColumnMaxWidth(1, $terminalWidth - $maxHeaderWidth - 5); array_unshift($rows, $headers, new TableSeparator()); $table->setRows($rows); $table->render(); $this->newLine(); } #[Override] 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(); $agent = AgentDetector::isRunningInAgent(); $this->progressBar->setOverwrite(!$ci && !$agent); if ($ci || $agent) { $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); } #[Override] public function progressStart(int $max = 0): void { if (!$this->showProgress) { return; } parent::progressStart($max); } #[Override] public function progressAdvance(int $step = 1): void { if (!$this->showProgress) { return; } parent::progressAdvance($step); } #[Override] public function progressFinish(): void { if (!$this->showProgress) { return; } parent::progressFinish(); } } |null */ private $processInProgress = null; private bool $fileMonitorActive = \true; /** * @param string[] $analysedPaths * @param string[] $composerAutoloaderProjectPaths * @param string[] $allConfigFiles * @param string[] $bootstrapFiles */ public function __construct( FileMonitor $fileMonitor, IgnoredErrorHelper $ignoredErrorHelper, StubFilesProvider $stubFilesProvider, #[AutowiredParameter] array $analysedPaths, #[AutowiredParameter] string $currentWorkingDirectory, #[AutowiredParameter('%pro.tmpDir%')] string $proTmpDir, #[AutowiredParameter] array $composerAutoloaderProjectPaths, #[AutowiredParameter] array $allConfigFiles, #[AutowiredParameter] ?string $cliAutoloadFile, #[AutowiredParameter] array $bootstrapFiles, #[AutowiredParameter] ?string $editorUrl, #[AutowiredParameter] string $usedLevel, HttpClientFactory $httpClientFactory, ForkParallelChecker $forkParallelChecker, \PHPStan\Command\FixerWorkerRunner $fixerWorkerRunner ) { $this->fileMonitor = $fileMonitor; $this->ignoredErrorHelper = $ignoredErrorHelper; $this->stubFilesProvider = $stubFilesProvider; $this->analysedPaths = $analysedPaths; $this->currentWorkingDirectory = $currentWorkingDirectory; $this->proTmpDir = $proTmpDir; $this->composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; $this->allConfigFiles = $allConfigFiles; $this->cliAutoloadFile = $cliAutoloadFile; $this->bootstrapFiles = $bootstrapFiles; $this->editorUrl = $editorUrl; $this->usedLevel = $usedLevel; $this->httpClientFactory = $httpClientFactory; $this->forkParallelChecker = $forkParallelChecker; $this->fixerWorkerRunner = $fixerWorkerRunner; } public function run(\PHPStan\Command\InceptionResult $inceptionResult, InputInterface $input, OutputInterface $output, int $filesCount, string $mainScript): int { $projectConfigFile = $inceptionResult->getProjectConfigFile(); $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, $inceptionResult, $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, $inceptionResult, $mainScript, $projectConfigFile, $input, $output, $encoder); $this->monitorFileChanges($loop, function (FileMonitorResult $changes) use ($loop, $inceptionResult, $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, $inceptionResult, $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 (GuzzleException $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, []); } /** * @throws GuzzleException */ private function downloadPhar(OutputInterface $output, string $pharPath, string $infoPath): void { $currentVersion = null; $branch = '2.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...'); } $client = $this->httpClientFactory->createClient([]); $latestUrl = sprintf('https://fixer-download-api.phpstan.com/latest?%s', http_build_query(['phpVersion' => PHP_VERSION_ID, 'branch' => $branch])); /** * @var array{url: string, version: string} $latestInfo */ $latestInfo = Json::decode($client->get($latestUrl)->getBody()->getContents(), 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...'); $progressBar = new ProgressBar($output); $bytes = 0; $client->get($latestInfo['url'], [RequestOptions::SINK => $pharPath, RequestOptions::TIMEOUT => 120, RequestOptions::PROGRESS => static function (int $downloadTotal, int $downloadedBytes) use ($progressBar, &$bytes): void { if ($downloadTotal === 0) { return; } if ($progressBar->getMaxSteps() === 0) { $progressBar->setFormat('file_download'); $progressBar->setMessage(sprintf('%.2f MB', $downloadTotal / 1000000), 'fileSize'); $progressBar->start($downloadTotal); } if ($downloadedBytes <= $bytes) { return; } $bytes = $downloadedBytes; $progressBar->setProgress($bytes); }]); $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(''); } 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, \PHPStan\Command\InceptionResult $inceptionResult, 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 = $this->createProcessPromise($this->forkParallelChecker->isSupported(), $loop, $server, $mainScript, $projectConfigFile, $input, $serverPort, $inceptionResult); $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; } /** * @param int<0, 65535> $serverPort */ private function createProcessPromise(bool $useFork, LoopInterface $loop, TcpServer $server, string $mainScript, ?string $projectConfigFile, InputInterface $input, int $serverPort, \PHPStan\Command\InceptionResult $inceptionResult): ProcessPromise { if ($useFork) { try { [$inceptionFiles, $isOnlyFiles] = $inceptionResult->getFiles(); } catch (PathNotFoundException|\PHPStan\Command\InceptionNotSuccessfulException $e) { throw new ShouldNotHappenException(); } return new ForkedProcessPromise($loop, $this->fixerWorkerRunner, $server, $inceptionResult->getErrorOutput(), $inceptionFiles, $isOnlyFiles, $inceptionResult->getProjectConfigArray(), $projectConfigFile, $serverPort, $input); } return new SpawnedProcessPromise($loop, ProcessHelper::getWorkerCommand($mainScript, 'fixer:worker', $projectConfigFile, ['--server-port', (string) $serverPort], $input)); } } composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; parent::__construct(); } #[Override] 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); } #[Override] 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(); try { [$inceptionFiles, $isOnlyFiles] = $inceptionResult->getFiles(); } catch (PathNotFoundException|\PHPStan\Command\InceptionNotSuccessfulException $e) { throw new ShouldNotHappenException(); } // Everything after the boot lives in FixerWorkerRunner so a // pcntl_fork()-ed child can reuse it without re-booting (see // FixerApplication). $fixerWorkerRunner = $container->getByType(\PHPStan\Command\FixerWorkerRunner::class); return $fixerWorkerRunner->run($inceptionResult->getErrorOutput(), $inceptionFiles, $isOnlyFiles, $inceptionResult->getProjectConfigArray(), $configuration, (int) $serverPort, $input); } } ignoredErrorHelper = $ignoredErrorHelper; $this->resultCacheManagerFactory = $resultCacheManagerFactory; $this->analyserResultFinalizer = $analyserResultFinalizer; $this->parallelAnalyser = $parallelAnalyser; $this->scheduler = $scheduler; $this->cpuCoreCounter = $cpuCoreCounter; } /** * @param string[] $inceptionFiles * @param mixed[]|null $projectConfigArray */ public function run(\PHPStan\Command\Output $errorOutput, array $inceptionFiles, bool $isOnlyFiles, ?array $projectConfigArray, ?string $configuration, int $serverPort, InputInterface $input): int { $ignoredErrorHelperResult = $this->ignoredErrorHelper->initialize(); if (count($ignoredErrorHelperResult->getErrors()) > 0) { throw new ShouldNotHappenException(); } // Always a fresh event loop: in a forked child the parent's inherited // loop must never be touched. $loop = new StreamSelectLoop(); $tcpConnector = new TcpConnector($loop); $tcpConnector->connect(sprintf('127.0.0.1:%d', $serverPort))->then(function (ConnectionInterface $connection) use ($errorOutput, $inceptionFiles, $isOnlyFiles, $projectConfigArray, $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 = $this->resultCacheManagerFactory->create([]); $out->write(['action' => 'analysisStart', 'result' => ['analysedFiles' => $inceptionFiles]]); $resultCache = $resultCacheManager->restore($inceptionFiles, \false, \false, $projectConfigArray, $errorOutput); $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, $filesToAnalyse, $inceptionFiles, $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 ($resultCacheManager, $resultCache, $errorOutput, $isOnlyFiles, $ignoredErrorHelperResult, $inceptionFiles, $out): void { $analyserResult = $resultCacheManager->process($intermediateAnalyserResult, $resultCache, $errorOutput, \false, \true)->getAnalyserResult(); $finalizerResult = $this->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', 'ignore.noComment'], \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 list $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 string[] $allAnalysedFiles * @param callable(list, list, string[]): void $onFileAnalysisHandler * @return PromiseInterface */ private function runAnalyser(LoopInterface $loop, array $files, array $allAnalysedFiles, ?string $configuration, InputInterface $input, callable $onFileAnalysisHandler): PromiseInterface { $filesCount = count($files); if ($filesCount === 0) { return resolve(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]; } return $this->parallelAnalyser->analyse($loop, $schedule, $allAnalysedFiles, $mainScript, null, $configuration, null, null, $input, $onFileAnalysisHandler); } } 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; } } */ private array $ignoredTypes; private bool $anchorsInTheMiddle; private bool $allErrorsIgnored; private ?string $wrongSequence; private ?string $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; } } 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 < 60) { $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); } } 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 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(); } } composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; parent::__construct(); } #[Override] 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); } #[Override] 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; } $container = $inceptionResult->getContainer(); try { [$analysedFiles] = $inceptionResult->getFiles(); } catch (PathNotFoundException $e) { $inceptionResult->getErrorOutput()->writeLineFormatted(sprintf('%s', $e->getMessage())); return 1; } catch (\PHPStan\Command\InceptionNotSuccessfulException $e) { return 1; } // Everything after the boot lives in WorkerRunner so a pcntl_fork()-ed // child can reuse it without re-booting (see ParallelAnalyser). $workerRunner = $container->getByType(WorkerRunner::class); return $workerRunner->run($output, $analysedFiles, (int) $port, $identifier, $tmpFile, $insteadOfFile); } } -----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----- > */ private array $classDependencies = []; public function __construct(FileHelper $fileHelper, ReflectionProvider $reflectionProvider, \PHPStan\Dependency\ExportedNodeResolver $exportedNodeResolver, FileTypeMapper $fileTypeMapper) { $this->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 (isset($node->namespacedName)) { $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 InPropertyHookNode) { $nativeMethod = $node->getHookReflection(); $this->extractThrowType($nativeMethod->getThrowType(), $dependenciesReflections); $this->extractFromParametersAcceptor($nativeMethod, $dependenciesReflections); } elseif ($node instanceof ClassPropertyNode) { $nativeType = $node->getNativeType(); if ($nativeType !== null) { 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 ExtendedParameterReflection) { 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->getInstancePropertyReflection($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->hasStaticProperty($node->name->toString())) { $propertyReflection = $propertyClassReflection->getStaticProperty($node->name->toString()); $this->addClassToDependencies($propertyReflection->getDeclaringClass()->getName(), $dependenciesReflections); } } } else { $propertyReflection = $scope->getStaticPropertyReflection($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); } } } } elseif ($node instanceof StaticMethodCallableNode) { foreach ($this->resolveDependencies(new Node\Expr\StaticCall($node->getClass(), $node->getName()), $scope)->getReflections() as $dependency) { $dependenciesReflections[] = $dependency; } } elseif ($node instanceof MethodCallableNode) { foreach ($this->resolveDependencies(new Node\Expr\MethodCall($node->getVar(), $node->getName()), $scope)->getReflections() as $dependency) { $dependenciesReflections[] = $dependency; } } elseif ($node instanceof FunctionCallableNode) { foreach ($this->resolveDependencies(new Node\Expr\FuncCall($node->getName()), $scope)->getReflections() as $dependency) { $dependenciesReflections[] = $dependency; } } elseif ($node instanceof InstantiationCallableNode) { foreach ($this->resolveDependencies(new Node\Expr\New_($node->getClass()), $scope)->getReflections() as $dependency) { $dependenciesReflections[] = $dependency; } } 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; } $itemType = $scope->getType($items[0]->value); return $itemType->isClassString()->yes(); } /** * @param array $dependenciesReflections */ private function addClassToDependencies(string $className, array &$dependenciesReflections): void { if (!array_key_exists($className, $this->classDependencies)) { $this->classDependencies[$className] = $this->buildClassDependencies($className); } $dependenciesReflections = array_merge($dependenciesReflections, $this->classDependencies[$className]); } /** * @return list */ private function buildClassDependencies(string $className): array { try { $classReflection = $this->reflectionProvider->getClass($className); } catch (ClassNotFoundException $e) { return []; } $dependencies = []; do { $dependencies[] = $classReflection; foreach ($classReflection->getInterfaces() as $interface) { $dependencies[] = $interface; } foreach ($classReflection->getTraits(\true) as $trait) { $dependencies[] = $trait; } foreach ($classReflection->getResolvedMixinTypes() as $mixinType) { foreach ($mixinType->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependencies[] = $this->reflectionProvider->getClass($referencedClass); } } foreach ($classReflection->getRequireExtendsTags() as $extendsTag) { foreach ($extendsTag->getType()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependencies[] = $this->reflectionProvider->getClass($referencedClass); } } foreach ($classReflection->getSealedTags() as $sealedTag) { foreach ($sealedTag->getType()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependencies[] = $this->reflectionProvider->getClass($referencedClass); } } foreach ($classReflection->getTemplateTags() as $templateTag) { foreach ($templateTag->getBound()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependencies[] = $this->reflectionProvider->getClass($referencedClass); } $default = $templateTag->getDefault(); if ($default === null) { continue; } foreach ($default->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependencies[] = $this->reflectionProvider->getClass($referencedClass); } } foreach ($classReflection->getPropertyTags() as $propertyTag) { if ($propertyTag->isReadable()) { foreach ($propertyTag->getReadableType()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependencies[] = $this->reflectionProvider->getClass($referencedClass); } } if (!$propertyTag->isWritable()) { continue; } foreach ($propertyTag->getWritableType()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependencies[] = $this->reflectionProvider->getClass($referencedClass); } } foreach ($classReflection->getMethodTags() as $methodTag) { foreach ($methodTag->getReturnType()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependencies[] = $this->reflectionProvider->getClass($referencedClass); } foreach ($methodTag->getParameters() as $parameter) { foreach ($parameter->getType()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependencies[] = $this->reflectionProvider->getClass($referencedClass); } if ($parameter->getDefaultValue() === null) { continue; } foreach ($parameter->getDefaultValue()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependencies[] = $this->reflectionProvider->getClass($referencedClass); } } } foreach ($classReflection->getExtendsTags() as $extendsTag) { foreach ($extendsTag->getType()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependencies[] = $this->reflectionProvider->getClass($referencedClass); } } foreach ($classReflection->getImplementsTags() as $implementsTag) { foreach ($implementsTag->getType()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependencies[] = $this->reflectionProvider->getClass($referencedClass); } } $phpDoc = $classReflection->getResolvedPhpDoc(); if ($phpDoc !== null) { foreach ($phpDoc->getTypeAliasImportTags() as $importTag) { $dependencies[] = $this->reflectionProvider->getClass($importTag->getImportedFrom()); } } $classReflection = $classReflection->getParentClass(); } while ($classReflection !== null); return $dependencies; } private function getFunctionReflection(Node\Name $nameNode, ?Scope $scope): FunctionReflection { return $this->reflectionProvider->getFunction($nameNode, $scope); } /** * @param array $dependenciesReflections */ private function extractFromParametersAcceptor(ExtendedParametersAcceptor $parametersAcceptor, array &$dependenciesReflections): void { foreach ($parametersAcceptor->getParameters() as $parameter) { foreach ($parameter->getNativeType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } foreach ($parameter->getPhpDocType()->getReferencedClasses() 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); } } foreach ($parametersAcceptor->getNativeReturnType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } foreach ($parametersAcceptor->getPhpDocReturnType()->getReferencedClasses() 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 array $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 */ public static function __set_state(array $properties): self { return new self($properties['name'], $properties['args']); } /** * @return mixed */ #[ReturnTypeWillChange] #[Override] public function jsonSerialize() { return ['type' => self::class, 'data' => ['name' => $this->name, 'args' => $this->args]]; } /** * @param mixed[] $data */ public static function decode(array $data): self { return new self($data['name'], $data['args']); } } 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 */ public static function __set_state(array $properties): self { return new self($properties['name'], $properties['value'], $properties['attributes']); } /** * @param mixed[] $data */ public static function decode(array $data): self { 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] #[Override] public function jsonSerialize() { return ['type' => self::class, 'data' => ['name' => $this->name, 'value' => $this->value, 'attributes' => $this->attributes]]; } } 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 */ public static function __set_state(array $properties): self { return new self($properties['constants'], $properties['public'], $properties['private'], $properties['final'], $properties['phpDoc']); } /** * @param mixed[] $data */ public static function decode(array $data): self { 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] #[Override] public function jsonSerialize() { return ['type' => self::class, 'data' => ['constants' => $this->constants, 'public' => $this->public, 'private' => $this->private, 'final' => $this->final, 'phpDoc' => $this->phpDoc]]; } } 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 */ public static function __set_state(array $properties): self { 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] #[Override] 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 */ public static function decode(array $data): self { 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->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 */ public static function __set_state(array $properties): self { return new self($properties['name'], $properties['value'], $properties['phpDoc']); } /** * @param mixed[] $data */ public static function decode(array $data): self { return new self($data['name'], $data['value'], $data['phpDoc'] !== null ? \PHPStan\Dependency\ExportedNode\ExportedPhpDocNode::decode($data['phpDoc']['data']) : null); } /** * @return mixed */ #[ReturnTypeWillChange] #[Override] public function jsonSerialize() { return ['type' => self::class, 'data' => ['name' => $this->name, 'value' => $this->value, 'phpDoc' => $this->phpDoc]]; } } 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 */ public static function __set_state(array $properties): self { return new self($properties['name'], $properties['scalarType'], $properties['phpDoc'], $properties['implements'], $properties['statements'], $properties['attributes']); } /** * @return mixed */ #[ReturnTypeWillChange] #[Override] 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 */ public static function decode(array $data): self { 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; } } 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 */ public static function __set_state(array $properties): self { return new self($properties['name'], $properties['phpDoc'], $properties['byRef'], $properties['returnType'], $properties['parameters'], $properties['attributes']); } /** * @return mixed */ #[ReturnTypeWillChange] #[Override] 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 */ public static function decode(array $data): self { 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; } } 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 */ public static function __set_state(array $properties): self { return new self($properties['name'], $properties['phpDoc'], $properties['extends'], $properties['statements']); } /** * @return mixed */ #[ReturnTypeWillChange] #[Override] public function jsonSerialize() { return ['type' => self::class, 'data' => ['name' => $this->name, 'phpDoc' => $this->phpDoc, 'extends' => $this->extends, 'statements' => $this->statements]]; } /** * @param mixed[] $data */ public static function decode(array $data): self { 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->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 */ public static function __set_state(array $properties): self { 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] #[Override] 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 */ public static function decode(array $data): self { 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'])); } } name = $name; $this->type = $type; $this->byRef = $byRef; $this->variadic = $variadic; $this->hasDefault = $hasDefault; $this->attributes = $attributes; $this->phpDoc = $phpDoc; $this->flags = $flags; } 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; } } 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->type === $node->type && $this->byRef === $node->byRef && $this->variadic === $node->variadic && $this->hasDefault === $node->hasDefault && $this->flags === $node->flags; } /** * @param mixed[] $properties */ public static function __set_state(array $properties): self { return new self($properties['name'], $properties['type'], $properties['byRef'], $properties['variadic'], $properties['hasDefault'], $properties['attributes'], $properties['phpDoc'] ?? null, $properties['flags'] ?? 0); } /** * @return mixed */ #[ReturnTypeWillChange] #[Override] 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, 'phpDoc' => $this->phpDoc, 'flags' => $this->flags]]; } /** * @param mixed[] $data */ public static function decode(array $data): self { 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']), isset($data['phpDoc']) ? \PHPStan\Dependency\ExportedNode\ExportedPhpDocNode::decode($data['phpDoc']['data']) : null, $data['flags'] ?? 0); } } */ private array $uses; /** * @var array */ private array $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] #[Override] public function jsonSerialize() { return ['type' => self::class, 'data' => ['phpDocString' => $this->phpDocString, 'namespace' => $this->namespace, 'uses' => $this->uses, 'constUses' => $this->constUses]]; } /** * @param mixed[] $properties */ public static function __set_state(array $properties): self { return new self($properties['phpDocString'], $properties['namespace'], $properties['uses'], $properties['constUses'] ?? []); } /** * @param mixed[] $data */ public static function decode(array $data): self { return new self($data['phpDocString'], $data['namespace'], $data['uses'], $data['constUses'] ?? []); } } names = $names; $this->phpDoc = $phpDoc; $this->type = $type; $this->public = $public; $this->private = $private; $this->static = $static; $this->readonly = $readonly; $this->abstract = $abstract; $this->final = $final; $this->publicSet = $publicSet; $this->protectedSet = $protectedSet; $this->privateSet = $privateSet; $this->virtual = $virtual; $this->attributes = $attributes; $this->hooks = $hooks; } 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; } } if (count($this->hooks) !== count($node->hooks)) { return \false; } foreach ($this->hooks as $i => $hook) { if (!$hook->equals($node->hooks[$i])) { return \false; } } return $this->type === $node->type && $this->public === $node->public && $this->private === $node->private && $this->static === $node->static && $this->readonly === $node->readonly && $this->abstract === $node->abstract && $this->final === $node->final && $this->publicSet === $node->publicSet && $this->protectedSet === $node->protectedSet && $this->privateSet === $node->privateSet && $this->virtual === $node->virtual; } /** * @param mixed[] $properties */ public static function __set_state(array $properties): self { return new self($properties['names'], $properties['phpDoc'], $properties['type'], $properties['public'], $properties['private'], $properties['static'], $properties['readonly'], $properties['abstract'], $properties['final'], $properties['publicSet'], $properties['protectedSet'], $properties['privateSet'], $properties['virtual'], $properties['attributes'], $properties['hooks']); } /** * @param mixed[] $data */ public static function decode(array $data): self { 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'], $data['abstract'], $data['final'], $data['publicSet'], $data['protectedSet'], $data['privateSet'], $data['virtual'], 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']), array_map(static function (array $attributeData): \PHPStan\Dependency\ExportedNode\ExportedPropertyHookNode { if ($attributeData['type'] !== \PHPStan\Dependency\ExportedNode\ExportedPropertyHookNode::class) { throw new ShouldNotHappenException(); } return \PHPStan\Dependency\ExportedNode\ExportedPropertyHookNode::decode($attributeData['data']); }, $data['hooks'])); } /** * @return mixed */ #[ReturnTypeWillChange] #[Override] 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, 'abstract' => $this->abstract, 'final' => $this->final, 'publicSet' => $this->publicSet, 'protectedSet' => $this->protectedSet, 'privateSet' => $this->privateSet, 'virtual' => $this->virtual, 'attributes' => $this->attributes, 'hooks' => $this->hooks]]; } } name = $name; $this->phpDoc = $phpDoc; $this->byRef = $byRef; $this->abstract = $abstract; $this->final = $final; $this->short = $short; $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->abstract === $node->abstract && $this->final === $node->final && $this->short === $node->short; } /** * @param mixed[] $properties */ public static function __set_state(array $properties): self { return new self($properties['name'], $properties['phpDoc'], $properties['byRef'], $properties['abstract'], $properties['final'], $properties['short'], $properties['parameters'], $properties['attributes']); } /** * @return mixed */ #[ReturnTypeWillChange] #[Override] public function jsonSerialize() { return ['type' => self::class, 'data' => ['name' => $this->name, 'phpDoc' => $this->phpDoc, 'byRef' => $this->byRef, 'abstract' => $this->abstract, 'final' => $this->final, 'short' => $this->short, 'parameters' => $this->parameters, 'attributes' => $this->attributes]]; } /** * @param mixed[] $data */ public static function decode(array $data): self { return new self($data['name'], $data['phpDoc'] !== null ? \PHPStan\Dependency\ExportedNode\ExportedPhpDocNode::decode($data['phpDoc']['data']) : null, $data['byRef'], $data['abstract'], $data['final'], $data['short'], 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'])); } } 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 */ public static function __set_state(array $properties): self { return new self($properties['name'], $properties['phpDoc'], $properties['usedTraits'], $properties['traitUseAdaptations'], $properties['statements'], $properties['attributes']); } /** * @return mixed */ #[ReturnTypeWillChange] #[Override] 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 */ public static function decode(array $data): self { 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; } } 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 */ public static function __set_state(array $properties): self { return new self($properties['traitName'], $properties['method'], $properties['newModifier'], $properties['newName'], $properties['insteadOfs']); } /** * @param mixed[] $data */ public static function decode(array $data): self { return new self($data['traitName'], $data['method'], $data['newModifier'], $data['newName'], $data['insteadOfs']); } /** * @return mixed */ #[ReturnTypeWillChange] #[Override] public function jsonSerialize() { return ['type' => self::class, 'data' => ['traitName' => $this->traitName, 'method' => $this->method, 'newModifier' => $this->newModifier, 'newName' => $this->newName, 'insteadOfs' => $this->insteadOfs]]; } } 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(); } } reflectionProvider = $reflectionProvider; $this->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 fn(Name $name): string => $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 fn(Name $name): string => (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 fn(Name $name): string => (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 fn(Name $name): string => $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, $fileName, null), $this->exportAttributeNodes($node->attrGroups)); } return null; } /** * @param Node\Param[] $params * @return ExportedParameterNode[] */ private function exportParameterNodes(array $params, string $fileName, ?string $className): 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); } } $docComment = $param->getDocComment(); $nodes[] = new ExportedParameterNode($param->var->name, NodeTypePrinter::printType($type), $param->byRef, $param->variadic, $param->default !== null, $this->exportAttributeNodes($param->attrGroups), $this->exportPhpDocNode($fileName, $className, null, $docComment !== null ? $docComment->getText() : null), $param->flags); } 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, $fileName, $namespacedName), $this->exportAttributeNodes($node->attrGroups)); } } if ($node instanceof Node\Stmt\Property) { if ($node->isPrivate()) { return null; } $docComment = $node->getDocComment(); $names = array_map(static fn(Node\PropertyItem $prop): string => $prop->name->toString(), $node->props); $virtual = \false; if ($this->reflectionProvider->hasClass($namespacedName)) { $classReflection = $this->reflectionProvider->getClass($namespacedName); if ($classReflection->hasNativeProperty($names[0])) { $virtual = $classReflection->getNativeProperty($names[0])->isVirtual()->yes(); } } return new ExportedPropertiesNode($names, $this->exportPhpDocNode($fileName, $namespacedName, null, $docComment !== null ? $docComment->getText() : null), NodeTypePrinter::printType($node->type), $node->isPublic(), $node->isPrivate(), $node->isStatic(), $node->isReadonly(), $node->isAbstract(), $node->isFinal(), $node->isPublicSet(), $node->isProtectedSet(), $node->isPrivateSet(), $virtual, $this->exportAttributeNodes($node->attrGroups), $this->exportPropertyHooks($node->hooks, $fileName, $namespacedName)); } 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; } /** * @param Node\PropertyHook[] $hooks * @return ExportedPropertyHookNode[] */ private function exportPropertyHooks(array $hooks, string $fileName, string $namespacedName): array { $nodes = []; foreach ($hooks as $hook) { $docComment = $hook->getDocComment(); $propertyName = $hook->getAttribute('propertyName'); if ($propertyName === null) { continue; } $nodes[] = new ExportedPropertyHookNode($hook->name->toString(), $this->exportPhpDocNode($fileName, $namespacedName, sprintf('$%s::%s', $propertyName, $hook->name->toString()), $docComment !== null ? $docComment->getText() : null), $hook->byRef, $hook->body === null, $hook->isFinal(), $hook->body instanceof Expr, $this->exportParameterNodes($hook->params, $fileName, $namespacedName), $this->exportAttributeNodes($hook->attrGroups)); } return $nodes; } } exportedNodeResolver = $exportedNodeResolver; } public function reset(string $fileName): void { $this->fileName = $fileName; $this->currentNodes = []; } /** * @return RootExportedNode[] */ public function getExportedNodes(): array { return $this->currentNodes; } #[Override] 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 NodeVisitor::DONT_TRAVERSE_CHILDREN; } return null; } } */ private array $reflections; private ?\PHPStan\Dependency\RootExportedNode $exportedNode; /** * @param array $reflections */ public function __construct(FileHelper $fileHelper, array $reflections, ?\PHPStan\Dependency\RootExportedNode $exportedNode) { $this->fileHelper = $fileHelper; $this->reflections = $reflections; $this->exportedNode = $exportedNode; } /** * @return array */ public function getReflections(): array { return $this->reflections; } /** * @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; } if ($currentFile === $dependencyFile) { 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; } } Expect::int()->nullable()->required()]); } #[Override] public function loadConfiguration(): void { require_once __DIR__ . '/../../vendor/attributes.php'; $builder = $this->getContainerBuilder(); $autowiredParameters = Attributes::findTargetMethodParameters(\PHPStan\DependencyInjection\AutowiredParameter::class); $constructorParameters = []; foreach ($autowiredParameters as $parameter) { if (strcasecmp($parameter->method, '__construct') !== 0) { continue; } $lowerClass = strtolower($parameter->class); $constructorParameters[$lowerClass] ??= []; $constructorParameters[$lowerClass][] = $parameter; } foreach (Attributes::findTargetClasses(\PHPStan\DependencyInjection\AutowiredService::class) as $class) { $reflection = new ReflectionClass($class->name); $attribute = $class->attribute; $definition = $builder->addDefinition($attribute->name)->setType($class->name)->setAutowired($attribute->as); if ($attribute->factory !== null) { [$ref, $method] = explode('::', $attribute->factory); $definition->setFactory(new Statement([new Reference(substr($ref, 1)), $method])); } self::processConstructorParameters($builder, $class->name, $definition, $constructorParameters); foreach (\PHPStan\DependencyInjection\ValidateServiceTagsExtension::INTERFACE_TAG_MAPPING as $interface => $tag) { if (!$reflection->implementsInterface($interface)) { continue; } $definition->addTag($tag); } } foreach (Attributes::findTargetClasses(\PHPStan\DependencyInjection\NonAutowiredService::class) as $class) { $attribute = $class->attribute; $definition = $builder->addDefinition($attribute->name)->setType($class->name)->setAutowired(\false); if ($attribute->factory !== null) { [$ref, $method] = explode('::', $attribute->factory); $definition->setFactory(new Statement([new Reference(substr($ref, 1)), $method])); } self::processConstructorParameters($builder, $class->name, $definition, $constructorParameters); } foreach (Attributes::findTargetClasses(\PHPStan\DependencyInjection\GenerateFactory::class) as $class) { $attribute = $class->attribute; $definition = $builder->addFactoryDefinition(null)->setImplement($attribute->interface); if ($attribute->resultType !== null) { $definition->getResultDefinition()->setType($attribute->resultType); } $resultDefinition = $definition->getResultDefinition(); self::processConstructorParameters($builder, $class->name, $resultDefinition, $constructorParameters); } /** @var stdClass&object{level: int|null} $config */ $config = $this->getConfig(); if ($config->level === null) { return; } foreach (Attributes::findTargetClasses(\PHPStan\DependencyInjection\RegisteredRule::class) as $class) { $attribute = $class->attribute; if ($attribute->level > $config->level) { continue; } $definition = $builder->addDefinition(null)->setFactory($class->name)->setAutowired($class->name)->addTag(LazyRegistry::RULE_TAG); self::processConstructorParameters($builder, $class->name, $definition, $constructorParameters); } foreach (Attributes::findTargetClasses(\PHPStan\DependencyInjection\RegisteredCollector::class) as $class) { $attribute = $class->attribute; if ($attribute->level > $config->level) { continue; } $definition = $builder->addDefinition(null)->setFactory($class->name)->setAutowired($class->name)->addTag(RegistryFactory::COLLECTOR_TAG); self::processConstructorParameters($builder, $class->name, $definition, $constructorParameters); } } /** * @param class-string $className * @param array>> $constructorParameters */ public static function processConstructorParameters(ContainerBuilder $builder, string $className, ServiceDefinition $definition, array $constructorParameters): void { foreach ($constructorParameters[strtolower($className)] ?? [] as $autowiredParameter) { $ref = $autowiredParameter->attribute->ref; if ($ref === null) { $argument = Helpers::expand('%' . Helpers::escape($autowiredParameter->name) . '%', $builder->parameters); } elseif (Strings::match($ref, '#^@[\w\\\\]+$#D') !== null) { $argument = new Reference(substr($ref, 1)); } else { $argument = Helpers::expand($ref, $builder->parameters); } $definition->setArgument($autowiredParameter->name, $argument); } } } ref = $ref; } } |class-string */ public $as; /** * @param true|list|class-string $as */ public function __construct(?string $name = null, ?string $factory = null, $as = \true) { $this->name = $name; $this->factory = $factory; $this->as = $as; } } min(1)); } #[Override] 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) { $parameter = is_array($parameter) ? array_reduce($parameter, fn($carry, $item) => $carry && $this->resolveValue($item), \true) : $this->resolveValue($parameter); if ($parameter) { $service->addTag($tag); continue; } } } } } /** * @param mixed $parameter */ public function resolveValue($parameter): bool { if (!$parameter instanceof Statement) { return (bool) $parameter; } if ($parameter->getEntity() === 'not') { return !(bool) $parameter->arguments[0]; } throw new InvalidArgumentException('Unsupported Statement.'); } } loaderFactory = $loaderFactory; $this->journalContainer = $journalContainer; parent::__construct(); } #[Override] protected function createLoader(): Loader { return $this->loaderFactory->createLoader(); } /** * @param string[] $allConfigFiles */ public function setAllConfigFiles(array $allConfigFiles): void { $this->allConfigFiles = $allConfigFiles; } /** * @return mixed[] */ #[Override] protected function getDefaultParameters(): array { return []; } public function getContainerCacheDirectory(): string { return $this->getCacheDirectory() . '/nette.configurator'; } #[Override] public function loadContainer(): string { $loader = new ContainerLoader($this->getContainerCacheDirectory(), $this->staticParameters['debugMode']); $attributesPhp = __DIR__ . '/../../vendor/attributes.php'; $staticParameters = $this->staticParameters; ksort($staticParameters['env']); unset($staticParameters['env']['_']); // make sure variables which can get defined by the shell // after user-interactions with the UI will not invalidate the container cache unset($staticParameters['env']['SHLVL']); unset($staticParameters['env']['OLDPWD']); unset($staticParameters['env']['LINES']); unset($staticParameters['env']['COLUMNS']); unset($staticParameters['env']['SHELL_VERBOSITY']); // make sure invocations via blackfire use the same container unset($staticParameters['env']['BLACKFIRE_AGENT_SOCKET']); $containerKey = [$staticParameters, array_keys($this->dynamicParameters), $this->configs, PHP_VERSION_ID - PHP_RELEASE_VERSION, is_file($attributesPhp) ? hash_file('sha256', $attributesPhp) : 'attributes-missing', \PHPStan\DependencyInjection\NeonAdapter::CACHE_KEY, $this->getAllConfigFilesHashes(), var_export(TurboExtensionEnabler::isLoaded(), \true)]; $className = $loader->load([$this, 'generateContainer'], $containerKey); if ($this->journalContainer) { $this->journal($className); } return $className; } private function journal(string $currentContainerClassName): void { $directory = $this->getContainerCacheDirectory(); if (!is_dir($directory)) { return; } $journalFile = $directory . '/container.journal'; if (!is_file($journalFile)) { try { FileWriter::write($journalFile, sprintf("%s:%d\n", $currentContainerClassName, time())); } catch (CouldNotWriteFileException $e) { // pass } return; } try { $journalContents = FileReader::read($journalFile); } catch (CouldNotReadFileException $e) { return; } $journalLines = explode("\n", trim($journalContents)); $linesToWrite = []; $usedInTheLastWeek = []; $now = time(); $currentAlreadyInTheJournal = \false; foreach ($journalLines as $journalLine) { if ($journalLine === '') { continue; } $journalLineParts = explode(':', $journalLine); if (count($journalLineParts) !== 2) { return; } $className = $journalLineParts[0]; $containerLastUsedTime = (int) $journalLineParts[1]; $week = 3600 * 24 * 7; if ($containerLastUsedTime + $week < $now) { continue; } $usedInTheLastWeek[] = $className; if ($currentContainerClassName !== $className) { $linesToWrite[] = sprintf('%s:%d', $className, $containerLastUsedTime); continue; } $linesToWrite[] = sprintf('%s:%d', $currentContainerClassName, $now); $currentAlreadyInTheJournal = \true; } if (!$currentAlreadyInTheJournal) { $linesToWrite[] = sprintf('%s:%d', $currentContainerClassName, $now); $usedInTheLastWeek[] = $currentContainerClassName; } try { FileWriter::write($journalFile, implode("\n", $linesToWrite) . "\n"); } catch (CouldNotWriteFileException $e) { return; } foreach (new DirectoryIterator($directory) as $fileInfo) { if ($fileInfo->isDot()) { continue; } $fileName = $fileInfo->getFilename(); if ($fileName === 'container.journal') { continue; } if (!str_ends_with($fileName, '.php')) { continue; } $fileClassName = substr($fileName, 0, -4); if (in_array($fileClassName, $usedInTheLastWeek, \true)) { continue; } $basePathname = $fileInfo->getPathname(); @unlink($basePathname); @unlink($basePathname . '.lock'); @unlink($basePathname . '.meta'); } } #[Override] 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 = hash_file('sha256', $file); if ($hash === \false) { throw new CouldNotReadFileException($file); } $hashes[$file] = $hash; } return $hashes; } } $className * @return T * @throws MissingServiceException */ 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); } currentWorkingDirectory = $currentWorkingDirectory; $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'; } public function setJournalContainer(): void { $this->journalContainer = \true; } /** * @param string[] $additionalConfigFiles * @param string[] $analysedPaths * @param string[] $composerAutoloaderProjectPaths * @param string[] $analysedPathsFromConfig * @param array $additionalParameters */ 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, array $additionalParameters = []): \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, $projectConfig['expandRelativePaths']), $this->journalContainer); $configurator->defaultExtensions = ['php' => PhpExtension::class, 'extensions' => ExtensionsExtension::class]; $configurator->setDebugMode(\true); $configurator->setTempDirectory($tempDirectory); $configurator->addParameters(array_merge(['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, 'env' => getenv()], $additionalParameters)); $configurator->addDynamicParameters(['singleReflectionFile' => $singleReflectionFile, 'singleReflectionInsteadOfFile' => $singleReflectionInsteadOfFile, 'analysedPaths' => $analysedPaths, 'analysedPathsFromConfig' => $analysedPathsFromConfig]); $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)); 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']); } 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\NeonCachedFileReader([]); $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_33c983f26\Nette\Schema\Helpers::merge($tmpConfigArray, $configArray); } $normalized = array_map(fn(string $file): string => $this->fileHelper->normalizePath($file), $allConfigFiles); $deduplicated = array_unique($normalized); if (count($normalized) <= count($deduplicated)) { 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\NeonCachedFileReader $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_33c983f26\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); if (array_key_exists('phpVersion', $parameters) && is_array($parameters['phpVersion'])) { $phpVersion = $parameters['phpVersion']; if ($phpVersion['max'] < $phpVersion['min']) { throw new \PHPStan\DependencyInjection\InvalidPhpVersionException('Invalid PHP version range: phpVersion.max should be greater or equal to phpVersion.min.'); } } foreach ($parameters['ignoreErrors'] ?? [] as $ignoreError) { if (is_string($ignoreError)) { continue; } $atLeastOneOf = ['message', 'messages', 'rawMessage', 'rawMessages', 'identifier', 'identifiers', 'path', 'paths']; if (array_intersect($atLeastOneOf, array_keys($ignoreError)) === []) { throw new \PHPStan\DependencyInjection\InvalidIgnoredErrorException('An ignoreErrors entry must contain at least one of the following fields: ' . implode(', ', $atLeastOneOf) . '.'); } foreach ([['rawMessage', 'rawMessages', 'message', 'messages'], ['identifier', 'identifiers'], ['path', 'paths']] as $incompatibleFields) { foreach ($incompatibleFields as $index => $field1) { $fieldsToCheck = array_slice($incompatibleFields, $index + 1); foreach ($fieldsToCheck as $field2) { if (array_key_exists($field1, $ignoreError) && array_key_exists($field2, $ignoreError)) { throw new \PHPStan\DependencyInjection\InvalidIgnoredErrorException(sprintf('An ignoreErrors entry cannot contain both %s and %s fields.', $field1, $field2)); } } } } if (array_key_exists('count', $ignoreError) && !array_key_exists('path', $ignoreError)) { throw new \PHPStan\DependencyInjection\InvalidIgnoredErrorException('An ignoreErrors entry with count field must also contain path field.'); } } } /** * @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(fn($argument) => $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; } } 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 * @param array $additionalParameters */ public function create(array $additionalConfigFiles, array $additionalParameters = []): \PHPStan\DependencyInjection\Container { $containerFactory = new \PHPStan\DependencyInjection\ContainerFactory($this->currentWorkingDirectory); $containerFactory->setJournalContainer(); 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, $additionalParameters); } } files = $files; parent::__construct(sprintf('These files are included multiple times: %s', implode(', ', $this->files))); } /** * @return string[] */ public function getFiles(): array { return $this->files; } } getContainerBuilder(); $nodeScopeResolverDef = $builder->getDefinitionByType(NodeScopeResolver::class); $nodeScopeResolverDef->setAutowired(\false); $fiberNodeScopeResolverDef = $builder->getDefinitionByType(FiberNodeScopeResolver::class); $fiberNodeScopeResolverDef->setAutowired([NodeScopeResolver::class, FiberNodeScopeResolver::class]); } } interface = $interface; $this->resultType = $resultType; } } , analyseAndScan?: list} */ private array $suggestOptional; /** * @param string[] $errors * @param array{analyse?: list, analyseAndScan?: list} $suggestOptional */ public function __construct(array $errors, array $suggestOptional) { $this->errors = $errors; $this->suggestOptional = $suggestOptional; parent::__construct(implode("\n", $this->errors)); } /** * @return string[] */ public function getErrors(): array { return $this->errors; } /** * @return array{analyse?: list, analyseAndScan?: list} */ public function getSuggestOptional(): array { return $this->suggestOptional; } } errors = $errors; parent::__construct(implode("\n", $this->errors)); } /** * @return string[] */ public function getErrors(): array { return $this->errors; } } */ private array $expandRelativePaths; /** * @param list $expandRelativePaths */ public function __construct(FileHelper $fileHelper, string $rootDir, string $currentWorkingDirectory, ?string $generateBaselineFile, array $expandRelativePaths) { $this->fileHelper = $fileHelper; $this->rootDir = $rootDir; $this->currentWorkingDirectory = $currentWorkingDirectory; $this->generateBaselineFile = $generateBaselineFile; $this->expandRelativePaths = $expandRelativePaths; } public function createLoader(): Loader { $neonAdapter = new \PHPStan\DependencyInjection\NeonCachedFileReader($this->expandRelativePaths); $loader = new \PHPStan\DependencyInjection\NeonLoader($this->fileHelper, $this->generateBaselineFile); $loader->addAdapter('dist', $neonAdapter); $loader->addAdapter('neon', $neonAdapter); $loader->setParameters(['rootDir' => $this->rootDir, 'currentWorkingDirectory' => $this->currentWorkingDirectory, 'env' => getenv()]); return $loader; } } */ private array $servicesByType = []; /** @var array */ private array $servicesByName = []; /** @var array */ private array $servicesByTag = []; public function __construct( #[\PHPStan\DependencyInjection\AutowiredParameter('@PHPStan\DependencyInjection\Nette\NetteContainer')] \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->servicesByName[$serviceName] ??= $this->originalContainer->getService($serviceName); } public function getByType(string $className) { return $this->servicesByType[$className] ??= $this->originalContainer->getByType($className); } public function findServiceNamesByType(string $className): array { return $this->originalContainer->findServiceNamesByType($className); } public function getServicesByTag(string $tagName): array { return $this->servicesByTag[$tagName] ??= $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); } } path = $path; } } */ private array $expandRelativePaths; public const CACHE_KEY = 'v31-expand-relative-paths'; private const PREVENT_MERGING_SUFFIX = '!'; /** @var FileHelper[] */ private array $fileHelpers = []; /** * @param list $expandRelativePaths */ public function __construct(array $expandRelativePaths) { $this->expandRelativePaths = $expandRelativePaths; } /** * @return mixed[] */ #[Override] public function load(string $file): array { $contents = FileReader::read($file); try { return $this->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, $this->expandRelativePaths, \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; } private function createFileHelperByFile(string $file): FileHelper { $dir = dirname($file); if (!isset($this->fileHelpers[$dir])) { $this->fileHelpers[$dir] = new FileHelper($dir); } return $this->fileHelpers[$dir]; } } */ private array $expandRelativePaths; private \PHPStan\DependencyInjection\NeonAdapter $adapter; /** @var array */ private static array $decodedCache = []; /** * @param list $expandRelativePaths */ public function __construct(array $expandRelativePaths) { $this->expandRelativePaths = $expandRelativePaths; $this->adapter = new \PHPStan\DependencyInjection\NeonAdapter($this->expandRelativePaths); } /** * @return mixed[] */ #[Override] public function load(string $file): array { try { if (isset(self::$decodedCache[$file])) { $neon = self::$decodedCache[$file]; } else { $contents = FileReader::read($file); $neon = (array) Neon::decode($contents); self::$decodedCache[$file] = $neon; } return $this->adapter->process($neon, '', $file); } catch (Exception $e) { throw new Exception(sprintf('Error while loading %s: %s', $file, $e->getMessage())); } } } fileHelper = $fileHelper; $this->generateBaselineFile = $generateBaselineFile; } /** * @return mixed[] */ #[Override] 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); } } container = $container; } public function hasService(string $serviceName): bool { return $this->container->hasService($serviceName); } /** * @return mixed */ public function getService(string $serviceName) { try { return $this->container->getService($serviceName); } catch (\_PHPStan_33c983f26\Nette\DI\MissingServiceException $e) { throw new MissingServiceException($e->getMessage(), 0, $e); } } /** * @template T of object * @param class-string $className * @return T */ public function getByType(string $className) { try { return $this->container->getByType($className); } catch (\_PHPStan_33c983f26\Nette\DI\MissingServiceException $e) { throw new MissingServiceException($e->getMessage(), 0, $e); } } /** * @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->parameters ??= $this->container->getParameters(); } public function hasParameter(string $parameterName): bool { $parameters = $this->parameters ??= $this->container->getParameters(); return array_key_exists($parameterName, $parameters); } /** * @return mixed */ public function getParameter(string $parameterName) { $parameters = $this->parameters ??= $this->container->getParameters(); if (!array_key_exists($parameterName, $parameters)) { throw new ParameterNotFoundException($parameterName); } return $parameters[$parameterName]; } /** * @param mixed[] $tags * @return mixed[] */ private function tagsToServices(array $tags): array { return array_map(fn(string $serviceName) => $this->getService($serviceName), array_keys($tags)); } } name = $name; $this->factory = $factory; } } min(1); } } $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 []; } } container = $container; } public function getRegistry(): ClassReflectionExtensionRegistry { if ($this->registry === null) { $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); $universalObjectCratesClassReflectionExtension = $this->container->getByType(UniversalObjectCratesClassReflectionExtension::class); $this->registry = new ClassReflectionExtensionRegistry(array_merge($this->container->getServicesByTag(BrokerFactory::PROPERTIES_CLASS_REFLECTION_EXTENSION_TAG), [$annotationsPropertiesClassReflectionExtension, $mixinPropertiesClassReflectionExtension, $universalObjectCratesClassReflectionExtension]), array_merge($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), $this->container->getByType(PhpClassReflectionExtension::class)); } return $this->registry; } } level = $level; } } level = $level; } } config; $builder = $this->getContainerBuilder(); foreach ($config as $key => $rule) { $builder->addDefinition($this->prefix((string) $key))->setFactory($rule)->setAutowired($rule)->addTag(LazyRegistry::RULE_TAG); } } } getContainerBuilder(); $autowiredParameters = Attributes::findTargetMethodParameters(\PHPStan\DependencyInjection\AutowiredParameter::class); $constructorParameters = []; foreach ($autowiredParameters as $parameter) { if (strcasecmp($parameter->method, '__construct') !== 0) { continue; } $lowerClass = strtolower($parameter->class); $constructorParameters[$lowerClass] ??= []; $constructorParameters[$lowerClass][] = $parameter; } foreach (Attributes::findTargetClasses(\PHPStan\DependencyInjection\ValidatesStubFiles::class) as $class) { $definition = $builder->addDefinition(null)->setFactory($class->name)->setAutowired(\false)->addTag(StubValidator::SERVICE_RULE_TAG); \PHPStan\DependencyInjection\AutowiredAttributeServicesExtension::processConstructorParameters($builder, $class->name, $definition, $constructorParameters); } } } container = $container; } public function getRegistry(): DynamicReturnTypeExtensionRegistry { return $this->registry ??= new DynamicReturnTypeExtensionRegistry($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)); } } 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 getRegistry(): ExpressionTypeResolverExtensionRegistry { return $this->registry ??= new ExpressionTypeResolverExtensionRegistry($this->container->getServicesByTag(BrokerFactory::EXPRESSION_TYPE_RESOLVER_EXTENSION_TAG)); } } container = $container; } public function getRegistry(): OperatorTypeSpecifyingExtensionRegistry { return $this->registry ??= new OperatorTypeSpecifyingExtensionRegistry($this->container->getServicesByTag(BrokerFactory::OPERATOR_TYPE_SPECIFYING_EXTENSION_TAG)); } } container = $container; } public function getFunctionParameterClosureThisExtensions(): array { return $this->functionExtensions ??= $this->container->getServicesByTag(self::FUNCTION_TAG); } public function getMethodParameterClosureThisExtensions(): array { return $this->methodExtensions ??= $this->container->getServicesByTag(self::METHOD_TAG); } public function getStaticMethodParameterClosureThisExtensions(): array { return $this->staticMethodExtensions ??= $this->container->getServicesByTag(self::STATIC_METHOD_TAG); } } 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 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(): UnaryOperatorTypeSpecifyingExtensionRegistry { return $this->registry ??= new UnaryOperatorTypeSpecifyingExtensionRegistry($this->container->getServicesByTag(BrokerFactory::UNARY_OPERATOR_TYPE_SPECIFYING_EXTENSION_TAG)); } } getContainerBuilder(); $excludePaths = $builder->parameters['excludePaths']; if ($excludePaths === null) { return; } $newExcludePaths = []; if (array_key_exists('analyseAndScan', $excludePaths)) { $newExcludePaths['analyseAndScan'] = $excludePaths['analyseAndScan']; } if (array_key_exists('analyse', $excludePaths)) { $newExcludePaths['analyse'] = $excludePaths['analyse']; } $errors = []; $suggestOptional = []; if ($builder->parameters['__validate']) { foreach ($newExcludePaths as $key => $paths) { 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; } $suggestOptional[$key][] = $path; $errors[] = sprintf('Path "%s" is neither a directory, nor a file path, nor a fnmatch pattern.', $path); } } } if (count($errors) !== 0) { throw new \PHPStan\DependencyInjection\InvalidExcludePathsException($errors, $suggestOptional); } foreach ($newExcludePaths as $key => $p) { $newExcludePaths[$key] = array_map(static fn($path) => $path instanceof OptionalPath ? $path->path : $path, $p); } $builder->parameters['excludePaths'] = $newExcludePaths; } } getContainerBuilder(); if (!$builder->parameters['__validate']) { return; } $ignoreErrors = $builder->parameters['ignoreErrors']; if (count($ignoreErrors) === 0) { return; } /** @throws void */ $parser = Llk::load(new Read(__DIR__ . '/../../resources/RegexGrammar.pp')); $reflectionProvider = new DummyReflectionProvider(); $reflectionProviderProvider = new DirectReflectionProviderProvider($reflectionProvider); try { $originalReflectionProvider = ReflectionProviderStaticAccessor::getInstance(); } catch (MissingStaticAccessorInstanceException $e) { $originalReflectionProvider = null; } try { $originalPhpVersion = PhpVersionStaticAccessor::getInstance(); } catch (MissingStaticAccessorInstanceException $e) { $originalPhpVersion = null; } ReflectionProviderStaticAccessor::registerInstance($reflectionProvider); PhpVersionStaticAccessor::registerInstance(new PhpVersion(PHP_VERSION_ID)); try { $composerPhpVersionFactory = new ComposerPhpVersionFactory([]); $constantResolver = new ConstantResolver($reflectionProviderProvider, [], null, $composerPhpVersionFactory, null); $phpDocParserConfig = new ParserConfig([]); $ignoredRegexValidator = new IgnoredRegexValidator($parser, new TypeStringResolver(new Lexer($phpDocParserConfig), new TypeParser($phpDocParserConfig, new ConstExprParser($phpDocParserConfig)), 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([]); } }, new class implements UnaryOperatorTypeSpecifyingExtensionRegistryProvider { public function getRegistry(): UnaryOperatorTypeSpecifyingExtensionRegistry { return new UnaryOperatorTypeSpecifyingExtensionRegistry([]); } }, new OversizedArrayBuilder(), \true)))); $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 ($reportUnmatched) { foreach ($ignoreErrors as $ignoreError) { if (!is_array($ignoreError)) { continue; } if (isset($ignoreError['path'])) { if (!is_string($ignoreError['path'])) { $errors[] = sprintf("Key 'path' of ignoreErrors expects a string, %s given. Did you mean 'paths'?", gettype($ignoreError['path'])); continue; } $ignorePaths = [$ignoreError['path']]; } elseif (isset($ignoreError['paths'])) { if (!is_array($ignoreError['paths'])) { $errors[] = sprintf("Key 'paths' of ignoreErrors expects an array, %s given. Did you mean 'path'?", gettype($ignoreError['paths'])); continue; } $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); } finally { if ($originalReflectionProvider !== null) { ReflectionProviderStaticAccessor::registerInstance($originalReflectionProvider); } if ($originalPhpVersion !== null) { PhpVersionStaticAccessor::registerInstance($originalPhpVersion); } ObjectType::resetCaches(); } } 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 fn(string $typeDescription): string => 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); } } BrokerFactory::PROPERTIES_CLASS_REFLECTION_EXTENSION_TAG, MethodsClassReflectionExtension::class => BrokerFactory::METHODS_CLASS_REFLECTION_EXTENSION_TAG, AllowedSubTypesClassReflectionExtension::class => BrokerFactory::ALLOWED_SUB_TYPES_CLASS_REFLECTION_EXTENSION_TAG, DynamicMethodReturnTypeExtension::class => BrokerFactory::DYNAMIC_METHOD_RETURN_TYPE_EXTENSION_TAG, DynamicStaticMethodReturnTypeExtension::class => BrokerFactory::DYNAMIC_STATIC_METHOD_RETURN_TYPE_EXTENSION_TAG, DynamicFunctionReturnTypeExtension::class => BrokerFactory::DYNAMIC_FUNCTION_RETURN_TYPE_EXTENSION_TAG, OperatorTypeSpecifyingExtension::class => BrokerFactory::OPERATOR_TYPE_SPECIFYING_EXTENSION_TAG, UnaryOperatorTypeSpecifyingExtension::class => BrokerFactory::UNARY_OPERATOR_TYPE_SPECIFYING_EXTENSION_TAG, ExpressionTypeResolverExtension::class => BrokerFactory::EXPRESSION_TYPE_RESOLVER_EXTENSION_TAG, TypeNodeResolverExtension::class => TypeNodeResolverExtension::EXTENSION_TAG, Rule::class => LazyRegistry::RULE_TAG, StubFilesExtension::class => StubFilesExtension::EXTENSION_TAG, AlwaysUsedClassConstantsExtension::class => AlwaysUsedClassConstantsExtensionProvider::EXTENSION_TAG, AlwaysUsedMethodExtension::class => AlwaysUsedMethodExtensionProvider::EXTENSION_TAG, ReadWritePropertiesExtension::class => ReadWritePropertiesExtensionProvider::EXTENSION_TAG, FunctionTypeSpecifyingExtension::class => TypeSpecifierFactory::FUNCTION_TYPE_SPECIFYING_EXTENSION_TAG, MethodTypeSpecifyingExtension::class => TypeSpecifierFactory::METHOD_TYPE_SPECIFYING_EXTENSION_TAG, StaticMethodTypeSpecifyingExtension::class => TypeSpecifierFactory::STATIC_METHOD_TYPE_SPECIFYING_EXTENSION_TAG, DynamicFunctionThrowTypeExtension::class => LazyDynamicThrowTypeExtensionProvider::FUNCTION_TAG, DynamicMethodThrowTypeExtension::class => LazyDynamicThrowTypeExtensionProvider::METHOD_TAG, DynamicStaticMethodThrowTypeExtension::class => LazyDynamicThrowTypeExtensionProvider::STATIC_METHOD_TAG, FunctionParameterClosureThisExtension::class => LazyParameterClosureThisExtensionProvider::FUNCTION_TAG, MethodParameterClosureThisExtension::class => LazyParameterClosureThisExtensionProvider::METHOD_TAG, StaticMethodParameterClosureThisExtension::class => LazyParameterClosureThisExtensionProvider::STATIC_METHOD_TAG, FunctionParameterClosureTypeExtension::class => LazyParameterClosureTypeExtensionProvider::FUNCTION_TAG, MethodParameterClosureTypeExtension::class => LazyParameterClosureTypeExtensionProvider::METHOD_TAG, StaticMethodParameterClosureTypeExtension::class => LazyParameterClosureTypeExtensionProvider::STATIC_METHOD_TAG, FunctionParameterOutTypeExtension::class => LazyParameterOutTypeExtensionProvider::FUNCTION_TAG, MethodParameterOutTypeExtension::class => LazyParameterOutTypeExtensionProvider::METHOD_TAG, StaticMethodParameterOutTypeExtension::class => LazyParameterOutTypeExtensionProvider::STATIC_METHOD_TAG, ResultCacheMetaExtension::class => ResultCacheMetaExtension::EXTENSION_TAG, ClassConstantDeprecationExtension::class => ClassConstantDeprecationExtension::CLASS_CONSTANT_EXTENSION_TAG, ClassDeprecationExtension::class => ClassDeprecationExtension::CLASS_EXTENSION_TAG, EnumCaseDeprecationExtension::class => EnumCaseDeprecationExtension::ENUM_CASE_EXTENSION_TAG, FunctionDeprecationExtension::class => FunctionDeprecationExtension::FUNCTION_EXTENSION_TAG, MethodDeprecationExtension::class => MethodDeprecationExtension::METHOD_EXTENSION_TAG, PropertyDeprecationExtension::class => PropertyDeprecationExtension::PROPERTY_EXTENSION_TAG, RestrictedMethodUsageExtension::class => RestrictedMethodUsageExtension::METHOD_EXTENSION_TAG, RestrictedClassNameUsageExtension::class => RestrictedClassNameUsageExtension::CLASS_NAME_EXTENSION_TAG, RestrictedFunctionUsageExtension::class => RestrictedFunctionUsageExtension::FUNCTION_EXTENSION_TAG, RestrictedPropertyUsageExtension::class => RestrictedPropertyUsageExtension::PROPERTY_EXTENSION_TAG, RestrictedClassConstantUsageExtension::class => RestrictedClassConstantUsageExtension::CLASS_CONSTANT_EXTENSION_TAG, NodeVisitor::class => RichParser::VISITOR_SERVICE_TAG, Collector::class => CollectorRegistryFactory::COLLECTOR_TAG, DiagnoseExtension::class => DiagnoseExtension::EXTENSION_TAG, IgnoreErrorExtension::class => IgnoreErrorExtension::EXTENSION_TAG, ExprHandler::class => ExprHandler::EXTENSION_TAG]; /** * @throws MissingImplementedInterfaceInServiceWithTagException */ #[Override] public function beforeCompile(): void { $builder = $this->getContainerBuilder(); $mappingCount = count(self::INTERFACE_TAG_MAPPING); $flippedMapping = array_flip(self::INTERFACE_TAG_MAPPING); if (count($flippedMapping) !== $mappingCount) { // @phpstan-ignore notIdentical.alwaysFalse throw new ShouldNotHappenException('A tag is mapped to multiple interfaces'); } foreach ($builder->getDefinitions() as $definition) { /** @var class-string|null $className */ $className = $definition->getType(); if ($className === null) { continue; } $reflection = new ReflectionClass($className); foreach (array_keys($definition->getTags()) as $tag) { if (!array_key_exists($tag, $flippedMapping)) { continue; } if ($reflection->implementsInterface($flippedMapping[$tag])) { continue; } throw new \PHPStan\DependencyInjection\MissingImplementedInterfaceInServiceWithTagException($className, $tag, $flippedMapping[$tag]); } } } } phpVersion = $phpVersion; $this->configPhpVersion = $configPhpVersion; $this->fileHelper = $fileHelper; $this->composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; $this->allConfigFiles = $allConfigFiles; $this->composerPhpVersionFactory = $composerPhpVersionFactory; $this->simpleRelativePathHelper = $simpleRelativePathHelper; } /** * @param list $processedFiles */ public function print(Output $output, array $processedFiles): void { $phpRuntimeVersion = new PhpVersion(PHP_VERSION_ID); $output->writeLineFormatted(sprintf('PHP runtime version: %s', $phpRuntimeVersion->getVersionString())); if ($this->phpVersion->getSource() === PhpVersion::SOURCE_CONFIG && is_array($this->configPhpVersion)) { $minVersion = new PhpVersion($this->configPhpVersion['min']); $maxVersion = new PhpVersion($this->configPhpVersion['max']); $output->writeLineFormatted(sprintf('PHP version for analysis: %s-%s (from %s)', $minVersion->getVersionString(), $maxVersion->getVersionString(), $this->phpVersion->getSourceLabel())); } else { $minComposerPhpVersion = $this->composerPhpVersionFactory->getMinVersion(); $maxComposerPhpVersion = $this->composerPhpVersionFactory->getMaxVersion(); if ($minComposerPhpVersion !== null && $maxComposerPhpVersion !== null) { if ($minComposerPhpVersion->getVersionId() !== $maxComposerPhpVersion->getVersionId()) { $output->writeLineFormatted(sprintf('PHP composer.json required version: %s-%s', $minComposerPhpVersion->getVersionString(), $maxComposerPhpVersion->getVersionString())); } else { $output->writeLineFormatted(sprintf('PHP composer.json required version: %s', $minComposerPhpVersion->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(''); $topFiles = $this->getTopMostAnalysedFiles($processedFiles, 5); if (count($topFiles) <= 0) { return; } $output->writeLineFormatted('Most often analysed files:'); foreach ($topFiles as $file => $count) { $output->writeLineFormatted(sprintf(' %s: %d times', $this->simpleRelativePathHelper->getRelativePath($file), $count)); } $output->writeLineFormatted(''); } /** * @param list $processedFiles * @return array> */ private function getTopMostAnalysedFiles(array $processedFiles, int $limit): array { if ($processedFiles === []) { return []; } $counts = array_count_values($processedFiles); arsort($counts); $result = []; foreach (array_slice($counts, 0, $limit, \true) as $file => $count) { if ($count <= 1) { continue; } $result[$file] = $count; } return $result; } } fileHelper = $fileHelper; 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 (is_file($normalized)) { $this->literalAnalyseFilesExcludes[] = $normalized; } elseif (is_dir($normalized)) { if (!$trailingDirSeparator) { $normalized .= DIRECTORY_SEPARATOR; } $this->literalAnalyseDirectoryExcludes[] = $normalized; } } $isWindows = DIRECTORY_SEPARATOR === '\\'; if ($isWindows) { $this->fnmatchFlags = FNM_NOESCAPE | FNM_CASEFOLD; } else { $this->fnmatchFlags = 0; } } public function isExcludedFromAnalysing(string $file): bool { $file = $this->fileHelper->normalizePath($file); 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; } } , analyseAndScan?: array} */ private array $excludePaths; /** * @param array{analyse?: array, analyseAndScan?: array} $excludePaths */ public function __construct( \PHPStan\File\FileExcluderRawFactory $fileExcluderRawFactory, #[AutowiredParameter] array $excludePaths ) { $this->fileExcluderRawFactory = $fileExcluderRawFactory; $this->excludePaths = $excludePaths; } public function createAnalyseFileExcluder(): \PHPStan\File\FileExcluder { $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 { $paths = []; if (array_key_exists('analyseAndScan', $this->excludePaths)) { $paths = $this->excludePaths['analyseAndScan']; } return $this->fileExcluderRawFactory->create(array_values(array_unique($paths))); } } 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[] = $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[] = $fileInfo->getPathname(); $onlyFiles = \false; } } } $files = array_filter($files, fn(string $file): bool => !$this->fileExcluder->isExcludedFromAnalysing($file)); sort($files); return new \PHPStan\File\FileFinderResult(array_values(array_unique(array_map(fn(string $file): string => $this->fileHelper->normalizePath($file), $files))), $onlyFiles); } } files = $files; $this->onlyFiles = $onlyFiles; } /** * @return string[] */ public function getFiles(): array { return $this->files; } public function isOnlyFiles(): bool { return $this->onlyFiles; } } > */ private static array $normalizedPathsCache = []; private string $workingDirectory; public function __construct( #[AutowiredParameter('%currentWorkingDirectory%')] string $workingDirectory ) { $this->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 { $cached = self::$normalizedPathsCache[$originalPath][$directorySeparator] ?? null; if ($cached !== null) { return $cached; } $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 self::$normalizedPathsCache[$originalPath][$directorySeparator] = ($scheme !== null ? $scheme . '://' : '') . $pathRoot . implode($directorySeparator, $normalizedPathParts); } } |null */ private ?array $fileHashes = null; /** @var array|null */ private ?array $filePaths = null; /** * @param string[] $analysedPaths * @param string[] $analysedPathsFromConfig * @param string[] $scanFiles * @param string[] $scanDirectories */ public function __construct( #[AutowiredParameter('@fileFinderAnalyse')] \PHPStan\File\FileFinder $analyseFileFinder, #[AutowiredParameter('@fileFinderScan')] \PHPStan\File\FileFinder $scanFileFinder, #[AutowiredParameter] array $analysedPaths, #[AutowiredParameter] array $analysedPathsFromConfig, #[AutowiredParameter] array $scanFiles, #[AutowiredParameter] 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); } private function getFileHash(string $filePath): string { $hash = hash_file('sha256', $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); } } newFiles = $newFiles; $this->changedFiles = $changedFiles; $this->deletedFiles = $deletedFiles; } /** * @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; } } 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)); } } 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); } } 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; } } differ = new Differ(new UnifiedDiffOutputBuilder()); } /** * @param FixedErrorDiff[] $diffs * @throws FileChangedException * @throws MergeConflictException */ public function applyDiffs(string $fileName, array $diffs): string { $fileContents = FileReader::read($fileName); $fileHash = hash('sha256', $fileContents); $diffHunks = []; foreach ($diffs as $diff) { if ($diff->originalHash !== $fileHash) { throw new \PHPStan\Fixable\FileChangedException(); } $diffHunks[] = Hunk::createArray(Line::createArray($this->reconstructFullDiff($fileContents, $diff->diff))); } if (count($diffHunks) === 0) { return $fileContents; } $baseLines = Line::createArray(array_map(static fn($l) => [$l, Differ::OLD], self::splitStringByLines($fileContents))); $refMerge = new ReflectionClass(PhpMerge::class); $refMergeMethod = $refMerge->getMethod('mergeHunks'); if (PHP_VERSION_ID < 80100) { $refMergeMethod->setAccessible(\true); } $result = Line::createArray(array_map(static fn($l) => [$l, Differ::OLD], $refMergeMethod->invokeArgs(null, [$baseLines, $diffHunks[0], []]))); for ($i = 0; $i < count($diffHunks); $i++) { /** @var MergeConflict[] $conflicts */ $conflicts = []; $merged = $refMergeMethod->invokeArgs(null, [$baseLines, Hunk::createArray(Line::createArray($this->differ->diffToArray($fileContents, implode('', array_map(static fn($l) => $l->getContent(), $result))))), $diffHunks[$i], &$conflicts]); if (count($conflicts) > 0) { throw new \PHPStan\Fixable\MergeConflictException(); } $result = Line::createArray(array_map(static fn($l) => [$l, Differ::OLD], $merged)); } return implode('', array_map(static fn($l) => $l->getContent(), $result)); } /** * @return array */ private function reconstructFullDiff(string $originalText, string $unifiedDiff): array { $originalLines = self::splitStringByLines($originalText); $diffLines = self::splitStringByLines($unifiedDiff); $result = []; $origLineNo = 0; $diffPos = 0; while ($diffPos < count($diffLines)) { $line = $diffLines[$diffPos]; $matches = Strings::match($line, '/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@/'); if ($matches !== null) { // Parse hunk header $origStart = (int) $matches[1] - 1; // 0-based $diffPos++; // Emit kept lines before hunk while ($origLineNo < $origStart) { $result[] = [$originalLines[$origLineNo], Differ::OLD]; $origLineNo++; } // Process hunk while ($diffPos < count($diffLines)) { $line = $diffLines[$diffPos]; if (str_starts_with($line, '@@')) { break; // next hunk } $prefix = $line[0] ?? ''; $content = substr($line, 1); if ($prefix === ' ') { $result[] = [$content, Differ::OLD]; $origLineNo++; } elseif ($prefix === '-') { $result[] = [$content, Differ::REMOVED]; $origLineNo++; } elseif ($prefix === '+') { $result[] = [$content, Differ::ADDED]; } $diffPos++; } } else { $diffPos++; } } // Emit remaining lines as kept while ($origLineNo < count($originalLines)) { $result[] = [$originalLines[$origLineNo], Differ::OLD]; $origLineNo++; } return $result; } /** * @return string[] */ private static function splitStringByLines(string $input): array { return Strings::split($input, '/(.*\R)/', PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); } } callback = $callback; } /** * @return Node[]|Node|null */ #[Override] public function enterNode(Node $node) { $callback = $this->callback; return $callback($node); } } printer = $printer; $this->lexer = $lexer; $this->phpDocParser = $phpDocParser; } /** * @param callable(Node): (Node|Node[]|null) $callback */ public function edit(\PhpParser\Node $node, callable $callback): void { $doc = $node->getDocComment(); if ($doc === null) { $phpDoc = '/** */'; } else { $phpDoc = $doc->getText(); } $tokens = new TokenIterator($this->lexer->tokenize($phpDoc)); $phpDocNode = $this->phpDocParser->parse($tokens); $cloningTraverser = new NodeTraverser([new CloningVisitor()]); /** @var PhpDocNode $newPhpDocNode */ [$newPhpDocNode] = $cloningTraverser->traverse([$phpDocNode]); $traverser = new NodeTraverser([new \PHPStan\Fixable\PhpDoc\CallbackVisitor($callback)]); /** @var PhpDocNode $newPhpDocNode */ [$newPhpDocNode] = $traverser->traverse([$newPhpDocNode]); if (count($newPhpDocNode->children) === 0) { $node->setAttribute('comments', []); return; } $doc = new Doc($this->printer->printFormatPreserving($newPhpDocNode, $phpDocNode, $tokens)); $node->setDocComment($doc); } } getAttribute(self::FUNC_ARGS_TRAILING_COMMA_ATTRIBUTE); if ($trailingComma === \false) { $result = rtrim($result, ','); } return $result; } } origTokens = $origTokens; } #[Override] public function enterNode(Node $node): ?int { if ($node instanceof Node\Stmt\Namespace_ || $node instanceof Node\Stmt\Declare_) { return null; } if (!property_exists($node, 'stmts')) { return null; } if (!is_array($node->stmts) || count($node->stmts) === 0) { return null; } $firstStmt = $node->stmts[0]; if (!$firstStmt instanceof Node) { return null; } $text = $this->origTokens->getTokenCode($node->getStartTokenPos(), $firstStmt->getStartTokenPos(), 0); $c = preg_match_all('~\n([\x09\x20]*)~', $text, $matches, PREG_SET_ORDER); if (in_array($c, [0, \false], \true)) { return null; } $char = ''; $size = 0; foreach ($matches as $match) { $l = strlen($match[1]); if ($l === 0) { continue; } $char = $match[1]; $size = $l; break; } if ($size > 0) { $d = preg_match('~^(\x20+)$~', $char); if ($d !== \false && $d > 0) { $size = strlen($char); $char = ' '; } $this->indentCharacter = $char; $this->indentSize = $size; return NodeVisitor::STOP_TRAVERSAL; } return null; } } originalNode = $originalNode; $this->newNodeCallable = $newNodeCallable; } #[Override] public function enterNode(Node $node): ?Node { $origNode = $node->getAttribute('origNode'); if ($origNode !== $this->originalNode) { return null; } $this->found = \true; $callable = $this->newNodeCallable; $newNode = $callable($node); if ($newNode instanceof VirtualNode) { throw new ShouldNotHappenException('Cannot print VirtualNode.'); } return $newNode; } public function isFound(): bool { return $this->found; } } $path */ public static function unsetKeyAtPath(array &$array, array $path): void { [$head, $tail] = [$path[0], array_slice($path, 1)]; if (count($tail) === 0) { unset($array[$head]); } elseif (isset($array[$head])) { self::unsetKeyAtPath($array[$head], $tail); } } } > $arrays * @return Traversable> */ public static function combinations(array $arrays): iterable { // from https://stackoverflow.com/a/70800936/565782 by Arnaud Le Blanc if ($arrays === []) { yield []; return; } $last = array_pop($arrays); foreach (self::combinations($arrays) as $combination) { foreach ($last as $elem) { $comb = $combination; $comb[] = $elem; yield $comb; } } } } */ private static array $decodedCache = []; /** @var array|null */ private static ?array $installed; /** @return array|null */ public static function getComposerConfig(string $root): ?array { if (isset(self::$decodedCache[$root])) { return self::$decodedCache[$root]; } $composerJsonPath = self::getComposerJsonPath($root); if ($composerJsonPath === null) { return null; } try { $composerJsonContents = FileReader::read($composerJsonPath); return self::$decodedCache[$root] ??= Json::decode($composerJsonContents, Json::FORCE_ARRAY); } catch (CouldNotReadFileException|JsonException $e) { return null; } } public static function getComposerJsonPath(string $root): ?string { $envComposer = getenv('COMPOSER'); $fileName = is_string($envComposer) ? $envComposer : 'composer.json'; $fileName = basename(trim($fileName)); $path = $root . '/' . $fileName; if (!is_file($path)) { return null; } return $path; } /** * @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, '/'); } /** * @return array */ private static function getInstalled(): array { return self::$installed ??= require __DIR__ . '/../../vendor/composer/installed.php'; } public static function getPhpStanVersion(): string { if (self::$phpstanVersion !== null) { return self::$phpstanVersion; } $installed = self::getInstalled(); $rootPackage = $installed['root'] ?? null; if ($rootPackage === null) { return self::$phpstanVersion = self::UNKNOWN_VERSION; } return self::$phpstanVersion = self::processPackageVersion($rootPackage); } public static function getBetterReflectionVersion(): string { if (self::$betterReflectionVersion !== null) { return self::$betterReflectionVersion; } $installed = self::getInstalled(); $rootPackage = $installed['versions']['ondrejmirtes/better-reflection'] ?? null; if ($rootPackage === null) { return self::$betterReflectionVersion = self::UNKNOWN_VERSION; } return self::$betterReflectionVersion = self::processPackageVersion($rootPackage); } public static function getPhpDocParserVersion(): string { if (self::$phpDocParserVersion !== null) { return self::$phpDocParserVersion; } $installed = self::getInstalled(); $rootPackage = $installed['versions']['phpstan/phpdoc-parser'] ?? null; if ($rootPackage === null) { return self::$phpDocParserVersion = self::UNKNOWN_VERSION; } return self::$phpDocParserVersion = self::processPackageVersion($rootPackage); } /** * @param array $package * @return string */ private static function processPackageVersion(array $package): string { if (preg_match('/[^v\d.]/', $package['pretty_version']) === 0) { // Handles tagged versions, see https://github.com/Jean85/pretty-package-versions/blob/2.0.5/src/Version.php#L31 return $package['pretty_version']; } return $package['pretty_version'] . '@' . substr((string) $package['reference'], 0, 7); } } $attributes */ public static function getDeprecatedDescription(array $attributes): ?string { $deprecated = ReflectionAttributeHelper::filterAttributesByName($attributes, 'Deprecated'); foreach ($deprecated as $attr) { $arguments = $attr->getArguments(); foreach ($arguments as $i => $arg) { if (!is_string($arg)) { continue; } if (is_int($i)) { if ($i !== 0) { continue; } return $arg; } if ($i !== 'message') { continue; } return $arg; } } return null; } } timeout = $timeout; $this->connectTimeout = $connectTimeout; } /** * @param array $config * * @see \GuzzleHttp\RequestOptions */ public function createClient(array $config): Client { if (!isset($config['headers']['Accept-Encoding']) && extension_loaded('zlib')) { $config['headers']['Accept-Encoding'] = 'gzip,deflate'; } $defaults = [RequestOptions::TIMEOUT => $this->timeout, RequestOptions::CONNECT_TIMEOUT => $this->connectTimeout]; return new Client($config + $defaults); } } getSubNodeNames() as $subNodeName) { $subNodes[$subNodeName] = $node->{$subNodeName}; } return new \PHPStan\Node\AnonymousClassNode($node->name, $subNodes, $node->getAttributes()); } #[Override] public function isAnonymous(): bool { return \true; } } originalNode = $originalNode; $this->rightScope = $rightScope; parent::__construct($originalNode->getAttributes()); } /** * @return \PhpParser\Node\Expr\BinaryOp\BooleanAnd|\PhpParser\Node\Expr\BinaryOp\LogicalAnd */ public function getOriginalNode() { return $this->originalNode; } public function getRightScope(): Scope { return $this->rightScope; } #[Override] public function getType(): string { return 'PHPStan_Node_BooleanAndNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } originalNode = $originalNode; $this->rightScope = $rightScope; parent::__construct($originalNode->getAttributes()); } /** * @return \PhpParser\Node\Expr\BinaryOp\BooleanOr|\PhpParser\Node\Expr\BinaryOp\LogicalOr */ public function getOriginalNode() { return $this->originalNode; } public function getRightScope(): Scope { return $this->rightScope; } #[Override] public function getType(): string { return 'PHPStan_Node_BooleanOrNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } originalNode = $originalNode; $this->exitPoints = $exitPoints; $this->hasYield = $hasYield; parent::__construct($originalNode->getAttributes()); } public function getOriginalNode(): While_ { return $this->originalNode; } /** * @return StatementExitPoint[] */ public function getExitPoints(): array { return $this->exitPoints; } public function hasYield(): bool { return $this->hasYield; } #[Override] public function getType(): string { return 'PHPStan_Node_BreaklessWhileLoop'; } /** * @return string[] */ #[Override] 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; } #[Override] public function getType(): string { return 'PHPStan_Node_CatchWithUnthrownExceptionNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } 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; } #[Override] public function getType(): string { return 'PHPStan_Node_ClassConstantsNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } public function getClassReflection(): ClassReflection { return $this->classReflection; } } node = $node; $this->isDeclaredInTrait = $isDeclaredInTrait; } public function getNode(): \PhpParser\Node\Stmt\ClassMethod { return $this->node; } public function isDeclaredInTrait(): bool { return $this->isDeclaredInTrait; } } */ private array $methodCalls; private ClassReflection $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; } #[Override] public function getType(): string { return 'PHPStan_Node_ClassMethodsNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } public function getClassReflection(): ClassReflection { return $this->classReflection; } } */ private array $propertyUsages; /** * @var array */ private array $methodCalls; /** * @var array */ private array $returnStatementNodes; /** * @var list */ private array $propertyAssigns; private ClassReflection $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; } #[Override] public function getType(): string { return 'PHPStan_Node_ClassPropertiesNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } public function getClassReflection(): ClassReflection { return $this->classReflection; } /** * @param string[] $constructors * @return array{array, array, array} */ public function getUninitializedProperties(Scope $scope, array $constructors): array { if (!$this->getClass() instanceof Class_) { return [[], [], []]; } $classReflection = $this->getClassReflection(); $uninitializedProperties = []; $originalProperties = []; $initialInitializedProperties = []; $initializedProperties = []; $extensions = $this->readWritePropertiesExtensionProvider->getExtensions(); $initializedViaExtension = []; foreach ($this->getProperties() as $property) { if ($property->isStatic()) { continue; } if ($property->isAbstract()) { 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()); if ($propertyReflection->isVirtual()->yes()) { continue; } 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, $constructors); $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->getInstancePropertyReflection($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]; if (in_array($function->getName(), $constructors, \true)) { $hasInitialization = $hasInitialization->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\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 * @param string[] $originalConstructors * * @return array> */ private function getMethodsCalledFromConstructor(ClassReflection $classReflection, array $initialInitializedProperties, array $initializedProperties, array $methods, array $initializedInConstructorProperties, array $originalConstructors): 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' && in_array($inMethod->getName(), $originalConstructors, \true)) { foreach (array_keys($initializedInConstructorProperties) as $propertyName) { $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, $originalConstructors); } /** * @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; } } name = $name; $this->flags = $flags; $this->type = $type; $this->default = $default; $this->phpDoc = $phpDoc; $this->phpDocType = $phpDocType; $this->isPromoted = $isPromoted; $this->isPromotedFromTrait = $isPromotedFromTrait; $this->originalNode = $originalNode; $this->isReadonlyByPhpDoc = $isReadonlyByPhpDoc; $this->isDeclaredInTrait = $isDeclaredInTrait; $this->isReadonlyClass = $isReadonlyClass; $this->isAllowedPrivateMutation = $isAllowedPrivateMutation; $this->classReflection = $classReflection; parent::__construct($originalNode->getAttributes()); } /** @return non-empty-string */ 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; } /** * @return \PhpParser\Node\Stmt\Property|\PhpParser\Node\Param */ public function getOriginalNode() { return $this->originalNode; } public function getPhpDoc(): ?string { return $this->phpDoc; } public function getPhpDocType(): ?Type { return $this->phpDocType; } public function isPublic(): bool { return ($this->flags & Modifiers::PUBLIC) !== 0 || ($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 isPrivateSet(): bool { return (bool) ($this->flags & Modifiers::PRIVATE_SET); } public function isProtectedSet(): bool { return (bool) ($this->flags & Modifiers::PROTECTED_SET); } public function isPublicSet(): bool { return (bool) ($this->flags & Modifiers::PUBLIC_SET); } public function isFinal(): bool { return (bool) ($this->flags & Modifiers::FINAL); } public function isStatic(): bool { return (bool) ($this->flags & Modifiers::STATIC); } public function isReadOnly(): bool { return (bool) ($this->flags & Modifiers::READONLY) || $this->isReadonlyClass; } public function isReadOnlyByPhpDoc(): bool { return $this->isReadonlyByPhpDoc; } public function isDeclaredInTrait(): bool { return $this->isDeclaredInTrait; } public function isAllowedPrivateMutation(): bool { return $this->isAllowedPrivateMutation; } public function isAbstract(): bool { return (bool) ($this->flags & Modifiers::ABSTRACT); } public function getNativeType(): ?Type { return $this->type; } /** * @return Node\Identifier|Node\Name|Node\ComplexType|null */ public function getNativeTypeNode() { return $this->originalNode->type; } public function getClassReflection(): ClassReflection { return $this->classReflection; } #[Override] public function getType(): string { return 'PHPStan_Node_ClassPropertyNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } public function hasHooks(): bool { return $this->getHooks() !== []; } /** * @return Node\PropertyHook[] */ public function getHooks(): array { return $this->originalNode->hooks; } public function isVirtual(): bool { return $this->classReflection->getNativeProperty($this->name)->isVirtual()->yes(); } public function isWritable(): bool { return $this->classReflection->getNativeProperty($this->name)->isWritable(); } public function isReadable(): bool { return $this->classReflection->getNativeProperty($this->name)->isReadable(); } /** * @return Node\AttributeGroup[] */ public function getAttrGroups(): array { return $this->originalNode->attrGroups; } } */ private array $propertyUsages = []; /** @var Node\Stmt\ClassConst[] */ private array $constants = []; /** @var ClassConstantFetch[] */ private array $constantFetches = []; /** @var array */ private array $returnStatementNodes = []; /** @var list */ private array $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) { $propertyFetch = $node->getPropertyFetch(); $assignedExpr = $node->getAssignedExpr(); if ($assignedExpr instanceof SetOffsetValueTypeExpr || $assignedExpr instanceof SetExistingOffsetValueTypeExpr) { $propertyType = $scope->getType($propertyFetch); if (!$propertyType->isObject()->no()) { $this->propertyUsages[] = new PropertyRead($propertyFetch, $scope); } } $this->propertyUsages[] = new PropertyWrite($propertyFetch, $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 \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; } if ($property->getName() === '') { throw new ShouldNotHappenException(); } $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; } if ($property->getName() === '') { throw new ShouldNotHappenException(); } $this->propertyUsages[] = new PropertyWrite(new PropertyFetch(new Expr\Variable('this'), new Identifier($property->getName()), $ancestorConstructorCall->getAttributes()), $scope, \false); } } } */ private array $returnStatements; /** * @var list */ private array $yieldStatements; private StatementResult $statementResult; /** * @var list */ private array $executionEnds; /** * @var ImpurePoint[] */ private array $impurePoints; private Node\Expr\Closure $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; } #[Override] public function getType(): string { return 'PHPStan_Node_ClosureReturnStatementsNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } 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 $filePath => $collectedDataPerCollector) { if (!isset($collectedDataPerCollector[$collectorType])) { continue; } foreach ($collectedDataPerCollector[$collectorType] as $rawData) { $result[$filePath][] = $rawData; } } 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; } #[Override] public function getType(): string { return 'PHPStan_Node_CollectedDataNode'; } /** * @return array{} */ #[Override] public function getSubNodeNames(): array { return []; } } node = $node; $this->scope = $scope; } public function getNode(): ClassConstFetch { return $this->node; } public function getScope(): Scope { return $this->scope; } } traverse([$node]); /** @var T */ return $clonedNode; } } cond = $cond; $this->exitPoints = $exitPoints; $this->hasYield = $hasYield; parent::__construct($cond->getAttributes()); } public function getCond(): Expr { return $this->cond; } /** * @return StatementExitPoint[] */ public function getExitPoints(): array { return $this->exitPoints; } public function hasYield(): bool { return $this->hasYield; } #[Override] public function getType(): string { return 'PHPStan_Node_ClosureReturnStatementsNode'; } /** * @return string[] */ #[Override] 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; } #[Override] public function getType(): string { return 'PHPStan_Node_ExecutionEndNode'; } /** * @return string[] */ #[Override] 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; } #[Override] public function getType(): string { return 'PHPStan_Node_AlwaysRememberedExpr'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return ['expr']; } } var = $var; $this->dim = $dim; parent::__construct([]); } public function getVar(): Expr { return $this->var; } public function getDim(): Expr { return $this->dim; } #[Override] public function getType(): string { return 'PHPStan_Node_ExistingArrayDimFetch'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } expr = $expr; parent::__construct([]); } public function getExpr(): Expr { return $this->expr; } #[Override] public function getType(): string { return 'PHPStan_Node_ForeachValueByRefExpr'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } expr = $expr; parent::__construct([]); } public function getExpr(): Expr { return $this->expr; } #[Override] public function getType(): string { return 'PHPStan_Node_GetIterableKeyTypeExpr'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } expr = $expr; parent::__construct([]); } public function getExpr(): Expr { return $this->expr; } #[Override] public function getType(): string { return 'PHPStan_Node_GetIterableValueTypeExpr'; } /** * @return string[] */ #[Override] 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; } #[Override] public function getType(): string { return 'PHPStan_Node_GetOffsetValueTypeExpr'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } variableName = $variableName; $this->expr = $expr; $this->assignedExpr = $assignedExpr; parent::__construct([]); } public function getVariableName(): string { return $this->variableName; } public function getExpr(): Expr { return $this->expr; } public function getAssignedExpr(): Expr { return $this->assignedExpr; } #[Override] public function getType(): string { return 'PHPStan_Node_IntertwinedVariableByReferenceWithExpr'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return ['expr']; } } phpdocType = $phpdocType; $this->nativeType = $nativeType; parent::__construct(); } public function getPhpDocType(): Type { return $this->phpdocType; } public function getNativeType(): Type { return $this->nativeType; } #[Override] public function getType(): string { return 'PHPStan_Node_NativeTypeExpr'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } variableName = $variableName; parent::__construct([]); $this->var = new Expr\Variable($this->variableName); } public function getVariableName(): string { return $this->variableName; } #[Override] public function getType(): string { return 'PHPStan_Node_OriginalForeachKeyExpr'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return ['var']; } } variableName = $variableName; parent::__construct([]); $this->var = new Expr\Variable($this->variableName); } public function getVariableName(): string { return $this->variableName; } #[Override] public function getType(): string { return 'PHPStan_Node_OriginalForeachValueExpr'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return ['var']; } } propertyFetch = $propertyFetch; parent::__construct([]); } /** * @return \PhpParser\Node\Expr\PropertyFetch|\PhpParser\Node\Expr\StaticPropertyFetch */ public function getPropertyFetch() { return $this->propertyFetch; } #[Override] public function getType(): string { return 'PHPStan_Node_OriginalPropertyTypeExpr'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } variableName = $variableName; parent::__construct([]); $this->var = new Expr\Variable($this->variableName); } public function getVariableName(): string { return $this->variableName; } #[Override] public function getType(): string { return 'PHPStan_Node_ParameterVariableOriginalValueExpr'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return ['var']; } } callExpr = $callExpr; $this->impactedExpr = $impactedExpr; $this->callDescription = $callDescription; parent::__construct([]); } public function getCallDescription(): string { return $this->callDescription; } #[Override] public function getType(): string { return 'PHPStan_Node_PossiblyImpureCallExpr'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return ['callExpr', 'impactedExpr']; } } propertyName = $propertyName; parent::__construct([]); } public function getPropertyName(): string { return $this->propertyName; } #[Override] public function getType(): string { return 'PHPStan_Node_PropertyInitializationExpr'; } /** * @return string[] */ #[Override] 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; } #[Override] public function getType(): string { return 'PHPStan_Node_SetExistingOffsetValueTypeExpr'; } /** * @return string[] */ #[Override] 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; } #[Override] public function getType(): string { return 'PHPStan_Node_SetOffsetValueTypeExpr'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } exprType = $exprType; parent::__construct(); } public function getExprType(): Type { return $this->exprType; } #[Override] public function getType(): string { return 'PHPStan_Node_TypeExpr'; } /** * @return string[] */ #[Override] 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; } #[Override] public function getType(): string { return 'PHPStan_Node_UnsetOffsetExpr'; } /** * @return string[] */ #[Override] 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; } #[Override] public function getType(): string { return 'PHPStan_Node_FileNode'; } /** * @return string[] */ #[Override] 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; } #[Override] public function getType(): string { return 'PHPStan_Node_FinallyExitPointsNode'; } /** * @return string[] */ #[Override] 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; } #[Override] public function getType(): string { return 'PHPStan_Node_FunctionCallableNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } */ private array $returnStatements; /** * @var list */ private array $yieldStatements; private StatementResult $statementResult; /** * @var list */ private array $executionEnds; /** * @var ImpurePoint[] */ private array $impurePoints; private PhpFunctionFromParserNodeReflection $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; } #[Override] public function getType(): string { return 'PHPStan_Node_FunctionReturnStatementsNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } public function getFunctionReflection(): PhpFunctionFromParserNodeReflection { return $this->functionReflection; } /** * @return Stmt[] */ public function getStatements(): array { return $this->function->getStmts(); } } 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; } #[Override] public function getType(): string { return 'PHPStan_Node_InArrowFunctionNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } 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; } #[Override] public function getType(): string { return 'PHPStan_Stmt_InClassMethodNode'; } /** * @return string[] */ #[Override] 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; } #[Override] public function getType(): string { return 'PHPStan_Stmt_InClassNode'; } /** * @return string[] */ #[Override] 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; } #[Override] public function getType(): string { return 'PHPStan_Node_InClosureNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } originalNode = $originalNode; parent::__construct($originalNode->getAttributes()); } public function getOriginalNode(): Foreach_ { return $this->originalNode; } #[Override] public function getType(): string { return 'PHPStan_Node_InForeachNode'; } /** * @return string[] */ #[Override] 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; } #[Override] public function getType(): string { return 'PHPStan_Stmt_InFunctionNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } classReflection = $classReflection; $this->hookReflection = $hookReflection; $this->propertyReflection = $propertyReflection; $this->originalNode = $originalNode; parent::__construct($originalNode->getAttributes()); } public function getClassReflection(): ClassReflection { return $this->classReflection; } public function getHookReflection(): PhpMethodFromParserNodeReflection { return $this->hookReflection; } public function getPropertyReflection(): PhpPropertyReflection { return $this->propertyReflection; } public function getOriginalNode(): Node\PropertyHook { return $this->originalNode; } #[Override] public function getType(): string { return 'PHPStan_Node_InPropertyHookNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } 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; } #[Override] public function getType(): string { return 'PHPStan_Stmt_InTraitNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } 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; } #[Override] public function getType(): string { return 'PHPStan_Node_InstantiationCallableNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } expr = $expr; parent::__construct($expr->getAttributes()); } public function getExpr(): Expr { return $this->expr; } #[Override] public function getType(): string { return 'PHPStan_Node_InvalidateExpr'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } expr = $expr; parent::__construct([]); } public function getExpr(): Expr { return $this->expr; } #[Override] public function getType(): string { return 'PHPStan_Node_IssetExpr'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } scope = $scope; $this->arrayItem = $arrayItem; } public function getScope(): Scope { return $this->scope; } public function getArrayItem(): ?ArrayItem { return $this->arrayItem; } } itemNodes = $itemNodes; parent::__construct($originalNode->getAttributes()); } /** * @return LiteralArrayItem[] */ public function getItemNodes(): array { return $this->itemNodes; } #[Override] public function getType(): string { return 'PHPStan_Node_LiteralArray'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } 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; } } scope = $scope; $this->body = $body; } public function getScope(): Scope { return $this->scope; } public function getBody(): Expr { return $this->body; } } 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; } } 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; } #[Override] public function getType(): string { return 'PHPStan_Node_MatchExpression'; } /** * @return string[] */ #[Override] 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; } } 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; } #[Override] public function getType(): string { return 'PHPStan_Node_MethodCallableNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } */ private array $returnStatements; /** * @var list */ private array $yieldStatements; private StatementResult $statementResult; /** * @var list */ private array $executionEnds; /** * @var ImpurePoint[] */ private array $impurePoints; private ClassReflection $classReflection; private PhpMethodFromParserNodeReflection $methodReflection; private ClassMethod $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; } #[Override] public function getType(): string { return 'PHPStan_Node_MethodReturnStatementsNode'; } /** * @return string[] */ #[Override] 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; } #[Override] public function getType(): string { return 'PHPStan_Node_NoopExpressionNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } printer = $printer; } public function printExpr(Expr $expr): string { // perf optimize for the most common path if ($expr instanceof Expr\Variable && !$expr->name instanceof Expr) { return '$' . $expr->name; } /** @var string|null $exprString */ $exprString = $expr->getAttribute(self::ATTRIBUTE_CACHE_KEY); if ($exprString === null) { $exprString = $this->printer->prettyPrintExpr($expr); $expr->setAttribute(self::ATTRIBUTE_CACHE_KEY, $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(); } } getExprType()->describe(VerbosityLevel::precise())); } protected function pPHPStan_Node_NativeTypeExpr(NativeTypeExpr $expr): string { return sprintf('__phpstanNativeType(%s, %s)', $expr->getPhpDocType()->describe(VerbosityLevel::precise()), $expr->getNativeType()->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('__phpstanRemembered(%s)', $this->p($expr->getExpr())); } protected function pPHPStan_Node_PossiblyImpureCallExpr(PossiblyImpureCallExpr $expr): string { return sprintf('__phpstanPossiblyImpure(%s, %s)', $this->p($expr->callExpr), $this->p($expr->impactedExpr)); } protected function pPHPStan_Node_PropertyInitializationExpr(PropertyInitializationExpr $expr): string { return sprintf('__phpstanPropertyInitialization(%s)', $expr->getPropertyName()); } protected function pPHPStan_Node_ForeachValueByRefExpr(ForeachValueByRefExpr $expr): string { return sprintf('__phpstanForeachValueByRef(%s)', $this->p($expr->getExpr())); } protected function pPHPStan_Node_ParameterVariableOriginalValueExpr(ParameterVariableOriginalValueExpr $expr): string { return sprintf('__phpstanParameterVariableOriginalValue(%s)', $expr->getVariableName()); } protected function pPHPStan_Node_OriginalForeachKeyExpr(OriginalForeachKeyExpr $expr): string { return sprintf('__phpstanOriginalForeachKey(%s)', $expr->getVariableName()); } protected function pPHPStan_Node_OriginalForeachValueExpr(OriginalForeachValueExpr $expr): string { return sprintf('__phpstanOriginalForeachValue(%s)', $expr->getVariableName()); } protected function pPHPStan_Node_IntertwinedVariableByReferenceWithExpr(IntertwinedVariableByReferenceWithExpr $expr): string { return sprintf('__phpstanIntertwinedVariableByReference(%s, %s, %s)', $expr->getVariableName(), $this->p($expr->getExpr()), $this->p($expr->getAssignedExpr())); } protected function pPHPStan_Node_IssetExpr(IssetExpr $expr): string { return sprintf('__phpstanIssetExpr(%s)', $this->p($expr->getExpr())); } protected function pPHPStan_Node_BooleanOrNode(BooleanOrNode $expr): string { return sprintf('__phpstanBooleanOr(%s, %s)', $this->p($expr->getOriginalNode()->left), $this->p($expr->getOriginalNode()->right)); } protected function pPHPStan_Node_BooleanAndNode(BooleanAndNode $expr): string { return sprintf('__phpstanBooleanAnd(%s, %s)', $this->p($expr->getOriginalNode()->left), $this->p($expr->getOriginalNode()->right)); } protected function pPHPStan_Node_FunctionCallableNode(FunctionCallableNode $expr): string { return sprintf('__phpstanFunctionCallable(%s)', $this->p($expr->getOriginalNode())); } protected function pPHPStan_Node_MethodCallableNode(MethodCallableNode $expr): string { return sprintf('__phpstanMethodCallable(%s)', $this->p($expr->getOriginalNode())); } protected function pPHPStan_Node_StaticMethodCallableNode(StaticMethodCallableNode $expr): string { return sprintf('__phpstanStaticMethodCallable(%s)', $this->p($expr->getOriginalNode())); } protected function pPHPStan_Node_InstantiationCallableNode(InstantiationCallableNode $expr): string { return sprintf('__phpstanInstantiationCallable(%s)', $this->p($expr->getOriginalNode())); } } assign = $assign; $this->scope = $scope; } public function getAssign(): PropertyAssignNode { return $this->assign; } public function getScope(): Scope { return $this->scope; } } fetch = $fetch; $this->scope = $scope; } /** * @return PropertyFetch|StaticPropertyFetch */ public function getFetch() { return $this->fetch; } 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; } } propertyFetch = $propertyFetch; $this->assignedExpr = $assignedExpr; $this->assignOp = $assignOp; parent::__construct($propertyFetch->getAttributes()); } /** * @return \PhpParser\Node\Expr\PropertyFetch|\PhpParser\Node\Expr\StaticPropertyFetch */ public function getPropertyFetch() { return $this->propertyFetch; } public function getAssignedExpr(): Expr { return $this->assignedExpr; } public function isAssignOp(): bool { return $this->assignOp; } #[Override] public function getType(): string { return 'PHPStan_Node_PropertyAssignNodeNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } */ private array $returnStatements; private StatementResult $statementResult; /** * @var list */ private array $executionEnds; /** * @var ImpurePoint[] */ private array $impurePoints; private ClassReflection $classReflection; private PhpMethodFromParserNodeReflection $hookReflection; private PhpPropertyReflection $propertyReflection; /** * @param list $returnStatements * @param list $executionEnds * @param ImpurePoint[] $impurePoints */ public function __construct(PropertyHook $hook, array $returnStatements, StatementResult $statementResult, array $executionEnds, array $impurePoints, ClassReflection $classReflection, PhpMethodFromParserNodeReflection $hookReflection, PhpPropertyReflection $propertyReflection) { $this->hook = $hook; $this->returnStatements = $returnStatements; $this->statementResult = $statementResult; $this->executionEnds = $executionEnds; $this->impurePoints = $impurePoints; $this->classReflection = $classReflection; $this->hookReflection = $hookReflection; $this->propertyReflection = $propertyReflection; parent::__construct($hook->getAttributes()); } public function getPropertyHookNode(): PropertyHook { return $this->hook; } public function returnsByRef(): bool { return $this->hook->byRef; } public function hasNativeReturnTypehint(): bool { return \false; } public function getYieldStatements(): array { return []; } public function isGenerator(): bool { return \false; } 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 getClassReflection(): ClassReflection { return $this->classReflection; } public function getHookReflection(): PhpMethodFromParserNodeReflection { return $this->hookReflection; } public function getPropertyReflection(): PhpPropertyReflection { return $this->propertyReflection; } #[Override] public function getType(): string { return 'PHPStan_Node_PropertyHookReturnStatementsNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } getAttributes()); } /** * @return null */ public function getReturnType() { return null; } #[Override] public function getType(): string { return 'PHPStan_Node_PropertyHookStatementNode'; } #[Override] public function getSubNodeNames(): array { return []; } } scope = $scope; $this->returnNode = $returnNode; } public function getScope(): Scope { return $this->scope; } public function getReturnNode(): Return_ { return $this->returnNode; } } */ 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; } 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; } #[Override] public function getType(): string { return 'PHPStan_Node_StaticMethodCallableNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } originalStatement = $originalStatement; $this->nextStatements = $nextStatements; parent::__construct($originalStatement->getAttributes()); } public function getOriginalStatement(): Stmt { return $this->originalStatement; } #[Override] public function getType(): string { return 'PHPStan_Stmt_UnreachableStatementNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } /** * @return Stmt[] */ public function getNextStatements(): array { return $this->nextStatements; } } varTag = $varTag; $this->expr = $expr; parent::__construct($expr->getAttributes()); } public function getVarTag(): VarTag { return $this->varTag; } public function getExpr(): Expr { return $this->expr; } #[Override] public function getType(): string { return 'PHPStan_Node_VarTagChangedExpressionType'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } variable = $variable; $this->assignedExpr = $assignedExpr; parent::__construct($variable->getAttributes()); } public function getVariable(): Expr\Variable { return $this->variable; } public function getAssignedExpr(): Expr { return $this->assignedExpr; } #[Override] public function getType(): string { return 'PHPStan_Node_VariableAssignNodeNode'; } /** * @return string[] */ #[Override] public function getSubNodeNames(): array { return []; } } getDisabledReason() === null; } public function print(Output $output): void { $output->writeLineFormatted('Parallel worker creation:'); $reason = $this->getDisabledReason(); if ($reason === null) { $output->writeLineFormatted('Mechanism: fork (pcntl_fork — experimental)'); $output->writeLineFormatted(''); return; } $output->writeLineFormatted('Mechanism: spawn (react/child-process)'); if (getenv('PHPSTAN_PARALLEL_FORK') === '1') { $output->writeLineFormatted(sprintf('Reason fork not used: %s', $reason)); } $output->writeLineFormatted(''); } private function getDisabledReason(): ?string { if (!function_exists('pcntl_fork') || !function_exists('pcntl_waitpid') || !function_exists('pcntl_wifexited') || !function_exists('pcntl_wexitstatus') || !function_exists('posix_kill')) { return 'pcntl/posix functions are not available'; } if (getenv('PHPSTAN_PARALLEL_FORK') !== '1') { return 'PHPSTAN_PARALLEL_FORK environment variable is not set to "1"'; } if ($this->isOpcacheOrJitEnabled()) { return 'OPcache or JIT is enabled (forked workers require both to be off — their shared memory corrupts under concurrent population)'; } return null; } private function isOpcacheOrJitEnabled(): bool { if (!function_exists('opcache_get_status')) { return \false; } $status = opcache_get_status(\false); if ($status === \false) { return \false; } if (($status['opcache_enabled'] ?? \false) === \true) { return \true; } return ($status['jit']['enabled'] ?? \false) === \true; } } workerRunner = $workerRunner; $this->server = $server; $this->serverPort = $serverPort; $this->identifier = $identifier; $this->analysedFiles = $analysedFiles; $this->tmpFile = $tmpFile; $this->insteadOfFile = $insteadOfFile; parent::__construct($loop, $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 { $this->setCallbacks($onData, $onError); // Created before the fork so the parent can read what the child wrote. $tmpStdOut = tmpfile(); if ($tmpStdOut === \false) { throw new ShouldNotHappenException('Failed creating temp file for stdout.'); } $this->stdOut = $tmpStdOut; $pid = pcntl_fork(); if ($pid === -1) { fclose($this->stdOut); $this->stdOut = null; // Deferred so it runs after ParallelAnalyser has attached this // process to the pool — otherwise tryQuitProcess() would no-op. $this->loop->futureTick(static function () use ($onExit): void { $onExit(null, 'pcntl_fork() failed.'); }); return; } if ($pid === 0) { // Child: drop the inherited listening socket immediately, then run // the worker on its own fresh event loop and never return. $this->server->close(); $output = new StreamOutput($this->stdOut); $exitCode = $this->workerRunner->run($output, $this->analysedFiles, $this->serverPort, $this->identifier, $this->tmpFile, $this->insteadOfFile); exit($exitCode); } // Parent: poll for the child to exit and report it through $onExit. $this->waitTimer = $this->loop->addPeriodicTimer(self::WAITPID_POLL_INTERVAL, function () use ($pid, $onExit): void { $status = 0; $result = pcntl_waitpid($pid, $status, WNOHANG); if ($result === 0) { return; } $this->cancelWaitTimer(); $this->cancelTimer(); $exitCode = null; if ($result > 0 && pcntl_wifexited($status)) { $exitStatus = pcntl_wexitstatus($status); if ($exitStatus !== \false) { $exitCode = $exitStatus; } } $output = ''; if ($this->stdOut !== null) { rewind($this->stdOut); $output = (string) stream_get_contents($this->stdOut); fclose($this->stdOut); $this->stdOut = null; } $onExit($exitCode, $output); }); } public function quit(): void { // Ending the connection makes the child's event loop drain and the // child exit; the waitpid poll timer must keep running until then so // the child is actually reaped (otherwise: zombie + hang). $this->endConnection(); } private function cancelWaitTimer(): void { if ($this->waitTimer === null) { return; } $this->loop->cancelTimer($this->waitTimer); $this->waitTimer = null; } } internalErrorsCountLimit = $internalErrorsCountLimit; $this->decoderBufferSize = $decoderBufferSize; $this->forkParallelChecker = $forkParallelChecker; $this->workerRunner = $workerRunner; $this->processTimeout = max($processTimeout, self::DEFAULT_TIMEOUT); } /** * @param string[] $allAnalysedFiles * @param Closure(int, list=): void|null $postFileCallback * @param (callable(list, list, string[]): void)|null $onFileAnalysisHandler * @return PromiseInterface */ public function analyse(LoopInterface $loop, \PHPStan\Parallel\Schedule $schedule, array $allAnalysedFiles, 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 list $allProcessedFiles */ $allProcessedFiles = []; /** @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, &$allProcessedFiles): 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), // not 100% correct as the peak usages of workers might not have met $allProcessedFiles )); }); $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(); }; $useFork = $this->forkParallelChecker->isSupported(); 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 = $this->createProcess($useFork, $loop, $server, $serverPort, $processIdentifier, $allAnalysedFiles, $mainScript, $projectConfigFile, $commandOptions, $tmpFile, $insteadOfFile, $input); $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, &$allProcessedFiles): 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 $file => $jsonDataByCollector) { foreach ($jsonDataByCollector as $collectorType => $listOfCollectedData) { foreach ($listOfCollectedData as $rawCollectedData) { $collectedData[$file][$collectorType][] = $rawCollectedData; } } } /** * @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); } foreach ($json['processedFiles'] as $processedFile) { $allProcessedFiles[] = $processedFile; } if ($postFileCallback !== null) { $postFileCallback(count($json['files']), $json['processedFiles']); } 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(); } /** * @param string[] $allAnalysedFiles * @param string[] $commandOptions */ private function createProcess(bool $useFork, LoopInterface $loop, TcpServer $server, int $serverPort, string $processIdentifier, array $allAnalysedFiles, string $mainScript, ?string $projectConfigFile, array $commandOptions, ?string $tmpFile, ?string $insteadOfFile, InputInterface $input): \PHPStan\Parallel\Process { if ($useFork) { return new \PHPStan\Parallel\ForkedProcess($loop, $this->processTimeout, $this->workerRunner, $server, $serverPort, $processIdentifier, $allAnalysedFiles, $tmpFile, $insteadOfFile); } return new \PHPStan\Parallel\SpawnedProcess(ProcessHelper::getWorkerCommand($mainScript, 'worker', $projectConfigFile, $commandOptions, $input), $loop, $this->processTimeout); } } loop = $loop; $this->timeoutSeconds = $timeoutSeconds; } /** * @param callable(mixed[] $json) : void $onData * @param callable(Throwable $exception): void $onError */ protected function setCallbacks(callable $onData, callable $onError): void { $this->onData = $onData; $this->onError = $onError; } protected function cancelTimer(): void { if ($this->timer === null) { return; } $this->loop->cancelTimer($this->timer); $this->timer = null; } /** Cancels the timeout timer and ends the writable side of the connection. */ protected function endConnection(): void { $this->cancelTimer(); if ($this->in === null) { return; } $this->in->end(); } /** * @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 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); }); } } */ private array $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 array $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 cores: %d', $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; parent::__construct($loop, $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 Process($this->command, \null, \null, [1 => $this->stdOut, 2 => $this->stdErr]); $this->process->start($this->loop); $this->setCallbacks($onData, $onError); $this->process->on('exit', function ($exitCode) use ($onExit): void { $this->cancelTimer(); $output = ''; rewind($this->stdOut); $output .= stream_get_contents($this->stdOut); rewind($this->stdErr); $output .= stream_get_contents($this->stdErr); $onExit($exitCode, $output); fclose($this->stdOut); fclose($this->stdErr); }); } public function quit(): void { $this->cancelTimer(); if (!$this->process->isRunning()) { return; } foreach ($this->process->pipes as $pipe) { $pipe->close(); } $this->endConnection(); } } fileAnalyser = $fileAnalyser; $this->ruleRegistry = $ruleRegistry; $this->collectorRegistry = $collectorRegistry; $this->nodeScopeResolver = $nodeScopeResolver; $this->decoderBufferSize = $decoderBufferSize; } /** * @param string[] $analysedFiles the full analysed-files list (raw, before tmp-file substitution) * @return int exit code (0 on success, 1 if a worker-communication error occurred) */ public function run(OutputInterface $output, array $analysedFiles, int $port, string $identifier, ?string $tmpFile, ?string $insteadOfFile): int { $analysedFiles = $this->switchTmpFile($analysedFiles, $insteadOfFile, $tmpFile); $this->nodeScopeResolver->setAnalysedFiles($analysedFiles); $analysedFiles = array_fill_keys($analysedFiles, \true); // Always a fresh event loop: in a forked child the parent's inherited // loop must never be touched. $loop = new StreamSelectLoop(); $errorCount = 0; $tcpConnector = new TcpConnector($loop); $tcpConnector->connect(sprintf('127.0.0.1:%d', $port))->then(function (ConnectionInterface $connection) use ($identifier, $output, $analysedFiles, $tmpFile, $insteadOfFile, &$errorCount): 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, $this->decoderBufferSize); $out->write(['action' => 'hello', 'identifier' => $identifier]); $this->runWorker($out, $in, $output, $analysedFiles, $tmpFile, $insteadOfFile, $errorCount); }); $loop->run(); return $errorCount > 0 ? 1 : 0; } /** * @param array $analysedFiles */ private function runWorker(WritableStreamInterface $out, ReadableStreamInterface $in, OutputInterface $output, array $analysedFiles, ?string $tmpFile, ?string $insteadOfFile, int &$errorCount): void { $handleError = static function (Throwable $error) use ($out, $output, &$errorCount): void { $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 = $this->fileAnalyser; $ruleRegistry = $this->ruleRegistry; $collectorRegistry = $this->collectorRegistry; $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 = []; $processedFiles = []; 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(); $processedFiles = array_merge($processedFiles, $fileAnalyserResult->getProcessedFiles()); foreach ($fileErrors as $fileError) { $errors[] = $fileError; } foreach ($fileAnalyserResult->getLocallyIgnoredErrors() as $locallyIgnoredError) { $locallyIgnoredErrors[] = $locallyIgnoredError; } foreach ($fileAnalyserResult->getCollectedData() as $collectedFile => $dataPerCollector) { foreach ($dataPerCollector as $collectorType => $collectorData) { foreach ($collectorData as $data) { $collectedData[$collectedFile][$collectorType][] = $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, 'processedFiles' => $processedFiles, '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 fn(string $file): bool => $file !== $insteadOfFile)); if ($tmpFile !== null) { array_unshift($analysedFiles, $tmpFile); } return $analysedFiles; } } > */ private array $nodesPerLine = []; #[Override] public function beforeTraverse(array $nodes): ?array { $this->nodesPerLine = []; return null; } #[Override] 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; } #[Override] 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; } } name instanceof Node\Name && !$node->isFirstClassCallable()) { $functionName = $node->name->toLowerString(); if ($functionName === 'array_filter') { $args = $node->getArgs(); if (isset($args[0])) { $args[0]->setAttribute(self::ATTRIBUTE_NAME, \true); } } } return null; } } name instanceof Node\Name && !$node->isFirstClassCallable()) { $functionName = $node->name->toLowerString(); if (in_array($functionName, ['array_all', 'array_any', 'array_find', 'array_find_key'], \true)) { $args = $node->getArgs(); if (isset($args[0])) { $args[0]->setAttribute(self::ATTRIBUTE_NAME, \true); } } } return null; } } name instanceof Node\Name && !$node->isFirstClassCallable()) { $functionName = $node->name->toLowerString(); if ($functionName === 'array_map') { $args = $node->getArgs(); $arrayArgs = []; foreach ($args as $i => $arg) { if ($arg->name === null && $i === 0) { continue; } if ($arg->name !== null && $arg->name->toString() === 'callback') { continue; } $arrayArgs[] = $arg; } if (isset($args[0])) { $slicedArgs = array_slice($args, 1); if (count($slicedArgs) > 0) { $args[0]->value->setAttribute(self::ATTRIBUTE_NAME, $arrayArgs); } } } } return null; } } name instanceof Node\Name && !$node->isFirstClassCallable()) { $functionName = $node->name->toLowerString(); if ($functionName === 'array_walk') { $args = $node->getArgs(); 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; } } */ private array $cachedNodesByString = []; private int $cachedNodesByStringCount = 0; /** @var array */ private array $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; } } 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); } } nodeFinder = new NodeFinder(); } #[Override] public function enterNode(Node $node): ?Node { if ($node instanceof Node\Stmt\Function_) { $node->stmts = $this->keepVariadicsAndYields($node->stmts, null); return $node; } if ($node instanceof Node\Stmt\ClassMethod && $node->stmts !== null) { $node->stmts = $this->keepVariadicsAndYields($node->stmts, null); return $node; } if ($node instanceof Node\Expr\Closure) { $node->stmts = $this->keepVariadicsAndYields($node->stmts, null); return $node; } if ($node instanceof Node\PropertyHook && is_array($node->body)) { $propertyName = $node->getAttribute('propertyName'); if ($propertyName !== null) { $node->body = $this->keepVariadicsAndYields($node->body, $propertyName); return $node; } } return null; } /** * @param list $stmts * @return list */ private function keepVariadicsAndYields(array $stmts, ?string $hookedPropertyName): array { $results = $this->nodeFinder->find($stmts, static function (Node $node) use ($hookedPropertyName): 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; } if ($hookedPropertyName !== null) { if ($node instanceof Node\Expr\PropertyFetch && $node->var instanceof Node\Expr\Variable && $node->var->name === 'this' && $node->name instanceof Node\Identifier && $node->name->toString() === $hookedPropertyName) { 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 || $result instanceof Node\Expr\PropertyFetch) { $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; } } 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; } } 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; } } 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; } } name instanceof Node\Name && !$node->isFirstClassCallable()) { $functionName = $node->name->toLowerString(); if ($functionName === 'curl_setopt') { $args = $node->getArgs(); if (isset($args[0])) { $args[0]->setAttribute(self::ATTRIBUTE_NAME, \true); } } } return null; } } name instanceof Node\Name && !$node->isFirstClassCallable()) { $functionName = $node->name->toLowerString(); if ($functionName === 'curl_setopt_array') { $args = $node->getArgs(); if (isset($args[1])) { $args[1]->setAttribute(self::ATTRIBUTE_NAME, \true); } } } return null; } } isFirstStatement = \true; return null; } #[Override] 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\Expr\Closure || $node->name instanceof Node\Expr\ArrowFunction) && !$node->isFirstClassCallable()) { $node->name->setAttribute(self::ATTRIBUTE_NAME, \true); $node->name->setAttribute(self::ARGS_ATTRIBUTE_NAME, $node->args); } return null; } } name instanceof Node\Name && !$node->isFirstClassCallable()) { $functionName = $node->name->toLowerString(); if (in_array($functionName, ['implode', 'join'], \true)) { $args = $node->getArgs(); if (isset($args[0])) { $args[0]->setAttribute(self::ATTRIBUTE_NAME, \true); } } } return null; } } elseifs !== []) { $lastElseIf = count($node->elseifs) - 1; $elseIsMissingOrThrowing = $node->else === null || count($node->else->stmts) === 1 && $node->else->stmts[0] instanceof Node\Stmt\Expression && $node->else->stmts[0]->expr instanceof Node\Expr\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; } $lastStatement = $statements[$statementCount - 1]; if (!$lastStatement instanceof Node\Stmt\Expression) { return null; } if (!$lastStatement->expr instanceof Node\Expr\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 ? array_last($if->elseifs)->cond : $if->cond; $cond->setAttribute(self::ATTRIBUTE_NAME, \true); } return null; } } phpVersion = $phpVersion; } public function create(): Lexer { if ($this->phpVersion->getVersionId() === PHP_VERSION_ID) { return new Lexer(); } return new Lexer\Emulative(\PhpParser\PhpVersion::fromString($this->phpVersion->getVersionString())); } public function createEmulative(): Lexer\Emulative { return new Lexer\Emulative(); } } startLine = $startLine; $this->endLine = $endLine; } #[Override] public function enterNode(Node $node): Node { if ($node->getStartLine() === -1) { $node->setAttribute('startLine', $this->startLine); } if ($node->getEndLine() === -1) { $node->setAttribute('endLine', $this->endLine); } return $node; } } default instanceof Node\Scalar\MagicConst) { $node->default->setAttribute(self::ATTRIBUTE_NAME, \true); } 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; } } > */ private array $typeStack = []; #[Override] public function beforeTraverse(array $nodes): ?array { $this->typeStack = []; return null; } #[Override] 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; } #[Override] public function leaveNode(Node $node): ?Node { if (!$node instanceof Node\Stmt && !$node instanceof Node\Expr\Closure) { return null; } array_pop($this->typeStack); return null; } } errors = $errors; $this->parsedFile = $parsedFile; parent::__construct(implode(', ', array_map(static fn(Error $error): string => $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; } } filePath(string) => bool(true) */ private array $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); } } wrappedParser = $wrappedParser; } /** * @return Node\Stmt[] */ #[Override] 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()); } } #[Override] public function getTokens(): array { throw new ShouldNotHappenException('PhpParserDecorator::getTokens() should not be called'); } } lexer = $lexer; $this->phpVersion = $phpVersion; } public function create(): ParserAbstract { $phpVersion = \PhpParser\PhpVersion::fromString($this->phpVersion->getVersionString()); if ($this->phpVersion->getVersionId() >= 80000) { return new Php8($this->lexer, $phpVersion); } return new Php7($this->lexer, $phpVersion); } } right instanceof Node\Expr\FuncCall && $node->right->isFirstClassCallable()) { return new FuncCall($node->right->name, [new Arg($node->left)], array_merge($node->right->getAttributes(), [self::ORIGINAL_PIPE_ATTRIBUTE_NAME => $node->getAttributes(), self::ORIGINAL_VARIADIC_PLACEHOLDER_ATTRIBUTE_NAME => $node->right->getRawArgs()[0]->getAttributes()])); } if ($node->right instanceof MethodCall && $node->right->isFirstClassCallable()) { return new MethodCall($node->right->var, $node->right->name, [new Arg($node->left)], array_merge($node->right->getAttributes(), [self::ORIGINAL_PIPE_ATTRIBUTE_NAME => $node->getAttributes(), self::ORIGINAL_VARIADIC_PLACEHOLDER_ATTRIBUTE_NAME => $node->right->getRawArgs()[0]->getAttributes()])); } if ($node->right instanceof Node\Expr\StaticCall && $node->right->isFirstClassCallable()) { return new Node\Expr\StaticCall($node->right->class, $node->right->name, [new Arg($node->left)], array_merge($node->right->getAttributes(), [self::ORIGINAL_PIPE_ATTRIBUTE_NAME => $node->getAttributes(), self::ORIGINAL_VARIADIC_PLACEHOLDER_ATTRIBUTE_NAME => $node->right->getRawArgs()[0]->getAttributes()])); } return new FuncCall($node->right, [new Arg($node->left)], [self::ORIGINAL_PIPE_ATTRIBUTE_NAME => $node->getAttributes()]); } } phpVersionString = $phpVersionString; } #[Override] 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\Int_ && $right instanceof Node\Expr\ConstFetch && $right->name->toString() === 'PHP_VERSION_ID') { return [(new PhpVersion($left->value))->getVersionString(), $this->phpVersionString]; } if ($right instanceof Node\Scalar\Int_ && $left instanceof Node\Expr\ConstFetch && $left->name->toString() === 'PHP_VERSION_ID') { return [$this->phpVersionString, (new PhpVersion($right->value))->getVersionString()]; } return null; } } isFirstClassCallable()) { $attributes = $node->getAttributes(); $origPipeAttributes = $attributes[\PHPStan\Parser\PipeTransformerVisitor::ORIGINAL_PIPE_ATTRIBUTE_NAME] ?? []; $origVariadicPlaceholderAttributes = $attributes[\PHPStan\Parser\PipeTransformerVisitor::ORIGINAL_VARIADIC_PLACEHOLDER_ATTRIBUTE_NAME] ?? []; if ($origPipeAttributes !== [] && count($node->getArgs()) === 1) { $origPipeAttributes[self::ARG_ATTRIBUTES_NAME] = $node->getArgs()[0]->getAttributes(); if ($node->name instanceof Node\Name) { unset($attributes[\PHPStan\Parser\PipeTransformerVisitor::ORIGINAL_PIPE_ATTRIBUTE_NAME]); unset($attributes[\PHPStan\Parser\PipeTransformerVisitor::ORIGINAL_VARIADIC_PLACEHOLDER_ATTRIBUTE_NAME]); return new Node\Expr\BinaryOp\Pipe($node->getArgs()[0]->value, new Node\Expr\FuncCall($node->name, [new Node\VariadicPlaceholder($origVariadicPlaceholderAttributes)], $attributes), $origPipeAttributes); } return new Node\Expr\BinaryOp\Pipe($node->getArgs()[0]->value, $node->name, $origPipeAttributes); } } if ($node instanceof Node\Expr\MethodCall && !$node->isFirstClassCallable()) { $attributes = $node->getAttributes(); $origPipeAttributes = $attributes[\PHPStan\Parser\PipeTransformerVisitor::ORIGINAL_PIPE_ATTRIBUTE_NAME] ?? []; $origVariadicPlaceholderAttributes = $attributes[\PHPStan\Parser\PipeTransformerVisitor::ORIGINAL_VARIADIC_PLACEHOLDER_ATTRIBUTE_NAME] ?? []; if ($origPipeAttributes !== [] && count($node->getArgs()) === 1) { $origPipeAttributes[self::ARG_ATTRIBUTES_NAME] = $node->getArgs()[0]->getAttributes(); unset($attributes[\PHPStan\Parser\PipeTransformerVisitor::ORIGINAL_PIPE_ATTRIBUTE_NAME]); unset($attributes[\PHPStan\Parser\PipeTransformerVisitor::ORIGINAL_VARIADIC_PLACEHOLDER_ATTRIBUTE_NAME]); return new Node\Expr\BinaryOp\Pipe($node->getArgs()[0]->value, new Node\Expr\MethodCall($node->var, $node->name, [new Node\VariadicPlaceholder($origVariadicPlaceholderAttributes)], $attributes), $origPipeAttributes); } } if ($node instanceof Node\Expr\StaticCall && !$node->isFirstClassCallable()) { $attributes = $node->getAttributes(); $origPipeAttributes = $attributes[\PHPStan\Parser\PipeTransformerVisitor::ORIGINAL_PIPE_ATTRIBUTE_NAME] ?? []; $origVariadicPlaceholderAttributes = $attributes[\PHPStan\Parser\PipeTransformerVisitor::ORIGINAL_VARIADIC_PLACEHOLDER_ATTRIBUTE_NAME] ?? []; if ($origPipeAttributes !== [] && count($node->getArgs()) === 1) { $origPipeAttributes[self::ARG_ATTRIBUTES_NAME] = $node->getArgs()[0]->getAttributes(); unset($attributes[\PHPStan\Parser\PipeTransformerVisitor::ORIGINAL_PIPE_ATTRIBUTE_NAME]); unset($attributes[\PHPStan\Parser\PipeTransformerVisitor::ORIGINAL_VARIADIC_PLACEHOLDER_ATTRIBUTE_NAME]); return new Node\Expr\BinaryOp\Pipe($node->getArgs()[0]->value, new Node\Expr\StaticCall($node->class, $node->name, [new Node\VariadicPlaceholder($origVariadicPlaceholderAttributes)], $attributes), $origPipeAttributes); } } return null; } } parser = $parser; $this->nameResolver = $nameResolver; $this->container = $container; $this->ignoreLexer = $ignoreLexer; } /** * @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); $tokens = $this->parser->getTokens(); if ($errorHandler->hasErrors()) { throw new \PHPStan\Parser\ParserErrorsException($errorHandler->getErrors(), null); } if ($nodes === null) { throw new ShouldNotHappenException(); } $pipeTransformer = new NodeTraverser(new \PHPStan\Parser\PipeTransformerVisitor()); /** @var array */ $nodes = $pipeTransformer->traverse($nodes); $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); $reversePipeTransformer = new NodeTraverser(new \PHPStan\Parser\ReversePipeTransformerVisitor()); /** @var array */ $nodes = $reversePipeTransformer->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 fn(int $line): bool => $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 Token[] $tokens * @return array{lines: array|null>, errors: array>} */ private function getLinesToIgnore(array $tokens): array { $lines = []; $previousToken = null; $pendingToken = null; $errors = []; foreach ($tokens as $token) { $type = $token->id; $line = $token->line; 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->text; $isNextLine = str_contains($text, '@phpstan-ignore-next-line'); $isCurrentLine = str_contains($text, '@phpstan-ignore-line'); if ($type === T_DOC_COMMENT) { $lines += $this->getLinesToIgnoreForTokenByIgnoreComment($text, $line, '@phpstan-ignore-line', \false); 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->text, "\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->line === $line) { try { foreach ($this->parseIdentifiers($text, $ignorePos) as $identifier) { $lines[$line][] = $identifier; } } catch (IgnoreParseException $e) { $errors[] = [$token->line + $e->getPhpDocLine() + $ignoreLine, $e->getMessage()]; } continue; } $line += substr_count($token->text, "\n"); $pendingToken = [$text, $ignorePos, $token->line + $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): 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')); $tokens = $this->ignoreLexer->tokenize($text); $c = count($tokens); $identifiers = []; $comment = null; $openParenthesisCount = 0; $expected = [IgnoreLexer::TOKEN_IDENTIFIER]; $lastTokenTypeLabel = '@phpstan-ignore'; for ($i = 0; $i < $c; $i++) { if (isset($tokenType) && $tokenType !== IgnoreLexer::TOKEN_WHITESPACE) { $lastTokenTypeLabel = $this->ignoreLexer->getLabel($tokenType); } [IgnoreLexer::VALUE_OFFSET => $content, IgnoreLexer::TYPE_OFFSET => $tokenType, IgnoreLexer::LINE_OFFSET => $tokenLine] = $tokens[$i]; if ($expected !== null && !in_array($tokenType, [...$expected, IgnoreLexer::TOKEN_WHITESPACE], \true)) { $tokenTypeLabel = $this->ignoreLexer->getLabel($tokenType); $otherTokenContent = $tokenType === IgnoreLexer::TOKEN_OTHER ? sprintf(" '%s'", $content) : ''; $expectedLabels = implode(' or ', array_map(fn($token) => $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) { if ($openParenthesisCount > 0) { $comment .= $content; } $openParenthesisCount++; $expected = null; continue; } if ($tokenType === IgnoreLexer::TOKEN_CLOSE_PARENTHESIS) { $openParenthesisCount--; if ($openParenthesisCount === 0) { $key = array_key_last($identifiers); if ($key !== null) { $identifiers[$key]['comment'] = $comment; $comment = null; } $expected = [IgnoreLexer::TOKEN_COMMA, IgnoreLexer::TOKEN_END]; } else { $comment .= $content; } continue; } if ($openParenthesisCount > 0) { $comment .= $content; continue; // waiting for comment end } if ($tokenType === IgnoreLexer::TOKEN_IDENTIFIER) { $identifiers[] = ['name' => $content, 'comment' => null]; $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; } } 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); } } expr instanceof Node\Expr\Throw_) { return null; } $node->expr->setAttribute(self::ATTRIBUTE_NAME, \true); return $node; } } 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); } } */ public array $traits = []; #[Override] public function enterNode(Node $node): ?Node { if (!$node instanceof Node\Stmt\Trait_) { return null; } $this->traits[] = $node; return null; } } |null> */ private array $typeStack = []; #[Override] public function beforeTraverse(array $nodes): ?array { $this->typeStack = []; return null; } #[Override] 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, array_last($this->typeStack)); } } 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; } #[Override] public function leaveNode(Node $node): ?Node { if (!$node instanceof Node\Stmt\TryCatch && !$node instanceof Node\FunctionLike) { return null; } array_pop($this->typeStack); return null; } } depth = 0; return null; } #[Override] 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; } #[Override] 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; } } alias name (original case) keyed by lowercase alias name */ private array $explicitAliases = []; #[Override] public function enterNode(Node $node): ?Node { if ($node instanceof Node\Stmt\Namespace_) { $this->explicitAliases = []; } if ($node instanceof Use_ && $node->type === Use_::TYPE_NORMAL) { foreach ($node->uses as $use) { if ($use->alias === null) { continue; } $this->explicitAliases[strtolower($use->alias->name)] = $use->alias->name; } } if ($node instanceof GroupUse) { foreach ($node->uses as $use) { if ($use->type !== Use_::TYPE_NORMAL && $node->type !== Use_::TYPE_NORMAL) { continue; } if ($use->alias === null) { continue; } $this->explicitAliases[strtolower($use->alias->name)] = $use->alias->name; } } if ($node instanceof Name) { $originalName = $node->getAttribute('originalName'); if ($originalName instanceof Name) { $originalParts = $originalName->getParts(); if (count($originalParts) === 1) { $lowerOriginal = strtolower($originalParts[0]); if (isset($this->explicitAliases[$lowerOriginal]) && $this->explicitAliases[$lowerOriginal] === $originalParts[0]) { $node->setAttribute(self::ATTRIBUTE_NAME, \true); } } } } return null; } } composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; } private function initializeVersions(): void { $this->initialized = \true; // don't limit minVersion... PHPStan can analyze even PHP5 $this->maxVersion = new \PHPStan\Php\PhpVersion(\PHPStan\Php\PhpVersionFactory::MAX_PHP_VERSION); // fallback to composer.json based php-version constraint $composerPhpVersion = $this->getComposerRequireVersion(); if ($composerPhpVersion === null) { return; } $parser = new \PHPStan\Php\ComposerPhpVersionParser(); [$minVersion, $maxVersion] = $parser->parse($composerPhpVersion, static function (string $version, int $versionId, bool $isMaxVersion): \PHPStan\Php\PhpVersion { if ($isMaxVersion && $version === '6.0.0.0-dev') { $versionId = min($versionId, \PHPStan\Php\PhpVersionFactory::MAX_PHP5_VERSION); } elseif ($isMaxVersion && $version === '8.0.0.0-dev') { $versionId = min($versionId, \PHPStan\Php\PhpVersionFactory::MAX_PHP7_VERSION); } else { $versionId = min($versionId, \PHPStan\Php\PhpVersionFactory::MAX_PHP_VERSION); } return new \PHPStan\Php\PhpVersion($versionId); }); if ($minVersion !== null) { $this->minVersion = new \PHPStan\Php\PhpVersion($minVersion->getVersionId()); } if ($maxVersion === null) { return; } $this->maxVersion = $maxVersion; } public function getMinVersion(): ?\PHPStan\Php\PhpVersion { if ($this->initialized === \false) { $this->initializeVersions(); } return $this->minVersion; } public function getMaxVersion(): ?\PHPStan\Php\PhpVersion { if ($this->initialized === \false) { $this->initializeVersions(); } return $this->maxVersion; } private function getComposerRequireVersion(): ?string { $composerPhpVersion = null; if (count($this->composerAutoloaderProjectPaths) > 0) { $composer = ComposerHelper::getComposerConfig(end($this->composerAutoloaderProjectPaths)); if ($composer !== null) { $requiredVersion = $composer['require']['php'] ?? null; if (is_string($requiredVersion)) { $composerPhpVersion = $requiredVersion; } } } return $composerPhpVersion; } } parseConstraints($version); if (!$constraint->getLowerBound()->isZero()) { $minVersion = $this->buildVersion($constraint->getLowerBound()->getVersion(), \false, $buildPhpVersion); } if ($constraint->getUpperBound()->isPositiveInfinity()) { return [$minVersion, null]; } $maxVersion = $this->buildVersion($constraint->getUpperBound()->getVersion(), \true, $buildPhpVersion); return [$minVersion, $maxVersion]; } /** * @param callable(string, int, bool):PhpVersion $buildPhpVersion */ private function buildVersion(string $version, bool $isMaxVersion, callable $buildPhpVersion): ?\PHPStan\Php\PhpVersion { $matches = Strings::match($version, '#^(\d+)\.(\d+)(?:\.(\d+))?#'); if ($matches === null) { return null; } $major = $matches[1]; $minor = $matches[2]; $patch = $matches[3] ?? 0; $versionId = (int) sprintf('%d%02d%02d', $major, $minor, $patch); return $buildPhpVersion($version, $versionId, $isMaxVersion); } } versionId = $versionId; $this->source = $source; } /** * @return self::SOURCE_* */ public function getSource(): int { return $this->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 getMajorVersionId(): int { return (int) floor($this->versionId / 10000); } public function getMinorVersionId(): int { return (int) floor($this->versionId % 10000 / 100); } public function getPatchVersionId(): int { return (int) floor($this->versionId % 100); } public function getVersionString(): string { $first = $this->getMajorVersionId(); $second = $this->getMinorVersionId(); $third = $this->getPatchVersionId(); 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 nonNumericStringAndIntegerIsFalseOnLooseComparison(): 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 supportsPropertyHooks(): bool { return $this->versionId >= 80400; } public function supportsFinalProperties(): bool { return $this->versionId >= 80400; } public function supportsAsymmetricVisibility(): bool { return $this->versionId >= 80400; } public function supportsAsymmetricVisibilityForStaticProperties(): bool { return $this->versionId >= 80500; } public function supportsLazyObjects(): bool { return $this->versionId >= 80400; } 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; } /** * whether curl handles are represented as 'resource' or CurlShareHandle */ public function supportsCurlShareHandle(): bool { return $this->versionId >= 80000; } public function supportsCurlSharePersistentHandle(): bool { return $this->versionId >= 80500; } public function highlightStringDoesNotReturnFalse(): bool { return $this->versionId >= 80400; } public function deprecatesImplicitlyNullableParameterTypes(): bool { return $this->versionId >= 80400; } public function substrReturnFalseInsteadOfEmptyString(): bool { return $this->versionId < 80000; } public function supportsBcMathNumberOperatorOverloading(): bool { return $this->versionId >= 80400; } public function hasPDOSubclasses(): bool { return $this->versionId >= 80400; } public function deprecatesImplicitlyFloatConversionToInt(): bool { return $this->versionId >= 80100; } public function deprecatesNullArrayOffset(): bool { return $this->versionId >= 80500; } public function supportsFinalPromotedProperties(): bool { return $this->versionId >= 80500; } public function supportsVoidCast(): bool { return $this->versionId >= 80500; } public function supportsNoDiscardAttribute(): bool { return $this->versionId >= 80500; } public function deprecatesNonStandardCasts(): bool { return $this->versionId >= 80500; } public function deprecatesBacktickOperator(): bool { return $this->versionId >= 80500; } public function supportsAttributesOnGlobalConstants(): bool { return $this->versionId >= 80500; } public function supportsDeprecatedTraits(): bool { return $this->versionId >= 80500; } public function supportsOverrideAttributeOnProperty(): bool { return $this->versionId >= 80500; } public function deprecatesDecOnNonNumericString(): bool { return $this->versionId >= 80300; } public function deprecatesIncOnNonNumericString(): bool { return $this->versionId >= 80500; } public function supportsObjectsInArraySumProduct(): bool { return $this->versionId >= 80300; } public function hasFilterThrowOnFailureConstant(): bool { return $this->versionId >= 80500; } public function throwsOnStringCast(): bool { return $this->versionId >= 70400; } } 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, self::MIN_PHP_VERSION); $versionId = min($tmp, self::MAX_PHP_VERSION); $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); } } phpVersion = $phpVersion; $this->composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; } public function create(): \PHPStan\Php\PhpVersionFactory { $composerPhpVersion = null; if (count($this->composerAutoloaderProjectPaths) > 0) { $composerJsonPath = end($this->composerAutoloaderProjectPaths); $composer = ComposerHelper::getComposerConfig($composerJsonPath); if ($composer !== null) { $platformVersion = $composer['config']['platform']['php'] ?? null; if (is_string($platformVersion)) { $composerPhpVersion = $platformVersion; } } } $versionId = null; if (is_int($this->phpVersion)) { $versionId = $this->phpVersion; } if (is_array($this->phpVersion)) { $versionId = $this->phpVersion['min']; } return new \PHPStan\Php\PhpVersionFactory($versionId, $composerPhpVersion); } } phpVersions = $phpVersions; } public function getType(): Type { return $this->phpVersions; } public function supportsNoncapturingCatches(): TrinaryLogic { return IntegerRangeType::fromInterval(80000, null)->isSuperTypeOf($this->phpVersions)->result; } public function producesWarningForFinalPrivateMethods(): TrinaryLogic { return IntegerRangeType::fromInterval(80000, null)->isSuperTypeOf($this->phpVersions)->result; } public function supportsNamedArguments(): TrinaryLogic { return IntegerRangeType::fromInterval(80000, null)->isSuperTypeOf($this->phpVersions)->result; } public function supportsNamedArgumentAfterUnpackedArgument(): TrinaryLogic { return IntegerRangeType::fromInterval(80100, null)->isSuperTypeOf($this->phpVersions)->result; } public function supportsTrueAndFalseStandaloneType(): TrinaryLogic { return IntegerRangeType::fromInterval(80200, null)->isSuperTypeOf($this->phpVersions)->result; } public function supportsMaxMemoryLimit(): TrinaryLogic { return IntegerRangeType::fromInterval(80500, null)->isSuperTypeOf($this->phpVersions)->result; } } phpVersion = $phpVersion; } public function getFiles(): array { if (!$this->phpVersion->supportsBcMathNumberOperatorOverloading()) { return []; } return [__DIR__ . '/../../stubs/bcmath.stub']; } } 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(); } } container = $container; $this->fileHelper = $fileHelper; $this->stubFiles = $stubFiles; $this->composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; } public function getStubFiles(): array { if ($this->cachedFiles !== null) { return $this->cachedFiles; } $files = array_map(fn($path) => $this->fileHelper->normalizePath($path), $this->stubFiles); $extensions = $this->container->getServicesByTag(\PHPStan\PhpDoc\StubFilesExtension::EXTENSION_TAG); foreach ($extensions as $extension) { foreach ($extension->getFiles() as $extensionFile) { $files[] = $this->fileHelper->normalizePath($extensionFile); } } return $this->cachedFiles = $files; } public function getProjectStubFiles(): array { if ($this->cachedProjectFiles !== null) { return $this->cachedProjectFiles; } $phpstanStubsDirectory = $this->fileHelper->normalizePath(dirname(dirname(__DIR__)) . '/stubs'); $filteredStubFiles = $this->getStubFiles(); $filteredStubFiles = array_filter($filteredStubFiles, static fn(string $file): bool => !str_starts_with($file, $phpstanStubsDirectory)); foreach ($this->composerAutoloaderProjectPaths as $composerAutoloaderProjectPath) { $composerConfig = ComposerHelper::getComposerConfig($composerAutoloaderProjectPath); if ($composerConfig === null) { continue; } $vendorDir = ComposerHelper::getVendorDirFromComposerConfig($composerAutoloaderProjectPath, $composerConfig); $vendorDir = $this->fileHelper->normalizePath($vendorDir); $filteredStubFiles = array_filter($filteredStubFiles, static fn(string $file): bool => !str_contains($file, $vendorDir)); } return $this->cachedProjectFiles = array_values($filteredStubFiles); } } registry = $registry; } public function getRegistry(): \PHPStan\PhpDoc\TypeNodeResolverExtensionRegistry { return $this->registry; } } */ private array $parameterNameMapping; /** * @param array $parameterNameMapping */ public function __construct(array $parameterNameMapping) { $this->parameterNameMapping = $parameterNameMapping; } /** * @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 { $nameMapping = $this->parameterNameMapping; return TypeTraverser::map($type, static function (Type $type, callable $traverse) use ($nameMapping): Type { if ($type instanceof ConditionalTypeForParameter) { $parameterName = substr($type->getParameterName(), 1); if (array_key_exists($parameterName, $nameMapping)) { $type = $type->changeParameterName('$' . $nameMapping[$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; } } phpVersion = $phpVersion; } public function getFiles(): array { if (!$this->phpVersion->supportsJsonValidate()) { return []; } return [__DIR__ . '/../../stubs/json_validate.stub']; } } container = $container; } public function getRegistry(): \PHPStan\PhpDoc\TypeNodeResolverExtensionRegistry { return $this->registry ??= new \PHPStan\PhpDoc\TypeNodeResolverExtensionAwareRegistry($this->container->getByType(\PHPStan\PhpDoc\TypeNodeResolver::class), $this->container->getServicesByTag(\PHPStan\PhpDoc\TypeNodeResolverExtension::EXTENSION_TAG)); } } fileTypeMapper = $fileTypeMapper; } public function resolvePhpDocForProperty(ClassReflection $declaringClass, string $propertyName, ?\PHPStan\PhpDoc\ResolvedPhpDocBlock $currentResolvedPhpDoc): ?\PHPStan\PhpDoc\ResolvedPhpDocBlock { $parent = $declaringClass->getParentClass(); if ($parent !== null) { $parentMethod = $this->resolvePropertyPhpDocFromParentClass($declaringClass, $parent, $propertyName, $currentResolvedPhpDoc); if ($parentMethod !== null) { return $parentMethod; } } foreach ($declaringClass->getImmediateInterfaces() as $interface) { $interfaceMethod = $this->resolvePropertyPhpDocFromParentClass($declaringClass, $interface, $propertyName, $currentResolvedPhpDoc); if ($interfaceMethod === null) { continue; } return $interfaceMethod; } return $currentResolvedPhpDoc; } public function resolvePhpDocForConstant(ClassReflection $declaringClass, string $constantName, ?\PHPStan\PhpDoc\ResolvedPhpDocBlock $currentResolvedPhpDoc): ?\PHPStan\PhpDoc\ResolvedPhpDocBlock { $parent = $declaringClass->getParentClass(); if ($parent !== null) { $parentMethod = $this->resolveConstantPhpDocFromParentClass($declaringClass, $parent, $constantName, $currentResolvedPhpDoc); if ($parentMethod !== null) { return $parentMethod; } } foreach ($declaringClass->getImmediateInterfaces() as $interface) { $interfaceMethod = $this->resolveConstantPhpDocFromParentClass($declaringClass, $interface, $constantName, $currentResolvedPhpDoc); if ($interfaceMethod === null) { continue; } return $interfaceMethod; } return $currentResolvedPhpDoc; } /** * @param array $currentPositionalParameterNames */ public function resolvePhpDocForMethod(ClassReflection $declaringClass, string $methodName, ?\PHPStan\PhpDoc\ResolvedPhpDocBlock $currentResolvedPhpDoc, array $currentPositionalParameterNames): ?\PHPStan\PhpDoc\ResolvedPhpDocBlock { $parent = $declaringClass->getParentClass(); if ($parent !== null) { if ($parent->hasNativeMethod($methodName)) { $parentMethod = $parent->getNativeMethod($methodName); if (!$parentMethod->isPrivate() && $parentMethod->getResolvedPhpDoc() !== null) { if ($parentMethod->getName() !== '__construct' || !$parentMethod->getDeclaringClass()->isBuiltin()) { return $this->resolveMethodPhpDocFromParentClass($parentMethod, $parentMethod->getResolvedPhpDoc(), $declaringClass, $parent, $currentResolvedPhpDoc, $currentPositionalParameterNames); } } } } foreach ($declaringClass->getImmediateInterfaces() as $interface) { if (!$interface->hasNativeMethod($methodName)) { continue; } $interfaceMethod = $interface->getNativeMethod($methodName); if ($interfaceMethod->isPrivate()) { continue; } if ($interfaceMethod->getResolvedPhpDoc() === null) { continue; } return $this->resolveMethodPhpDocFromParentClass($interfaceMethod, $interfaceMethod->getResolvedPhpDoc(), $declaringClass, $interface, $currentResolvedPhpDoc, $currentPositionalParameterNames); } foreach ($declaringClass->getTraits() as $trait) { if (!$trait->hasNativeMethod($methodName)) { continue; } $traitMethod = $trait->getNativeMethod($methodName); if ($traitMethod->getDocComment() === null) { continue; } if ($declaringClass->getFileName() === null) { continue; } $abstract = $traitMethod->isAbstract(); if (is_bool($abstract)) { if (!$abstract) { continue; } } elseif (!$abstract->yes()) { continue; } $resolvedPhpDocBlock = $this->fileTypeMapper->getResolvedPhpDoc($declaringClass->getFileName(), $declaringClass->getName(), $trait->getName(), $methodName, $traitMethod->getDocComment()); return $this->resolveMethodPhpDocFromParentClass($traitMethod, $resolvedPhpDocBlock, $declaringClass, $trait, $currentResolvedPhpDoc, $currentPositionalParameterNames); } return $currentResolvedPhpDoc; } /** * @param array $currentPositionalParameterNames */ private function resolveMethodPhpDocFromParentClass(ExtendedMethodReflection $parentMethod, \PHPStan\PhpDoc\ResolvedPhpDocBlock $resolvedPhpDocBlock, ClassReflection $declaringClass, ClassReflection $parent, ?\PHPStan\PhpDoc\ResolvedPhpDocBlock $currentResolvedPhpDoc, array $currentPositionalParameterNames): \PHPStan\PhpDoc\ResolvedPhpDocBlock { if ($currentResolvedPhpDoc === null) { $currentResolvedPhpDoc = \PHPStan\PhpDoc\ResolvedPhpDocBlock::createEmpty(); } $methodVariants = $parentMethod->getVariants(); $positionalMethodParameterNames = []; $lowercaseMethodName = strtolower($parentMethod->getName()); if (count($methodVariants) === 1 && $lowercaseMethodName !== '__construct' && $lowercaseMethodName !== strtolower($parentMethod->getDeclaringClass()->getName())) { $methodParameters = $methodVariants[0]->getParameters(); foreach ($methodParameters as $methodParameter) { $positionalMethodParameterNames[] = $methodParameter->getName(); } } else { $positionalMethodParameterNames = $currentPositionalParameterNames; } $parentClassForMerge = $parent; $phpDocDeclaringClass = $parentMethod->getDeclaringClass(); if ($phpDocDeclaringClass->getName() !== $parent->getName()) { $ancestor = $parent->getAncestorWithClassName($phpDocDeclaringClass->getName()); if ($ancestor !== null) { $parentClassForMerge = $ancestor; } } return $currentResolvedPhpDoc->merge($resolvedPhpDocBlock, new \PHPStan\PhpDoc\InheritedPhpDocParameterMapping(self::remapParameterNames($currentPositionalParameterNames, $positionalMethodParameterNames)), $declaringClass, $parentClassForMerge); } /** * @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; } private function resolveConstantPhpDocFromParentClass(ClassReflection $declaringClass, ClassReflection $parent, string $constantName, ?\PHPStan\PhpDoc\ResolvedPhpDocBlock $currentResolvedPhpDoc): ?\PHPStan\PhpDoc\ResolvedPhpDocBlock { if (!$parent->hasConstant($constantName)) { return null; } $parentConstant = $parent->getConstant($constantName); if ($parentConstant->isPrivate()) { return null; } if ($parentConstant->getResolvedPhpDoc() === null) { return null; } if ($currentResolvedPhpDoc === null) { $currentResolvedPhpDoc = \PHPStan\PhpDoc\ResolvedPhpDocBlock::createEmpty(); } $parentClassForMerge = $parent; $phpDocDeclaringClass = $parentConstant->getDeclaringClass(); if ($phpDocDeclaringClass->getName() !== $parent->getName()) { $ancestor = $parent->getAncestorWithClassName($phpDocDeclaringClass->getName()); if ($ancestor !== null) { $parentClassForMerge = $ancestor; } } return $currentResolvedPhpDoc->merge($parentConstant->getResolvedPhpDoc(), new \PHPStan\PhpDoc\InheritedPhpDocParameterMapping([]), $declaringClass, $parentClassForMerge); } private function resolvePropertyPhpDocFromParentClass(ClassReflection $declaringClass, ClassReflection $parent, string $propertyName, ?\PHPStan\PhpDoc\ResolvedPhpDocBlock $currentResolvedPhpDoc): ?\PHPStan\PhpDoc\ResolvedPhpDocBlock { if (!$parent->hasNativeProperty($propertyName)) { return null; } $parentProperty = $parent->getNativeProperty($propertyName); if ($parentProperty->isPrivate()) { return null; } if ($parentProperty->getResolvedPhpDoc() === null) { return null; } if ($currentResolvedPhpDoc === null) { $currentResolvedPhpDoc = \PHPStan\PhpDoc\ResolvedPhpDocBlock::createEmpty(); } $parentClassForMerge = $parent; $phpDocDeclaringClass = $parentProperty->getDeclaringClass(); if ($phpDocDeclaringClass->getName() !== $parent->getName()) { $ancestor = $parent->getAncestorWithClassName($phpDocDeclaringClass->getName()); if ($ancestor !== null) { $parentClassForMerge = $ancestor; } } return $currentResolvedPhpDoc->merge($parentProperty->getResolvedPhpDoc(), new \PHPStan\PhpDoc\InheritedPhpDocParameterMapping([]), $declaringClass, $parentClassForMerge); } } 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); } } 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, $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); } } 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 fn(TemplateTag $tag): Type => TemplateTypeFactory::fromTemplateTag($templateTypeScope, $tag), $templateTags)); $nameScope = $nameScope->withTemplateTypeMap($templateTypeMap, $templateTags); } $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; } /** * @param array $templatePhpDocNodes * @return array */ public function resolveTemplateTags(array $templatePhpDocNodes, NameScope $nameScope): array { $resolved = []; foreach ($templatePhpDocNodes as $name => [$tagName, $valueNode]) { 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; } $nameScopeWithoutCurrent = $nameScope->unsetTemplateType($valueNode->name); $resolved[$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); } 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(fn(MixinTagValueNode $mixinTagValueNode): MixinTag => 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 resolveSealedTags(PhpDocNode $phpDocNode, NameScope $nameScope): array { $resolved = []; foreach (['@psalm-inheritors', '@phpstan-sealed'] as $tagName) { foreach ($phpDocNode->getSealedTagValues($tagName) as $tagValue) { $resolved[] = new SealedTypeTag($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, \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, \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, \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 resolveAllMethodsPure(PhpDocNode $phpDocNode): bool { return count($phpDocNode->getTagsByName('@phpstan-all-methods-pure')) > 0; } public function resolveAllMethodsImpure(PhpDocNode $phpDocNode): bool { return count($phpDocNode->getTagsByName('@phpstan-all-methods-impure')) > 0; } 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; } } 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; } } phpVersion = $phpVersion; } public function getFiles(): array { if (!$this->phpVersion->supportsLazyObjects()) { return [__DIR__ . '/../../stubs/ReflectionClass.stub']; } return [__DIR__ . '/../../stubs/ReflectionClassWithLazyObjects.stub']; } } phpVersion = $phpVersion; } public function getFiles(): array { if (!$this->phpVersion->supportsEnums()) { return []; } if (!$this->phpVersion->supportsLazyObjects()) { return [__DIR__ . '/../../stubs/ReflectionEnum.stub']; } return [__DIR__ . '/../../stubs/ReflectionEnumWithLazyObjects.stub']; } } */ private array $templateTags; private \PHPStan\PhpDoc\PhpDocNodeResolver $phpDocNodeResolver; private ReflectionProvider $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 \PHPStan\PhpDoc\Tag\ReturnTag|false|null */ private $returnTag = \false; /** * @var \PHPStan\PhpDoc\Tag\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 $sealedTypeTags = \false; /** @var array|false */ private $typeAliasTags = \false; /** @var array|false */ private $typeAliasImportTags = \false; /** @var array|false */ private $assertTags = \false; /** * @var \PHPStan\PhpDoc\Tag\SelfOutTypeTag|false|null */ private $selfOutTypeTag = \false; /** * @var \PHPStan\PhpDoc\Tag\DeprecatedTag|false|null */ private $deprecatedTag = \false; private ?bool $isDeprecated = null; private ?bool $isNotDeprecated = null; private ?bool $isInternal = null; private ?bool $isFinal = null; /** @var bool|'notLoaded'|null */ private $isPure = 'notLoaded'; private ?bool $areAllMethodsPure = null; private ?bool $areAllMethodsImpure = null; private ?bool $isReadOnly = null; private ?bool $isImmutable = null; private ?bool $isAllowedPrivateMutation = null; private ?bool $hasConsistentConstructor = null; private ?bool $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->sealedTypeTags = []; $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->areAllMethodsPure = \false; $self->areAllMethodsImpure = \false; $self->isReadOnly = \false; $self->isImmutable = \false; $self->isAllowedPrivateMutation = \false; $self->hasConsistentConstructor = \false; $self->acceptsNamedArguments = \true; return $self; } public function merge(\PHPStan\PhpDoc\ResolvedPhpDocBlock $parent, \PHPStan\PhpDoc\InheritedPhpDocParameterMapping $parameterMapping, ClassReflection $declaringClass, ClassReflection $parentClass): self { // 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 ($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(), $parent, $parentClass); $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(), $parent, $parameterMapping, $parentClass); $result->paramOutTags = self::mergeParamOutTags($this->getParamOutTags(), $parent, $parameterMapping, $parentClass); $result->paramsImmediatelyInvokedCallable = self::mergeParamsImmediatelyInvokedCallable($this->getParamsImmediatelyInvokedCallable(), $parent, $parameterMapping); $result->paramClosureThisTags = self::mergeParamClosureThisTags($this->getParamClosureThisTags(), $parent, $parameterMapping, $parentClass); $result->returnTag = self::mergeReturnTags($this->getReturnTag(), $declaringClass, $parent, $parameterMapping, $parentClass); $result->throwsTag = self::mergeThrowsTags($this->getThrowsTag(), $parent); $result->mixinTags = $this->getMixinTags(); $result->requireExtendsTags = $this->getRequireExtendsTags(); $result->requireImplementsTags = $this->getRequireImplementsTags(); $result->sealedTypeTags = $this->getSealedTags(); $result->typeAliasTags = $this->getTypeAliasTags(); $result->typeAliasImportTags = $this->getTypeAliasImportTags(); $result->assertTags = self::mergeAssertTags($this->getAssertTags(), $parent, $parameterMapping, $parentClass); $result->selfOutTypeTag = self::mergeSelfOutTypeTags($this->getSelfOutTag(), $parent); $result->deprecatedTag = self::mergeDeprecatedTags($this->getDeprecatedTag(), $this->isNotDeprecated(), $parent); $result->isDeprecated = $result->deprecatedTag !== null; $result->isNotDeprecated = $this->isNotDeprecated(); $result->isInternal = $this->isInternal(); $result->isFinal = $this->isFinal(); $result->isPure = self::mergePureTags($this->isPure(), $parent); $result->areAllMethodsPure = $this->areAllMethodsPure(); $result->areAllMethodsImpure = $this->areAllMethodsImpure(); $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 getSealedTags(): array { if ($this->sealedTypeTags === \false) { $this->sealedTypeTags = $this->phpDocNodeResolver->resolveSealedTags($this->phpDocNode, $this->getNameScope()); } return $this->sealedTypeTags; } /** * @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 { return $this->isDeprecated ??= $this->phpDocNodeResolver->resolveIsDeprecated($this->phpDocNode); } /** * @internal */ public function isNotDeprecated(): bool { return $this->isNotDeprecated ??= $this->phpDocNodeResolver->resolveIsNotDeprecated($this->phpDocNode); } public function isInternal(): bool { return $this->isInternal ??= $this->phpDocNodeResolver->resolveIsInternal($this->phpDocNode); } public function isFinal(): bool { return $this->isFinal ??= $this->phpDocNodeResolver->resolveIsFinal($this->phpDocNode); } public function hasConsistentConstructor(): bool { return $this->hasConsistentConstructor ??= $this->phpDocNodeResolver->resolveHasConsistentConstructor($this->phpDocNode); } public function acceptsNamedArguments(): bool { return $this->acceptsNamedArguments ??= $this->phpDocNodeResolver->resolveAcceptsNamedArguments($this->phpDocNode); } 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 areAllMethodsPure(): bool { return $this->areAllMethodsPure ??= $this->phpDocNodeResolver->resolveAllMethodsPure($this->phpDocNode); } public function areAllMethodsImpure(): bool { return $this->areAllMethodsImpure ??= $this->phpDocNodeResolver->resolveAllMethodsImpure($this->phpDocNode); } public function isReadOnly(): bool { return $this->isReadOnly ??= $this->phpDocNodeResolver->resolveIsReadOnly($this->phpDocNode); } public function isImmutable(): bool { return $this->isImmutable ??= $this->phpDocNodeResolver->resolveIsImmutable($this->phpDocNode); } public function isAllowedPrivateMutation(): bool { return $this->isAllowedPrivateMutation ??= $this->phpDocNodeResolver->resolveAllowPrivateMutation($this->phpDocNode); } /** * @param array $varTags * @return array */ private static function mergeVarTags(array $varTags, self $parent, ClassReflection $parentClass): array { // Only allow one var tag per comment. Check the parent if child does not have this tag. if (count($varTags) > 0) { return $varTags; } $result = self::mergeOneParentVarTags($parent, $parentClass); if ($result === null) { return []; } return $result; } /** * @return array|null */ private static function mergeOneParentVarTags(self $parent, ClassReflection $parentClass): ?array { foreach ($parent->getVarTags() as $key => $parentVarTag) { return [$key => self::resolveTemplateTypeInTag($parentVarTag->toImplicit(), $parentClass, TemplateTypeVariance::createInvariant())]; } return null; } /** * @param array $paramTags * @return array */ private static function mergeParamTags(array $paramTags, self $parent, \PHPStan\PhpDoc\InheritedPhpDocParameterMapping $parameterMapping, ClassReflection $parentClass): array { return self::mergeOneParentParamTags($paramTags, $parent, $parameterMapping, $parentClass); } /** * @param array $paramTags * @return array */ private static function mergeOneParentParamTags(array $paramTags, self $parent, \PHPStan\PhpDoc\InheritedPhpDocParameterMapping $parameterMapping, ClassReflection $parentClass): array { $parentParamTags = $parameterMapping->transformArrayKeysWithParameterNameMapping($parent->getParamTags()); foreach ($parentParamTags as $name => $parentParamTag) { if (array_key_exists($name, $paramTags)) { continue; } $paramTags[$name] = self::resolveTemplateTypeInTag($parentParamTag->withType($parameterMapping->transformConditionalReturnTypeWithParameterNameMapping($parentParamTag->getType())), $parentClass, TemplateTypeVariance::createContravariant()); } return $paramTags; } private static function mergeReturnTags(?ReturnTag $returnTag, ClassReflection $classReflection, self $parent, \PHPStan\PhpDoc\InheritedPhpDocParameterMapping $parameterMapping, ClassReflection $parentClass): ?ReturnTag { if ($returnTag !== null) { return $returnTag; } return self::mergeOneParentReturnTag($returnTag, $classReflection, $parent, $parameterMapping, $parentClass); } private static function mergeOneParentReturnTag(?ReturnTag $returnTag, ClassReflection $classReflection, self $parent, \PHPStan\PhpDoc\InheritedPhpDocParameterMapping $parameterMapping, ClassReflection $parentClass): ?ReturnTag { $parentReturnTag = $parent->getReturnTag(); if ($parentReturnTag === null) { return $returnTag; } $parentType = $parentReturnTag->getType(); $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($parameterMapping->transformConditionalReturnTypeWithParameterNameMapping($parentReturnTag->getType()))->toImplicit(), $parentClass, TemplateTypeVariance::createCovariant()); } /** * @param array $assertTags * @return array */ private static function mergeAssertTags(array $assertTags, self $parent, \PHPStan\PhpDoc\InheritedPhpDocParameterMapping $parameterMapping, ClassReflection $parentClass): array { if (count($assertTags) > 0) { return $assertTags; } return array_map(static fn(AssertTag $assertTag) => self::resolveTemplateTypeInTag($assertTag->withParameter($parameterMapping->transformAssertTagParameterWithParameterNameMapping($assertTag->getParameter()))->toImplicit(), $parentClass, TemplateTypeVariance::createCovariant()), $parent->getAssertTags()); } private static function mergeSelfOutTypeTags(?SelfOutTypeTag $selfOutTypeTag, self $parent): ?SelfOutTypeTag { if ($selfOutTypeTag !== null) { return $selfOutTypeTag; } return $parent->getSelfOutTag(); } private static function mergeDeprecatedTags(?DeprecatedTag $deprecatedTag, bool $hasNotDeprecatedTag, self $parent): ?DeprecatedTag { if ($deprecatedTag !== null) { return $deprecatedTag; } if ($hasNotDeprecatedTag) { return null; } $result = $parent->getDeprecatedTag(); if ($result === null && !$parent->isNotDeprecated()) { return null; } return $result; } private static function mergeThrowsTags(?ThrowsTag $throwsTag, self $parent): ?ThrowsTag { if ($throwsTag !== null) { return $throwsTag; } return $parent->getThrowsTag(); } /** * @param array $paramOutTags * @return array */ private static function mergeParamOutTags(array $paramOutTags, self $parent, \PHPStan\PhpDoc\InheritedPhpDocParameterMapping $parameterMapping, ClassReflection $parentClass): array { return self::mergeOneParentParamOutTags($paramOutTags, $parent, $parameterMapping, $parentClass); } /** * @param array $paramOutTags * @return array */ private static function mergeOneParentParamOutTags(array $paramOutTags, self $parent, \PHPStan\PhpDoc\InheritedPhpDocParameterMapping $parameterMapping, ClassReflection $parentClass): array { $parentParamOutTags = $parameterMapping->transformArrayKeysWithParameterNameMapping($parent->getParamOutTags()); foreach ($parentParamOutTags as $name => $parentParamTag) { if (array_key_exists($name, $paramOutTags)) { continue; } $paramOutTags[$name] = self::resolveTemplateTypeInTag($parentParamTag->withType($parameterMapping->transformConditionalReturnTypeWithParameterNameMapping($parentParamTag->getType())), $parentClass, TemplateTypeVariance::createCovariant()); } return $paramOutTags; } /** * @param array $paramsImmediatelyInvokedCallable * @return array */ private static function mergeParamsImmediatelyInvokedCallable(array $paramsImmediatelyInvokedCallable, self $parent, \PHPStan\PhpDoc\InheritedPhpDocParameterMapping $parameterMapping): array { return self::mergeOneParentParamImmediatelyInvokedCallable($paramsImmediatelyInvokedCallable, $parent, $parameterMapping); } /** * @param array $paramsImmediatelyInvokedCallable * @return array */ private static function mergeOneParentParamImmediatelyInvokedCallable(array $paramsImmediatelyInvokedCallable, self $parent, \PHPStan\PhpDoc\InheritedPhpDocParameterMapping $parameterMapping): array { $parentImmediatelyInvokedCallable = $parameterMapping->transformArrayKeysWithParameterNameMapping($parent->getParamsImmediatelyInvokedCallable()); foreach ($parentImmediatelyInvokedCallable as $name => $parentIsImmediatelyInvokedCallable) { if (array_key_exists($name, $paramsImmediatelyInvokedCallable)) { continue; } $paramsImmediatelyInvokedCallable[$name] = $parentIsImmediatelyInvokedCallable; } return $paramsImmediatelyInvokedCallable; } /** * @param array $paramsClosureThisTags * @return array */ private static function mergeParamClosureThisTags(array $paramsClosureThisTags, self $parent, \PHPStan\PhpDoc\InheritedPhpDocParameterMapping $parameterMapping, ClassReflection $parentClass): array { return self::mergeOneParentParamClosureThisTag($paramsClosureThisTags, $parent, $parameterMapping, $parentClass); } /** * @param array $paramsClosureThisTags * @return array */ private static function mergeOneParentParamClosureThisTag(array $paramsClosureThisTags, self $parent, \PHPStan\PhpDoc\InheritedPhpDocParameterMapping $parameterMapping, ClassReflection $parentClass): array { $parentClosureThisTags = $parameterMapping->transformArrayKeysWithParameterNameMapping($parent->getParamClosureThisTags()); foreach ($parentClosureThisTags as $name => $parentParamClosureThisTag) { if (array_key_exists($name, $paramsClosureThisTags)) { continue; } $paramsClosureThisTags[$name] = self::resolveTemplateTypeInTag($parentParamClosureThisTag->withType($parameterMapping->transformConditionalReturnTypeWithParameterNameMapping($parentParamClosureThisTag->getType())), $parentClass, TemplateTypeVariance::createContravariant()); } return $paramsClosureThisTags; } private static function mergePureTags(?bool $isPure, self $parent): ?bool { if ($isPure !== null) { return $isPure; } return $parent->isPure(); } /** * @template T of TypedTag * @param T $tag * @return T */ private static function resolveTemplateTypeInTag(TypedTag $tag, ClassReflection $classReflection, TemplateTypeVariance $positionVariance): TypedTag { $type = TemplateTypeHelper::resolveTemplateTypes($tag->getType(), $classReflection->getActiveTemplateTypeMap(), $classReflection->getCallSiteVarianceMap(), $positionVariance); return $tag->withType($type); } } phpVersion = $phpVersion; } public function getFiles(): array { if ($this->phpVersion->getVersionId() >= 80000) { return [__DIR__ . '/../../stubs/socket_select_php8.stub']; } return [__DIR__ . '/../../stubs/socket_select.stub']; } } */ private array $classMap = []; /** @var array> */ private array $propertyMap = []; /** @var array> */ private array $constantMap = []; /** @var array> */ private array $methodMap = []; /** @var array */ private array $functionMap = []; private bool $initialized = \false; private bool $initializing = \false; /** @var array */ private array $knownClassesDocComments = []; /** @var array */ private array $knownFunctionsDocComments = []; /** @var array> */ private array $knownPropertiesDocComments = []; /** @var array> */ private array $knownConstantsDocComments = []; /** @var array> */ private array $knownMethodsDocComments = []; /** @var array>> */ private array $knownMethodsParameterNames = []; /** @var array> */ private array $knownFunctionParameterNames = []; public function __construct( #[AutowiredParameter('@stubParser')] Parser $parser, #[AutowiredParameter('@stubFileTypeMapper')] 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()); } } } } php8Parser = $php8Parser; $this->phpStormStubsSourceStubber = $phpStormStubsSourceStubber; $this->optimizedSingleFileSourceLocatorRepository = $optimizedSingleFileSourceLocatorRepository; $this->optimizedPsrAutoloaderLocatorFactory = $optimizedPsrAutoloaderLocatorFactory; $this->allStubFiles = $allStubFiles; } public function create(): SourceLocator { $locators = []; $astPhp8Locator = new Locator($this->php8Parser); foreach ($this->allStubFiles 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)); } } derivativeContainerFactory = $derivativeContainerFactory; $this->stubFilesProvider = $stubFilesProvider; } /** * @param string[] $stubFiles * @return list */ public function validate(array $stubFiles, bool $debug): array { if (count($stubFiles) === 0) { return []; } $originalReflectionProvider = ReflectionProviderStaticAccessor::getInstance(); $originalPhpVersion = PhpVersionStaticAccessor::getInstance(); try { $container = $this->derivativeContainerFactory->create([__DIR__ . '/../../conf/config.stubValidator.neon'], ['allStubFiles' => $this->stubFilesProvider->getStubFiles()]); $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); $ruleRegistry = new DirectRuleRegistry($container->getServicesByTag(self::SERVICE_RULE_TAG)); $collectorRegistry = new CollectorRegistry([]); $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()]); } } } finally { ReflectionProviderStaticAccessor::registerInstance($originalReflectionProvider); PhpVersionStaticAccessor::registerInstance($originalPhpVersion); ObjectType::resetCaches(); } return $errors; } } 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->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); } } 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; } } message = $message; } public function getMessage(): ?string { return $this->message; } } type = $type; } public function getType(): Type { return $this->type; } } type = $type; } public function getType(): Type { return $this->type; } } */ private array $parameters; /** * @var array */ private array $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; } } 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; } } type = $type; } public function getType(): Type { return $this->type; } } type = $type; } public function getType(): Type { return $this->type; } public function withType(Type $type): self { return new self($type); } } type = $type; } public function getType(): Type { return $this->type; } public function withType(Type $type): self { return new self($type); } } type = $type; $this->isVariadic = $isVariadic; } public function getType(): Type { return $this->type; } public function isVariadic(): bool { return $this->isVariadic; } public function withType(Type $type): self { return new self($type, $this->isVariadic); } } readableType = $readableType; $this->writableType = $writableType; } 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; } } 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; } public function isExplicit(): bool { return $this->isExplicit; } public function withType(Type $type): self { 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; } public function withType(Type $type): self { return new self($type); } } type = $type; } public function getType(): Type { return $this->type; } public function withType(Type $type): self { 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; } } type = $type; } public function getType(): Type { return $this->type; } } 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; } } 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; } public function getType(): Type { return $this->type; } } type = $type; $this->isExplicit = $isExplicit; } public function getType(): Type { return $this->type; } public function withType(Type $type): self { return new self($type, $this->isExplicit); } public function isExplicit(): bool { return $this->isExplicit; } public function toImplicit(): self { return new self($this->type, \false); } } */ private array $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': return new IntegerType(); case 'integer': $type = $this->tryResolvePseudoTypeClassType($typeNode, $nameScope); if ($type !== null) { return $type; } 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': return new ClassStringType(); case 'enum-string': return new GenericClassStringType(new ObjectType('UnitEnum')); 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 new IntersectionType([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 new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new MixedType()), new AccessoryArrayListType()]); case 'non-empty-list': return new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new MixedType()), new NonEmptyArrayType(), new AccessoryArrayListType()]); case 'empty': $type = $this->tryResolvePseudoTypeClassType($typeNode, $nameScope); if ($type !== null) { return $type; } return StaticTypeFactory::falsey(); case '__stringandstringable': return new StringAlwaysAcceptingObjectWithToStringType(); case '__stringnotstringable': return new StringNeverAcceptingObjectWithToStringType(); } 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()); $parentClass = $classReflection->getNativeReflection()->getParentClass(); if ($parentClass !== \false) { return new ObjectType($parentClass->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 instanceof GenericObjectType) { $type = new IntersectionType([$type, new IterableType(new MixedType(), $arrayTypeType)]); } elseif ($type instanceof ArrayType) { $type = new ArrayType(new MixedType(), $arrayTypeType); } elseif ($type instanceof ConstantArrayType) { $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); $result = $types[0]; for ($i = 1, $count = count($types); $i < $count; $i++) { $result = TypeCombinator::intersect($result, $types[$i]); } return $result; } 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]->toArrayKey(), new UnionType([new IntegerType(), new StringType()]))->toArrayKey(); $finiteTypes = $keyType->getFiniteTypes(); if (count($finiteTypes) === 1 && ($finiteTypes[0] instanceof ConstantStringType || $finiteTypes[0] instanceof ConstantIntegerType)) { $arrayBuilder = ConstantArrayTypeBuilder::createEmpty(); $arrayBuilder->setOffsetValueType($finiteTypes[0], $genericTypes[1], \true); $arrayType = $arrayBuilder->getArray(); } else { $arrayType = new ArrayType($keyType, $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 = new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $genericTypes[0]), new AccessoryArrayListType()]); 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 === 'enum-string') { if (count($genericTypes) === 1) { $genericType = $genericTypes[0]; return new GenericClassStringType(TypeCombinator::intersect($genericType, new ObjectType('UnitEnum'))); } 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 fn(TemplateTag $tag): Type => TemplateTypeFactory::fromTemplateTag($templateTypeScope, $tag), $templateTags)); $nameScope = $nameScope->withTemplateTypeMap($templateTypeMap, $templateTags); } else { $templateTypeMap = TemplateTypeMap::createEmpty(); } $mainType = $this->resolve($typeNode->identifier, $nameScope); $isVariadic = \false; $parameters = array_values(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(), $mainType->mustUseReturnValue()); 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(); $builder->disableArrayDegradation(); foreach ($typeNode->items as $itemNode) { if ($itemNode->valueType instanceof CallableTypeNode) { $builder->disableClosureDegradation(); } $offsetType = $this->resolveArrayShapeOffsetType($itemNode, $nameScope); $builder->setOffsetValueType($offsetType, $this->resolve($itemNode->valueType, $nameScope), $itemNode->optional); } $arrayType = $builder->getArray(); $accessories = []; if (in_array($typeNode->kind, [ArrayShapeNode::KIND_LIST, ArrayShapeNode::KIND_NON_EMPTY_LIST], \true)) { $accessories[] = new AccessoryArrayListType(); } if (in_array($typeNode->kind, [ArrayShapeNode::KIND_NON_EMPTY_ARRAY, ArrayShapeNode::KIND_NON_EMPTY_LIST], \true)) { $accessories[] = new NonEmptyArrayType(); } if (count($accessories) > 0) { return TypeCombinator::intersect($arrayType, ...$accessories); } return $arrayType; } private function resolveArrayShapeOffsetType(ArrayShapeItemNode $itemNode, NameScope $nameScope): ?Type { if ($itemNode->keyName instanceof ConstExprIntegerNode) { return new ConstantIntegerType((int) $itemNode->keyName->value); } elseif ($itemNode->keyName instanceof IdentifierTypeNode) { return new ConstantStringType($itemNode->keyName->name); } elseif ($itemNode->keyName instanceof ConstExprStringNode) { return new ConstantStringType($itemNode->keyName->value); } elseif ($itemNode->keyName instanceof ConstFetchNode) { $constExpr = $itemNode->keyName; if ($constExpr->className === '') { throw new ShouldNotHappenException(); // global constant should get parsed as class name in IdentifierTypeNode } $isStatic = \false; if ($nameScope->getClassName() !== null) { switch (strtolower($constExpr->className)) { case 'static': $className = $nameScope->getClassName(); $isStatic = \true; break; 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); if ($isStatic && $classReflection->isFinal()) { $isStatic = \false; } $constantName = $constExpr->name; if (!$classReflection->hasConstant($constantName)) { return new ErrorType(); } if ($isStatic) { return new ClassConstantAccessType(new StaticType($classReflection), $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)); } elseif ($itemNode->keyName !== null) { throw new ShouldNotHappenException('Unsupported key node type: ' . get_class($itemNode->keyName)); } return null; } 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 } $isStatic = \false; if ($nameScope->getClassName() !== null) { switch (strtolower($constExpr->className)) { case 'static': $className = $nameScope->getClassName(); $isStatic = \true; break; 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); if ($isStatic && $classReflection->isFinal()) { $isStatic = \false; } $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); } if ($isStatic) { return new ClassConstantAccessType(new StaticType($classReflection), $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 fn(ConstantIntegerType $type) => $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 fn($value) => new ConstantIntegerType($value), $values)); } /** * @api * @param TypeNode[] $typeNodes * @return list */ 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(); } } 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; } } 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, [])); } } loadLimit = $loadLimit; } public function getNumberOfCpuCores(): int { if ($this->count !== null) { return $this->count; } try { $this->count = (new FidryCpuCoreCounter())->getAvailableForParallelisation(0, null, $this->loadLimit)->availableCpus; } catch (NumberOfCpuCoreNotFound $e) { $this->count = 1; } return $this->count; } } */ private Deferred $deferred; private ?int $childPid = null; /** @var resource|null */ private $stdOut = null; private ?TimerInterface $waitTimer = null; private bool $canceled = \false; /** * @param string[] $inceptionFiles * @param mixed[]|null $projectConfigArray */ public function __construct(LoopInterface $loop, FixerWorkerRunner $fixerWorkerRunner, TcpServer $server, Output $errorOutput, array $inceptionFiles, bool $isOnlyFiles, ?array $projectConfigArray, ?string $configuration, int $serverPort, InputInterface $input) { $this->loop = $loop; $this->fixerWorkerRunner = $fixerWorkerRunner; $this->server = $server; $this->errorOutput = $errorOutput; $this->inceptionFiles = $inceptionFiles; $this->isOnlyFiles = $isOnlyFiles; $this->projectConfigArray = $projectConfigArray; $this->configuration = $configuration; $this->serverPort = $serverPort; $this->input = $input; $this->deferred = new Deferred(function (): void { $this->cancel(); }); } /** * @return PromiseInterface */ public function run(): PromiseInterface { // Created before the fork so the parent can read what the child wrote. $tmpStdOut = tmpfile(); if ($tmpStdOut === \false) { throw new ShouldNotHappenException('Failed creating temp file for stdout.'); } $this->stdOut = $tmpStdOut; $pid = pcntl_fork(); if ($pid === -1) { fclose($this->stdOut); $this->stdOut = null; // Deferred so it runs after FixerApplication has stored the promise. $this->loop->futureTick(function (): void { $this->deferred->reject(new \PHPStan\Process\ProcessCrashedException('pcntl_fork() failed.')); }); return $this->deferred->promise(); } if ($pid === 0) { // Child: drop the inherited listening socket immediately, then run // the worker on its own fresh event loop and never return. $this->server->close(); $exitCode = $this->fixerWorkerRunner->run($this->errorOutput, $this->inceptionFiles, $this->isOnlyFiles, $this->projectConfigArray, $this->configuration, $this->serverPort, $this->input); exit($exitCode); } // Parent: poll for the child to exit and resolve/reject accordingly. $this->childPid = $pid; $this->waitTimer = $this->loop->addPeriodicTimer(self::WAITPID_POLL_INTERVAL, function () use ($pid): void { $status = 0; $result = pcntl_waitpid($pid, $status, WNOHANG); if ($result === 0) { return; } $this->cancelWaitTimer(); $output = ''; if ($this->stdOut !== null) { rewind($this->stdOut); $output = (string) stream_get_contents($this->stdOut); fclose($this->stdOut); $this->stdOut = null; } if ($this->canceled) { // cancel() already rejected the promise; just reap the child. return; } $exitCode = null; if ($result > 0 && pcntl_wifexited($status)) { $exitStatus = pcntl_wexitstatus($status); if ($exitStatus !== \false) { $exitCode = $exitStatus; } } if ($exitCode === 0) { $this->deferred->resolve($output); return; } $this->deferred->reject(new \PHPStan\Process\ProcessCrashedException($output)); }); return $this->deferred->promise(); } private function cancel(): void { if ($this->childPid === null) { throw new ShouldNotHappenException('Cancelling process before running'); } $this->canceled = \true; // SIGTERM the child; the waitpid poll timer keeps running so it still // gets reaped (otherwise: zombie). posix_kill($this->childPid, SIGTERM); $this->deferred->reject(new \PHPStan\Process\ProcessCanceledException()); } private function cancelWaitTimer(): void { if ($this->waitTimer === null) { return; } $this->loop->cancelTimer($this->waitTimer); $this->waitTimer = null; } } 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); } } */ public function run(): PromiseInterface; } */ private Deferred $deferred; private ?Process $process = null; private bool $canceled = \false; public function __construct(LoopInterface $loop, string $command) { $this->loop = $loop; $this->command = $command; $this->deferred = new Deferred(function (): void { $this->cancel(); }); } /** * @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) { $this->deferred->resolve($stdOut); return; } $this->deferred->reject(new \PHPStan\Process\ProcessCrashedException($stdOut . $stdErr)); }); return $this->deferred->promise(); } private 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 getAllowedSubTypes(\PHPStan\Reflection\ClassReflection $classReflection): array; } */ private array $parameters; private bool $isStatic; private bool $isVariadic; private ?Type $throwType; private TemplateTypeMap $templateTypeMap; /** @var list|null */ private ?array $variants = null; /** * @param list $parameters */ public function __construct(string $name, ClassReflection $declaringClass, Type $returnType, array $parameters, bool $isStatic, bool $isVariadic, ?Type $throwType, TemplateTypeMap $templateTypeMap) { $this->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 { return $this->variants ??= [new ExtendedFunctionVariant($this->templateTypeMap, null, $this->parameters, $this->isVariadic, $this->returnType, $this->returnType, new MixedType())]; } public function getOnlyVariant(): ExtendedParametersAcceptor { 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 isBuiltin(): 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(): TrinaryLogic { return TrinaryLogic::createFromBoolean($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(); } public function getAttributes(): array { return []; } public function mustUseReturnValue(): TrinaryLogic { return TrinaryLogic::createNo(); } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return null; } } name = $name; $this->declaringClass = $declaringClass; $this->readableType = $readableType; $this->writableType = $writableType; $this->readable = $readable; $this->writable = $writable; } public function getName(): string { return $this->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 hasPhpDocType(): bool { return \true; } public function getPhpDocType(): Type { return $this->readableType; } public function hasNativeType(): bool { return \false; } public function getNativeType(): Type { return new MixedType(); } 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; } public function isAbstract(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinalByKeyword(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinal(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isVirtual(): TrinaryLogic { return TrinaryLogic::createNo(); } public function hasHook(string $hookType): bool { return \false; } public function getHook(string $hookType): ExtendedMethodReflection { throw new ShouldNotHappenException(); } public function isProtectedSet(): bool { return \false; } public function isPrivateSet(): bool { return \false; } public function getAttributes(): array { return []; } public function isDummy(): TrinaryLogic { return TrinaryLogic::createNo(); } } 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 hasNativeType(): bool { return \false; } 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; } public function getAttributes(): array { return []; } } methods[$classReflection->getCacheKey()][$methodName])) { $method = $this->findClassReflectionWithMethod($classReflection, $classReflection, $methodName); if ($method === null) { return \false; } $this->methods[$classReflection->getCacheKey()][$methodName] = $method; } return \true; } public function getMethod(ClassReflection $classReflection, string $methodName): ExtendedMethodReflection { 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 fn(TemplateTag $tag): Type => 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(); if ($parentClass !== null) { $methodWithDeclaringClass = $this->findClassReflectionWithMethod($parentClass, $parentClass, $methodName); if ($methodWithDeclaringClass !== null) { return $methodWithDeclaringClass; } } 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(); } } properties[$classReflection->getCacheKey()][$propertyName])) { $property = $this->findClassReflectionWithProperty($classReflection, $classReflection, $propertyName); if ($property === null) { return \false; } $this->properties[$classReflection->getCacheKey()][$propertyName] = $property; } return \true; } public function getProperty(ClassReflection $classReflection, string $propertyName): ExtendedPropertyReflection { 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); if (!$nativeProperty->isPrivate() && !$nativeProperty->isStatic()) { $isReadable = $isReadable || $nativeProperty->isReadable(); $isWritable = $isWritable || $nativeProperty->isWritable(); } } return new \PHPStan\Reflection\Annotations\AnnotationPropertyReflection($propertyName, $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(); if ($parentClass !== null) { $methodWithDeclaringClass = $this->findClassReflectionWithProperty($parentClass, $parentClass, $propertyName); if ($methodWithDeclaringClass !== null) { return $methodWithDeclaringClass; } } foreach ($classReflection->getInterfaces() as $interfaceClass) { $methodWithDeclaringClass = $this->findClassReflectionWithProperty($interfaceClass, $interfaceClass, $propertyName); if ($methodWithDeclaringClass === null) { continue; } return $methodWithDeclaringClass; } return null; } } asserts = $asserts; } /** @return AssertTag[] */ public function getAll(): array { return $this->asserts; } /** * Unconditional assertions — narrow parameter types regardless of the method's return value. * * @return AssertTag[] */ public function getAsserts(): array { return array_filter($this->asserts, static fn(AssertTag $assert) => $assert->getIf() === AssertTag::NULL); } /** * Includes @phpstan-assert-if-true tags and negated @phpstan-assert-if-false tags. * * @return AssertTag[] */ public function getAssertsIfTrue(): array { return array_merge(array_filter($this->asserts, static fn(AssertTag $assert) => $assert->getIf() === AssertTag::IF_TRUE), array_map(static fn(AssertTag $assert) => $assert->negate(), array_filter($this->asserts, static fn(AssertTag $assert) => $assert->getIf() === AssertTag::IF_FALSE && !$assert->isEquality()))); } /** * Includes @phpstan-assert-if-false tags and negated @phpstan-assert-if-true tags. * * @return AssertTag[] */ public function getAssertsIfFalse(): array { return array_merge(array_filter($this->asserts, static fn(AssertTag $assert) => $assert->getIf() === AssertTag::IF_FALSE), array_map(static fn(AssertTag $assert) => $assert->negate(), array_filter($this->asserts, static fn(AssertTag $assert) => $assert->getIf() === AssertTag::IF_TRUE && !$assert->isEquality()))); } /** @param callable(Type): Type $callable */ public function mapTypes(callable $callable): self { $assertTagsCallback = static fn(AssertTag $tag): AssertTag => $tag->withType($callable($tag->getType())); return self::create(array_map($assertTagsCallback, $this->asserts)); } /** * @deprecated use union() or intersect() instead */ public function intersectWith(\PHPStan\Reflection\Assertions $other): self { return $this->union($other); } public function union(\PHPStan\Reflection\Assertions $other): self { if ($this === self::$empty) { return $other; } if ($other === self::$empty) { return $this; } return self::create(array_merge($this->getAll(), $other->getAll())); } public function intersect(\PHPStan\Reflection\Assertions $other): self { if ($this === self::$empty) { return $other; } if ($other === self::$empty) { return $this; } $otherAsserts = $other->getAll(); $thisAsserts = $this->getAll(); $merged = []; foreach ($thisAsserts as $thisAssert) { $key = self::getAssertKey($thisAssert); foreach ($otherAsserts as $otherAssert) { if (self::getAssertKey($otherAssert) !== $key) { continue; } $merged[] = $thisAssert->withType(TypeCombinator::union($thisAssert->getType(), $otherAssert->getType())); } } return self::create($merged); } private static function getAssertKey(AssertTag $assert): string { return sprintf('%s-%s-%s', $assert->getParameter()->describe(), $assert->getIf(), $assert->isNegated() ? '1' : '0'); } /** * @param AssertTag[] $asserts */ private static function create(array $asserts): self { if (count($asserts) === 0) { return self::createEmpty(); } return new self($asserts); } 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(); return self::create($tags); } } */ private array $argumentTypes; /** * @param array $argumentTypes Argument types keyed by parameter name */ public function __construct(string $name, array $argumentTypes) { $this->name = $name; $this->argumentTypes = $argumentTypes; } public function getName(): string { return $this->name; } /** @return array */ public function getArgumentTypes(): array { return $this->argumentTypes; } } initializerExprTypeResolver = $initializerExprTypeResolver; $this->reflectionProviderProvider = $reflectionProviderProvider; } /** * @param list $reflections * @return list */ public function fromNativeReflection(array $reflections, \PHPStan\Reflection\InitializerExprContext $context): array { $attributes = []; foreach ($reflections as $reflection) { $attribute = $this->fromNameAndArgumentExpressions($reflection->getName(), $reflection->getArgumentsExpressions(), $context); if ($attribute === null) { continue; } $attributes[] = $attribute; } return $attributes; } /** * @param AttributeGroup[] $attrGroups * @return list */ public function fromAttrGroups(array $attrGroups, \PHPStan\Reflection\InitializerExprContext $context): array { $attributes = []; foreach ($attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { $arguments = []; foreach ($attr->args as $i => $arg) { if ($arg->name === null) { $argName = $i; } else { $argName = $arg->name->toString(); } $arguments[$argName] = $arg->value; } $attributeReflection = $this->fromNameAndArgumentExpressions($attr->name->toString(), $arguments, $context); if ($attributeReflection === null) { continue; } $attributes[] = $attributeReflection; } } return $attributes; } /** * @param array $arguments */ private function fromNameAndArgumentExpressions(string $name, array $arguments, \PHPStan\Reflection\InitializerExprContext $context): ?\PHPStan\Reflection\AttributeReflection { if (count($arguments) === 0) { return new \PHPStan\Reflection\AttributeReflection($name, []); } $reflectionProvider = $this->reflectionProviderProvider->getReflectionProvider(); if (!$reflectionProvider->hasClass($name)) { return null; } $classReflection = $reflectionProvider->getClass($name); if (!$classReflection->hasConstructor()) { return null; } if (!$classReflection->isAttributeClass()) { return null; } $constructor = $classReflection->getConstructor(); $parameters = $constructor->getOnlyVariant()->getParameters(); $namedArgTypes = []; foreach ($arguments as $i => $argExpr) { if (is_int($i)) { if (isset($parameters[$i])) { $namedArgTypes[$parameters[$i]->getName()] = $this->initializerExprTypeResolver->getType($argExpr, $context); continue; } if (count($parameters) > 0) { $lastParameter = array_last($parameters); if ($lastParameter->isVariadic()) { $parameterName = $lastParameter->getName(); if (array_key_exists($parameterName, $namedArgTypes)) { $namedArgTypes[$parameterName] = TypeCombinator::union($namedArgTypes[$parameterName], $this->initializerExprTypeResolver->getType($argExpr, $context)); continue; } $namedArgTypes[$parameterName] = $this->initializerExprTypeResolver->getType($argExpr, $context); } } continue; } foreach ($parameters as $parameter) { if ($parameter->getName() !== $i) { continue; } $namedArgTypes[$i] = $this->initializerExprTypeResolver->getType($argExpr, $context); break; } } return new \PHPStan\Reflection\AttributeReflection($classReflection->getName(), $namedArgTypes); } } */ private array $universalObjectCratesClasses; /** @var FunctionReflection[] */ private array $functionReflections = []; /** @var ClassReflection[] */ private array $classReflections = []; /** @var ClassReflection[] */ private static array $anonymousClasses = []; /** @var array> */ private array $cachedConstants = []; /** * @param list $universalObjectCratesClasses */ public function __construct( InitializerExprTypeResolver $initializerExprTypeResolver, ClassReflectionFactory $classReflectionFactory, #[AutowiredParameter('@betterReflectionReflector')] Reflector $reflector, FileTypeMapper $fileTypeMapper, DeprecationProvider $deprecationProvider, PhpVersion $phpVersion, NativeFunctionReflectionProvider $nativeFunctionReflectionProvider, StubPhpDocProvider $stubPhpDocProvider, FunctionReflectionFactory $functionReflectionFactory, RelativePathHelper $relativePathHelper, AnonymousClassNameHelper $anonymousClassNameHelper, FileHelper $fileHelper, PhpStormStubsSourceStubber $phpstormStubsSourceStubber, AttributeReflectionFactory $attributeReflectionFactory, #[AutowiredParameter('%universalObjectCratesClasses%')] array $universalObjectCratesClasses ) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->classReflectionFactory = $classReflectionFactory; $this->reflector = $reflector; $this->fileTypeMapper = $fileTypeMapper; $this->deprecationProvider = $deprecationProvider; $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->attributeReflectionFactory = $attributeReflectionFactory; $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]; } if ($reflectionClass instanceof ReflectionEnum && PHP_VERSION_ID >= 80000) { $enumAdapter = base64_decode('UEhQU3RhblxCZXR0ZXJSZWZsZWN0aW9uXFJlZmxlY3Rpb25cQWRhcHRlclxSZWZsZWN0aW9uRW51bQ==', \true); $adaptedClass = new $enumAdapter($reflectionClass); } else { $adaptedClass = new ReflectionClass($reflectionClass); } return $this->classReflections[$reflectionClassName] = $this->classReflectionFactory->create($reflectionClass->getName(), $adaptedClass, null, null, $this->stubPhpDocProvider->findClassPhpDoc($reflectionClass->getName())); } 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 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(); } } $className = $this->anonymousClassNameHelper->getAnonymousClassName($classNode, $scopeFile); $classNode->name = new Node\Identifier($className); $classNode->namespacedName = null; 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); $displayParentName = $reflectionClass->getParentClassName(); if ($displayParentName === null) { // https://3v4l.org/6FBuP $classInterfaceNames = $reflectionClass->getInterfaceNames(); if ($classInterfaceNames !== []) { $displayParentName = $classInterfaceNames[array_key_first($classInterfaceNames)]; } else { $displayParentName = 'class'; } } /** @var int|null $classLineIndex */ $classLineIndex = $classNode->getAttribute(AnonymousClassVisitor::ATTRIBUTE_LINE_INDEX); $filename = $this->fileHelper->normalizePath($this->relativePathHelper->getRelativePath($scopeFile), '/'); if ($classLineIndex === null) { $displayName = sprintf('%s@anonymous/%s:%s', $displayParentName, $filename, $classNode->getStartLine()); } else { $displayName = sprintf('%s@anonymous/%s:%s:%d', $displayParentName, $filename, $classNode->getStartLine(), $classLineIndex); } return $this->classReflections[$className] = self::$anonymousClasses[$className] = $this->classReflectionFactory->create($displayName, new ReflectionClass($reflectionClass), $scopeFile, null, $this->stubPhpDocProvider->findClassPhpDoc($className)); } public function getUniversalObjectCratesClasses(): array { return $this->universalObjectCratesClasses; } 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; $deprecation = $this->deprecationProvider->getFunctionDeprecation($reflectionFunction); $deprecationDescription = $deprecation === null ? null : $deprecation->getDescription(); $isDeprecated = $deprecation !== null; $isInternal = \false; $isPure = null; $asserts = Assertions::createEmpty(); $acceptsNamedArguments = \true; $phpDocComment = null; $phpDocParameterOutTags = []; $phpDocParameterImmediatelyInvokedCallable = []; $phpDocParameterClosureThisTypeTags = []; $resolvedPhpDoc = $this->stubPhpDocProvider->findFunctionPhpDoc($reflectionFunction->getName(), array_map(static fn(ReflectionParameter $parameter): string => $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 fn($tag) => $tag->getType(), $resolvedPhpDoc->getParamTags()); $phpDocReturnTag = $resolvedPhpDoc->getReturnTag(); $phpDocThrowsTag = $resolvedPhpDoc->getThrowsTag(); if (!$isDeprecated) { $deprecationDescription = $resolvedPhpDoc->getDeprecatedTag() !== null ? $resolvedPhpDoc->getDeprecatedTag()->getMessage() : $deprecationDescription; $isDeprecated = $resolvedPhpDoc->isDeprecated(); } $isInternal = $resolvedPhpDoc->isInternal(); $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, $deprecationDescription, $isDeprecated, $isInternal, $reflectionFunction->getFileName() !== \false ? $reflectionFunction->getFileName() : null, $isPure, $asserts, $acceptsNamedArguments, $phpDocComment, array_map(static fn(ParamOutTag $paramOutTag): Type => $paramOutTag->getType(), $phpDocParameterOutTags), $phpDocParameterImmediatelyInvokedCallable, array_map(static fn(ParamClosureThisTag $tag): Type => $tag->getType(), $phpDocParameterClosureThisTypeTags), $this->attributeReflectionFactory->fromNativeReflection($reflectionFunction->getAttributes(), InitializerExprContext::fromFunction($reflectionFunction->getName(), $reflectionFunction->getFileName() !== \false ? $reflectionFunction->getFileName() : null))); } 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): ConstantReflection { $constantName = $this->resolveConstantName($nameNode, $namespaceAnswerer); if ($constantName === null) { throw new ConstantNotFoundException((string) $nameNode); } $phpVersionType = null; $versionKey = 'current_version'; if ($namespaceAnswerer instanceof Scope) { $phpVersionType = $namespaceAnswerer->getPhpVersion()->getType(); $versionKey = $phpVersionType->describe(VerbosityLevel::cache()); } if (!array_key_exists($versionKey, $this->cachedConstants)) { $this->cachedConstants[$versionKey] = []; } if (array_key_exists($constantName, $this->cachedConstants[$versionKey])) { return $this->cachedConstants[$versionKey][$constantName]; } $constantReflection = $this->reflector->reflectConstant($constantName); $fileName = $constantReflection->getFileName(); $constantValueType = $this->initializerExprTypeResolver->getType($constantReflection->getValueExpression(), InitializerExprContext::fromGlobalConstant($constantReflection)); $docComment = $constantReflection->getDocComment(); $deprecation = $this->deprecationProvider->getConstantDeprecation($constantReflection); $isDeprecated = $deprecation !== null; $deprecatedDescription = $deprecation === null ? null : $deprecation->getDescription(); if ($isDeprecated === \false && $docComment !== null) { $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($fileName, null, null, null, $docComment); $isDeprecated = $resolvedPhpDoc->isDeprecated(); if ($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); if ($phpVersionType !== null) { $isDeprecated = IntegerRangeType::fromInterval((int) $versionId, null)->isSuperTypeOf($phpVersionType)->yes(); } else { $isDeprecated = $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; } } elseif (!$isDeprecated) { $isDeprecated = $constantReflection->isDeprecated(); } } elseif (!$isDeprecated) { $isDeprecated = $constantReflection->isDeprecated(); } return $this->cachedConstants[$versionKey][$constantName] = new RuntimeConstantReflection($constantName, $constantValueType, $fileName, TrinaryLogic::createFromBoolean($isDeprecated), $deprecatedDescription, $this->attributeReflectionFactory->fromNativeReflection(array_map(static fn(BetterReflectionAttribute $betterReflectionAttribute) => ReflectionAttributeFactory::create($betterReflectionAttribute), $constantReflection->getAttributes()), InitializerExprContext::fromGlobalConstant($constantReflection))); } 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; } } parser = $parser; $this->php8Parser = $php8Parser; $this->phpVersion = $phpVersion; $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 { $initializer = function () { $locators = [$this->optimizedSingleFileSourceLocatorRepository->getOrCreate(PHP_VERSION_ID < 80500 ? __DIR__ . '/../../../stubs/runtime/Attribute84.php' : __DIR__ . '/../../../stubs/runtime/Attribute85.php')]; 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); $composerLocators = []; foreach ($this->composerAutoloaderProjectPaths as $composerAutoloaderProjectPath) { $locator = $this->composerJsonAndInstalledJsonSourceLocatorMaker->create($composerAutoloaderProjectPath); if ($locator === null) { continue; } $composerLocators[] = $locator; } if (count($composerLocators) > 0) { $fileLocators[] = new SkipPolyfillSourceLocator(new AggregateSourceLocator($composerLocators), $this->phpVersion); } 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 AggregateSourceLocator($locators); }; return new MemoizingSourceLocator(new LazySourceLocator($initializer)); } } */ private array $classReflections = []; /** @var array */ private array $constantReflections = []; /** @var array */ private array $functionReflections = []; public function __construct( #[AutowiredParameter('@originalBetterReflectionReflector')] Reflector $reflector ) { $this->reflector = $reflector; } #[Override] 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; } } #[Override] 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; } } #[Override] 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; } } #[Override] public function reflectAllClasses(): iterable { return $this->reflector->reflectAllClasses(); } #[Override] public function reflectAllFunctions(): iterable { return $this->reflector->reflectAllFunctions(); } #[Override] public function reflectAllConstants(): iterable { return $this->reflector->reflectAllConstants(); } } autoloadSourceLocator = $autoloadSourceLocator; $this->reflectionClassSourceLocator = $reflectionClassSourceLocator; } #[Override] 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; } #[Override] public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array { return []; } } , functions: array, constants: array} */ private array $presentSymbols = ['classes' => [], 'functions' => [], 'constants' => []]; /** @var array */ private array $scannedFiles = []; /** @var array */ private array $startLineByClass = []; public function __construct(\PHPStan\Reflection\BetterReflection\SourceLocator\FileNodesFetcher $fileNodesFetcher, bool $executeAutoloadersInFileReadTrap) { $this->fileNodesFetcher = $fileNodesFetcher; $this->executeAutoloadersInFileReadTrap = $executeAutoloadersInFileReadTrap; } #[Override] 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; } #[Override] 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 fn(): bool => \true); } } >> */ private array $classNodes; /** @var array>> */ private array $functionNodes; /** @var array>> */ private array $constantNodes; private ?Node\Stmt\Namespace_ $currentNamespaceNode = null; #[Override] 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 NodeVisitor::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 NodeVisitor::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 NodeVisitor::DONT_TRAVERSE_CHILDREN; } if ($node instanceof Node\Expr\FuncCall && !$node->isFirstClassCallable()) { 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 NodeVisitor::DONT_TRAVERSE_CHILDREN; } return null; } /** * @return null */ #[Override] 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; } } 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(fn(array $package): array => $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(fn(array $package): array => $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(fn(array $package): array => $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(fn(array $package): array => $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, 'odsl-installed-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 fn($namespacePaths): array => (array) $namespacePaths, $package[$autoloadSection]['psr-4'] ?? []); } /** * @param mixed[] $package * * @return array> */ private function packageToPsr0AutoloadNamespaces(array $package, string $autoloadSection = 'autoload'): array { return array_map(static fn($namespacePaths): array => (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(fn(array $paths): array => $this->prefixPaths($paths, $prefix), $paths); } /** * @param array> $paths * * @return array> */ private function prefixWithInstallationPath(array $paths, string $trimmedInstallationPath): array { return array_map(fn(array $paths): array => $this->prefixPaths($paths, $trimmedInstallationPath . '/'), $paths); } /** * @param array $paths * * @return array */ private function prefixPaths(array $paths, string $prefix): array { return array_map(static fn(string $path): string => $prefix . $path, $paths); } } 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; } } >> */ private array $classNodes; /** * @var array>> */ private array $functionNodes; /** * @var array>> */ private array $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; } } 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; } } 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; } /** * @return true */ 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 * * @return false */ 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 ''; } } initializer = $initializer; } private function lazyInitialize(): SourceLocator { return $this->wrappedSourceLocator ??= ($this->initializer)(); } #[Override] public function locateIdentifier(Reflector $reflector, Identifier $identifier): ?Reflection { return $this->lazyInitialize()->locateIdentifier($reflector, $identifier); } #[Override] public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array { return $this->lazyInitialize()->locateIdentifiersByType($reflector, $identifierType); } } */ private array $classToFile; /** * @var array> */ private array $functionToFiles; /** * @var array */ private array $constantToFile; /** * @param array $classToFile * @param array> $functionToFiles * @param array $constantToFile */ public function __construct(\PHPStan\Reflection\BetterReflection\SourceLocator\FileNodesFetcher $fileNodesFetcher, Cache $cache, PhpVersion $phpVersion, array $classToFile, array $functionToFiles, array $constantToFile) { $this->fileNodesFetcher = $fileNodesFetcher; $this->cache = $cache; $this->phpVersion = $phpVersion; $this->classToFile = $classToFile; $this->functionToFiles = $functionToFiles; $this->constantToFile = $constantToFile; } /** * @return array{non-empty-string, string} */ private function getCacheKeys(string $file, Identifier $identifier): array { $fileHash = hash_file('sha256', $file); if ($fileHash === \false) { throw new CouldNotReadFileException($file); } $reflectionCacheKey = sprintf('odsl-%s-%s-%s', $file, $identifier->getType()->getName(), $identifier->getName()); $variableCacheKey = sprintf('v2-%s-%s-%s', ComposerHelper::getBetterReflectionVersion(), $this->phpVersion->getVersionString(), $fileHash); return [$reflectionCacheKey, $variableCacheKey]; } #[Override] public function locateIdentifier(Reflector $reflector, Identifier $identifier): ?Reflection { if ($identifier->isClass()) { $identifierName = strtolower($identifier->getName()); $file = $this->findFileByClass($identifierName); if ($file === null) { return null; } $files = [$file]; } elseif ($identifier->isFunction()) { $identifierName = strtolower($identifier->getName()); $files = $this->findFilesByFunction($identifierName); } elseif ($identifier->isConstant()) { $identifierName = ConstantNameHelper::normalize($identifier->getName()); $file = $this->findFileByConstant($identifierName); if ($file === null) { return null; } $files = [$file]; } else { return null; } foreach ($files as $file) { [$reflectionCacheKey, $variableCacheKey] = $this->getCacheKeys($file, $identifier); $cachedReflection = $this->cache->load($reflectionCacheKey, $variableCacheKey); if ($cachedReflection === null) { continue; } if ($identifier->isConstant()) { return ReflectionConstant::importFromCache($reflector, $cachedReflection); } if ($identifier->isFunction()) { return ReflectionFunction::importFromCache($reflector, $cachedReflection); } if ($identifier->isClass()) { if (array_key_exists('backingType', $cachedReflection)) { return ReflectionEnum::importFromCache($reflector, $cachedReflection); } return ReflectionClass::importFromCache($reflector, $cachedReflection); } } if ($identifier->isClass()) { $fetchedClassNode = null; foreach ($files as $file) { $fetchedClassNodes = $this->fileNodesFetcher->fetchNodes($file)->getClassNodes(); if (!array_key_exists($identifierName, $fetchedClassNodes)) { return null; } /** @var FetchedNode $fetchedClassNode */ $fetchedClassNode = current($fetchedClassNodes[$identifierName]); } if ($fetchedClassNode === null) { return null; } [$reflectionCacheKey, $variableCacheKey] = $this->getCacheKeys($file, $identifier); $classReflection = $this->nodeToReflection($reflector, $fetchedClassNode); $this->cache->save($reflectionCacheKey, $variableCacheKey, $classReflection->exportToCache()); return $classReflection; } elseif ($identifier->isFunction()) { $fetchedFunctionNode = null; foreach ($files as $file) { $fetchedFunctionNodes = $this->fileNodesFetcher->fetchNodes($file)->getFunctionNodes(); if (!array_key_exists($identifierName, $fetchedFunctionNodes)) { continue; } /** @var FetchedNode $fetchedFunctionNode */ $fetchedFunctionNode = current($fetchedFunctionNodes[$identifierName]); } if ($fetchedFunctionNode === null) { return null; } [$reflectionCacheKey, $variableCacheKey] = $this->getCacheKeys($file, $identifier); // @phpstan-ignore variable.undefined $functionReflection = $this->nodeToReflection($reflector, $fetchedFunctionNode); $this->cache->save($reflectionCacheKey, $variableCacheKey, $functionReflection->exportToCache()); return $functionReflection; } elseif ($identifier->isConstant()) { $fetchedConstantNode = null; foreach ($files as $file) { $fetchedConstantNodes = $this->fileNodesFetcher->fetchNodes($file)->getConstantNodes(); if (!array_key_exists($identifierName, $fetchedConstantNodes)) { return null; } /** @var FetchedNode $fetchedConstantNode */ $fetchedConstantNode = current($fetchedConstantNodes[$identifierName]); } if ($fetchedConstantNode === null) { return null; } [$reflectionCacheKey, $variableCacheKey] = $this->getCacheKeys($file, $identifier); $constantReflection = $this->nodeToReflection($reflector, $fetchedConstantNode, $this->findConstantPositionInConstNode($fetchedConstantNode->getNode(), $identifierName)); $this->cache->save($reflectionCacheKey, $variableCacheKey, $constantReflection->exportToCache()); return $constantReflection; } return null; } /** * @param FetchedNode|FetchedNode|FetchedNode $fetchedNode * @return \PHPStan\BetterReflection\Reflection\ReflectionClass|\PHPStan\BetterReflection\Reflection\ReflectionConstant|\PHPStan\BetterReflection\Reflection\ReflectionFunction */ private function nodeToReflection(Reflector $reflector, \PHPStan\Reflection\BetterReflection\SourceLocator\FetchedNode $fetchedNode, ?int $positionInNode = null) { $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 */ #[Override] 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 \PhpParser\Node\Stmt\Const_|\PhpParser\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(); } } fileNodesFetcher = $fileNodesFetcher; $this->fileFinder = $fileFinder; $this->phpVersion = $phpVersion; $this->symbolFinderInFiles = $symbolFinderInFiles; $this->cache = $cache; } public function createByDirectory(string $directory): \PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedDirectorySourceLocator { $files = $this->fileFinder->findFiles([$directory])->getFiles(); $fileHashes = []; foreach ($files as $file) { $hash = hash_file('sha256', $file); if ($hash === \false) { continue; } $fileHashes[$file] = $hash; } $cacheKey = sprintf('odsl-%s', $directory); return $this->createCachedDirectorySourceLocator($fileHashes, $cacheKey); } /** * @param array $fileHashes * @param non-empty-string $cacheKey */ private function createCachedDirectorySourceLocator(array $fileHashes, string $cacheKey): \PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedDirectorySourceLocator { $variableCacheKey = sprintf('v1-%s', $this->phpVersion->supportsEnums() ? 'enums' : 'no-enums'); $originalFileHashes = $fileHashes; /** @var array|null $cached */ $cached = $this->cache->load($cacheKey, $variableCacheKey); $findInFiles = []; 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; } $findInFiles[] = $file; } } else { $cached = []; } foreach (array_keys($fileHashes) as $file) { $findInFiles[] = $file; } foreach ($this->symbolFinderInFiles->findSymbols($findInFiles, $this->phpVersion->supportsEnums()) as $file => [$newClasses, $newFunctions, $newConstants]) { $newHash = $originalFileHashes[$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\OptimizedDirectorySourceLocator($this->fileNodesFetcher, $this->cache, $this->phpVersion, $classToFile, $functionToFiles, $constantToFile); } /** * @param string[] $files * @param non-empty-string&literal-string $uniqueCacheIdentifier */ public function createByFiles(array $files, string $uniqueCacheIdentifier): \PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedDirectorySourceLocator { $fileHashes = []; foreach ($files as $file) { $hash = hash_file('sha256', $file); if ($hash === \false) { continue; } $fileHashes[$file] = $hash; } return $this->createCachedDirectorySourceLocator($fileHashes, $uniqueCacheIdentifier); } /** * @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]; } } */ private array $locators = []; public function __construct(\PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedDirectorySourceLocatorFactory $factory) { $this->factory = $factory; } public function getOrCreate(string $directory): \PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedDirectorySourceLocator { if (array_key_exists($directory, $this->locators)) { return $this->locators[$directory]; } $this->locators[$directory] = $this->factory->createByDirectory($directory); return $this->locators[$directory]; } } */ private array $locators = []; public function __construct(PsrAutoloaderMapping $mapping, \PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedSingleFileSourceLocatorRepository $optimizedSingleFileSourceLocatorRepository) { $this->mapping = $mapping; $this->optimizedSingleFileSourceLocatorRepository = $optimizedSingleFileSourceLocatorRepository; } #[Override] 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 */ #[Override] public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array { return []; } } , functions: array, constants: array}|null */ private ?array $presentSymbols = null; public function __construct(\PHPStan\Reflection\BetterReflection\SourceLocator\FileNodesFetcher $fileNodesFetcher, Cache $cache, PhpVersion $phpVersion, string $fileName) { $this->fileNodesFetcher = $fileNodesFetcher; $this->cache = $cache; $this->phpVersion = $phpVersion; $this->fileName = $fileName; } private function getVariableCacheKey(string $file): string { $fileHash = hash_file('sha256', $file); if ($fileHash === \false) { throw new CouldNotReadFileException($file); } return sprintf('v2-%s-%s', $fileHash, $this->phpVersion->getVersionString()); } #[Override] public function locateIdentifier(Reflector $reflector, Identifier $identifier): ?Reflection { $presentSymbolsCacheKey = sprintf('osfsl-%s-presentSymbols', $this->fileName); if ($this->presentSymbols === null) { $variableCacheKey = $this->getVariableCacheKey($this->fileName); $this->presentSymbols = $this->cache->load($presentSymbolsCacheKey, $variableCacheKey); } 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; } } } $reflectionCacheKey = sprintf('osfsl-%s-%s-%s', $this->fileName, $identifier->getType()->getName(), $identifier->getName()); $variableCacheKey ??= $this->getVariableCacheKey($this->fileName); $reflectionVariableCacheKey = sprintf('%s-%s', $variableCacheKey, ComposerHelper::getBetterReflectionVersion()); $cachedReflection = $this->cache->load($reflectionCacheKey, $reflectionVariableCacheKey); if ($cachedReflection !== null) { if ($identifier->isConstant()) { return ReflectionConstant::importFromCache($reflector, $cachedReflection); } if ($identifier->isFunction()) { return ReflectionFunction::importFromCache($reflector, $cachedReflection); } if ($identifier->isClass()) { if (array_key_exists('backingType', $cachedReflection)) { return ReflectionEnum::importFromCache($reflector, $cachedReflection); } return ReflectionClass::importFromCache($reflector, $cachedReflection); } } $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; $this->cache->save($presentSymbolsCacheKey, $variableCacheKey, $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(); } $this->cache->save($reflectionCacheKey, $reflectionVariableCacheKey, $classReflection->exportToCache()); 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(); } $this->cache->save($reflectionCacheKey, $reflectionVariableCacheKey, $functionReflection->exportToCache()); 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(); } $this->cache->save($reflectionCacheKey, $reflectionVariableCacheKey, $constantReflection->exportToCache()); return $constantReflection; } return null; } throw new ShouldNotHappenException(); } #[Override] 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; } } */ private array $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]; } } * @see https://github.com/composer/composer/pull/10107 */ final class PhpFileCleaner { /** @var array */ private array $typeConfig = []; private string $rejectChars; private string $contents = ''; private int $len = 0; private int $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->rejectChars = '{}?"\'typeConfig)); } 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; $skip = strcspn($this->contents, $this->rejectChars, $this->index); if ($skip > 0) { $clean .= $char . substr($this->contents, $this->index, $skip); $this->index += $skip; } 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 { $rejectChars = '\\' . $delimiter; $this->index += 1; while ($this->index < $this->len) { $this->index += strcspn($this->contents, $rejectChars, $this->index); if ($this->index >= $this->len) { break; } 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) { $this->index += strcspn($this->contents, '*', $this->index); if ($this->peek('/')) { $this->index += 2; break; } $this->index += 1; } } private function skipToNewline(): void { $this->index += strcspn($this->contents, "\r\n", $this->index); } 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 $this->skipToNewline(); // skip newlines $this->index += strspn($this->contents, "\r\n", $this->index); } } 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; } } sourceLocator = $sourceLocator; $this->phpStormStubsSourceStubber = $phpStormStubsSourceStubber; } #[Override] 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); } #[Override] public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array { return $this->sourceLocator->locateIdentifiersByType($reflector, $identifierType); } } astLocator = $astLocator; $this->reflectionSourceStubber = $reflectionSourceStubber; } #[Override] 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))); } #[Override] public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array { return []; } } originalSourceLocator = $originalSourceLocator; } #[Override] 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); } #[Override] public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array { return $this->originalSourceLocator->locateIdentifiersByType($reflector, $identifierType); } } sourceLocator = $sourceLocator; } #[Override] 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); } #[Override] public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array { return $this->sourceLocator->locateIdentifiersByType($reflector, $identifierType); } } sourceLocator = $sourceLocator; $this->phpVersion = $phpVersion; } #[Override] public function locateIdentifier(Reflector $reflector, Identifier $identifier): ?Reflection { $reflection = $this->sourceLocator->locateIdentifier($reflector, $identifier); if ($reflection === null) { return null; } if ($reflection instanceof ReflectionClass || $reflection instanceof ReflectionFunction || $reflection instanceof ReflectionConstant) { $fileName = $reflection->getFileName(); if ($fileName !== null) { $normalized = str_replace('\\', '/', $fileName); if (str_contains($normalized, '/symfony/polyfill-php80/') && $this->phpVersion->getVersionId() >= 80000) { return null; } if (str_contains($normalized, '/symfony/polyfill-php81/') && $this->phpVersion->getVersionId() >= 80100) { return null; } if (str_contains($normalized, '/symfony/polyfill-php82/') && $this->phpVersion->getVersionId() >= 80200) { return null; } if (str_contains($normalized, '/symfony/polyfill-php83/') && $this->phpVersion->getVersionId() >= 80300) { return null; } if (str_contains($normalized, '/symfony/polyfill-php84/') && $this->phpVersion->getVersionId() >= 80400) { return null; } if (str_contains($normalized, '/symfony/polyfill-php85/') && $this->phpVersion->getVersionId() >= 80500) { return null; } } } return $reflection; } #[Override] public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array { return $this->sourceLocator->locateIdentifiersByType($reflector, $identifierType); } } cleaner = $cleaner; } /** * @param string[] $files * @return array */ public function findSymbols(array $files, bool $supportsEnums): array { $result = []; foreach ($files as $file) { $result[$file] = $this->findSymbolsInFile($file, $supportsEnums); } return $result; } /** * 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 findSymbolsInFile(string $file, bool $supportsEnums): array { $contents = @php_strip_whitespace($file); if ($contents === '') { return [[], [], []]; } $extraTypes = $supportsEnums ? '|enum' : ''; $matchResults = (bool) preg_match_all(sprintf('{\b(?:(?:class|interface|trait|const|function%s)\s)|(?:define\s*\()}i', $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', $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[] = self::normalizeConstantName(ltrim($namespace . $matches['cname'][$i], '\\')); } if ($matches['define'][$i] !== '') { $constants[] = self::normalizeConstantName($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]; } private static function normalizeConstantName(string $name): string { if (!str_contains($name, '\\')) { return $name; } $nameParts = array_filter(explode('\\', $name), static fn($part) => $part !== ''); return strtolower(implode('\\', array_slice($nameParts, 0, -1))) . '\\' . end($nameParts); } } 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()); } } phpVersion = $phpVersion; $this->class = $class; } public function getClass(): string { return $this->class; } public function isMethodSupported(MethodReflection $methodReflection): bool { return in_array($methodReflection->getName(), ['getDocComment', 'getType'], \true); } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type { if ($this->phpVersion->getVersionId() >= 80000) { return null; } if ($methodReflection->getName() === 'getDocComment') { return new UnionType([new StringType(), new ConstantBooleanType(\false)]); } if ($methodReflection->getName() === 'getType') { return new UnionType([new ObjectType(ReflectionType::class), new NullType()]); } return null; } } phpVersion = $phpVersion; } public function getClass(): string { return ReflectionEnum::class; } public function isMethodSupported(MethodReflection $methodReflection): bool { return in_array($methodReflection->getName(), ['getFileName', 'getStartLine', 'getEndLine', 'getDocComment', 'getReflectionConstant', 'getParentClass', 'getExtensionName', 'getBackingType'], \true); } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type { if ($this->phpVersion->getVersionId() >= 80000) { return null; } if (in_array($methodReflection->getName(), ['getFileName', 'getExtensionName'], \true)) { return new UnionType([new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]), new ConstantBooleanType(\false)]); } if ($methodReflection->getName() === 'getDocComment') { return new UnionType([new StringType(), new ConstantBooleanType(\false)]); } if (in_array($methodReflection->getName(), ['getStartLine', 'getEndLine'], \true)) { return new IntegerType(); } if ($methodReflection->getName() === 'getReflectionConstant') { return new UnionType([new ObjectType(ReflectionClassConstant::class), new ConstantBooleanType(\false)]); } if ($methodReflection->getName() === 'getParentClass') { return new UnionType([new ObjectType(ReflectionClass::class), new ConstantBooleanType(\false)]); } if ($methodReflection->getName() === 'getBackingType') { return new UnionType([new ObjectType(ReflectionNamedType::class), new NullType()]); } return null; } } function = $function; $this->variant = $variant; } /** * @param list $variants * @return list * @param \PHPStan\Reflection\FunctionReflection|\PHPStan\Reflection\ExtendedMethodReflection $function */ public static function createFromVariants($function, array $variants): array { return array_map(static fn(ExtendedParametersAcceptor $variant) => new self($function, $variant), $variants); } public function getTemplateTypeMap(): TemplateTypeMap { return $this->variant->getTemplateTypeMap(); } public function getResolvedTemplateTypeMap(): TemplateTypeMap { return $this->variant->getResolvedTemplateTypeMap(); } /** * @return list */ 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(): TrinaryLogic { return $this->function->acceptsNamedArguments(); } public function mustUseReturnValue(): TrinaryLogic { return $this->function->mustUseReturnValue(); } public function getAsserts(): Assertions { return $this->function->getAsserts(); } } [name, pos, testName] 'print_r' => ['return', 1, 'isTruthy'], 'var_export' => ['return', 1, 'isTruthy'], 'highlight_string' => ['return', 1, 'isTruthy'], ]; /** * @param ImpurePointIdentifier $identifier */ public function __construct(string $identifier, string $description, bool $certain) { $this->identifier = $identifier; $this->description = $description; $this->certain = $certain; } /** * Returns null if the function is known to be pure (no side effects). * * @param Arg[] $args * @param \PHPStan\Reflection\FunctionReflection|\PHPStan\Reflection\ExtendedMethodReflection $function */ public static function createFromVariant($function, ?ParametersAcceptor $variant, ?Scope $scope = null, array $args = []): ?self { if (!$function->hasSideEffects()->no()) { $certain = $function->isPure()->no(); if ($variant !== null) { $certain = $certain || $variant->getReturnType()->isVoid()->yes(); } if ($function instanceof FunctionReflection) { if (isset(self::SIDE_EFFECT_FLIP_PARAMETERS[$function->getName()]) && $scope !== null) { [$flipParameterName, $flipParameterPosition, $testName] = self::SIDE_EFFECT_FLIP_PARAMETERS[$function->getName()]; $sideEffectFlipped = \false; $hasNamedParameter = \false; $checker = ['isNotNull' => static fn(Type $type) => $type->isNull()->no(), 'isTruthy' => static fn(Type $type) => $type->toBoolean()->isTrue()->yes()][$testName]; foreach ($args as $i => $arg) { $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 null; } } 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; } } getClassReflection() */ public function isInClass(): bool; public function getClassReflection(): ?\PHPStan\Reflection\ClassReflection; /** * @deprecated Use canReadProperty() or canWriteProperty() */ public function canAccessProperty(\PHPStan\Reflection\PropertyReflection $propertyReflection): bool; public function canReadProperty(\PHPStan\Reflection\ExtendedPropertyReflection $propertyReflection): bool; public function canWriteProperty(\PHPStan\Reflection\ExtendedPropertyReflection $propertyReflection): bool; public function canCallMethod(\PHPStan\Reflection\MethodReflection $methodReflection): bool; public function canAccessConstant(\PHPStan\Reflection\ClassConstantReflection $constantReflection): bool; } */ private static array $checked = []; public static function isValidClassName(string $name): bool { if (!array_key_exists($name, self::$checked)) { // from https://stackoverflow.com/questions/3195614/validate-class-method-names-with-regex#comment104531582_12011255 self::$checked[$name] = Strings::match(ltrim($name, '\\'), '/^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*(\\\\[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)*$/') !== null; } return self::$checked[$name]; } } |null */ private ?array $ancestors = null; private ?string $cacheKey = null; /** @var array */ private array $subclasses = []; /** * @var string|false|null */ private $filename = \false; /** * @var string|false|null */ private $reflectionDocComment = \false; /** * @var false|\PHPStan\PhpDoc\ResolvedPhpDocBlock */ private $resolvedPhpDocBlock = \false; /** * @var false|\PHPStan\PhpDoc\ResolvedPhpDocBlock */ private $traitContextResolvedPhpDocBlock = \false; /** @var array|null */ private ?array $cachedInterfaces = null; /** * @var \PHPStan\Reflection\ClassReflection|false|null */ private $cachedParentClass = \false; /** @var array|null */ private ?array $typeAliases = null; /** @var array */ private static array $resolvingTypeAliasImports = []; /** @var array */ private array $hasMethodCache = []; /** @var array */ private array $hasPropertyCache = []; /** @var array */ private array $hasInstancePropertyCache = []; /** @var array */ private array $hasStaticPropertyCache = []; /** * @param ReflectionClass|ReflectionEnum $reflection */ public function __construct(\PHPStan\Reflection\ClassReflectionFactory $classReflectionFactory, \PHPStan\Reflection\ReflectionProvider $reflectionProvider, \PHPStan\Reflection\InitializerExprTypeResolver $initializerExprTypeResolver, FileTypeMapper $fileTypeMapper, StubPhpDocProvider $stubPhpDocProvider, PhpDocInheritanceResolver $phpDocInheritanceResolver, PhpVersion $phpVersion, SignatureMapProvider $signatureMapProvider, DeprecationProvider $deprecationProvider, \PHPStan\Reflection\AttributeReflectionFactory $attributeReflectionFactory, ClassReflectionExtensionRegistryProvider $classReflectionExtensionRegistryProvider, string $displayName, CoreReflectionClass $reflection, ?string $anonymousFilename, ?TemplateTypeMap $resolvedTemplateTypeMap, ?ResolvedPhpDocBlock $stubPhpDocBlock, ?string $extraCacheKey = null, ?TemplateTypeVarianceMap $resolvedCallSiteVarianceMap = null, ?bool $finalByKeywordOverride = null) { $this->classReflectionFactory = $classReflectionFactory; $this->reflectionProvider = $reflectionProvider; $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->fileTypeMapper = $fileTypeMapper; $this->stubPhpDocProvider = $stubPhpDocProvider; $this->phpDocInheritanceResolver = $phpDocInheritanceResolver; $this->phpVersion = $phpVersion; $this->signatureMapProvider = $signatureMapProvider; $this->deprecationProvider = $deprecationProvider; $this->attributeReflectionFactory = $attributeReflectionFactory; $this->classReflectionExtensionRegistryProvider = $classReflectionExtensionRegistryProvider; $this->displayName = $displayName; $this->reflection = $reflection; $this->anonymousFilename = $anonymousFilename; $this->resolvedTemplateTypeMap = $resolvedTemplateTypeMap; $this->stubPhpDocBlock = $stubPhpDocBlock; $this->extraCacheKey = $extraCacheKey; $this->resolvedCallSiteVarianceMap = $resolvedCallSiteVarianceMap; $this->finalByKeywordOverride = $finalByKeywordOverride; } /** * @return \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass|\PHPStan\BetterReflection\Reflection\Adapter\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; } 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->getActiveTemplateTypeMapForAncestorResolution(), $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 fn(): Type => 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->hasFinalByKeywordOverride()) { $cacheKey .= '-f=' . ($this->isFinalByKeyword() ? 't' : 'f'); } 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 list * @param \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass|\PHPStan\BetterReflection\Reflection\Adapter\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; } $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 || !$reflection->allowsDynamicProperties()) { continue; } return \true; } if ($this->isReadOnly()) { return \false; } if (UniversalObjectCratesClassReflectionExtension::isUniversalObjectCrate($this->reflectionProvider, $this)) { return \true; } $class = $this; do { $attributes = $class->reflection->getAttributes('AllowDynamicProperties'); $class = $class->getParentClass(); } while ($attributes === [] && $class !== null); return $attributes !== []; } /** * @deprecated Use hasInstanceProperty or hasStaticProperty instead */ public function hasProperty(string $propertyName): bool { if (array_key_exists($propertyName, $this->hasPropertyCache)) { return $this->hasPropertyCache[$propertyName]; } if ($this->isEnum()) { return $this->hasPropertyCache[$propertyName] = $this->hasNativeProperty($propertyName); } if ($this->classReflectionExtensionRegistryProvider->getRegistry()->getPhpClassReflectionExtension()->hasProperty($this, $propertyName)) { return $this->hasPropertyCache[$propertyName] = \true; } if ($this->allowsDynamicProperties()) { foreach ($this->classReflectionExtensionRegistryProvider->getRegistry()->getPropertiesClassReflectionExtensions() as $extension) { if ($extension->hasProperty($this, $propertyName)) { return $this->hasPropertyCache[$propertyName] = \true; } } } if ($this->classReflectionExtensionRegistryProvider->getRegistry()->getRequireExtendsPropertyClassReflectionExtension()->hasProperty($this, $propertyName)) { return $this->hasPropertyCache[$propertyName] = \true; } return $this->hasPropertyCache[$propertyName] = \false; } public function hasInstanceProperty(string $propertyName): bool { if (array_key_exists($propertyName, $this->hasInstancePropertyCache)) { return $this->hasInstancePropertyCache[$propertyName]; } if ($this->isEnum()) { return $this->hasInstancePropertyCache[$propertyName] = $this->hasNativeProperty($propertyName); } $phpClassReflectionExtension = $this->classReflectionExtensionRegistryProvider->getRegistry()->getPhpClassReflectionExtension(); if ($phpClassReflectionExtension->hasProperty($this, $propertyName)) { $property = $phpClassReflectionExtension->getNativeProperty($this, $propertyName); if (!$property->isStatic()) { return $this->hasInstancePropertyCache[$propertyName] = \true; } } if ($this->allowsDynamicProperties()) { foreach ($this->classReflectionExtensionRegistryProvider->getRegistry()->getPropertiesClassReflectionExtensions() as $extension) { if ($extension->hasProperty($this, $propertyName)) { $property = $extension->getProperty($this, $propertyName); if ($property->isStatic()) { continue; } return $this->hasInstancePropertyCache[$propertyName] = \true; } } } if ($this->classReflectionExtensionRegistryProvider->getRegistry()->getRequireExtendsPropertyClassReflectionExtension()->hasInstanceProperty($this, $propertyName)) { return $this->hasPropertyCache[$propertyName] = \true; } return $this->hasPropertyCache[$propertyName] = \false; } public function hasStaticProperty(string $propertyName): bool { if (array_key_exists($propertyName, $this->hasStaticPropertyCache)) { return $this->hasStaticPropertyCache[$propertyName]; } $phpClassReflectionExtension = $this->classReflectionExtensionRegistryProvider->getRegistry()->getPhpClassReflectionExtension(); if ($phpClassReflectionExtension->hasProperty($this, $propertyName)) { $property = $phpClassReflectionExtension->getNativeProperty($this, $propertyName); if ($property->isStatic()) { return $this->hasStaticPropertyCache[$propertyName] = \true; } } if ($this->classReflectionExtensionRegistryProvider->getRegistry()->getRequireExtendsPropertyClassReflectionExtension()->hasStaticProperty($this, $propertyName)) { return $this->hasStaticPropertyCache[$propertyName] = \true; } return $this->hasStaticPropertyCache[$propertyName] = \false; } public function hasMethod(string $methodName): bool { if (array_key_exists($methodName, $this->hasMethodCache)) { return $this->hasMethodCache[$methodName]; } if ($this->classReflectionExtensionRegistryProvider->getRegistry()->getPhpClassReflectionExtension()->hasMethod($this, $methodName)) { return $this->hasMethodCache[$methodName] = \true; } foreach ($this->classReflectionExtensionRegistryProvider->getRegistry()->getMethodsClassReflectionExtensions() as $extension) { if ($extension->hasMethod($this, $methodName)) { return $this->hasMethodCache[$methodName] = \true; } } if ($this->classReflectionExtensionRegistryProvider->getRegistry()->getRequireExtendsMethodsClassReflectionExtension()->hasMethod($this, $methodName)) { return $this->hasMethodCache[$methodName] = \true; } return $this->hasMethodCache[$methodName] = \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()); } $phpClassReflectionExtension = $this->classReflectionExtensionRegistryProvider->getRegistry()->getPhpClassReflectionExtension(); if ($phpClassReflectionExtension->hasMethod($this, $methodName)) { $method = $phpClassReflectionExtension->getMethod($this, $methodName); if ($scope->canCallMethod($method)) { return $this->methods[$key] = $method; } $this->methods[$key] = $method; } foreach ($this->classReflectionExtensionRegistryProvider->getRegistry()->getMethodsClassReflectionExtensions() 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])) { $requireExtendsMethodsClassReflectionExtension = $this->classReflectionExtensionRegistryProvider->getRegistry()->getRequireExtendsMethodsClassReflectionExtension(); if ($requireExtendsMethodsClassReflectionExtension->hasMethod($this, $methodName)) { $method = $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(string $propertyName, \PHPStan\Reflection\PropertyReflection $method): \PHPStan\Reflection\ExtendedPropertyReflection { if ($method instanceof \PHPStan\Reflection\ExtendedPropertyReflection) { return $method; } return new \PHPStan\Reflection\WrappedExtendedPropertyReflection($propertyName, $method); } public function hasNativeMethod(string $methodName): bool { return $this->classReflectionExtensionRegistryProvider->getRegistry()->getPhpClassReflectionExtension()->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->classReflectionExtensionRegistryProvider->getRegistry()->getPhpClassReflectionExtension()->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; } /** @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->instanceProperties as $name => $property) { if (!$property->isPrivate()) { continue; } unset($this->instanceProperties[$name]); } foreach ($this->staticProperties as $name => $property) { if (!$property->isPrivate()) { continue; } unset($this->staticProperties[$name]); } foreach ($this->methods as $name => $method) { if (!$method->isPrivate()) { continue; } unset($this->methods[$name]); } $this->classReflectionExtensionRegistryProvider->getRegistry()->getPhpClassReflectionExtension()->evictPrivateSymbols($this->getCacheKey()); } /** @deprecated Use getInstanceProperty or getStaticProperty */ 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()); } $phpClassReflectionExtension = $this->classReflectionExtensionRegistryProvider->getRegistry()->getPhpClassReflectionExtension(); if (!isset($this->properties[$key])) { if ($phpClassReflectionExtension->hasProperty($this, $propertyName)) { $property = $this->classReflectionExtensionRegistryProvider->getRegistry()->getPhpClassReflectionExtension()->getProperty($this, $propertyName, $scope); if ($scope->canReadProperty($property)) { return $this->properties[$key] = $property; } $this->properties[$key] = $property; } if ($this->allowsDynamicProperties()) { foreach ($this->classReflectionExtensionRegistryProvider->getRegistry()->getPropertiesClassReflectionExtensions() as $extension) { if (!$extension->hasProperty($this, $propertyName)) { continue; } $property = $this->wrapExtendedProperty($propertyName, $extension->getProperty($this, $propertyName)); if ($scope->canReadProperty($property)) { return $this->properties[$key] = $property; } $this->properties[$key] = $property; } } } // For BC purpose if ($phpClassReflectionExtension->hasProperty($this, $propertyName)) { $property = $phpClassReflectionExtension->getProperty($this, $propertyName, $scope); return $this->properties[$key] = $property; } if (!isset($this->properties[$key])) { $requireExtendsPropertiesClassReflectionExtension = $this->classReflectionExtensionRegistryProvider->getRegistry()->getRequireExtendsPropertyClassReflectionExtension(); if ($requireExtendsPropertiesClassReflectionExtension->hasProperty($this, $propertyName)) { $property = $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 getInstanceProperty(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->instanceProperties[$key])) { $phpClassReflectionExtension = $this->classReflectionExtensionRegistryProvider->getRegistry()->getPhpClassReflectionExtension(); if ($phpClassReflectionExtension->hasProperty($this, $propertyName)) { $property = $phpClassReflectionExtension->getProperty($this, $propertyName, $scope); if (!$property->isStatic()) { if ($scope->canReadProperty($property)) { return $this->instanceProperties[$key] = $property; } $this->instanceProperties[$key] = $property; } } if ($this->allowsDynamicProperties()) { foreach ($this->classReflectionExtensionRegistryProvider->getRegistry()->getPropertiesClassReflectionExtensions() as $extension) { if (!$extension->hasProperty($this, $propertyName)) { continue; } $nakedProperty = $extension->getProperty($this, $propertyName); if ($nakedProperty->isStatic()) { continue; } $property = $this->wrapExtendedProperty($propertyName, $nakedProperty); if ($scope->canReadProperty($property)) { return $this->instanceProperties[$key] = $property; } $this->instanceProperties[$key] = $property; } } } if (!isset($this->instanceProperties[$key])) { $requireExtendsPropertiesClassReflectionExtension = $this->classReflectionExtensionRegistryProvider->getRegistry()->getRequireExtendsPropertyClassReflectionExtension(); if ($requireExtendsPropertiesClassReflectionExtension->hasInstanceProperty($this, $propertyName)) { $property = $requireExtendsPropertiesClassReflectionExtension->getInstanceProperty($this, $propertyName); $this->instanceProperties[$key] = $property; } } if (!isset($this->instanceProperties[$key])) { throw new \PHPStan\Reflection\MissingPropertyFromReflectionException($this->getName(), $propertyName); } return $this->instanceProperties[$key]; } public function getStaticProperty(string $propertyName): \PHPStan\Reflection\ExtendedPropertyReflection { $key = $propertyName; if (isset($this->staticProperties[$key])) { return $this->staticProperties[$key]; } $phpClassReflectionExtension = $this->classReflectionExtensionRegistryProvider->getRegistry()->getPhpClassReflectionExtension(); if ($phpClassReflectionExtension->hasProperty($this, $propertyName)) { $nakedProperty = $phpClassReflectionExtension->getProperty($this, $propertyName, new OutOfClassScope()); if ($nakedProperty->isStatic()) { $property = $this->wrapExtendedProperty($propertyName, $nakedProperty); if ($property->isStatic()) { return $this->staticProperties[$key] = $property; } } } $requireExtendsPropertiesClassReflectionExtension = $this->classReflectionExtensionRegistryProvider->getRegistry()->getRequireExtendsPropertyClassReflectionExtension(); if ($requireExtendsPropertiesClassReflectionExtension->hasStaticProperty($this, $propertyName)) { $property = $requireExtendsPropertiesClassReflectionExtension->getStaticProperty($this, $propertyName); return $this->staticProperties[$key] = $property; } throw new \PHPStan\Reflection\MissingPropertyFromReflectionException($this->getName(), $propertyName); } public function hasNativeProperty(string $propertyName): bool { return $this->classReflectionExtensionRegistryProvider->getRegistry()->getPhpClassReflectionExtension()->hasProperty($this, $propertyName); } public function getNativeProperty(string $propertyName): PhpPropertyReflection { if (!$this->hasNativeProperty($propertyName)) { throw new \PHPStan\Reflection\MissingPropertyFromReflectionException($this->getName(), $propertyName); } return $this->classReflectionExtensionRegistryProvider->getRegistry()->getPhpClassReflectionExtension()->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 * @phpstan-assert-if-true ReflectionEnum $this->getNativeReflection() */ 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 && $case->hasBackingValue()) { $valueType = $this->initializerExprTypeResolver->getType($case->getValueExpression(), $initializerExprContext); } $caseName = $case->getName(); $attributes = $this->attributeReflectionFactory->fromNativeReflection($case->getAttributes(), \PHPStan\Reflection\InitializerExprContext::fromClass($this->getName(), $this->getFileName())); $cases[$caseName] = new \PHPStan\Reflection\EnumCaseReflection($this, $case, $valueType, $attributes, $this->deprecationProvider); } 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 && $case->hasBackingValue()) { $valueType = $this->initializerExprTypeResolver->getType($case->getValueExpression(), \PHPStan\Reflection\InitializerExprContext::fromClassReflection($this)); } $attributes = $this->attributeReflectionFactory->fromNativeReflection($case->getAttributes(), \PHPStan\Reflection\InitializerExprContext::fromClass($this->getName(), $this->getFileName())); return new \PHPStan\Reflection\EnumCaseReflection($this, $case, $valueType, $attributes, $this->deprecationProvider); } 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); } /** * @deprecated Use isSubclassOfClass instead. */ public function isSubclassOf(string $className): bool { if (!$this->reflectionProvider->hasClass($className)) { return \false; } return $this->isSubclassOfClass($this->reflectionProvider->getClass($className)); } public function isSubclassOfClass(self $class): bool { $cacheKey = $class->getCacheKey(); if (isset($this->subclasses[$cacheKey])) { return $this->subclasses[$cacheKey]; } if ($class->isFinalByKeyword() || $class->isAnonymous()) { return $this->subclasses[$cacheKey] = \false; } try { return $this->subclasses[$cacheKey] = $this->reflection->isSubclassOf($class->getName()); } catch (ReflectionException $e) { return $this->subclasses[$cacheKey] = \false; } } public function implementsInterface(string $className): bool { try { return $this->reflection->implementsInterface($className); } catch (ReflectionException $e) { return \false; } } /** * @return list */ public function getParents(): array { $parents = []; $parent = $this->getParentClass(); while ($parent !== null) { $parents[] = $parent; $parent = $parent->getParentClass(); } return $parents; } /** * @return array */ 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 array */ 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 array */ 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->getActiveTemplateTypeMapForAncestorResolution(), $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 fn(): Type => 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(fn(ReflectionClass $trait): \PHPStan\Reflection\ClassReflection => $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); } $deprecation = $this->deprecationProvider->getClassConstantDeprecation($reflectionConstant); $deprecatedDescription = $deprecation === null ? null : $deprecation->getDescription(); $isDeprecated = $deprecation !== null; $declaringClass = $this->getAncestorWithClassName($reflectionConstant->getDeclaringClass()->getName()); if ($declaringClass === null) { throw new ShouldNotHappenException(); } $fileName = $declaringClass->getFileName(); $phpDocType = null; $currentResolvedPhpDoc = $this->findConstantResolvedPhpDoc($reflectionConstant); $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']; } $resolvedPhpDoc = $this->phpDocInheritanceResolver->resolvePhpDocForConstant($declaringClass, $name, $currentResolvedPhpDoc); $isInternal = \false; $isFinal = \false; if ($resolvedPhpDoc !== null) { if (!$isDeprecated) { $deprecatedDescription = $resolvedPhpDoc->getDeprecatedTag() !== null ? $resolvedPhpDoc->getDeprecatedTag()->getMessage() : null; $isDeprecated = $resolvedPhpDoc->isDeprecated(); } $isInternal = $resolvedPhpDoc->isInternal(); $isFinal = $resolvedPhpDoc->isFinal(); $phpDocType = self::resolveConstantVarPhpDocType($resolvedPhpDoc, $nativeType, $declaringClass); } $this->constants[$name] = new \PHPStan\Reflection\RealClassClassConstantReflection($this->initializerExprTypeResolver, $declaringClass, $reflectionConstant, $nativeType, $phpDocType, $resolvedPhpDoc, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal, $this->attributeReflectionFactory->fromNativeReflection($reflectionConstant->getAttributes(), \PHPStan\Reflection\InitializerExprContext::fromClass($declaringClass->getName(), $fileName))); } return $this->constants[$name]; } /** * Returns the @var PHPDoc type of a class constant, if any. * Does not walk ancestors, so it's safe to call from class-constant * type resolution (which re-enters via @extends>). * * @internal */ public function getConstantPhpDocType(string $name): ?Type { $reflectionConstant = $this->getNativeReflection()->getReflectionConstant($name); if ($reflectionConstant === \false) { return null; } $resolvedPhpDoc = $this->findConstantResolvedPhpDoc($reflectionConstant); if ($resolvedPhpDoc === null) { return null; } $nativeType = null; if ($reflectionConstant->getType() !== null) { $nativeType = TypehintHelper::decideTypeFromReflection($reflectionConstant->getType()); } $declaringClassName = $reflectionConstant->getDeclaringClass()->getName(); if ($declaringClassName === $this->getName()) { $declaringClass = $this; } else { $declaringClass = $this->getAncestorWithClassName($declaringClassName); if ($declaringClass === null) { return null; } } return self::resolveConstantVarPhpDocType($resolvedPhpDoc, $nativeType, $declaringClass); } private function findConstantResolvedPhpDoc(ReflectionClassConstant $reflectionConstant): ?ResolvedPhpDocBlock { $declaringClassName = $reflectionConstant->getDeclaringClass()->getName(); $resolvedPhpDoc = $this->stubPhpDocProvider->findClassConstantPhpDoc($declaringClassName, $reflectionConstant->getName()); if ($resolvedPhpDoc !== null) { return $resolvedPhpDoc; } $docComment = $reflectionConstant->getDocComment(); if ($docComment === \false) { return null; } return $this->fileTypeMapper->getResolvedPhpDoc($reflectionConstant->getDeclaringClass()->getFileName() ?: null, $declaringClassName, null, null, $docComment); } private static function resolveConstantVarPhpDocType(ResolvedPhpDocBlock $resolvedPhpDoc, ?Type $nativeType, self $declaringClass): ?Type { $varTags = $resolvedPhpDoc->getVarTags(); if (!isset($varTags[0]) || count($varTags) !== 1) { return null; } $varTag = $varTags[0]; if (!$varTag->isExplicit() && $nativeType !== null && !$nativeType->isSuperTypeOf($varTag->getType())->yes()) { return null; } return TemplateTypeHelper::resolveTemplateTypes($varTag->getType(), $declaringClass->getActiveTemplateTypeMap(), $declaringClass->getCallSiteVarianceMap(), TemplateTypeVariance::createInvariant()); } public function hasTraitUse(string $traitName): bool { return in_array($traitName, $this->getTraitNames(), \true); } /** * @return list */ private function getTraitNames(): array { $class = $this->reflection; $traitNames = array_map(static fn(ReflectionClass $class) => $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(); $localAliases = array_map(static fn(TypeAliasTag $typeAliasTag): TypeAlias => $typeAliasTag->getTypeAlias(), $typeAliasTags); // prevent circular imports if (array_key_exists($this->getName(), self::$resolvingTypeAliasImports)) { if ($localAliases !== []) { return $this->typeAliases = $localAliases; } 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()]); $this->typeAliases = array_filter(array_merge($importedAliases, $localAliases), static fn(?TypeAlias $typeAlias): bool => $typeAlias !== null); } return $this->typeAliases; } public function getDeprecatedDescription(): ?string { if ($this->isDeprecated === null) { $this->resolveDeprecation(); } return $this->deprecatedDescription; } public function isDeprecated(): bool { if ($this->isDeprecated === null) { $this->resolveDeprecation(); } return $this->isDeprecated; } /** * @phpstan-assert bool $this->isDeprecated */ private function resolveDeprecation(): void { $deprecation = $this->deprecationProvider->getClassDeprecation($this->reflection); if ($deprecation !== null) { $this->isDeprecated = \true; $this->deprecatedDescription = $deprecation->getDescription(); return; } $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc !== null && $resolvedPhpDoc->isDeprecated()) { $this->isDeprecated = \true; $this->deprecatedDescription = $resolvedPhpDoc->getDeprecatedTag() !== null ? $resolvedPhpDoc->getDeprecatedTag()->getMessage() : null; return; } if ($this->isTrait() && count($this->getNativeReflection()->getAttributes('Deprecated')) > 0) { $this->isDeprecated = \true; $this->deprecatedDescription = null; return; } $this->isDeprecated = \false; $this->deprecatedDescription = null; } 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 hasFinalByKeywordOverride(): bool { return $this->finalByKeywordOverride !== null; } public function isFinalByKeyword(): bool { if ($this->isAnonymous()) { return \true; } if ($this->finalByKeywordOverride !== null) { return $this->finalByKeywordOverride; } 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) { if ($i === '') { throw new ShouldNotHappenException(); } $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; } /** * @return list */ public function getAttributes(): array { return $this->attributeReflectionFactory->fromNativeReflection($this->reflection->getAttributes(), \PHPStan\Reflection\InitializerExprContext::fromClass($this->getName(), $this->getFileName())); } public function getAttributeClassFlags(): int { $flags = $this->findAttributeFlags(); if ($flags === null) { throw new ShouldNotHappenException(); } return $flags; } public function getObjectType(): ObjectType { if (!$this->isGeneric()) { return new ObjectType($this->getName()); } return new GenericObjectType($this->getName(), $this->typeMapToList($this->getActiveTemplateTypeMap()), \null, \null, $this->varianceMapToList($this->getCallSiteVarianceMap())); } 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 fn(TemplateTag $tag): Type => 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(); } /** * Returns a template type map for resolving ancestor type declarations (@extends, @implements). * Like getPossiblyIncompleteActiveTemplateTypeMap(), but resolves ErrorType entries * to their template bounds when the bound is not mixed. This ensures that when a child * class narrows a template bound (e.g. `@template T of SpecificType`), the narrowed bound * is propagated to ancestor declarations instead of being lost as ErrorType. */ private function getActiveTemplateTypeMapForAncestorResolution(): TemplateTypeMap { $map = $this->getPossiblyIncompleteActiveTemplateTypeMap(); $templateTypeMap = $this->getTemplateTypeMap(); return $map->map(static function (string $name, Type $type) use ($templateTypeMap): Type { if (!$type instanceof ErrorType) { return $type; } $templateType = $templateTypeMap->getType($name); if (!$templateType instanceof TemplateType) { return $type; } $bound = $templateType->getBound(); if ($bound instanceof MixedType) { return $type; } return TemplateTypeHelper::resolveToDefaults($templateType); }); } 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->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; $className = $this->getName(); foreach ($resolvedPhpDoc->getTemplateTags() as $tag) { $type = $types[$i] ?? $tag->getDefault() ?? $tag->getBound(); if ($type instanceof TemplateType && $type->getScope()->getClassName() === $className) { $resolved = $map[$type->getName()] ?? null; if ($resolved !== null && !$resolved instanceof TemplateType) { $type = $resolved; } } $map[$tag->getName()] = $type; $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 list */ 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 list */ 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 $this->classReflectionFactory->create($this->displayName, $this->reflection, $this->anonymousFilename, $this->typeMapFromList($types), $this->stubPhpDocBlock, null, $this->resolvedCallSiteVarianceMap, $this->finalByKeywordOverride); } /** * @param array $variances */ public function withVariances(array $variances): self { return $this->classReflectionFactory->create($this->displayName, $this->reflection, $this->anonymousFilename, $this->resolvedTemplateTypeMap, $this->stubPhpDocBlock, null, $this->varianceMapFromList($variances), $this->finalByKeywordOverride); } public function asFinal(): self { if ($this->getNativeReflection()->isFinal()) { return $this; } if ($this->finalByKeywordOverride === \true) { return $this; } if (!$this->isClass()) { return $this; } if ($this->isAbstract()) { return $this; } return $this->classReflectionFactory->create($this->displayName, $this->reflection, $this->anonymousFilename, $this->resolvedTemplateTypeMap, $this->stubPhpDocBlock, null, $this->resolvedCallSiteVarianceMap, \true); } public function removeFinalKeywordOverride(): self { if ($this->getNativeReflection()->isFinal()) { return $this; } if ($this->finalByKeywordOverride === \false) { return $this; } if (!$this->isClass()) { return $this; } if ($this->isAbstract()) { return $this; } return $this->classReflectionFactory->create($this->displayName, $this->reflection, $this->anonymousFilename, $this->resolvedTemplateTypeMap, $this->stubPhpDocBlock, null, $this->resolvedCallSiteVarianceMap, \false); } 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 getSealedTags(): array { $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { return []; } return $resolvedPhpDoc->getSealedTags(); } /** * @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 list */ 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->classReflectionExtensionRegistryProvider->getRegistry()->getAllowedSubTypesClassReflectionExtensions() as $allowedSubTypesClassReflectionExtension) { if ($allowedSubTypesClassReflectionExtension->supports($this)) { return $allowedSubTypesClassReflectionExtension->getAllowedSubTypes($this); } } return null; } } propertiesClassReflectionExtensions = $propertiesClassReflectionExtensions; $this->methodsClassReflectionExtensions = $methodsClassReflectionExtensions; $this->allowedSubTypesClassReflectionExtensions = $allowedSubTypesClassReflectionExtensions; $this->requireExtendsPropertiesClassReflectionExtension = $requireExtendsPropertiesClassReflectionExtension; $this->requireExtendsMethodsClassReflectionExtension = $requireExtendsMethodsClassReflectionExtension; $this->phpClassReflectionExtension = $phpClassReflectionExtension; } /** * @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; } public function getPhpClassReflectionExtension(): PhpClassReflectionExtension { return $this->phpClassReflectionExtension; } } */ private array $attributes; /** * @param list $attributes */ public function __construct(string $name, Type $valueType, ?string $fileName, TrinaryLogic $isDeprecated, ?string $deprecatedDescription, array $attributes) { $this->name = $name; $this->valueType = $valueType; $this->fileName = $fileName; $this->isDeprecated = $isDeprecated; $this->deprecatedDescription = $deprecatedDescription; $this->attributes = $attributes; } 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(); } public function getAttributes(): array { return $this->attributes; } } $part !== ''); return strtolower(implode('\\', array_slice($nameParts, 0, -1))) . '\\' . end($nameParts); } } */ public function getAttributes(): array; } */ private array $additionalConstructors; /** @var array> */ private array $additionalConstructorsCache = []; /** * @param list $additionalConstructors */ public function __construct( Container $container, #[AutowiredParameter] 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; } } description; } public static function createWithDescription(string $description): self { $clone = new self(); $clone->description = $description; return $clone; } } $propertyDeprecationExtensions */ private ?array $propertyDeprecationExtensions = null; /** @var ?array $methodDeprecationExtensions */ private ?array $methodDeprecationExtensions = null; /** @var ?array $classConstantDeprecationExtensions */ private ?array $classConstantDeprecationExtensions = null; /** @var ?array $classDeprecationExtensions */ private ?array $classDeprecationExtensions = null; /** @var ?array $functionDeprecationExtensions */ private ?array $functionDeprecationExtensions = null; /** @var ?array $constantDeprecationExtensions */ private ?array $constantDeprecationExtensions = null; /** @var ?array $enumCaseDeprecationExtensions */ private ?array $enumCaseDeprecationExtensions = null; public function __construct(Container $container) { $this->container = $container; } public function getPropertyDeprecation(ReflectionProperty $reflectionProperty): ?\PHPStan\Reflection\Deprecation\Deprecation { $this->propertyDeprecationExtensions ??= $this->container->getServicesByTag(\PHPStan\Reflection\Deprecation\PropertyDeprecationExtension::PROPERTY_EXTENSION_TAG); foreach ($this->propertyDeprecationExtensions as $extension) { $deprecation = $extension->getPropertyDeprecation($reflectionProperty); if ($deprecation !== null) { return $deprecation; } } return null; } public function getMethodDeprecation(ReflectionMethod $methodReflection): ?\PHPStan\Reflection\Deprecation\Deprecation { $this->methodDeprecationExtensions ??= $this->container->getServicesByTag(\PHPStan\Reflection\Deprecation\MethodDeprecationExtension::METHOD_EXTENSION_TAG); foreach ($this->methodDeprecationExtensions as $extension) { $deprecation = $extension->getMethodDeprecation($methodReflection); if ($deprecation !== null) { return $deprecation; } } return null; } public function getClassConstantDeprecation(ReflectionClassConstant $reflectionConstant): ?\PHPStan\Reflection\Deprecation\Deprecation { $this->classConstantDeprecationExtensions ??= $this->container->getServicesByTag(\PHPStan\Reflection\Deprecation\ClassConstantDeprecationExtension::CLASS_CONSTANT_EXTENSION_TAG); foreach ($this->classConstantDeprecationExtensions as $extension) { $deprecation = $extension->getClassConstantDeprecation($reflectionConstant); if ($deprecation !== null) { return $deprecation; } } return null; } /** * @param \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass|\PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnum $reflection */ public function getClassDeprecation($reflection): ?\PHPStan\Reflection\Deprecation\Deprecation { $this->classDeprecationExtensions ??= $this->container->getServicesByTag(\PHPStan\Reflection\Deprecation\ClassDeprecationExtension::CLASS_EXTENSION_TAG); foreach ($this->classDeprecationExtensions as $extension) { $deprecation = $extension->getClassDeprecation($reflection); if ($deprecation !== null) { return $deprecation; } } return null; } public function getFunctionDeprecation(ReflectionFunction $reflectionFunction): ?\PHPStan\Reflection\Deprecation\Deprecation { $this->functionDeprecationExtensions ??= $this->container->getServicesByTag(\PHPStan\Reflection\Deprecation\FunctionDeprecationExtension::FUNCTION_EXTENSION_TAG); foreach ($this->functionDeprecationExtensions as $extension) { $deprecation = $extension->getFunctionDeprecation($reflectionFunction); if ($deprecation !== null) { return $deprecation; } } return null; } public function getConstantDeprecation(ReflectionConstant $constantReflection): ?\PHPStan\Reflection\Deprecation\Deprecation { $this->constantDeprecationExtensions ??= $this->container->getServicesByTag(\PHPStan\Reflection\Deprecation\ConstantDeprecationExtension::CONSTANT_EXTENSION_TAG); foreach ($this->constantDeprecationExtensions as $extension) { $deprecation = $extension->getConstantDeprecation($constantReflection); if ($deprecation !== null) { return $deprecation; } } return null; } /** * @param \PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumUnitCase|\PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumBackedCase $enumCaseReflection */ public function getEnumCaseDeprecation($enumCaseReflection): ?\PHPStan\Reflection\Deprecation\Deprecation { $this->enumCaseDeprecationExtensions ??= $this->container->getServicesByTag(\PHPStan\Reflection\Deprecation\EnumCaseDeprecationExtension::ENUM_CASE_EXTENSION_TAG); foreach ($this->enumCaseDeprecationExtensions as $extension) { $deprecation = $extension->getEnumCaseDeprecation($enumCaseReflection); if ($deprecation !== null) { return $deprecation; } } return null; } } */ private array $variants; /** * @var list|null */ private ?array $namedArgumentsVariants; private ?Type $selfOutType; private ?Type $throwType; private Assertions $assertions; /** * @param list $variants * @param list|null $namedArgumentsVariants */ public function __construct(ClassReflection $declaringClass, ExtendedMethodReflection $reflection, array $variants, ?array $namedArgumentsVariants, ?Type $selfOutType, ?Type $throwType, Assertions $assertions) { $this->declaringClass = $declaringClass; $this->reflection = $reflection; $this->variants = $variants; $this->namedArgumentsVariants = $namedArgumentsVariants; $this->selfOutType = $selfOutType; $this->throwType = $throwType; $this->assertions = $assertions; } 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(): ExtendedParametersAcceptor { $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 isBuiltin(): TrinaryLogic { $builtin = $this->reflection->isBuiltin(); if (is_bool($builtin)) { return TrinaryLogic::createFromBoolean($builtin); } return $builtin; } public function getThrowType(): ?Type { return $this->throwType; } public function hasSideEffects(): TrinaryLogic { return $this->reflection->hasSideEffects(); } public function getAsserts(): Assertions { return $this->assertions; } public function acceptsNamedArguments(): TrinaryLogic { return $this->reflection->acceptsNamedArguments(); } public function getSelfOutType(): ?Type { 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; } public function isPure(): TrinaryLogic { return $this->reflection->isPure(); } public function getAttributes(): array { return $this->reflection->getAttributes(); } public function mustUseReturnValue(): TrinaryLogic { return $this->reflection->mustUseReturnValue(); } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return $this->reflection->getResolvedPhpDoc(); } } declaringClass = $declaringClass; $this->reflection = $reflection; $this->readableType = $readableType; $this->writableType = $writableType; $this->phpDocType = $phpDocType; $this->nativeType = $nativeType; } public function getName(): string { return $this->reflection->getName(); } 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 hasPhpDocType(): bool { return $this->reflection->hasPhpDocType(); } public function getPhpDocType(): Type { return $this->phpDocType; } public function hasNativeType(): bool { return $this->reflection->hasNativeType(); } public function getNativeType(): Type { return $this->nativeType; } 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; } public function isAbstract(): TrinaryLogic { return $this->reflection->isAbstract(); } public function isFinalByKeyword(): TrinaryLogic { return $this->reflection->isFinalByKeyword(); } public function isFinal(): TrinaryLogic { return $this->reflection->isFinal(); } public function isVirtual(): TrinaryLogic { return $this->reflection->isVirtual(); } public function hasHook(string $hookType): bool { return $this->reflection->hasHook($hookType); } public function getHook(string $hookType): ExtendedMethodReflection { return $this->reflection->getHook($hookType); } public function isProtectedSet(): bool { return $this->reflection->isProtectedSet(); } public function isPrivateSet(): bool { return $this->reflection->isPrivateSet(); } public function getAttributes(): array { return $this->reflection->getAttributes(); } public function isDummy(): TrinaryLogic { return $this->reflection->isDummy(); } } name = $name; } public function getDeclaringClass(): ClassReflection { $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); return $reflectionProvider->getClass(stdClass::class); } public function isFinal(): bool { return \false; } public function isFinalByKeyword(): bool { return \false; } 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; } 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; } public function hasPhpDocType(): bool { return \false; } public function getPhpDocType(): ?Type { return null; } public function hasNativeType(): bool { return \false; } public function getNativeType(): ?Type { return null; } public function getAttributes(): array { return []; } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { 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 ExtendedFunctionVariant(TemplateTypeMap::createEmpty(), null, [], \false, new VoidType(), new MixedType(), new MixedType(), null)]; } public function getOnlyVariant(): ExtendedParametersAcceptor { 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 isBuiltin(): 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(): TrinaryLogic { return TrinaryLogic::createFromBoolean($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(); } public function getAttributes(): array { return []; } public function mustUseReturnValue(): TrinaryLogic { // Align with the getAttributes() returning empty return TrinaryLogic::createNo(); } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return null; } } 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(): ExtendedParametersAcceptor { 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 isBuiltin(): 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(): TrinaryLogic { return TrinaryLogic::createYes(); } 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(); } public function getAttributes(): array { return []; } public function mustUseReturnValue(): TrinaryLogic { // Align with the getAttributes() returning empty return TrinaryLogic::createNo(); } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return null; } } name = $name; } public function getName(): string { return $this->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 hasPhpDocType(): bool { return \false; } public function getPhpDocType(): Type { return new MixedType(); } public function hasNativeType(): bool { return \false; } public function getNativeType(): Type { return new MixedType(); } 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; } public function isAbstract(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinalByKeyword(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinal(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isVirtual(): TrinaryLogic { return TrinaryLogic::createNo(); } public function hasHook(string $hookType): bool { return \false; } public function getHook(string $hookType): ExtendedMethodReflection { throw new ShouldNotHappenException(); } public function isProtectedSet(): bool { return \false; } public function isPrivateSet(): bool { return \false; } public function getAttributes(): array { return []; } public function isDummy(): TrinaryLogic { return TrinaryLogic::createYes(); } } */ private array $attributes; private bool $isDeprecated; private ?string $deprecatedDescription; /** * @param list $attributes * @param \PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumUnitCase|\PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumBackedCase $reflection */ public function __construct(\PHPStan\Reflection\ClassReflection $declaringEnum, $reflection, ?Type $backingValueType, array $attributes, DeprecationProvider $deprecationProvider) { $this->declaringEnum = $declaringEnum; $this->reflection = $reflection; $this->backingValueType = $backingValueType; $this->attributes = $attributes; $deprecation = $deprecationProvider->getEnumCaseDeprecation($reflection); if ($deprecation !== null) { $this->isDeprecated = \true; $this->deprecatedDescription = $deprecation->getDescription(); } elseif ($reflection->isDeprecated()) { $attributes = $this->reflection->getBetterReflection()->getAttributes(); $this->isDeprecated = \true; $this->deprecatedDescription = DeprecatedAttributeHelper::getDeprecatedDescription($attributes); } else { $this->isDeprecated = \false; $this->deprecatedDescription = null; } } public function getDeclaringEnum(): \PHPStan\Reflection\ClassReflection { return $this->declaringEnum; } public function getName(): string { return $this->reflection->getName(); } public function getEnumCaseObjectType(): EnumCaseObjectType { return new EnumCaseObjectType($this->declaringEnum->getName(), $this->getName()); } public function getBackingValueType(): ?Type { return $this->backingValueType; } public function isDeprecated(): TrinaryLogic { return TrinaryLogic::createFromBoolean($this->isDeprecated); } public function getDeprecatedDescription(): ?string { return $this->deprecatedDescription; } /** * @return list */ public function getAttributes(): array { return $this->attributes; } } $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, TrinaryLogic $acceptsNamedArguments, TrinaryLogic $mustUseReturnValue, ?\PHPStan\Reflection\Assertions $assertions = null) { $this->throwPoints = $throwPoints; $this->isPure = $isPure; $this->impurePoints = $impurePoints; $this->invalidateExpressions = $invalidateExpressions; $this->usedVariables = $usedVariables; $this->acceptsNamedArguments = $acceptsNamedArguments; $this->mustUseReturnValue = $mustUseReturnValue; $this->assertions = $assertions; 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(): TrinaryLogic { return $this->acceptsNamedArguments; } public function mustUseReturnValue(): TrinaryLogic { return $this->mustUseReturnValue; } public function getAsserts(): \PHPStan\Reflection\Assertions { return $this->assertions ?? \PHPStan\Reflection\Assertions::createEmpty(); } } $parameters * @api */ 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 list */ public function getParameters(): array { /** @var list $parameters */ $parameters = parent::getParameters(); return $parameters; } public function getPhpDocReturnType(): Type { return $this->phpDocReturnType; } public function getNativeReturnType(): Type { return $this->nativeReturnType; } } */ public function getVariants(): array; /** @internal */ public function getOnlyVariant(): \PHPStan\Reflection\ExtendedParametersAcceptor; /** * Returns alternative signatures used when the method is called with named arguments. * Returns null if the named argument variants are the same as regular variants. * * @return list|null */ public function getNamedArgumentsVariants(): ?array; public function acceptsNamedArguments(): TrinaryLogic; public function getAsserts(): \PHPStan\Reflection\Assertions; /** * Used for fluent interfaces where calling a method changes the generic * type parameters of $this (e.g. a builder pattern). */ public function getSelfOutType(): ?Type; public function returnsByReference(): TrinaryLogic; public function isFinalByKeyword(): TrinaryLogic; /** * @return \PHPStan\TrinaryLogic|bool */ public function isAbstract(); /** * @return \PHPStan\TrinaryLogic|bool */ public function isBuiltin(); /** * In most cases hasSideEffects() is more practical as it also accounts * for void return type (methods returning void are always impure). */ public function isPure(): TrinaryLogic; /** @return list */ public function getAttributes(): array; /** * On PHP 8.5+ if the return value is unused at runtime, a warning is emitted. * PHPStan reports this during analysis regardless of PHP version. */ public function mustUseReturnValue(): TrinaryLogic; public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock; } */ public function getAttributes(): array; } */ public function getParameters(): array; public function getPhpDocReturnType(): Type; public function getNativeReturnType(): Type; public function getCallSiteVarianceMap(): TemplateTypeVarianceMap; } */ public function getAttributes(): array; /** * Returns yes() for properties that represent possibly-defined properties * on non-final classes, mixed, object, etc. — placeholders PHPStan creates * when it cannot prove a property doesn't exist. */ public function isDummy(): TrinaryLogic; } */ public function getVariants(): array; /** @internal */ public function getOnlyVariant(): \PHPStan\Reflection\ExtendedParametersAcceptor; /** * Returns alternative signatures used when the function is called with named arguments. * Returns null if the named argument variants are the same as regular variants. * * @return list|null */ public function getNamedArgumentsVariants(): ?array; public function acceptsNamedArguments(): TrinaryLogic; public function isDeprecated(): TrinaryLogic; public function getDeprecatedDescription(): ?string; public function isInternal(): TrinaryLogic; public function getThrowType(): ?Type; public function hasSideEffects(): TrinaryLogic; public function isBuiltin(): bool; public function getAsserts(): \PHPStan\Reflection\Assertions; public function getDocComment(): ?string; public function returnsByReference(): TrinaryLogic; /** * In most cases hasSideEffects() is more practical as it also accounts * for void return type (functions returning void are always impure). */ public function isPure(): TrinaryLogic; /** @return list */ public function getAttributes(): array; /** * On PHP 8.5+ if the return value is unused at runtime, a warning is emitted. * PHPStan reports this during analysis regardless of PHP version. */ public function mustUseReturnValue(): TrinaryLogic; } $phpDocParameterTypes * @param array $phpDocParameterOutTypes * @param array $phpDocParameterImmediatelyInvokedCallable * @param array $phpDocParameterClosureThisTypes * @param list $attributes */ public function create(ReflectionFunction $reflection, TemplateTypeMap $templateTypeMap, array $phpDocParameterTypes, ?Type $phpDocReturnType, ?Type $phpDocThrowType, ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, ?string $filename, ?bool $isPure, \PHPStan\Reflection\Assertions $asserts, bool $acceptsNamedArguments, ?string $phpDocComment, array $phpDocParameterOutTypes, array $phpDocParameterImmediatelyInvokedCallable, array $phpDocParameterClosureThisTypes, array $attributes): PhpFunctionReflection; } */ private array $parameters; private bool $isVariadic; private Type $returnType; private TemplateTypeVarianceMap $callSiteVarianceMap; /** * @api * @param list $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 list */ public function getParameters(): array { return $this->parameters; } public function isVariadic(): bool { return $this->isVariadic; } public function getReturnType(): Type { return $this->returnType; } } $argTypes */ public static function resolve(array $argTypes, \PHPStan\Reflection\ParametersAcceptor $parametersAcceptor): \PHPStan\Reflection\ExtendedParametersAcceptor { $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 = array_last($parameters); 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 ($parameters as $param) { if (isset($namedArgTypes[$param->getName()])) { $argType = $namedArgTypes[$param->getName()]; } elseif ($param->getDefaultValue() !== null) { $argType = $param->getDefaultValue(); } elseif ($param->isVariadic()) { $argType = new NeverType(\true); } 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 fn(string $name, Type $type): Type => new ErrorType())->getTypes(), $typeMap->getTypes())); $originalParametersAcceptor = $parametersAcceptor; if (!$parametersAcceptor instanceof \PHPStan\Reflection\ExtendedParametersAcceptor) { $parametersAcceptor = new \PHPStan\Reflection\ExtendedFunctionVariant($parametersAcceptor->getTemplateTypeMap(), $parametersAcceptor->getResolvedTemplateTypeMap(), array_map(static fn(\PHPStan\Reflection\ParameterReflection $parameter): \PHPStan\Reflection\ExtendedParameterReflection => new ExtendedDummyParameter($parameter->getName(), $parameter->getType(), $parameter->isOptional(), $parameter->passedByReference(), $parameter->isVariadic(), $parameter->getDefaultValue(), new MixedType(), $parameter->getType(), null, TrinaryLogic::createMaybe(), null, []), $parameters), $parametersAcceptor->isVariadic(), $returnType, $returnType, 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(), $originalParametersAcceptor->mustUseReturnValue(), $originalParametersAcceptor->getAsserts()); } return $result; } } 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(); } 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(): TrinaryLogic { return $this->methodReflection->acceptsNamedArguments(); } public function mustUseReturnValue(): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getAsserts(): \PHPStan\Reflection\Assertions { return \PHPStan\Reflection\Assertions::createEmpty(); } } file = $file; $this->namespace = $namespace; $this->className = $className; $this->traitName = $traitName; $this->function = $function; $this->method = $method; $this->property = $property; } public static function fromScope(Scope $scope): self { $function = $scope->getFunction(); return new self($scope->getFile(), $scope->getNamespace(), $scope->isInClass() ? $scope->getClassReflection()->getName() : null, $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, $scope->isInAnonymousFunction() ? '{closure}' : ($function !== null ? $function->getName() : null), $scope->isInAnonymousFunction() ? '{closure}' : ($function instanceof \PHPStan\Reflection\MethodReflection ? sprintf('%s::%s', $function->getDeclaringClass()->getName(), $function->getName()) : ($function instanceof \PHPStan\Reflection\FunctionReflection ? $function->getName() : null)), $function instanceof PhpMethodFromParserNodeReflection && $function->isPropertyHook() ? $function->getHookedPropertyName() : 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, null); } public static function fromFunction(string $functionName, ?string $fileName): self { return new self($fileName, self::parseNamespace($functionName), null, null, $functionName, $functionName, null); } public static function fromClassMethod(string $className, ?string $traitName, string $methodName, ?string $fileName): self { return new self($fileName, self::parseNamespace($className), $className, $traitName, $methodName, sprintf('%s::%s', $className, $methodName), 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(), null); } $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()), null); } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\PropertyHook $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()); } $functionName = null; $propertyName = null; if ($function instanceof Function_ && $function->namespacedName !== null) { $functionName = $function->namespacedName->toString(); } elseif ($function instanceof ClassMethod) { $functionName = $function->name->toString(); } elseif ($function instanceof PropertyHook) { $propertyName = $function->getAttribute('propertyName'); $functionName = sprintf('$%s::%s', $propertyName, $function->name->toString()); } $methodName = null; if ($function instanceof ClassMethod && $className !== null) { $methodName = sprintf('%s::%s', $className, $function->name->toString()); } elseif ($function instanceof PropertyHook) { $propertyName = $function->getAttribute('propertyName'); $methodName = sprintf('%s::$%s::%s', $className, $propertyName, $function->name->toString()); } elseif ($function instanceof Function_ && $function->namespacedName !== null) { $methodName = $function->namespacedName->toString(); } return new self($stubFile, $namespace, $className, null, $functionName, $methodName, $propertyName); } public static function fromGlobalConstant(ReflectionConstant $constant): self { return new self($constant->getFileName(), $constant->getNamespaceName(), null, null, null, null, null); } public static function createEmpty(): self { return new self(null, 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; } public function getProperty(): ?string { return $this->property; } } */ private array $currentlyResolvingClassConstant = []; /** @var array */ private array $classConstantValueTypeCache = []; public function __construct( ConstantResolver $constantResolver, ReflectionProviderProvider $reflectionProviderProvider, PhpVersion $phpVersion, OperatorTypeSpecifyingExtensionRegistryProvider $operatorTypeSpecifyingExtensionRegistryProvider, UnaryOperatorTypeSpecifyingExtensionRegistryProvider $unaryOperatorTypeSpecifyingExtensionRegistryProvider, OversizedArrayBuilder $oversizedArrayBuilder, #[AutowiredParameter] bool $usePathConstantsAsConstantString ) { $this->constantResolver = $constantResolver; $this->reflectionProviderProvider = $reflectionProviderProvider; $this->phpVersion = $phpVersion; $this->operatorTypeSpecifyingExtensionRegistryProvider = $operatorTypeSpecifyingExtensionRegistryProvider; $this->unaryOperatorTypeSpecifyingExtensionRegistryProvider = $unaryOperatorTypeSpecifyingExtensionRegistryProvider; $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 Int_) { return new ConstantIntegerType($expr->value); } if ($expr instanceof Float_) { 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, fn(Expr $expr): Type => $this->getType($expr, $context)); } if ($expr instanceof Expr\Cast) { return $this->getCastType($expr, fn(Expr $expr): Type => $this->getType($expr, $context)); } if ($expr instanceof Expr\CallLike && $expr->isFirstClassCallable()) { return $this->getFirstClassCallableType($expr, $context, \false); } if ($expr instanceof Expr\Closure && $expr->static) { $parameters = []; $isVariadic = \false; $firstOptionalParameterIndex = null; foreach ($expr->params as $i => $param) { $isOptionalCandidate = $param->default !== null || $param->variadic; if ($isOptionalCandidate) { if ($firstOptionalParameterIndex === null) { $firstOptionalParameterIndex = $i; } } else { $firstOptionalParameterIndex = null; } } foreach ($expr->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, $context), $param->byRef ? \PHPStan\Reflection\PassedByReference::createCreatesNewVariable() : \PHPStan\Reflection\PassedByReference::createNo(), $param->variadic, $param->default !== null ? $this->getType($param->default, $context) : null); } $returnType = new MixedType(\false); if ($expr->returnType !== null) { $returnType = $this->getFunctionType($expr->returnType, \false, \false, $context); } return new ClosureType($parameters, $returnType, $isVariadic, TemplateTypeMap::createEmpty(), TemplateTypeMap::createEmpty(), TemplateTypeVarianceMap::createEmpty(), [], [], \null, [], [], TrinaryLogic::createYes()); } 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(), fn(Expr $expr): Type => $this->getType($expr, $context)); } if ($expr instanceof Expr\UnaryPlus) { return $this->getUnaryPlusType($expr->expr, fn(Expr $expr): Type => $this->getType($expr, $context)); } if ($expr instanceof Expr\UnaryMinus) { return $this->getUnaryMinusType($expr->expr, fn(Expr $expr): Type => $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) { $elseType = $this->getType($expr->else, $context); if ($expr->if === null) { $condType = $this->getType($expr->cond, $context); 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, fn(Expr $expr): Type => $this->getType($expr, $context)); } if ($expr instanceof Expr\BinaryOp\Concat) { return $this->getConcatType($expr->left, $expr->right, fn(Expr $expr): Type => $this->getType($expr, $context)); } if ($expr instanceof Expr\BinaryOp\BitwiseAnd) { return $this->getBitwiseAndType($expr->left, $expr->right, fn(Expr $expr): Type => $this->getType($expr, $context)); } if ($expr instanceof Expr\BinaryOp\BitwiseOr) { return $this->getBitwiseOrType($expr->left, $expr->right, fn(Expr $expr): Type => $this->getType($expr, $context)); } if ($expr instanceof Expr\BinaryOp\BitwiseXor) { return $this->getBitwiseXorType($expr->left, $expr->right, fn(Expr $expr): Type => $this->getType($expr, $context)); } if ($expr instanceof Expr\BinaryOp\Spaceship) { return $this->getSpaceshipType($expr->left, $expr->right, fn(Expr $expr): Type => $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, fn(Expr $expr): Type => $this->getType($expr, $context)); } if ($expr instanceof Expr\BinaryOp\Mod) { return $this->getModType($expr->left, $expr->right, fn(Expr $expr): Type => $this->getType($expr, $context)); } if ($expr instanceof Expr\BinaryOp\Plus) { return $this->getPlusType($expr->left, $expr->right, fn(Expr $expr): Type => $this->getType($expr, $context)); } if ($expr instanceof Expr\BinaryOp\Minus) { return $this->getMinusType($expr->left, $expr->right, fn(Expr $expr): Type => $this->getType($expr, $context)); } if ($expr instanceof Expr\BinaryOp\Mul) { return $this->getMulType($expr->left, $expr->right, fn(Expr $expr): Type => $this->getType($expr, $context)); } if ($expr instanceof Expr\BinaryOp\Pow) { return $this->getPowType($expr->left, $expr->right, fn(Expr $expr): Type => $this->getType($expr, $context)); } if ($expr instanceof Expr\BinaryOp\ShiftLeft) { return $this->getShiftLeftType($expr->left, $expr->right, fn(Expr $expr): Type => $this->getType($expr, $context)); } if ($expr instanceof Expr\BinaryOp\ShiftRight) { return $this->getShiftRightType($expr->left, $expr->right, fn(Expr $expr): Type => $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), $this->phpVersion)->toBooleanType(); } if ($expr instanceof Expr\BinaryOp\SmallerOrEqual) { return $this->getType($expr->left, $context)->isSmallerThanOrEqual($this->getType($expr->right, $context), $this->phpVersion)->toBooleanType(); } if ($expr instanceof Expr\BinaryOp\Greater) { return $this->getType($expr->right, $context)->isSmallerThan($this->getType($expr->left, $context), $this->phpVersion)->toBooleanType(); } if ($expr instanceof Expr\BinaryOp\GreaterOrEqual) { return $this->getType($expr->right, $context)->isSmallerThanOrEqual($this->getType($expr->left, $context), $this->phpVersion)->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 new IntersectionType([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 new IntersectionType([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 MagicConst\Property) { $contextProperty = $context->getProperty(); if ($contextProperty === null) { return new ConstantStringType(''); } return new ConstantStringType($contextProperty); } if ($expr instanceof PropertyFetch && $expr->name instanceof Identifier) { $fetchedOnType = $this->getType($expr->var, $context); if (!$fetchedOnType->hasInstanceProperty($expr->name->name)->yes()) { return new ErrorType(); } return $fetchedOnType->getInstanceProperty($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 <= self::CALCULATE_SCALARS_LIMIT) { $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()) { $validationCallback = $left->isInteger()->yes() ? static fn(string $value): bool => !str_starts_with($value, '-') : static fn(string $value): bool => Strings::match($value, '#^\d+$#') !== null; $allRightConstantsZeroOrMore = \false; foreach ($rightConstantStrings as $rightConstantString) { if ($rightConstantString->getValue() === '') { continue; } if (!is_numeric($rightConstantString->getValue()) || !$validationCallback($rightConstantString->getValue())) { $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; $hasOffsetValueTypes = []; foreach ($expr->items as $arrayItem) { $valueType = $getTypeCallback($arrayItem->value); if ($arrayItem->unpack) { $constantArrays = $valueType->getConstantArrays(); if (count($constantArrays) === 1) { $constantArrayType = $constantArrays[0]; $hasStringKey = \false; if ($this->phpVersion->supportsArrayUnpackingWithStringKeys()) { foreach ($constantArrayType->getKeyTypes() as $keyType) { if ($keyType->isString()->yes()) { $hasStringKey = \true; break; } } } foreach ($constantArrayType->getValueTypes() as $i => $innerValueType) { if ($hasStringKey) { $arrayBuilder->setOffsetValueType($constantArrayType->getKeyTypes()[$i], $innerValueType, $constantArrayType->isOptionalKey($i)); if (!$constantArrayType->isOptionalKey($i)) { $hasOffsetValueTypes[$constantArrayType->getKeyTypes()[$i]->getValue()] = new HasOffsetValueType($constantArrayType->getKeyTypes()[$i], $innerValueType); } } else { $arrayBuilder->setOffsetValueType(null, $innerValueType, $constantArrayType->isOptionalKey($i)); } } } else { $arrayBuilder->degradeToGeneralArray(); if ($this->phpVersion->supportsArrayUnpackingWithStringKeys() && !$valueType->getIterableKeyType()->isString()->no()) { $isList = \false; $offsetType = $valueType->getIterableKeyType(); foreach ($hasOffsetValueTypes as $key => $hasOffsetValueType) { if (!$offsetType->isSuperTypeOf($hasOffsetValueType->getOffsetType())->yes()) { continue; } unset($hasOffsetValueTypes[$key]); } } else { $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) { $arrayType = TypeCombinator::intersect($arrayType, new AccessoryArrayListType()); } if (count($hasOffsetValueTypes) > 0 && !$arrayType->isConstantArray()->yes()) { $arrayType = TypeCombinator::intersect($arrayType, ...array_values($hasOffsetValueTypes)); } return $arrayType; } /** * @param callable(Expr): Type $getTypeCallback */ public function getCastType(Expr\Cast $expr, callable $getTypeCallback): Type { if ($expr instanceof \PhpParser\Node\Expr\Cast\Int_) { return $getTypeCallback($expr->expr)->toInteger(); } if ($expr instanceof Bool_) { return $getTypeCallback($expr->expr)->toBoolean(); } if ($expr instanceof Double) { return $getTypeCallback($expr->expr)->toFloat(); } if ($expr instanceof \PhpParser\Node\Expr\Cast\String_) { return $getTypeCallback($expr->expr)->toString(); } if ($expr instanceof Array_) { return $getTypeCallback($expr->expr)->toArray(); } if ($expr instanceof Object_) { return $this->getCastObjectType($getTypeCallback($expr->expr)); } return new MixedType(); } public function getCastObjectType(Type $exprType): Type { $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) { $valueType = $constantArray->getValueTypes()[$i]; $optional = $constantArray->isOptionalKey($i); if ($optional) { $optionalProperties[] = $keyType->getValue(); } $properties[$keyType->getValue()] = $valueType; } $objects[] = new IntersectionType([new ObjectShapeType($properties, $optionalProperties), new ObjectType(stdClass::class)]); } return TypeCombinator::union(...$objects); } if ($type->isObject()->yes()) { return $type; } return new ObjectType('stdClass'); }; if ($exprType instanceof UnionType) { return TypeCombinator::union(...array_map($castToObject, $exprType->getTypes())); } return $castToObject($exprType); } /** * @param Name|Identifier|ComplexType|null $type */ public function getFunctionType($type, bool $isNullable, bool $isVariadic, \PHPStan\Reflection\InitializerExprContext $context): Type { if ($isNullable) { return TypeCombinator::addNull($this->getFunctionType($type, \false, $isVariadic, $context)); } if ($isVariadic) { if (!$this->phpVersion->supportsNamedArguments()) { return new ArrayType(new UnionType([new IntegerType(), new StringType()]), $this->getFunctionType($type, \false, \false, $context)); } return new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $this->getFunctionType($type, \false, \false, $context)), new AccessoryArrayListType()]); } if ($type instanceof Name) { $className = (string) $type; $lowercasedClassName = strtolower($className); if ($lowercasedClassName === 'parent') { $classReflection = null; if ($context->getClassName() !== null && $this->getReflectionProvider()->hasClass($context->getClassName())) { $classReflection = $this->getReflectionProvider()->getClass($context->getClassName()); } if ($classReflection !== null && $classReflection->getParentClass() !== null) { return new ObjectType($classReflection->getParentClass()->getName()); } return new NonexistentParentClassType(); } } $classReflection = null; if ($context->getClassName() !== null && $this->getReflectionProvider()->hasClass($context->getClassName())) { $classReflection = $this->getReflectionProvider()->getClass($context->getClassName()); } return ParserNodeTypeToPHPStanType::resolve($type, $classReflection); } private function isParameterValueNullable(Param $parameter): bool { if ($parameter->default instanceof ConstFetch) { return strtolower((string) $parameter->default->name) === 'null'; } return \false; } public function getFirstClassCallableType(Expr\CallLike $expr, \PHPStan\Reflection\InitializerExprContext $context, bool $nativeTypesPromoted): Type { if ($expr instanceof FuncCall) { if ($expr->name instanceof Name) { if ($this->getReflectionProvider()->hasFunction($expr->name, $context)) { $function = $this->getReflectionProvider()->getFunction($expr->name, $context); return $this->createFirstClassCallable($function, $function->getVariants(), $nativeTypesPromoted); } return new ObjectType(Closure::class); } } if ($expr instanceof Expr\StaticCall) { if (!$expr->class instanceof Name) { return new ObjectType(Closure::class); } if (!$expr->name instanceof Identifier) { return new ObjectType(Closure::class); } $classReflection = null; if ($context->getClassName() !== null && $this->getReflectionProvider()->hasClass($context->getClassName())) { $classReflection = $this->getReflectionProvider()->getClass($context->getClassName()); } $classType = $this->resolveTypeByName($expr->class, $classReflection); $methodName = $expr->name->toString(); if (!$classType->hasMethod($methodName)->yes()) { return new ObjectType(Closure::class); } $method = $classType->getMethod($methodName, new OutOfClassScope()); $classType = $this->resolveTypeByNameWithLateStaticBinding($expr->class, $classType, $method); if (!$classType->hasMethod($methodName)->yes()) { return new ObjectType(Closure::class); } $method = $classType->getMethod($methodName, new OutOfClassScope()); return $this->createFirstClassCallable($method, $method->getVariants(), $nativeTypesPromoted); } if ($expr instanceof New_) { return new ErrorType(); } throw new ShouldNotHappenException(); } /** * @param ParametersAcceptor[] $variants * @param \PHPStan\Reflection\FunctionReflection|\PHPStan\Reflection\ExtendedMethodReflection|null $function */ public function createFirstClassCallable($function, array $variants, bool $nativeTypesPromoted): Type { $closureTypes = []; foreach ($variants as $variant) { $returnType = $variant->getReturnType(); if ($variant instanceof \PHPStan\Reflection\ExtendedParametersAcceptor) { $returnType = $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 = TrinaryLogic::createYes(); $mustUseReturnValue = TrinaryLogic::createMaybe(); if ($variant instanceof CallableParametersAcceptor) { $throwPoints = $variant->getThrowPoints(); $impurePoints = $variant->getImpurePoints(); $acceptsNamedArguments = $variant->acceptsNamedArguments(); $mustUseReturnValue = $variant->mustUseReturnValue(); } 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(); $mustUseReturnValue = $function->mustUseReturnValue(); } $parameters = $variant->getParameters(); $assertions = $function !== null ? $function->getAsserts() : \PHPStan\Reflection\Assertions::createEmpty(); $closureTypes[] = new ClosureType($parameters, $returnType, $variant->isVariadic(), $variant->getTemplateTypeMap(), $variant->getResolvedTemplateTypeMap(), $variant instanceof \PHPStan\Reflection\ExtendedParametersAcceptor ? $variant->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), $templateTags, $throwPoints, $impurePoints, [], [], $acceptsNamedArguments, $mustUseReturnValue, $assertions); } return TypeCombinator::union(...$closureTypes); } /** * @param callable(Expr): Type $getTypeCallback */ public function getBitwiseAndType(Expr $left, Expr $right, callable $getTypeCallback): Type { $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); $specifiedTypes = $this->operatorTypeSpecifyingExtensionRegistryProvider->getRegistry()->callOperatorTypeSpecifyingExtensions(new BinaryOp\BitwiseAnd($left, $right), $leftType, $rightType); if ($specifiedTypes !== null) { return $specifiedTypes; } return $this->getBitwiseAndTypeFromTypes($leftType, $rightType); } public function getBitwiseAndTypeFromTypes(Type $leftType, Type $rightType): Type { if ($leftType instanceof NeverType || $rightType instanceof NeverType) { return $this->getNeverType($leftType, $rightType); } $result = $this->getFiniteOrConstantScalarTypes($leftType, $rightType, static fn($a, $b) => $a & $b); if ($result instanceof Type) { return $result; } elseif ($result === self::IS_SCALAR_TYPE) { $leftType = $this->optimizeScalarType($leftType); $rightType = $this->optimizeScalarType($rightType); } if ($leftType instanceof MixedType && $rightType instanceof MixedType) { return new BenevolentUnionType([new IntegerType(), new StringType()]); } $leftIsString = $leftType->isString(); $rightIsString = $rightType->isString(); if (($leftIsString->yes() || $leftType instanceof MixedType) && ($rightIsString->yes() || $rightType instanceof MixedType)) { return new StringType(); } if ($leftIsString->maybe() && $rightIsString->maybe()) { return new ErrorType(); } $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); $specifiedTypes = $this->operatorTypeSpecifyingExtensionRegistryProvider->getRegistry()->callOperatorTypeSpecifyingExtensions(new BinaryOp\BitwiseOr($left, $right), $leftType, $rightType); if ($specifiedTypes !== null) { return $specifiedTypes; } return $this->getBitwiseOrTypeFromTypes($leftType, $rightType); } public function getBitwiseOrTypeFromTypes(Type $leftType, Type $rightType): Type { if ($leftType instanceof NeverType || $rightType instanceof NeverType) { return $this->getNeverType($leftType, $rightType); } $result = $this->getFiniteOrConstantScalarTypes($leftType, $rightType, static fn($a, $b) => $a | $b); if ($result instanceof Type) { return $result; } elseif ($result === self::IS_SCALAR_TYPE) { $leftType = $this->optimizeScalarType($leftType); $rightType = $this->optimizeScalarType($rightType); } if ($leftType instanceof MixedType && $rightType instanceof MixedType) { return new BenevolentUnionType([new IntegerType(), new StringType()]); } $leftIsString = $leftType->isString(); $rightIsString = $rightType->isString(); if (($leftIsString->yes() || $leftType instanceof MixedType) && ($rightIsString->yes() || $rightType instanceof MixedType)) { return new StringType(); } if ($leftIsString->maybe() && $rightIsString->maybe()) { return new ErrorType(); } if ($leftType->toNumber() instanceof ErrorType || $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); $specifiedTypes = $this->operatorTypeSpecifyingExtensionRegistryProvider->getRegistry()->callOperatorTypeSpecifyingExtensions(new BinaryOp\BitwiseXor($left, $right), $leftType, $rightType); if ($specifiedTypes !== null) { return $specifiedTypes; } return $this->getBitwiseXorTypeFromTypes($leftType, $rightType); } private const IS_SCALAR_TYPE = 1; private const IS_UNKNOWN = 2; /** * @param callable(bool|float|int|string|null, bool|float|int|string|null):string $operationCallable * * @return self::IS_UNKNOWN|self::IS_SCALAR_TYPE|Type */ private function getFiniteOrConstantScalarTypes(Type $leftType, Type $rightType, callable $operationCallable) { if ($leftType instanceof IntegerRangeType) { $leftTypes = $leftType->getFiniteTypes(); } else { $leftTypes = $leftType->getConstantScalarTypes(); } if ($rightType instanceof IntegerRangeType) { $rightTypes = $rightType->getFiniteTypes(); } else { $rightTypes = $rightType->getConstantScalarTypes(); } $leftTypesCount = count($leftTypes); $rightTypesCount = count($rightTypes); if ($leftTypesCount === 0 || $rightTypesCount === 0) { return self::IS_UNKNOWN; } $generalize = $leftTypesCount * $rightTypesCount > self::CALCULATE_SCALARS_LIMIT; if ($generalize) { return self::IS_SCALAR_TYPE; } $resultTypes = []; foreach ($leftTypes as $leftTypeInner) { foreach ($rightTypes as $rightTypeInner) { if ($leftTypeInner instanceof ConstantStringType && $rightTypeInner instanceof ConstantStringType) { $resultValue = $operationCallable($leftTypeInner->getValue(), $rightTypeInner->getValue()); $resultType = $this->getTypeFromValue($resultValue); } 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(); } $resultValue = $operationCallable($leftNumberType->getValue(), $rightNumberType->getValue()); $resultType = $this->getTypeFromValue($resultValue); } $resultTypes[] = $resultType; } } return TypeCombinator::union(...$resultTypes); } public function getBitwiseXorTypeFromTypes(Type $leftType, Type $rightType): Type { if ($leftType instanceof NeverType || $rightType instanceof NeverType) { return $this->getNeverType($leftType, $rightType); } $result = $this->getFiniteOrConstantScalarTypes($leftType, $rightType, static fn($a, $b) => $a ^ $b); if ($result instanceof Type) { return $result; } elseif ($result === self::IS_SCALAR_TYPE) { $leftType = $this->optimizeScalarType($leftType); $rightType = $this->optimizeScalarType($rightType); } if ($leftType instanceof MixedType && $rightType instanceof MixedType) { return new BenevolentUnionType([new IntegerType(), new StringType()]); } $leftIsString = $leftType->isString(); $rightIsString = $rightType->isString(); if (($leftIsString->yes() || $leftType instanceof MixedType) && ($rightIsString->yes() || $rightType instanceof MixedType)) { return new StringType(); } if ($leftIsString->maybe() && $rightIsString->maybe()) { return new ErrorType(); } if ($leftType->toNumber() instanceof ErrorType || $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); return $this->getSpaceshipTypeFromTypes($callbackLeftType, $callbackRightType); } public function getSpaceshipTypeFromTypes(Type $leftTypes, Type $rightTypes): Type { if ($leftTypes instanceof NeverType || $rightTypes instanceof NeverType) { return $this->getNeverType($leftTypes, $rightTypes); } $leftTypes = $leftTypes->getConstantScalarTypes(); $rightTypes = $rightTypes->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); return $this->getDivTypeFromTypes($left, $right, $leftType, $rightType); } public function getDivTypeFromTypes(Expr $left, Expr $right, Type $leftType, Type $rightType): Type { $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 (in_array($scalarValue, [0, 0.0], \true)) { 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); return $this->getModTypeFromTypes($left, $right, $leftType, $rightType); } public function getModTypeFromTypes(Expr $left, Expr $right, Type $leftType, Type $rightType): Type { if ($leftType instanceof NeverType || $rightType instanceof NeverType) { return $this->getNeverType($leftType, $rightType); } $extensionSpecified = $this->operatorTypeSpecifyingExtensionRegistryProvider->getRegistry()->callOperatorTypeSpecifyingExtensions(new BinaryOp\Mod($left, $right), $leftType, $rightType); if ($extensionSpecified !== null) { return $extensionSpecified; } 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 (in_array($scalarValue, [0, 0.0], \true)) { 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); return $this->getPlusTypeFromTypes($left, $right, $leftType, $rightType); } public function getPlusTypeFromTypes(Expr $left, Expr $right, Type $leftType, Type $rightType): Type { 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); } $leftIterableValueType = $leftType->getIterableValueType(); $arrayType = new ArrayType($keyType, TypeCombinator::union($leftIterableValueType, $rightType->getIterableValueType())); $accessories = []; if ($leftCount > 0) { // Use the first constant array as a reference to list potential offsets. // We only need to check the first array because we're looking for offsets that exist in ALL arrays. $constantArray = $leftConstantArrays[0]; foreach ($constantArray->getKeyTypes() as $offsetType) { if (!$leftType->hasOffsetValueType($offsetType)->yes()) { continue; } $valueType = $leftType->getOffsetValueType($offsetType); $accessories[] = new HasOffsetValueType($offsetType, $valueType); } } if ($rightCount > 0) { // Use the first constant array as a reference to list potential offsets. // We only need to check the first array because we're looking for offsets that exist in ALL arrays. $constantArray = $rightConstantArrays[0]; foreach ($constantArray->getKeyTypes() as $offsetType) { if (!$rightType->hasOffsetValueType($offsetType)->yes()) { continue; } $valueType = TypeCombinator::union($leftIterableValueType, $rightType->getOffsetValueType($offsetType)); $accessories[] = new HasOffsetValueType($offsetType, $valueType); } } if ($leftType->isIterableAtLeastOnce()->yes() || $rightType->isIterableAtLeastOnce()->yes()) { $accessories[] = new NonEmptyArrayType(); } if ($leftType->isList()->yes() && $rightType->isList()->yes()) { $accessories[] = new AccessoryArrayListType(); } if (count($accessories) > 0) { $arrayType = TypeCombinator::intersect($arrayType, ...$accessories); } 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); return $this->getMinusTypeFromTypes($left, $right, $leftType, $rightType); } public function getMinusTypeFromTypes(Expr $left, Expr $right, Type $leftType, Type $rightType): Type { $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); return $this->getMulTypeFromTypes($left, $right, $leftType, $rightType); } public function getMulTypeFromTypes(Expr $left, Expr $right, Type $leftType, Type $rightType): Type { $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); return $this->getPowTypeFromTypes($left, $right, $leftType, $rightType); } public function getPowTypeFromTypes(Expr $left, Expr $right, Type $leftType, Type $rightType): Type { $extensionSpecified = $this->operatorTypeSpecifyingExtensionRegistryProvider->getRegistry()->callOperatorTypeSpecifyingExtensions(new BinaryOp\Pow($left, $right), $leftType, $rightType); if ($extensionSpecified !== null) { return $extensionSpecified; } $exponentiatedTyped = $leftType->exponentiate($rightType); if (!$exponentiatedTyped instanceof ErrorType) { return $exponentiatedTyped; } return new ErrorType(); } /** * @param callable(Expr): Type $getTypeCallback */ public function getShiftLeftType(Expr $left, Expr $right, callable $getTypeCallback): Type { $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); $specifiedTypes = $this->operatorTypeSpecifyingExtensionRegistryProvider->getRegistry()->callOperatorTypeSpecifyingExtensions(new BinaryOp\ShiftLeft($left, $right), $leftType, $rightType); if ($specifiedTypes !== null) { return $specifiedTypes; } return $this->getShiftLeftTypeFromTypes($left, $right, $leftType, $rightType); } public function getShiftLeftTypeFromTypes(Expr $left, Expr $right, Type $leftType, Type $rightType): Type { 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); $specifiedTypes = $this->operatorTypeSpecifyingExtensionRegistryProvider->getRegistry()->callOperatorTypeSpecifyingExtensions(new BinaryOp\ShiftRight($left, $right), $leftType, $rightType); if ($specifiedTypes !== null) { return $specifiedTypes; } return $this->getShiftRightTypeFromTypes($left, $right, $leftType, $rightType); } public function getShiftRightTypeFromTypes(Expr $left, Expr $right, Type $leftType, Type $rightType): Type { 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->isSuperTypeOf($rightType); $rightIsSuperTypeOfLeft = $rightType->isSuperTypeOf($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, fn($leftValueType, $rightValueType): TypeResult => $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, fn($leftValueType, $rightValueType): TypeResult => $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(), []); } /** * @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 { $specifiedTypes = $this->operatorTypeSpecifyingExtensionRegistryProvider->getRegistry()->callOperatorTypeSpecifyingExtensions($expr, $leftType, $rightType); if ($specifiedTypes !== null) { return $specifiedTypes; } $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(); } } 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 \PhpParser\Node\Name|\PhpParser\Node\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 $constantClassType->toClassConstantType($this->getReflectionProvider()); } if ($constantClassType->isClassString()->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)) { if ($constantClassReflection->getName() === 'Attribute' && $constantName === 'TARGET_CONSTANT') { return new ConstantIntegerType(1 << 16); } 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; } if (!$isObject && array_key_exists($resolvingName, $this->classConstantValueTypeCache)) { $types[] = $this->classConstantValueTypeCache[$resolvingName]; 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); } $resolvedType = $this->constantResolver->resolveClassConstantType($constantClassReflection->getName(), $constantName, $constantType, $nativeType, $constantClassReflection->getConstantPhpDocType($constantName)); $this->classConstantValueTypeCache[$resolvingName] = $resolvedType; $types[] = $resolvedType; 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, $constantClassReflection->getConstantPhpDocType($constantName)); 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 \PhpParser\Node\Name|\PhpParser\Node\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 getUnaryPlusType(Expr $expr, callable $getTypeCallback): Type { $type = $getTypeCallback($expr); $specifiedTypes = $this->unaryOperatorTypeSpecifyingExtensionRegistryProvider->getRegistry()->callUnaryOperatorTypeSpecifyingExtensions('+', $type); if ($specifiedTypes !== null) { return $specifiedTypes; } return $type->toNumber(); } /** * @param callable(Expr): Type $getTypeCallback */ public function getUnaryMinusType(Expr $expr, callable $getTypeCallback): Type { $type = $getTypeCallback($expr); $specifiedTypes = $this->unaryOperatorTypeSpecifyingExtensionRegistryProvider->getRegistry()->callUnaryOperatorTypeSpecifyingExtensions('-', $type); if ($specifiedTypes !== null) { return $specifiedTypes; } $type = $this->getUnaryMinusTypeFromType($expr, $type); if ($type instanceof IntegerRangeType) { return $getTypeCallback(new Expr\BinaryOp\Mul($expr, new Int_(-1))); } return $type; } public function getUnaryMinusTypeFromType(Expr $expr, Type $type): Type { $type = $type->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); } return $type; } /** * @param callable(Expr): Type $getTypeCallback */ public function getBitwiseNotType(Expr $expr, callable $getTypeCallback): Type { $exprType = $getTypeCallback($expr); $specifiedTypes = $this->unaryOperatorTypeSpecifyingExtensionRegistryProvider->getRegistry()->callUnaryOperatorTypeSpecifyingExtensions('~', $exprType); if ($specifiedTypes !== null) { return $specifiedTypes; } return $this->getBitwiseNotTypeFromType($exprType); } public function getBitwiseNotTypeFromType(Type $exprType): Type { return $exprType->toBitwiseNotType(); } 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); } private function resolveTypeByNameWithLateStaticBinding(Name $class, Type $classType, \PHPStan\Reflection\MethodReflection $methodReflectionCandidate): Type { if ($classType instanceof StaticType && !in_array($class->toLowerString(), ['self', 'static', 'parent'], \true)) { if ($methodReflectionCandidate->isStatic()) { $classType = $classType->getStaticObjectType(); } } return $classType; } /** * @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(); } } name = $name; $this->declaringClass = $declaringClass; $this->isStatic = $isStatic; $this->isPrivate = $isPrivate; $this->isPublic = $isPublic; $this->isAbstract = $isAbstract; $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 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; } } */ public function getVariants(): array; public function isDeprecated(): TrinaryLogic; public function getDeprecatedDescription(): ?string; public function isFinal(): TrinaryLogic; public function isInternal(): TrinaryLogic; public function getThrowType(): ?Type; /** * Void methods are always considered impure since they must do something * to be useful. */ public function hasSideEffects(): TrinaryLogic; } 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(); } } > */ private array $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(); if ($parentClass !== null) { $method = $this->findMethod($parentClass, $methodName); if ($method !== null) { return $method; } } return null; } } > */ private array $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->hasInstanceProperty($propertyName)->yes()) { unset($this->inProcess[$typeDescription][$propertyName]); continue; } $property = $type->getInstanceProperty($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(); if ($parentClass !== null) { $property = $this->findProperty($parentClass, $propertyName); if ($property !== null) { return $property; } } return null; } } */ private array $attributes; /** * @param list $attributes */ public function __construct(string $name, bool $optional, Type $type, Type $phpDocType, Type $nativeType, PassedByReference $passedByReference, bool $variadic, ?Type $defaultValue, ?Type $outType, TrinaryLogic $immediatelyInvokedCallable, ?Type $closureThisType, array $attributes) { $this->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; $this->attributes = $attributes; } 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 hasNativeType(): bool { return !$this->nativeType instanceof MixedType || $this->nativeType->isExplicitMixed(); } 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; } public function getAttributes(): array { return $this->attributes; } } */ private array $variants; /** * @var list|null */ private ?array $namedArgumentsVariants; private ?Type $throwType; private TrinaryLogic $hasSideEffects; private bool $isDeprecated; private ?string $phpDocComment; private bool $acceptsNamedArguments; /** * @var list */ private array $attributes; private Assertions $assertions; private TrinaryLogic $returnsByReference; /** * @param list $variants * @param list|null $namedArgumentsVariants * @param list $attributes */ public function __construct(string $name, array $variants, ?array $namedArgumentsVariants, ?Type $throwType, TrinaryLogic $hasSideEffects, bool $isDeprecated, ?Assertions $assertions, ?string $phpDocComment, ?TrinaryLogic $returnsByReference, bool $acceptsNamedArguments, array $attributes) { $this->name = $name; $this->variants = $variants; $this->namedArgumentsVariants = $namedArgumentsVariants; $this->throwType = $throwType; $this->hasSideEffects = $hasSideEffects; $this->isDeprecated = $isDeprecated; $this->phpDocComment = $phpDocComment; $this->acceptsNamedArguments = $acceptsNamedArguments; $this->attributes = $attributes; $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(): ExtendedParametersAcceptor { $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 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(): TrinaryLogic { return TrinaryLogic::createFromBoolean($this->acceptsNamedArguments); } public function getAttributes(): array { return $this->attributes; } public function mustUseReturnValue(): TrinaryLogic { foreach ($this->attributes as $attrib) { if (strtolower($attrib->getName()) === 'nodiscard') { return TrinaryLogic::createYes(); } } return TrinaryLogic::createNo(); } } */ private array $variants; /** * @var list|null */ private ?array $namedArgumentsVariants; private TrinaryLogic $hasSideEffects; private ?Type $throwType; private Assertions $assertions; private bool $acceptsNamedArguments; private ?Type $selfOutType; private ?string $phpDocComment; /** * @var list */ private array $attributes; /** * @param list $variants * @param list|null $namedArgumentsVariants * @param list $attributes */ public function __construct(ReflectionProvider $reflectionProvider, ClassReflection $declaringClass, ReflectionMethod $reflection, ?ResolvedPhpDocBlock $resolvedPhpDocBlock, array $variants, ?array $namedArgumentsVariants, TrinaryLogic $hasSideEffects, ?Type $throwType, Assertions $assertions, bool $acceptsNamedArguments, ?Type $selfOutType, ?string $phpDocComment, array $attributes) { $this->reflectionProvider = $reflectionProvider; $this->declaringClass = $declaringClass; $this->reflection = $reflection; $this->resolvedPhpDocBlock = $resolvedPhpDocBlock; $this->variants = $variants; $this->namedArgumentsVariants = $namedArgumentsVariants; $this->hasSideEffects = $hasSideEffects; $this->throwType = $throwType; $this->assertions = $assertions; $this->acceptsNamedArguments = $acceptsNamedArguments; $this->selfOutType = $selfOutType; $this->phpDocComment = $phpDocComment; $this->attributes = $attributes; } 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(), \null, $prototypeDeclaringClass); } return new MethodPrototypeReflection($prototypeMethod->getName(), $prototypeDeclaringClass, $prototypeMethod->isStatic(), $prototypeMethod->isPrivate(), $prototypeMethod->isPublic(), $prototypeMethod->isAbstract(), $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(): ExtendedParametersAcceptor { $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 TrinaryLogic::createFromBoolean($this->reflection->isDeprecated()); } public function isInternal(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isBuiltin(): 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()); if ($name !== '__construct' && $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 getDocComment(): ?string { return $this->phpDocComment; } public function getAsserts(): Assertions { return $this->assertions; } public function acceptsNamedArguments(): TrinaryLogic { return TrinaryLogic::createFromBoolean($this->declaringClass->acceptsNamedArguments() && $this->acceptsNamedArguments); } public function getSelfOutType(): ?Type { return $this->selfOutType; } public function returnsByReference(): TrinaryLogic { return TrinaryLogic::createFromBoolean($this->reflection->returnsReference()); } public function getAttributes(): array { return $this->attributes; } public function mustUseReturnValue(): TrinaryLogic { foreach ($this->attributes as $attrib) { if (strtolower($attrib->getName()) === 'nodiscard') { return TrinaryLogic::createYes(); } } return TrinaryLogic::createNo(); } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return $this->resolvedPhpDocBlock; } } 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); } } 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); } } */ public function getParameters(): array; public function isVariadic(): bool; public function getReturnType(): Type; } 0 && count($parametersAcceptors) > 0) { $arrayMapArgs = $args[0]->value->getAttribute(ArrayMapArgVisitor::ATTRIBUTE_NAME); if ($arrayMapArgs !== null) { $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); } } $acceptor = $parametersAcceptors[0]; $parameters = $acceptor->getParameters(); if (isset($parameters[0])) { $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\ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty())]; } } if (count($args) >= 3 && (bool) $args[0]->getAttribute(CurlSetOptArgVisitor::ATTRIBUTE_NAME)) { $optType = $scope->getType($args[1]->value); $valueTypes = []; foreach ($optType->getConstantScalarValues() as $scalarValue) { if (!is_int($scalarValue)) { $valueTypes = []; break; } $valueType = self::getCurlOptValueType($scalarValue); if ($valueType === null) { $valueTypes = []; break; } $valueTypes[] = $valueType; } $acceptor = $parametersAcceptors[0]; $parameters = $acceptor->getParameters(); if (count($valueTypes) !== 0 && isset($parameters[2])) { $parameters[2] = new NativeParameterReflection($parameters[2]->getName(), $parameters[2]->isOptional(), TypeCombinator::union(...$valueTypes), $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\ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty())]; } } if (count($args) >= 2 && (bool) $args[1]->getAttribute(CurlSetOptArrayArgVisitor::ATTRIBUTE_NAME)) { $optArrayType = $scope->getType($args[1]->value); $hasTypes = \false; $builder = ConstantArrayTypeBuilder::createEmpty(); foreach ($optArrayType->getIterableKeyType()->getConstantScalarTypes() as $optType) { $optValue = $optType->getValue(); if (!is_int($optValue)) { $hasTypes = \false; break; } $optValueType = self::getCurlOptValueType($optValue); if ($optValueType === null) { $hasTypes = \false; break; } $hasTypes = \true; $builder->setOffsetValueType(new ConstantIntegerType($optValue), $optValueType, !$optArrayType->hasOffsetValueType($optType)->yes()); } $acceptor = $parametersAcceptors[0]; $parameters = $acceptor->getParameters(); if ($hasTypes && isset($parameters[1])) { $parameters[1] = new NativeParameterReflection($parameters[1]->getName(), $parameters[1]->isOptional(), $builder->getArray(), $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\ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty())]; } } if ((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(); if (isset($parameters[1])) { $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\ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty())]; } } if (count($args) <= 2 && (bool) $args[0]->getAttribute(ImplodeArgVisitor::ATTRIBUTE_NAME)) { $acceptor = $namedArgumentsVariants[0] ?? $parametersAcceptors[0]; $parameters = $acceptor->getParameters(); if ((isset($args[1]) || $args[0]->name !== null && $args[0]->name->name === 'array') && isset($parameters[0]) && isset($parameters[1])) { $parameters = [new NativeParameterReflection($parameters[0]->getName(), \false, new StringType(), \PHPStan\Reflection\PassedByReference::createNo(), \false, null), new NativeParameterReflection($parameters[1]->getName(), \false, new ArrayType(new MixedType(), new MixedType()), \PHPStan\Reflection\PassedByReference::createNo(), \false, null)]; } elseif (isset($parameters[0])) { $parameters = [new NativeParameterReflection($parameters[0]->getName(), \false, new ArrayType(new MixedType(), new MixedType()), \PHPStan\Reflection\PassedByReference::createNo(), \false, null)]; } $parametersAcceptors = [new \PHPStan\Reflection\FunctionVariant($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), $parameters, $acceptor->isVariadic(), $acceptor->getReturnType(), $acceptor instanceof \PHPStan\Reflection\ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty())]; } if ((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(); if (isset($parameters[1])) { $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\ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty())]; } } if ((bool) $args[0]->getAttribute(ArrayFindArgVisitor::ATTRIBUTE_NAME)) { $acceptor = $parametersAcceptors[0]; $parameters = $acceptor->getParameters(); if (isset($parameters[1])) { $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\ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty())]; } } $closureBindToVar = $args[0]->getAttribute(ClosureBindToVarVisitor::ATTRIBUTE_NAME); if ($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(); if (isset($parameters[0])) { $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\ExtendedParametersAcceptor ? $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(); if (isset($parameters[1])) { $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\ExtendedParametersAcceptor ? $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) { if (!array_is_list($args)) { // actually $args parameter should be typed to list but we can't atm, // because its a BC break. $args = array_values($args); } $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 = array_last($parameters); } } if ($parameter !== null && $scope instanceof MutatingScope) { $rememberTypes = !$originalArg->value instanceof Node\Expr\Closure && !$originalArg->value instanceof Node\Expr\ArrowFunction; $scope = $scope->pushInFunctionCall(null, $parameter, $rememberTypes); } $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; $constantArrays = $type->getConstantArrays(); if (count($constantArrays) > 0) { foreach ($constantArrays as $constantArray) { $values = $constantArray->getValueTypes(); foreach ($constantArray->getKeyTypes() as $j => $keyType) { $valueType = $values[$j]; $valueIndex = $keyType->getValue(); if (is_string($valueIndex)) { $hasName = \true; } else { $valueIndex = $i + $j; } $types[$valueIndex] = isset($types[$valueIndex]) ? TypeCombinator::union($types[$valueIndex], $valueType) : $valueType; } } } else { $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 ($acceptor->getReturnType()->hasTemplateOrLateResolvableType()) { return \true; } foreach ($acceptor->getParameters() as $parameter) { if ($parameter instanceof \PHPStan\Reflection\ExtendedParameterReflection && $parameter->getOutType() !== null && $parameter->getOutType()->hasTemplateOrLateResolvableType()) { return \true; } if ($parameter instanceof \PHPStan\Reflection\ExtendedParameterReflection && $parameter->getClosureThisType() !== null && $parameter->getClosureThisType()->hasTemplateOrLateResolvableType()) { return \true; } if (!$parameter->getType()->hasTemplateOrLateResolvableType()) { continue; } return \true; } return \false; } /** * @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)->result); } } 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\ExtendedParametersAcceptor { 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 = TrinaryLogic::createNo(); $mustUseReturnValue = TrinaryLogic::createMaybe(); foreach ($acceptors as $acceptor) { $returnTypes[] = $acceptor->getReturnType(); if ($acceptor instanceof \PHPStan\Reflection\ExtendedParametersAcceptor) { $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->or($acceptor->acceptsNamedArguments()); $mustUseReturnValue = $mustUseReturnValue->or($acceptor->mustUseReturnValue()); } $isVariadic = $isVariadic || $acceptor->isVariadic(); foreach ($acceptor->getParameters() as $i => $parameter) { if (!isset($parameters[$i])) { $parameters[$i] = new ExtendedDummyParameter($parameter->getName(), $parameter->getType(), $i + 1 > $minimumNumberOfParameters, $parameter->passedByReference(), $parameter->isVariadic(), $parameter->getDefaultValue(), $parameter instanceof \PHPStan\Reflection\ExtendedParameterReflection ? $parameter->getNativeType() : new MixedType(), $parameter instanceof \PHPStan\Reflection\ExtendedParameterReflection ? $parameter->getPhpDocType() : new MixedType(), $parameter instanceof \PHPStan\Reflection\ExtendedParameterReflection ? $parameter->getOutType() : null, $parameter instanceof \PHPStan\Reflection\ExtendedParameterReflection ? $parameter->isImmediatelyInvokedCallable() : TrinaryLogic::createMaybe(), $parameter instanceof \PHPStan\Reflection\ExtendedParameterReflection ? $parameter->getClosureThisType() : null, $parameter instanceof \PHPStan\Reflection\ExtendedParameterReflection ? $parameter->getAttributes() : []); 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(); $attributes = $parameters[$i]->getAttributes(); if ($parameter instanceof \PHPStan\Reflection\ExtendedParameterReflection) { $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); $attributes = array_merge($attributes, $parameter->getAttributes()); } else { $nativeType = new MixedType(); $phpDocType = $type; $outType = null; $immediatelyInvokedCallable = TrinaryLogic::createMaybe(); $closureThisType = null; } $parameters[$i] = new ExtendedDummyParameter($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, $attributes); 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\ExtendedCallableFunctionVariant(TemplateTypeMap::createEmpty(), null, array_values($parameters), $isVariadic, $returnType, $phpDocReturnType ?? $returnType, $nativeReturnType ?? new MixedType(), null, $throwPoints, $isPure, $impurePoints, $invalidateExpressions, $usedVariables, $acceptsNamedArguments, $mustUseReturnValue); } return new \PHPStan\Reflection\ExtendedFunctionVariant(TemplateTypeMap::createEmpty(), null, array_values($parameters), $isVariadic, $returnType, $phpDocReturnType ?? $returnType, $nativeReturnType ?? new MixedType()); } private static function wrapAcceptor(\PHPStan\Reflection\ParametersAcceptor $acceptor): \PHPStan\Reflection\ExtendedParametersAcceptor { if ($acceptor instanceof \PHPStan\Reflection\ExtendedParametersAcceptor) { return $acceptor; } if ($acceptor instanceof CallableParametersAcceptor) { return new \PHPStan\Reflection\ExtendedCallableFunctionVariant($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), array_map(static fn(\PHPStan\Reflection\ParameterReflection $parameter): \PHPStan\Reflection\ExtendedParameterReflection => 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(), $acceptor->mustUseReturnValue(), $acceptor->getAsserts()); } return new \PHPStan\Reflection\ExtendedFunctionVariant($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), array_map(static fn(\PHPStan\Reflection\ParameterReflection $parameter): \PHPStan\Reflection\ExtendedParameterReflection => 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\ExtendedParameterReflection { return $parameter instanceof \PHPStan\Reflection\ExtendedParameterReflection ? $parameter : new ExtendedDummyParameter($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(); } } $nullableStringConstants = ['CURLOPT_CUSTOMREQUEST', 'CURLOPT_DNS_INTERFACE', 'CURLOPT_DNS_LOCAL_IP4', 'CURLOPT_DNS_LOCAL_IP6', 'CURLOPT_DOH_URL', 'CURLOPT_FTP_ACCOUNT', 'CURLOPT_FTPPORT', 'CURLOPT_HSTS', 'CURLOPT_KRBLEVEL', 'CURLOPT_RANGE', 'CURLOPT_RTSP_SESSION_ID', 'CURLOPT_UNIX_SOCKET_PATH', 'CURLOPT_XOAUTH2_BEARER']; foreach ($nullableStringConstants as $constName) { if (defined($constName) && constant($constName) === $curlOpt) { return new UnionType([new NullType(), new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()])]); } } $nonEmptyStringConstants = ['CURLOPT_ABSTRACT_UNIX_SOCKET', 'CURLOPT_ALTSVC', 'CURLOPT_AWS_SIGV4', 'CURLOPT_CAINFO', 'CURLOPT_CAPATH', 'CURLOPT_COOKIE', 'CURLOPT_COOKIEJAR', 'CURLOPT_COOKIELIST', 'CURLOPT_DEFAULT_PROTOCOL', 'CURLOPT_DNS_SERVERS', 'CURLOPT_EGDSOCKET', 'CURLOPT_FTP_ALTERNATIVE_TO_USER', 'CURLOPT_INTERFACE', 'CURLOPT_KEYPASSWD', 'CURLOPT_KRB4LEVEL', 'CURLOPT_LOGIN_OPTIONS', 'CURLOPT_MAIL_AUTH', 'CURLOPT_MAIL_FROM', 'CURLOPT_NOPROXY', 'CURLOPT_PASSWORD', 'CURLOPT_PINNEDPUBLICKEY', 'CURLOPT_PROTOCOLS_STR', 'CURLOPT_PROXY_CAINFO', 'CURLOPT_PROXY_CAPATH', 'CURLOPT_PROXY_CRLFILE', 'CURLOPT_PROXY_ISSUERCERT', 'CURLOPT_PROXY_KEYPASSWD', 'CURLOPT_PROXY_PINNEDPUBLICKEY', 'CURLOPT_PROXY_SERVICE_NAME', 'CURLOPT_PROXY_SSL_CIPHER_LIST', 'CURLOPT_PROXY_SSLCERT', 'CURLOPT_PROXY_SSLCERTTYPE', 'CURLOPT_PROXY_SSLKEY', 'CURLOPT_PROXY_SSLKEYTYPE', 'CURLOPT_PROXY_TLS13_CIPHERS', 'CURLOPT_PROXY_TLSAUTH_PASSWORD', 'CURLOPT_PROXY_TLSAUTH_TYPE', 'CURLOPT_PROXY_TLSAUTH_USERNAME', 'CURLOPT_PROXYPASSWORD', 'CURLOPT_PROXYUSERNAME', 'CURLOPT_PROXYUSERPWD', 'CURLOPT_RANDOM_FILE', 'CURLOPT_REDIR_PROTOCOLS_STR', 'CURLOPT_REFERER', 'CURLOPT_REQUEST_TARGET', 'CURLOPT_RTSP_STREAM_URI', 'CURLOPT_RTSP_TRANSPORT', 'CURLOPT_SASL_AUTHZID', 'CURLOPT_SERVICE_NAME', 'CURLOPT_SOCKS5_GSSAPI_SERVICE', 'CURLOPT_SSH_HOST_PUBLIC_KEY_MD5', 'CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256', 'CURLOPT_SSH_PRIVATE_KEYFILE', 'CURLOPT_SSH_PUBLIC_KEYFILE', 'CURLOPT_SSL_CIPHER_LIST', 'CURLOPT_SSL_EC_CURVES', 'CURLOPT_SSLCERT', 'CURLOPT_SSLCERTPASSWD', 'CURLOPT_SSLCERTTYPE', 'CURLOPT_SSLENGINE', 'CURLOPT_SSLENGINE_DEFAULT', 'CURLOPT_SSLKEY', 'CURLOPT_SSLKEYPASSWD', 'CURLOPT_SSLKEYTYPE', 'CURLOPT_TLS13_CIPHERS', 'CURLOPT_TLSAUTH_PASSWORD', 'CURLOPT_TLSAUTH_TYPE', 'CURLOPT_TLSAUTH_USERNAME', 'CURLOPT_TRANSFER_ENCODING', 'CURLOPT_URL', 'CURLOPT_USERAGENT', 'CURLOPT_USERNAME', 'CURLOPT_USERPWD']; foreach ($nonEmptyStringConstants as $constName) { if (defined($constName) && constant($constName) === $curlOpt) { return new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]); } } $stringConstants = [ 'CURLOPT_COOKIEFILE', 'CURLOPT_ENCODING', // Alias: CURLOPT_ACCEPT_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(); } } if (defined('CURLOPT_SHARE') && $curlOpt === CURLOPT_SHARE) { $phpversion = \PHPStan\Reflection\PhpVersionStaticAccessor::getInstance(); if ($phpversion->supportsCurlShareHandle()) { $shareType = new ObjectType('CurlShareHandle'); } else { $shareType = new ResourceType(); } if ($phpversion->supportsCurlSharePersistentHandle()) { $shareType = TypeCombinator::union($shareType, new ObjectType('CurlSharePersistentHandle')); } return $shareType; } // unknown constant return null; } } 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; } /** CreatesNewVariable > ReadsArgument > No. */ public function combine(self $other): self { if ($this->value > $other->value) { return $this; } elseif ($this->value < $other->value) { return $other; } return $this; } } 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 ExtendedFunctionVariant($this->closureType->getTemplateTypeMap(), $this->closureType->getResolvedTemplateTypeMap(), array_map(static fn(ParameterReflection $parameter): ExtendedParameterReflection => new \PHPStan\Reflection\Php\ExtendedDummyParameter($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(): ExtendedParametersAcceptor { 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 isBuiltin(): TrinaryLogic { $builtin = $this->nativeMethodReflection->isBuiltin(); if (is_bool($builtin)) { return TrinaryLogic::createFromBoolean($builtin); } return $builtin; } 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(): TrinaryLogic { 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(); } public function getAttributes(): array { return $this->nativeMethodReflection->getAttributes(); } public function mustUseReturnValue(): TrinaryLogic { return $this->nativeMethodReflection->mustUseReturnValue(); } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return $this->nativeMethodReflection->getResolvedPhpDoc(); } } 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); } } 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; } } isEnum(); } public function getAllowedSubTypes(ClassReflection $classReflection): array { $cases = []; foreach (array_keys($classReflection->getEnumCases()) as $name) { $cases[] = new EnumCaseObjectType($classReflection->getName(), $name); } return $cases; } } 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 ExtendedFunctionVariant(TemplateTypeMap::createEmpty(), TemplateTypeMap::createEmpty(), [], \false, $this->returnType, new MixedType(), $this->returnType)]; } public function getOnlyVariant(): ExtendedParametersAcceptor { 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 isBuiltin(): TrinaryLogic { return TrinaryLogic::createYes(); } public function getThrowType(): ?Type { return null; } public function hasSideEffects(): TrinaryLogic { return TrinaryLogic::createNo(); } public function getAsserts(): Assertions { return Assertions::createEmpty(); } public function acceptsNamedArguments(): TrinaryLogic { return TrinaryLogic::createFromBoolean($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(); } public function getAttributes(): array { return []; } public function mustUseReturnValue(): TrinaryLogic { return TrinaryLogic::createNo(); } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return null; } } name = $name; $this->declaringClass = $declaringClass; $this->type = $type; } public function getName(): string { return $this->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 hasPhpDocType(): bool { return \false; } public function getPhpDocType(): Type { return new MixedType(); } public function hasNativeType(): bool { return \false; } public function getNativeType(): Type { return new MixedType(); } 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(); } public function isAbstract(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinalByKeyword(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinal(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isVirtual(): TrinaryLogic { return TrinaryLogic::createNo(); } public function hasHook(string $hookType): bool { return \false; } public function getHook(string $hookType): ExtendedMethodReflection { throw new ShouldNotHappenException(); } public function isProtectedSet(): bool { return \false; } public function isPrivateSet(): bool { return \false; } public function getAttributes(): array { return []; } public function isDummy(): TrinaryLogic { return TrinaryLogic::createNo(); } } 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; } } 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 ExtendedFunctionVariant(TemplateTypeMap::createEmpty(), TemplateTypeMap::createEmpty(), [new \PHPStan\Reflection\Php\ExtendedDummyParameter('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(): ExtendedParametersAcceptor { return $this->getVariants()[0]; } /** * @return list */ public function getNamedArgumentsVariants(): array { return $this->getVariants(); } public function acceptsNamedArguments(): TrinaryLogic { return TrinaryLogic::createYes(); } public function isDeprecated(): TrinaryLogic { return TrinaryLogic::createNo(); } public function getDeprecatedDescription(): ?string { return null; } public function isInternal(): TrinaryLogic { return TrinaryLogic::createNo(); } 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(); } public function getAttributes(): array { return []; } public function mustUseReturnValue(): TrinaryLogic { return TrinaryLogic::createNo(); } } */ private array $attributes; /** * @param list $attributes */ public function __construct(string $name, Type $type, bool $optional, ?PassedByReference $passedByReference, bool $variadic, ?Type $defaultValue, Type $nativeType, Type $phpDocType, ?Type $outType, TrinaryLogic $immediatelyInvokedCallable, ?Type $closureThisType, array $attributes) { $this->nativeType = $nativeType; $this->phpDocType = $phpDocType; $this->outType = $outType; $this->immediatelyInvokedCallable = $immediatelyInvokedCallable; $this->closureThisType = $closureThisType; $this->attributes = $attributes; parent::__construct($name, $type, $optional, $passedByReference, $variadic, $defaultValue); } public function getPhpDocType(): Type { return $this->phpDocType; } public function hasNativeType(): bool { return !$this->nativeType instanceof MixedType || $this->nativeType->isExplicitMixed(); } 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; } public function getAttributes(): array { return $this->attributes; } } > */ private array $propertyTypesCache = []; /** @var array */ private array $inferClassConstructorPropertyTypesInProcess = []; public function __construct(ScopeFactory $scopeFactory, NodeScopeResolver $nodeScopeResolver, \PHPStan\Reflection\Php\PhpMethodReflectionFactory $methodReflectionFactory, PhpDocInheritanceResolver $phpDocInheritanceResolver, DeprecationProvider $deprecationProvider, AnnotationsMethodsClassReflectionExtension $annotationsMethodsClassReflectionExtension, AnnotationsPropertiesClassReflectionExtension $annotationsPropertiesClassReflectionExtension, SignatureMapProvider $signatureMapProvider, Parser $parser, StubPhpDocProvider $stubPhpDocProvider, ReflectionProvider\ReflectionProviderProvider $reflectionProviderProvider, FileTypeMapper $fileTypeMapper, AttributeReflectionFactory $attributeReflectionFactory, bool $inferPrivatePropertyTypeFromConstructor) { $this->scopeFactory = $scopeFactory; $this->nodeScopeResolver = $nodeScopeResolver; $this->methodReflectionFactory = $methodReflectionFactory; $this->phpDocInheritanceResolver = $phpDocInheritanceResolver; $this->deprecationProvider = $deprecationProvider; $this->annotationsMethodsClassReflectionExtension = $annotationsMethodsClassReflectionExtension; $this->annotationsPropertiesClassReflectionExtension = $annotationsPropertiesClassReflectionExtension; $this->signatureMapProvider = $signatureMapProvider; $this->parser = $parser; $this->stubPhpDocProvider = $stubPhpDocProvider; $this->reflectionProviderProvider = $reflectionProviderProvider; $this->fileTypeMapper = $fileTypeMapper; $this->attributeReflectionFactory = $attributeReflectionFactory; $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); } public function getProperty(ClassReflection $classReflection, string $propertyName, ClassMemberAccessAnswerer $scope): \PHPStan\Reflection\Php\PhpPropertyReflection { $cacheKey = $classReflection->getCacheKey(); if ($scope->isInClass()) { $cacheKey = sprintf('%s-%s', $cacheKey, $scope->getClassReflection()->getCacheKey()); } if (!isset($this->propertiesIncludingAnnotations[$cacheKey][$propertyName])) { $this->propertiesIncludingAnnotations[$cacheKey][$propertyName] = $this->createProperty($classReflection, $propertyName, $scope, \true); } return $this->propertiesIncludingAnnotations[$cacheKey][$propertyName]; } public function getNativeProperty(ClassReflection $classReflection, string $propertyName): \PHPStan\Reflection\Php\PhpPropertyReflection { if (!isset($this->nativeProperties[$classReflection->getCacheKey()][$propertyName])) { $property = $this->createProperty($classReflection, $propertyName, new OutOfClassScope(), \false); $this->nativeProperties[$classReflection->getCacheKey()][$propertyName] = $property; } return $this->nativeProperties[$classReflection->getCacheKey()][$propertyName]; } private function createProperty(ClassReflection $classReflection, string $propertyName, ClassMemberAccessAnswerer $scope, bool $includingAnnotations): \PHPStan\Reflection\Php\PhpPropertyReflection { $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 ($classReflection->getEnumCases() as $name => $case) { if ($propertyName === 'name') { $types[] = new ConstantStringType($name); continue; } $value = $case->getBackingValueType(); if ($value === null) { throw new ShouldNotHappenException(); } $types[] = $value; } $phpDocType = TypeCombinator::union(...$types); return new \PHPStan\Reflection\Php\PhpPropertyReflection($declaringClassReflection, null, new MixedType(), $phpDocType, $phpDocType, $classReflection->getNativeReflection()->getProperty($propertyName), null, null, null, null, \false, \false, \false, \false, [], \false, \true, \false, \false, \true); } } $deprecation = $this->deprecationProvider->getPropertyDeprecation($propertyReflection); $deprecatedDescription = $deprecation === null ? null : $deprecation->getDescription(); $isDeprecated = $deprecation !== null; $isInternal = \false; $isReadOnlyByPhpDoc = $classReflection->isImmutable(); $isFinal = $classReflection->isFinal() || $propertyReflection->isFinal(); $isAllowedPrivateMutation = \false; $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) { $currentResolvedPhpDoc = $this->stubPhpDocProvider->findPropertyPhpDoc($declaringClassName, $propertyName); if ($currentResolvedPhpDoc === null && $declaringTraitName !== null) { $currentResolvedPhpDoc = $this->stubPhpDocProvider->findPropertyPhpDoc($declaringTraitName, $propertyName); } if ($currentResolvedPhpDoc === null && $docComment !== null) { $currentResolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($declaringClassReflection->getFileName(), $declaringClassName, $declaringTraitName, null, $docComment); } $resolvedPhpDoc = $this->phpDocInheritanceResolver->resolvePhpDocForProperty($declaringClassReflection, $propertyName, $currentResolvedPhpDoc); } elseif ($docComment !== null) { $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($declaringClassReflection->getFileName(), $declaringClassName, $declaringTraitName, $constructorName, $docComment); } 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, $declaringClassReflection->getActiveTemplateTypeMap(), $declaringClassReflection->getCallSiteVarianceMap(), TemplateTypeVariance::createInvariant()) : null; if (!$isDeprecated) { $deprecatedDescription = $resolvedPhpDoc->getDeprecatedTag() !== null ? $resolvedPhpDoc->getDeprecatedTag()->getMessage() : null; $isDeprecated = $resolvedPhpDoc->isDeprecated(); } $isInternal = $resolvedPhpDoc->isInternal(); $isReadOnlyByPhpDoc = $isReadOnlyByPhpDoc || $resolvedPhpDoc->isReadOnly(); $isFinal = $isFinal || $resolvedPhpDoc->isFinal(); $isAllowedPrivateMutation = $resolvedPhpDoc->isAllowedPrivateMutation(); } if ($phpDocType === null) { if (isset($constructorName)) { $resolvedConstructorPhpDoc = $declaringClassReflection->getConstructor()->getResolvedPhpDoc(); if ($resolvedConstructorPhpDoc !== null) { $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 = TypehintHelper::decideTypeFromReflection($propertyReflection->getType(), \null, $declaringClassReflection); $declaringTrait = null; $reflectionProvider = $this->reflectionProviderProvider->getReflectionProvider(); if ($declaringTraitName !== null && $reflectionProvider->hasClass($declaringTraitName)) { $declaringTrait = $reflectionProvider->getClass($declaringTraitName); } $getHook = null; $setHook = null; $betterReflection = $propertyReflection->getBetterReflection(); if ($betterReflection->hasHook('get')) { $betterReflectionGetHook = $betterReflection->getHook('get'); if ($betterReflectionGetHook === null) { throw new ShouldNotHappenException(); } $getHook = $this->createUserlandMethodReflection($declaringClassReflection, $declaringClassReflection, new ReflectionMethod($betterReflectionGetHook), $declaringTraitName); if ($phpDocType !== null) { $getHookMethodReflectionVariant = $getHook->getOnlyVariant(); $getHookMethodReflectionVariantPhpDocReturnType = $getHookMethodReflectionVariant->getPhpDocReturnType(); if ($getHookMethodReflectionVariantPhpDocReturnType instanceof MixedType && !$getHookMethodReflectionVariantPhpDocReturnType instanceof TemplateMixedType && !$getHookMethodReflectionVariantPhpDocReturnType->isExplicitMixed()) { $getHook = $getHook->changePropertyGetHookPhpDocType($phpDocType); } } } if ($betterReflection->hasHook('set')) { $betterReflectionSetHook = $betterReflection->getHook('set'); if ($betterReflectionSetHook === null) { throw new ShouldNotHappenException(); } $setHook = $this->createUserlandMethodReflection($declaringClassReflection, $declaringClassReflection, new ReflectionMethod($betterReflectionSetHook), $declaringTraitName); if ($phpDocType !== null) { $setHookMethodReflectionVariant = $setHook->getOnlyVariant(); $setHookMethodReflectionParameters = $setHookMethodReflectionVariant->getParameters(); if (isset($setHookMethodReflectionParameters[0])) { $setHookMethodReflectionParameter = $setHookMethodReflectionParameters[0]; $setHookMethodReflectionParameterPhpDocType = $setHookMethodReflectionParameter->getPhpDocType(); if ($setHookMethodReflectionParameterPhpDocType instanceof MixedType && !$setHookMethodReflectionParameterPhpDocType instanceof TemplateMixedType && !$setHookMethodReflectionParameterPhpDocType->isExplicitMixed()) { $setHook = $setHook->changePropertySetHookPhpDocType($setHookMethodReflectionParameter->getName(), $phpDocType); } } } } $nativeProperty = new \PHPStan\Reflection\Php\PhpPropertyReflection($declaringClassReflection, $declaringTrait, $nativeType, $phpDocType, $phpDocType, $propertyReflection, $getHook, $setHook, $resolvedPhpDoc, $deprecatedDescription, $isDeprecated, $isInternal, $isReadOnlyByPhpDoc, $isAllowedPrivateMutation, $this->attributeReflectionFactory->fromNativeReflection($propertyReflection->getAttributes(), InitializerExprContext::fromClass($declaringClassReflection->getName(), $declaringClassReflection->getFileName())), $isFinal, \true, \true, $propertyReflection->isPrivate(), $propertyReflection->isPublic()); if ($includingAnnotations && !$declaringClassReflection->isEnum() && !$propertyReflection->isStatic() && ($classReflection->allowsDynamicProperties() || $scope->canReadProperty($nativeProperty)) && $this->annotationsPropertiesClassReflectionExtension->hasProperty($classReflection, $propertyName) && ($nativeProperty->isPublic() || !$scope->isInClass() || $scope->getClassReflection()->getName() !== $declaringClassReflection->getName())) { $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]) { if ($nativeType->isSuperTypeOf($annotationProperty->getReadableType())->yes() || !$scope->canReadProperty($nativeProperty)) { $nativeType = new MixedType(); } return new \PHPStan\Reflection\Php\PhpPropertyReflection($annotationProperty->getDeclaringClass(), $declaringTrait, $nativeType, $annotationProperty->getReadableType(), $annotationProperty->getWritableType(), $propertyReflection, $getHook, $setHook, $nativeProperty->getResolvedPhpDoc(), $deprecatedDescription, $isDeprecated, $isInternal, $isReadOnlyByPhpDoc, $isAllowedPrivateMutation, $this->attributeReflectionFactory->fromNativeReflection($propertyReflection->getAttributes(), InitializerExprContext::fromClass($declaringClassReflection->getName(), $declaringClassReflection->getFileName())), $isFinal, $annotationProperty->isReadable(), $annotationProperty->isWritable(), \false, \true); } } return $nativeProperty; } public function hasMethod(ClassReflection $classReflection, string $methodName): bool { return $classReflection->getNativeReflection()->hasMethod($methodName); } public function getMethod(ClassReflection $classReflection, string $methodName): ExtendedMethodReflection { if (isset($this->methodsIncludingAnnotations[$classReflection->getCacheKey()][$methodName])) { return $this->methodsIncludingAnnotations[$classReflection->getCacheKey()][$methodName]; } $nativeMethodReflection = $classReflection->getNativeReflection()->getMethod($methodName); if (!isset($this->methodsIncludingAnnotations[$classReflection->getCacheKey()][$nativeMethodReflection->getName()])) { $method = $this->createMethod($classReflection, $methodName, $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(); } $nativeMethodReflection = $classReflection->getNativeReflection()->getMethod($methodName); if (!isset($this->nativeMethods[$classReflection->getCacheKey()][$nativeMethodReflection->getName()])) { $method = $this->createMethod($classReflection, $methodName, $nativeMethodReflection, \false); $this->nativeMethods[$classReflection->getCacheKey()][$nativeMethodReflection->getName()] = $method; } return $this->nativeMethods[$classReflection->getCacheKey()][$nativeMethodReflection->getName()]; } private function createMethod(ClassReflection $classReflection, string $methodName, ReflectionMethod $methodReflection, bool $includingAnnotations): ExtendedMethodReflection { if ($includingAnnotations) { if ($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; } } return $this->getNativeMethod($classReflection, $methodName); } $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 (($declaringClass->isBuiltin() || $declaringClass->isEnum()) && $this->signatureMapProvider->hasMethodSignature($declaringClassName, $methodReflection->getName())) { $variantsByType = ['positional' => []]; $throwType = null; $asserts = Assertions::createEmpty(); $acceptsNamedArguments = \true; $selfOutType = null; $phpDocComment = null; $isPure = null; if ($this->signatureMapProvider->hasMethodMetadata($declaringClassName, $methodReflection->getName())) { $isPure = !$this->signatureMapProvider->getMethodMetadata($declaringClassName, $methodReflection->getName())['hasSideEffects']; } $methodSignaturesResult = $this->signatureMapProvider->getMethodSignatures($declaringClassName, $methodReflection->getName(), $methodReflection); foreach ($methodSignaturesResult as $signatureType => $methodSignatures) { if ($methodSignatures === null) { continue; } foreach ($methodSignatures as $methodSignature) { $phpDocParameterNameMapping = []; foreach ($methodSignature->getParameters() as $parameter) { $phpDocParameterNameMapping[$parameter->getName()] = $parameter->getName(); } $phpDocParameterTypes = []; $phpDocReturnType = null; $phpDocParameterOutTypes = []; $immediatelyInvokedCallableParameters = []; $closureThisParameters = []; $currentResolvedPhpDoc = null; $phpDocDeclaringClass = $declaringClass; $phpDocFromStubs = \false; if (count($methodSignatures) === 1) { $stubPhpDocPair = $this->findMethodPhpDocIncludingAncestors($declaringClass, $declaringClass, $methodReflection->getName(), array_map(static fn(ParameterSignature $parameterSignature): string => $parameterSignature->getName(), $methodSignature->getParameters())); if ($stubPhpDocPair !== null) { [$currentResolvedPhpDoc, $phpDocDeclaringClass] = $stubPhpDocPair; $phpDocFromStubs = \true; } } if ($currentResolvedPhpDoc === null && $methodReflection->getDocComment() !== \false) { $currentResolvedPhpDoc = $this->phpDocInheritanceResolver->resolvePhpDocForMethod($declaringClass, $methodReflection->getName(), $this->fileTypeMapper->getResolvedPhpDoc($methodReflection->getFileName() === \false ? null : $methodReflection->getFileName(), $declaringClassName, null, $methodReflection->getName(), $methodReflection->getDocComment()), array_map(static fn(ReflectionParameter $parameter): string => $parameter->getName(), $methodReflection->getParameters())); } if ($currentResolvedPhpDoc !== null) { $templateTypeMap = $phpDocDeclaringClass->getActiveTemplateTypeMap(); $callSiteVarianceMap = $phpDocDeclaringClass->getCallSiteVarianceMap(); $returnTag = $currentResolvedPhpDoc->getReturnTag(); $immediatelyInvokedCallableParameters = array_map(static fn(bool $immediate) => TrinaryLogic::createFromBoolean($immediate), $currentResolvedPhpDoc->getParamsImmediatelyInvokedCallable()); if ($returnTag !== null && count($methodSignatures) === 1) { $phpDocReturnType = TemplateTypeHelper::resolveTemplateTypes($returnTag->getType(), $templateTypeMap, $callSiteVarianceMap, TemplateTypeVariance::createCovariant()); } $closureThisParameters = array_map(static fn($tag) => $tag->getType(), $currentResolvedPhpDoc->getParamClosureThisTags()); foreach ($currentResolvedPhpDoc->getParamTags() as $name => $paramTag) { $phpDocParameterTypes[$name] = TemplateTypeHelper::resolveTemplateTypes($paramTag->getType(), $templateTypeMap, $callSiteVarianceMap, TemplateTypeVariance::createContravariant()); } $throwsTag = $currentResolvedPhpDoc->getThrowsTag(); if ($throwsTag !== null) { $throwType = $throwsTag->getType(); } $asserts = Assertions::createFromResolvedPhpDocBlock($currentResolvedPhpDoc); $acceptsNamedArguments = $currentResolvedPhpDoc->acceptsNamedArguments(); $isPure ??= $currentResolvedPhpDoc->isPure(); $selfOutTypeTag = $currentResolvedPhpDoc->getSelfOutTag(); if ($selfOutTypeTag !== null) { $selfOutType = $selfOutTypeTag->getType(); } foreach ($currentResolvedPhpDoc->getParamOutTags() as $name => $paramOutTag) { $phpDocParameterOutTypes[$name] = TemplateTypeHelper::resolveTemplateTypes($paramOutTag->getType(), $templateTypeMap, $callSiteVarianceMap, TemplateTypeVariance::createCovariant()); } if ($currentResolvedPhpDoc->hasPhpDocString()) { $phpDocComment = $currentResolvedPhpDoc->getPhpDocString(); } if (!$phpDocFromStubs) { $signatureParameters = $methodSignature->getParameters(); foreach ($methodReflection->getParameters() as $paramI => $reflectionParameter) { if (!array_key_exists($paramI, $signatureParameters)) { continue; } $phpDocParameterNameMapping[$signatureParameters[$paramI]->getName()] = $reflectionParameter->getName(); } } } $variantsByType[$signatureType][] = $this->createNativeMethodVariant($methodSignature, $phpDocParameterTypes, $phpDocReturnType, $phpDocParameterNameMapping, $phpDocParameterOutTypes, $immediatelyInvokedCallableParameters, $closureThisParameters, $phpDocFromStubs, $signatureType !== 'named'); } } if ($isPure === null) { $classResolvedPhpDoc = $declaringClass->getResolvedPhpDoc(); if ($classResolvedPhpDoc !== null && $classResolvedPhpDoc->areAllMethodsPure()) { $isPure = \true; } elseif ($classResolvedPhpDoc !== null && $classResolvedPhpDoc->areAllMethodsImpure()) { $isPure = \false; } } return new NativeMethodReflection($this->reflectionProviderProvider->getReflectionProvider(), $declaringClass, $methodReflection, $currentResolvedPhpDoc ?? null, $variantsByType['positional'], $variantsByType['named'] ?? null, $isPure !== null ? TrinaryLogic::createFromBoolean(!$isPure) : TrinaryLogic::createMaybe(), $throwType, $asserts, $acceptsNamedArguments, $selfOutType, $phpDocComment, $this->attributeReflectionFactory->fromNativeReflection($methodReflection->getAttributes(), InitializerExprContext::fromClassMethod($declaringClassName, null, $methodReflection->getName(), null))); } return $this->createUserlandMethodReflection($declaringClass, $declaringClass, $methodReflection, $this->findMethodTrait($methodReflection)); } public function createUserlandMethodReflection(ClassReflection $fileDeclaringClass, ClassReflection $actualDeclaringClass, ReflectionMethod $methodReflection, ?string $declaringTraitName): \PHPStan\Reflection\Php\PhpMethodReflection { $deprecation = $this->deprecationProvider->getMethodDeprecation($methodReflection); $deprecatedDescription = $deprecation === null ? null : $deprecation->getDescription(); $isDeprecated = $deprecation !== null; $currentResolvedPhpDoc = null; $stubPhpDocPair = $this->findMethodPhpDocIncludingAncestors($fileDeclaringClass, $fileDeclaringClass, $methodReflection->getName(), array_map(static fn(ReflectionParameter $parameter): string => $parameter->getName(), $methodReflection->getParameters())); $phpDocBlockClassReflection = $fileDeclaringClass; $methodDeclaringClass = $methodReflection->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 fn(ReflectionParameter $parameter): string => $parameter->getName(), $methodReflection->getParameters())); } } if ($stubPhpDocPair !== null) { [$currentResolvedPhpDoc, $phpDocBlockClassReflection] = $stubPhpDocPair; } if ($currentResolvedPhpDoc === null && $methodReflection->getDocComment() !== \false) { $currentResolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($actualDeclaringClass->getFileName(), $actualDeclaringClass->getName(), $declaringTraitName, $methodReflection->getName(), $methodReflection->getDocComment()); } $resolvedPhpDoc = $this->phpDocInheritanceResolver->resolvePhpDocForMethod($actualDeclaringClass, $methodReflection->getName(), $currentResolvedPhpDoc, array_map(static fn(ReflectionParameter $parameter): string => $parameter->getName(), $methodReflection->getParameters())); $declaringTrait = null; $reflectionProvider = $this->reflectionProviderProvider->getReflectionProvider(); if ($declaringTraitName !== null && $reflectionProvider->hasClass($declaringTraitName)) { $declaringTrait = $reflectionProvider->getClass($declaringTraitName); } $phpDocParameterTypes = []; if ($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; } } $nativeReturnType = TypehintHelper::decideTypeFromReflection($methodReflection->getReturnType(), \null, $actualDeclaringClass); $isPure = null; if ($actualDeclaringClass->isBuiltin() || $actualDeclaringClass->isEnum()) { foreach (array_keys($actualDeclaringClass->getAncestors()) as $className) { if ($this->signatureMapProvider->hasMethodMetadata($className, $methodReflection->getName())) { $hasSideEffects = $this->signatureMapProvider->getMethodMetadata($className, $methodReflection->getName())['hasSideEffects']; $isPure = !$hasSideEffects; break; } } } $phpDocParameterOutTypes = []; $phpDocReturnType = null; $templateTypeMap = TemplateTypeMap::createEmpty(); $immediatelyInvokedCallableParameters = []; $closureThisParameters = []; $phpDocThrowType = null; $isInternal = \false; $isFinal = \false; $asserts = Assertions::createEmpty(); $acceptsNamedArguments = \true; $selfOutType = null; $phpDocComment = null; if ($resolvedPhpDoc !== null) { $templateTypeMap = $resolvedPhpDoc->getTemplateTypeMap(); $immediatelyInvokedCallableParameters = array_map(static fn(bool $immediate) => TrinaryLogic::createFromBoolean($immediate), $resolvedPhpDoc->getParamsImmediatelyInvokedCallable()); $closureThisParameters = array_map(static fn($tag) => $tag->getType(), $resolvedPhpDoc->getParamClosureThisTags()); $phpDocReturnType = $this->getPhpDocReturnType($phpDocBlockClassReflection, $resolvedPhpDoc, $nativeReturnType); $phpDocThrowType = $resolvedPhpDoc->getThrowsTag() !== null ? $resolvedPhpDoc->getThrowsTag()->getType() : null; foreach ($resolvedPhpDoc->getParamTags() as $paramName => $paramTag) { if (array_key_exists($paramName, $phpDocParameterTypes)) { continue; } $phpDocParameterTypes[$paramName] = $paramTag->getType(); } foreach ($resolvedPhpDoc->getParamOutTags() as $paramName => $paramOutTag) { $phpDocParameterOutTypes[$paramName] = TemplateTypeHelper::resolveTemplateTypes($paramOutTag->getType(), $phpDocBlockClassReflection->getActiveTemplateTypeMap(), $phpDocBlockClassReflection->getCallSiteVarianceMap(), TemplateTypeVariance::createCovariant()); } if (!$isDeprecated) { $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; if ($resolvedPhpDoc->hasPhpDocString()) { $phpDocComment = $resolvedPhpDoc->getPhpDocString(); } } if ($isPure === null) { $classResolvedPhpDoc = $phpDocBlockClassReflection->getResolvedPhpDoc(); if ($classResolvedPhpDoc !== null && $classResolvedPhpDoc->areAllMethodsPure()) { if (strtolower($methodReflection->getName()) === '__construct' || ($phpDocReturnType === null || !$phpDocReturnType->isVoid()->yes()) && !$nativeReturnType->isVoid()->yes()) { $isPure = \true; } } elseif ($classResolvedPhpDoc !== null && $classResolvedPhpDoc->areAllMethodsImpure()) { $isPure = \false; } } foreach ($phpDocParameterTypes as $paramName => $paramType) { $phpDocParameterTypes[$paramName] = TemplateTypeHelper::resolveTemplateTypes($paramType, $phpDocBlockClassReflection->getActiveTemplateTypeMap(), $phpDocBlockClassReflection->getCallSiteVarianceMap(), TemplateTypeVariance::createContravariant()); } return $this->methodReflectionFactory->create($actualDeclaringClass, $declaringTrait, $methodReflection, $templateTypeMap, $phpDocParameterTypes, $phpDocReturnType, $phpDocThrowType, $resolvedPhpDoc, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal, $isPure, $asserts, $selfOutType, $phpDocComment, $phpDocParameterOutTypes, $immediatelyInvokedCallableParameters, $closureThisParameters, $acceptsNamedArguments, $this->attributeReflectionFactory->fromNativeReflection($methodReflection->getAttributes(), InitializerExprContext::fromClassMethod($actualDeclaringClass->getName(), $declaringTraitName, $methodReflection->getName(), $actualDeclaringClass->getFileName()))); } /** * @param array $phpDocParameterTypes * @param array $phpDocParameterNameMapping * @param array $phpDocParameterOutTypes * @param array $immediatelyInvokedCallableParameters * @param array $closureThisParameters */ private function createNativeMethodVariant(FunctionSignature $methodSignature, array $phpDocParameterTypes, ?Type $phpDocReturnType, array $phpDocParameterNameMapping, array $phpDocParameterOutTypes, array $immediatelyInvokedCallableParameters, array $closureThisParameters, bool $phpDocFromStubs, bool $usePhpDocParameterNames): ExtendedFunctionVariant { $parameters = []; foreach ($methodSignature->getParameters() as $parameterSignature) { $type = null; $phpDocType = null; $parameterOutType = null; $phpDocParameterName = $phpDocParameterNameMapping[$parameterSignature->getName()] ?? $parameterSignature->getName(); if (isset($phpDocParameterTypes[$phpDocParameterName])) { $phpDocType = $phpDocParameterTypes[$phpDocParameterName]; $type = $phpDocFromStubs ? $phpDocType : TypehintHelper::decideType($parameterSignature->getType(), $phpDocType); } if (isset($phpDocParameterOutTypes[$phpDocParameterName])) { $parameterOutType = $phpDocParameterOutTypes[$phpDocParameterName]; } if (isset($immediatelyInvokedCallableParameters[$phpDocParameterName])) { $immediatelyInvoked = $immediatelyInvokedCallableParameters[$phpDocParameterName]; } else { $immediatelyInvoked = TrinaryLogic::createMaybe(); } $closureThisType = null; if (isset($closureThisParameters[$phpDocParameterName])) { $closureThisType = $closureThisParameters[$phpDocParameterName]; } $parameters[] = new ExtendedNativeParameterReflection($usePhpDocParameterNames ? $phpDocParameterName : $parameterSignature->getName(), $parameterSignature->isOptional(), $type ?? $parameterSignature->getType(), $phpDocType ?? new MixedType(), $parameterSignature->getNativeType(), $parameterSignature->passedByReference(), $parameterSignature->isVariadic(), $parameterSignature->getDefaultValue(), $parameterOutType ?? $parameterSignature->getOutType(), $immediatelyInvoked, $closureThisType, []); } if ($phpDocFromStubs && $phpDocReturnType !== null) { $returnType = $phpDocReturnType; } else { $returnType = TypehintHelper::decideType($methodSignature->getReturnType(), $phpDocReturnType); } return new ExtendedFunctionVariant(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(ReflectionMethod $methodReflection): ?string { $declaringClass = $methodReflection->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()) { return $phpDocReturnType; } if ($nativeReturnType->isSuperTypeOf($phpDocReturnType)->yes()) { return $phpDocReturnType; } if ($phpDocReturnType instanceof UnionType) { $types = []; foreach ($phpDocReturnType->getTypes() as $innerType) { if (!$nativeReturnType->isSuperTypeOf($innerType)->yes()) { continue; } $types[] = $innerType; } if (count($types) === 0) { return null; } return TypeCombinator::union(...$types); } 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]; } $isKnownClass = $this->stubPhpDocProvider->isKnownClass($declaringClassName); if (!$isKnownClass && !$declaringClass->isBuiltin()) { 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; } if (!$isKnownClass && $ancestor->isGeneric()) { continue; } return [$resolved, $ancestor]; } return null; } } > */ private array $parameterAttributes; private Type $realReturnType; private ?Type $phpDocReturnType; private ?Type $throwType; private ?string $deprecatedDescription; private bool $isDeprecated; private bool $isInternal; protected ?bool $isPure; private bool $acceptsNamedArguments; private Assertions $assertions; private ?string $phpDocComment; /** * @var Type[] */ private array $parameterOutTypes; /** * @var array */ private array $immediatelyInvokedCallableParameters; /** * @var array */ private array $phpDocClosureThisTypeParameters; /** * @var list */ private array $attributes; /** @var Function_|ClassMethod|Node\PropertyHook */ private Node\FunctionLike $functionLike; /** @var list|null */ private ?array $variants = null; /** * @param Function_|ClassMethod|Node\PropertyHook $functionLike * @param Type[] $realParameterTypes * @param Type[] $phpDocParameterTypes * @param Type[] $realParameterDefaultValues * @param array> $parameterAttributes * @param Type[] $parameterOutTypes * @param array $immediatelyInvokedCallableParameters * @param array $phpDocClosureThisTypeParameters * @param list $attributes */ public function __construct(FunctionLike $functionLike, string $fileName, TemplateTypeMap $templateTypeMap, array $realParameterTypes, array $phpDocParameterTypes, array $realParameterDefaultValues, array $parameterAttributes, Type $realReturnType, ?Type $phpDocReturnType, ?Type $throwType, ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, ?bool $isPure, bool $acceptsNamedArguments, Assertions $assertions, ?string $phpDocComment, array $parameterOutTypes, array $immediatelyInvokedCallableParameters, array $phpDocClosureThisTypeParameters, array $attributes) { $this->fileName = $fileName; $this->templateTypeMap = $templateTypeMap; $this->realParameterTypes = $realParameterTypes; $this->phpDocParameterTypes = $phpDocParameterTypes; $this->realParameterDefaultValues = $realParameterDefaultValues; $this->parameterAttributes = $parameterAttributes; $this->realReturnType = $realReturnType; $this->phpDocReturnType = $phpDocReturnType; $this->throwType = $throwType; $this->deprecatedDescription = $deprecatedDescription; $this->isDeprecated = $isDeprecated; $this->isInternal = $isInternal; $this->isPure = $isPure; $this->acceptsNamedArguments = $acceptsNamedArguments; $this->assertions = $assertions; $this->phpDocComment = $phpDocComment; $this->parameterOutTypes = $parameterOutTypes; $this->immediatelyInvokedCallableParameters = $immediatelyInvokedCallableParameters; $this->phpDocClosureThisTypeParameters = $phpDocClosureThisTypeParameters; $this->attributes = $attributes; $this->functionLike = $functionLike; } /** * @phpstan-assert-if-true PhpMethodFromParserNodeReflection $this */ public function isMethodOrPropertyHook(): bool { return $this instanceof \PHPStan\Reflection\Php\PhpMethodFromParserNodeReflection; } 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 instanceof Function_) { // PropertyHook is handled in PhpMethodFromParserNodeReflection subclass throw new ShouldNotHappenException(); } if ($this->functionLike->namespacedName === null) { throw new ShouldNotHappenException(); } return (string) $this->functionLike->namespacedName; } public function getVariants(): array { return $this->variants ??= [new ExtendedFunctionVariant($this->getTemplateTypeMap(), $this->getResolvedTemplateTypeMap(), $this->getParameters(), $this->isVariadic(), $this->getReturnType(), $this->getPhpDocReturnType(), $this->getNativeReturnType())]; } public function getOnlyVariant(): ExtendedParametersAcceptor { return $this; } public function getNamedArgumentsVariants(): ?array { return null; } public function getTemplateTypeMap(): TemplateTypeMap { return $this->templateTypeMap; } public function getResolvedTemplateTypeMap(): TemplateTypeMap { return TemplateTypeMap::createEmpty(); } /** * @return list */ 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, $this->parameterAttributes[$parameter->var->name] ?? []); } 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 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(): TrinaryLogic { return TrinaryLogic::createFromBoolean($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); } public function getAttributes(): array { return $this->attributes; } public function mustUseReturnValue(): TrinaryLogic { foreach ($this->attributes as $attrib) { if (strtolower($attrib->getName()) === 'nodiscard') { return TrinaryLogic::createYes(); } } return TrinaryLogic::createNo(); } } */ private array $phpDocParameterTypes; private ?Type $phpDocReturnType; private ?Type $phpDocThrowType; private ?string $deprecatedDescription; private bool $isDeprecated; private bool $isInternal; private ?string $filename; private ?bool $isPure; private Assertions $asserts; private bool $acceptsNamedArguments; private ?string $phpDocComment; /** * @var array */ private array $phpDocParameterOutTypes; /** * @var array */ private array $phpDocParameterImmediatelyInvokedCallable; /** * @var array */ private array $phpDocParameterClosureThisTypes; /** * @var list */ private array $attributes; /** @var list|null */ private ?array $variants = null; /** * @param array $phpDocParameterTypes * @param array $phpDocParameterOutTypes * @param array $phpDocParameterImmediatelyInvokedCallable * @param array $phpDocParameterClosureThisTypes * @param list $attributes */ public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver, ReflectionFunction $reflection, AttributeReflectionFactory $attributeReflectionFactory, TemplateTypeMap $templateTypeMap, array $phpDocParameterTypes, ?Type $phpDocReturnType, ?Type $phpDocThrowType, ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, ?string $filename, ?bool $isPure, Assertions $asserts, bool $acceptsNamedArguments, ?string $phpDocComment, array $phpDocParameterOutTypes, array $phpDocParameterImmediatelyInvokedCallable, array $phpDocParameterClosureThisTypes, array $attributes) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->reflection = $reflection; $this->attributeReflectionFactory = $attributeReflectionFactory; $this->templateTypeMap = $templateTypeMap; $this->phpDocParameterTypes = $phpDocParameterTypes; $this->phpDocReturnType = $phpDocReturnType; $this->phpDocThrowType = $phpDocThrowType; $this->deprecatedDescription = $deprecatedDescription; $this->isDeprecated = $isDeprecated; $this->isInternal = $isInternal; $this->filename = $filename; $this->isPure = $isPure; $this->asserts = $asserts; $this->acceptsNamedArguments = $acceptsNamedArguments; $this->phpDocComment = $phpDocComment; $this->phpDocParameterOutTypes = $phpDocParameterOutTypes; $this->phpDocParameterImmediatelyInvokedCallable = $phpDocParameterImmediatelyInvokedCallable; $this->phpDocParameterClosureThisTypes = $phpDocParameterClosureThisTypes; $this->attributes = $attributes; } 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; } public function getVariants(): array { return $this->variants ??= [new ExtendedFunctionVariant($this->templateTypeMap, null, $this->getParameters(), $this->isVariadic(), $this->getReturnType(), $this->getPhpDocReturnType(), $this->getNativeReturnType())]; } public function getOnlyVariant(): ExtendedParametersAcceptor { return $this->getVariants()[0]; } public function getNamedArgumentsVariants(): ?array { return null; } /** * @return list */ 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->attributeReflectionFactory->fromNativeReflection($reflection->getAttributes(), InitializerExprContext::fromReflectionParameter($reflection))); }, $this->reflection->getParameters()); } private function isVariadic(): bool { return $this->reflection->isVariadic(); } 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; } if ($this->reflection->isDeprecated()) { $attributes = $this->reflection->getBetterReflection()->getAttributes(); return DeprecatedAttributeHelper::getDeprecatedDescription($attributes); } 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 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(): TrinaryLogic { return TrinaryLogic::createFromBoolean($this->acceptsNamedArguments); } public function getAttributes(): array { return $this->attributes; } public function mustUseReturnValue(): TrinaryLogic { foreach ($this->attributes as $attrib) { if (strtolower($attrib->getName()) === 'nodiscard') { return TrinaryLogic::createYes(); } } return TrinaryLogic::createNo(); } } > $parameterAttributes * @param array $immediatelyInvokedCallableParameters * @param array $phpDocClosureThisTypeParameters * @param list $attributes * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\PropertyHook $classMethod */ public function __construct(ClassReflection $declaringClass, $classMethod, ?string $hookForProperty, string $fileName, TemplateTypeMap $templateTypeMap, array $realParameterTypes, array $phpDocParameterTypes, array $realParameterDefaultValues, array $parameterAttributes, Type $realReturnType, ?Type $phpDocReturnType, ?Type $throwType, ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, bool $isFinal, ?bool $isPure, bool $acceptsNamedArguments, Assertions $assertions, ?Type $selfOutType, ?string $phpDocComment, ?ResolvedPhpDocBlock $resolvedPhpDoc, array $parameterOutTypes, array $immediatelyInvokedCallableParameters, array $phpDocClosureThisTypeParameters, bool $isConstructor, array $attributes) { $this->declaringClass = $declaringClass; $this->classMethod = $classMethod; $this->hookForProperty = $hookForProperty; $this->isFinal = $isFinal; $this->selfOutType = $selfOutType; $this->resolvedPhpDoc = $resolvedPhpDoc; $this->isConstructor = $isConstructor; if ($this->classMethod instanceof Node\PropertyHook) { if ($this->hookForProperty === null) { throw new ShouldNotHappenException('Hook was provided but property was not'); } } elseif ($this->hookForProperty !== null) { throw new ShouldNotHappenException('Hooked property was provided but hook was not'); } $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(new UnionType([new ArrayType(new MixedType(\true), new MixedType(\true)), new NullType()]), $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, $parameterAttributes, $realReturnType, $phpDocReturnType, $throwType, $deprecatedDescription, $isDeprecated, $isInternal, $isPure, $acceptsNamedArguments, $assertions, $phpDocComment, $parameterOutTypes, $immediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters, $attributes); } 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; } } /** * @return \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\PropertyHook */ private function getClassMethod() { /** @var Node\Stmt\ClassMethod|Node\PropertyHook $functionLike */ $functionLike = $this->getFunctionLike(); return $functionLike; } public function getName(): string { $function = $this->getFunctionLike(); if (!$function instanceof Node\PropertyHook) { return parent::getName(); } if ($this->hookForProperty === null) { throw new ShouldNotHappenException('Hook was provided but property was not'); } return sprintf('$%s::%s', $this->hookForProperty, $function->name->toString()); } /** * @phpstan-assert-if-true !null $this->getHookedPropertyName() * @phpstan-assert-if-true !null $this->getPropertyHookName() */ public function isPropertyHook(): bool { return $this->hookForProperty !== null; } public function getHookedPropertyName(): ?string { return $this->hookForProperty; } /** * @return 'get'|'set'|null */ public function getPropertyHookName(): ?string { $function = $this->getFunctionLike(); if (!$function instanceof Node\PropertyHook) { return null; } $name = $function->name->toLowerString(); if (!in_array($name, ['get', 'set'], \true)) { throw new ShouldNotHappenException(sprintf('Unknown property hook: %s', $name)); } return $name; } public function isStatic(): bool { $method = $this->getClassMethod(); if ($method instanceof Node\PropertyHook) { return \false; } return $method->isStatic(); } public function isPrivate(): bool { $method = $this->getClassMethod(); if ($method instanceof Node\PropertyHook) { return \false; } return $method->isPrivate(); } public function isPublic(): bool { $method = $this->getClassMethod(); if ($method instanceof Node\PropertyHook) { return \true; } return $method->isPublic(); } public function isFinal(): TrinaryLogic { $method = $this->getClassMethod(); if ($method instanceof Node\PropertyHook) { return TrinaryLogic::createFromBoolean($method->isFinal()); } return TrinaryLogic::createFromBoolean($method->isFinal() || $this->isFinal); } public function isFinalByKeyword(): TrinaryLogic { return TrinaryLogic::createFromBoolean($this->getClassMethod()->isFinal()); } 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 { $method = $this->getClassMethod(); if ($method instanceof Node\PropertyHook) { return TrinaryLogic::createFromBoolean($method->body === null); } return TrinaryLogic::createFromBoolean($method->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(); } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return $this->resolvedPhpDoc; } } */ private array $immediatelyInvokedCallableParameters; /** * @var array */ private array $phpDocClosureThisTypeParameters; /** * @var list */ private array $attributes; /** @var list|null */ private ?array $parameters = null; private ?Type $returnType = null; private ?Type $nativeReturnType = null; /** @var list|null */ private ?array $variants = null; /** * @param Type[] $phpDocParameterTypes * @param Type[] $phpDocParameterOutTypes * @param array $immediatelyInvokedCallableParameters * @param array $phpDocClosureThisTypeParameters * @param list $attributes */ public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver, ClassReflection $declaringClass, ?ClassReflection $declaringTrait, ReflectionMethod $reflection, ReflectionProvider $reflectionProvider, AttributeReflectionFactory $attributeReflectionFactory, TemplateTypeMap $templateTypeMap, array $phpDocParameterTypes, ?Type $phpDocReturnType, ?Type $phpDocThrowType, ?ResolvedPhpDocBlock $resolvedPhpDocBlock, ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, bool $isFinal, ?bool $isPure, Assertions $asserts, bool $acceptsNamedArguments, ?Type $selfOutType, ?string $phpDocComment, array $phpDocParameterOutTypes, array $immediatelyInvokedCallableParameters, array $phpDocClosureThisTypeParameters, array $attributes) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->declaringClass = $declaringClass; $this->declaringTrait = $declaringTrait; $this->reflection = $reflection; $this->reflectionProvider = $reflectionProvider; $this->attributeReflectionFactory = $attributeReflectionFactory; $this->templateTypeMap = $templateTypeMap; $this->phpDocParameterTypes = $phpDocParameterTypes; $this->phpDocReturnType = $phpDocReturnType; $this->phpDocThrowType = $phpDocThrowType; $this->resolvedPhpDocBlock = $resolvedPhpDocBlock; $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; $this->attributes = $attributes; } 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(), \null, $prototypeDeclaringClass); } return new MethodPrototypeReflection($prototypeMethod->getName(), $prototypeDeclaringClass, $prototypeMethod->isStatic(), $prototypeMethod->isPrivate(), $prototypeMethod->isPublic(), $prototypeMethod->isAbstract(), $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 list */ public function getVariants(): array { return $this->variants ??= [new ExtendedFunctionVariant($this->templateTypeMap, null, $this->getParameters(), $this->isVariadic(), $this->getReturnType(), $this->getPhpDocReturnType(), $this->getNativeReturnType())]; } public function getOnlyVariant(): ExtendedParametersAcceptor { return $this->getVariants()[0]; } public function getNamedArgumentsVariants(): ?array { return null; } /** * @return list */ private function getParameters(): array { return $this->parameters ??= array_map(fn(ReflectionParameter $reflection): \PHPStan\Reflection\Php\PhpParameterReflection => new \PHPStan\Reflection\Php\PhpParameterReflection($this->initializerExprTypeResolver, $reflection, $this->phpDocParameterTypes[$reflection->getName()] ?? null, $this->getDeclaringClass(), $this->phpDocParameterOutTypes[$reflection->getName()] ?? null, $this->immediatelyInvokedCallableParameters[$reflection->getName()] ?? TrinaryLogic::createMaybe(), $this->phpDocClosureThisTypeParameters[$reflection->getName()] ?? null, $this->attributeReflectionFactory->fromNativeReflection($reflection->getAttributes(), InitializerExprContext::fromReflectionParameter($reflection))), $this->reflection->getParameters()); } private function isVariadic(): bool { return $this->reflection->isVariadic(); } 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 { return $this->nativeReturnType ??= TypehintHelper::decideTypeFromReflection($this->reflection->getReturnType(), \null, $this->declaringClass); } public function getDeprecatedDescription(): ?string { if ($this->isDeprecated) { return $this->deprecatedDescription; } if ($this->reflection->isDeprecated()) { $attributes = $this->reflection->getBetterReflection()->getAttributes(); return DeprecatedAttributeHelper::getDeprecatedDescription($attributes); } return null; } public function isDeprecated(): TrinaryLogic { if ($this->isDeprecated) { return TrinaryLogic::createYes(); } return TrinaryLogic::createFromBoolean($this->reflection->isDeprecated()); } public function isInternal(): TrinaryLogic { return TrinaryLogic::createFromBoolean($this->isInternal); } public function isBuiltin(): TrinaryLogic { return TrinaryLogic::createFromBoolean($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(): TrinaryLogic { return TrinaryLogic::createFromBoolean($this->declaringClass->acceptsNamedArguments() && $this->acceptsNamedArguments); } public function getSelfOutType(): ?Type { return $this->selfOutType; } public function getDocComment(): ?string { return $this->phpDocComment; } public function returnsByReference(): TrinaryLogic { return TrinaryLogic::createFromBoolean($this->reflection->returnsReference()); } public function isPure(): TrinaryLogic { if ($this->isPure === null) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createFromBoolean($this->isPure); } public function changePropertyGetHookPhpDocType(Type $phpDocType): self { return new self($this->initializerExprTypeResolver, $this->declaringClass, $this->declaringTrait, $this->reflection, $this->reflectionProvider, $this->attributeReflectionFactory, $this->templateTypeMap, $this->phpDocParameterTypes, $phpDocType, $this->phpDocThrowType, $this->resolvedPhpDocBlock, $this->deprecatedDescription, $this->isDeprecated, $this->isInternal, $this->isFinal, $this->isPure, $this->asserts, $this->acceptsNamedArguments, $this->selfOutType, $this->phpDocComment, $this->phpDocParameterOutTypes, $this->immediatelyInvokedCallableParameters, $this->phpDocClosureThisTypeParameters, $this->attributes); } public function changePropertySetHookPhpDocType(string $parameterName, Type $phpDocType): self { $phpDocParameterTypes = $this->phpDocParameterTypes; $phpDocParameterTypes[$parameterName] = $phpDocType; return new self($this->initializerExprTypeResolver, $this->declaringClass, $this->declaringTrait, $this->reflection, $this->reflectionProvider, $this->attributeReflectionFactory, $this->templateTypeMap, $phpDocParameterTypes, $this->phpDocReturnType, $this->phpDocThrowType, $this->resolvedPhpDocBlock, $this->deprecatedDescription, $this->isDeprecated, $this->isInternal, $this->isFinal, $this->isPure, $this->asserts, $this->acceptsNamedArguments, $this->selfOutType, $this->phpDocComment, $this->phpDocParameterOutTypes, $this->immediatelyInvokedCallableParameters, $this->phpDocClosureThisTypeParameters, $this->attributes); } public function getAttributes(): array { return $this->attributes; } public function mustUseReturnValue(): TrinaryLogic { foreach ($this->attributes as $attrib) { if (strtolower($attrib->getName()) === 'nodiscard') { return TrinaryLogic::createYes(); } } return TrinaryLogic::createNo(); } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return $this->resolvedPhpDocBlock; } } $immediatelyInvokedCallableParameters * @param array $phpDocClosureThisTypeParameters * @param list $attributes */ public function create(ClassReflection $declaringClass, ?ClassReflection $declaringTrait, ReflectionMethod $reflection, TemplateTypeMap $templateTypeMap, array $phpDocParameterTypes, ?Type $phpDocReturnType, ?Type $phpDocThrowType, ?ResolvedPhpDocBlock $resolvedPhpDocBlock, ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, bool $isFinal, ?bool $isPure, Assertions $asserts, ?Type $selfOutType, ?string $phpDocComment, array $phpDocParameterOutTypes, array $immediatelyInvokedCallableParameters, array $phpDocClosureThisTypeParameters, bool $acceptsNamedArguments, array $attributes): \PHPStan\Reflection\Php\PhpMethodReflection; } */ private array $attributes; private ?Type $type = null; /** * @param list $attributes */ public function __construct(string $name, bool $optional, Type $realType, ?Type $phpDocType, PassedByReference $passedByReference, ?Type $defaultValue, bool $variadic, ?Type $outType, TrinaryLogic $immediatelyInvokedCallable, ?Type $closureThisType, array $attributes) { $this->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; $this->attributes = $attributes; } 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 hasNativeType(): bool { return !$this->realType instanceof MixedType || $this->realType->isExplicitMixed(); } 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; } public function getAttributes(): array { return $this->attributes; } } */ private array $attributes; private ?Type $type = null; private ?Type $nativeType = null; /** * @param list $attributes */ public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver, ReflectionParameter $reflection, ?Type $phpDocType, ?ClassReflection $declaringClass, ?Type $outType, TrinaryLogic $immediatelyInvokedCallable, ?Type $closureThisType, array $attributes) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->reflection = $reflection; $this->phpDocType = $phpDocType; $this->declaringClass = $declaringClass; $this->outType = $outType; $this->immediatelyInvokedCallable = $immediatelyInvokedCallable; $this->closureThisType = $closureThisType; $this->attributes = $attributes; } 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->declaringClass, $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 hasNativeType(): bool { return $this->reflection->getType() !== null; } public function getNativeType(): Type { return $this->nativeType ??= TypehintHelper::decideTypeFromReflection($this->reflection->getType(), \null, $this->declaringClass, $this->isVariadic()); } 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; } public function getAttributes(): array { return $this->attributes; } } */ private array $attributes; private bool $isFinal; private bool $readable; private bool $writable; private bool $private; private bool $public; private ?Type $readableType = null; private ?Type $writableType = null; /** * @param list $attributes */ public function __construct(ClassReflection $declaringClass, ?ClassReflection $declaringTrait, Type $nativeType, ?Type $readablePhpDocType, ?Type $writablePhpDocType, ReflectionProperty $reflection, ?ExtendedMethodReflection $getHook, ?ExtendedMethodReflection $setHook, ?ResolvedPhpDocBlock $resolvedPhpDocBlock, ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, bool $isReadOnlyByPhpDoc, bool $isAllowedPrivateMutation, array $attributes, bool $isFinal, bool $readable, bool $writable, bool $private, bool $public) { $this->declaringClass = $declaringClass; $this->declaringTrait = $declaringTrait; $this->nativeType = $nativeType; $this->readablePhpDocType = $readablePhpDocType; $this->writablePhpDocType = $writablePhpDocType; $this->reflection = $reflection; $this->getHook = $getHook; $this->setHook = $setHook; $this->resolvedPhpDocBlock = $resolvedPhpDocBlock; $this->deprecatedDescription = $deprecatedDescription; $this->isDeprecated = $isDeprecated; $this->isInternal = $isInternal; $this->isReadOnlyByPhpDoc = $isReadOnlyByPhpDoc; $this->isAllowedPrivateMutation = $isAllowedPrivateMutation; $this->attributes = $attributes; $this->isFinal = $isFinal; $this->readable = $readable; $this->writable = $writable; $this->private = $private; $this->public = $public; } public function getName(): string { return $this->reflection->getName(); } 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->private; } public function isPublic(): bool { return $this->public; } public function isReadOnly(): bool { return $this->reflection->isReadOnly(); } public function isReadOnlyByPhpDoc(): bool { return $this->isReadOnlyByPhpDoc; } public function getReadableType(): Type { return $this->readableType ??= TypehintHelper::decideType($this->nativeType, $this->readablePhpDocType); } public function getWritableType(): Type { if ($this->hasHook('set')) { $setHookVariant = $this->getHook('set')->getOnlyVariant(); $parameters = $setHookVariant->getParameters(); if (isset($parameters[0])) { return $parameters[0]->getType(); } } if ($this->writableType !== null) { return $this->writableType; } if ($this->writablePhpDocType === null || $this->writablePhpDocType instanceof NeverType) { return $this->writableType = TypehintHelper::decideType($this->nativeType, $this->readablePhpDocType); } if ($this->readablePhpDocType !== null && !$this->readablePhpDocType->equals($this->writablePhpDocType)) { return $this->writableType = $this->writablePhpDocType; } return $this->writableType = TypehintHelper::decideType($this->nativeType, $this->writablePhpDocType); } public function canChangeTypeAfterAssignment(): bool { if ($this->isStatic()) { return $this->getReadableType()->equals($this->getWritableType()); } if ($this->isVirtual()->yes()) { return \false; } if ($this->hasHook('get')) { return \false; } if ($this->hasHook('set')) { return \false; } return $this->getReadableType()->equals($this->getWritableType()); } public function isPromoted(): bool { return $this->reflection->isPromoted(); } public function hasPhpDocType(): bool { return $this->readablePhpDocType !== null; } public function getPhpDocType(): Type { if ($this->readablePhpDocType !== null) { return $this->readablePhpDocType; } return new MixedType(); } public function hasNativeType(): bool { return !$this->nativeType instanceof MixedType || $this->nativeType->isExplicitMixed(); } public function getNativeType(): Type { return $this->nativeType; } public function isReadable(): bool { if (!$this->readable) { return \false; } if ($this->isStatic()) { return \true; } if (!$this->isVirtual()->yes()) { return \true; } return $this->hasHook('get'); } public function isWritable(): bool { if (!$this->writable) { return \false; } if ($this->isStatic()) { return \true; } if (!$this->isVirtual()->yes()) { return \true; } return $this->hasHook('set'); } 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; } public function isAbstract(): TrinaryLogic { return TrinaryLogic::createFromBoolean($this->reflection->isAbstract()); } public function isFinalByKeyword(): TrinaryLogic { return TrinaryLogic::createFromBoolean($this->reflection->isFinal()); } public function isFinal(): TrinaryLogic { return TrinaryLogic::createFromBoolean($this->isFinal); } public function isVirtual(): TrinaryLogic { return TrinaryLogic::createFromBoolean($this->reflection->isVirtual()); } public function hasHook(string $hookType): bool { if ($hookType === 'get') { return $this->getHook !== null; } return $this->setHook !== null; } public function isHooked(): bool { return $this->getHook !== null || $this->setHook !== null; } public function getHook(string $hookType): ExtendedMethodReflection { if ($hookType === 'get') { if ($this->getHook === null) { throw new MissingMethodFromReflectionException($this->declaringClass->getName(), sprintf('$%s::get', $this->reflection->getName())); } return $this->getHook; } if ($this->setHook === null) { throw new MissingMethodFromReflectionException($this->declaringClass->getName(), sprintf('$%s::set', $this->reflection->getName())); } return $this->setHook; } public function isProtectedSet(): bool { return $this->reflection->isProtectedSet(); } public function isPrivateSet(): bool { return $this->reflection->isPrivateSet(); } public function getAttributes(): array { return $this->attributes; } public function isDummy(): TrinaryLogic { return TrinaryLogic::createNo(); } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return $this->resolvedPhpDocBlock; } } getSealedTags()) > 0; } public function getAllowedSubTypes(ClassReflection $classReflection): array { $types = []; foreach ($classReflection->getSealedTags() as $sealedTag) { $type = $sealedTag->getType(); if ($type instanceof UnionType) { $types = $type->getTypes(); } else { $types = [$type]; } } if ($classReflection->isClass() && !$classReflection->isAbstract()) { $types[] = new ObjectType($classReflection->getName()); } return $types; } } name = $name; $this->declaringClass = $declaringClass; $this->type = $type; } public function getName(): string { return $this->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 hasPhpDocType(): bool { return \false; } public function getPhpDocType(): Type { return new MixedType(); } public function hasNativeType(): bool { return \false; } public function getNativeType(): Type { return new MixedType(); } 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; } public function isAbstract(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinalByKeyword(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinal(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isVirtual(): TrinaryLogic { return TrinaryLogic::createNo(); } public function hasHook(string $hookType): bool { return \false; } public function getHook(string $hookType): ExtendedMethodReflection { throw new ShouldNotHappenException(); } public function isProtectedSet(): bool { return \false; } public function isPrivateSet(): bool { return \false; } public function getAttributes(): array { return []; } public function isDummy(): TrinaryLogic { return TrinaryLogic::createNo(); } } 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(); } } is('SoapClient'); } public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection { return new \PHPStan\Reflection\Php\Soap\SoapClientMethodReflection($classReflection, $methodName); } } name = $name; $this->declaringClass = $declaringClass; $this->readableType = $readableType; $this->writableType = $writableType; } public function getName(): string { return $this->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 hasPhpDocType(): bool { return \false; } public function getPhpDocType(): Type { return new MixedType(); } public function hasNativeType(): bool { return \false; } public function getNativeType(): Type { return new MixedType(); } 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; } public function isAbstract(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinalByKeyword(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinal(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isVirtual(): TrinaryLogic { return TrinaryLogic::createNo(); } public function hasHook(string $hookType): bool { return \false; } public function getHook(string $hookType): ExtendedMethodReflection { throw new ShouldNotHappenException(); } public function isProtectedSet(): bool { return \false; } public function isPrivateSet(): bool { return \false; } public function getAttributes(): array { return []; } public function isDummy(): TrinaryLogic { return TrinaryLogic::createNo(); } } */ private array $classes; private AnnotationsPropertiesClassReflectionExtension $annotationClassReflection; /** * @param list $classes */ public function __construct(ReflectionProvider $reflectionProvider, array $classes, AnnotationsPropertiesClassReflectionExtension $annotationClassReflection) { $this->reflectionProvider = $reflectionProvider; $this->classes = $classes; $this->annotationClassReflection = $annotationClassReflection; } public function hasProperty(ClassReflection $classReflection, string $propertyName): bool { return self::isUniversalObjectCrateImplementation($this->reflectionProvider, $this->classes, $classReflection); } public static function isUniversalObjectCrate(ReflectionProvider $reflectionProvider, ClassReflection $classReflection): bool { return self::isUniversalObjectCrateImplementation($reflectionProvider, $reflectionProvider->getUniversalObjectCratesClasses(), $classReflection); } /** * @param list $classes */ private static function isUniversalObjectCrateImplementation(ReflectionProvider $reflectionProvider, array $classes, ClassReflection $classReflection): bool { foreach ($classes as $className) { if (!$reflectionProvider->hasClass($className)) { continue; } if ($classReflection->is($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($propertyName, $classReflection, $readableType, $writableType); } } */ private array $attributes; private ?Type $valueType = null; /** * @param list $attributes */ public function __construct(\PHPStan\Reflection\InitializerExprTypeResolver $initializerExprTypeResolver, \PHPStan\Reflection\ClassReflection $declaringClass, ReflectionClassConstant $reflection, ?Type $nativeType, ?Type $phpDocType, ?ResolvedPhpDocBlock $resolvedPhpDocBlock, ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, bool $isFinal, array $attributes) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->declaringClass = $declaringClass; $this->reflection = $reflection; $this->nativeType = $nativeType; $this->phpDocType = $phpDocType; $this->resolvedPhpDocBlock = $resolvedPhpDocBlock; $this->deprecatedDescription = $deprecatedDescription; $this->isDeprecated = $isDeprecated; $this->isInternal = $isInternal; $this->isFinal = $isFinal; $this->attributes = $attributes; } public function getName(): string { return $this->reflection->getName(); } public function getFileName(): ?string { return $this->declaringClass->getFileName(); } 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 getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return $this->resolvedPhpDocBlock; } 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 isFinalByKeyword(): bool { return $this->reflection->isFinal(); } public function isDeprecated(): TrinaryLogic { return TrinaryLogic::createFromBoolean($this->isDeprecated || $this->reflection->isDeprecated()); } public function getDeprecatedDescription(): ?string { if ($this->isDeprecated) { return $this->deprecatedDescription; } if ($this->reflection->isDeprecated()) { $attributes = $this->reflection->getBetterReflection()->getAttributes(); return DeprecatedAttributeHelper::getDeprecatedDescription($attributes); } 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; } public function getAttributes(): array { return $this->attributes; } } */ public function getUniversalObjectCratesClasses(): array; public function hasFunction(Node\Name $nameNode, ?\PHPStan\Reflection\NamespaceAnswerer $namespaceAnswerer): bool; public function getFunction(Node\Name $nameNode, ?\PHPStan\Reflection\NamespaceAnswerer $namespaceAnswerer): \PHPStan\Reflection\FunctionReflection; public function resolveFunctionName(Node\Name $nameNode, ?\PHPStan\Reflection\NamespaceAnswerer $namespaceAnswerer): ?string; public function hasConstant(Node\Name $nameNode, ?\PHPStan\Reflection\NamespaceAnswerer $namespaceAnswerer): bool; public function getConstant(Node\Name $nameNode, ?\PHPStan\Reflection\NamespaceAnswerer $namespaceAnswerer): \PHPStan\Reflection\ConstantReflection; public function resolveConstantName(Node\Name $nameNode, ?\PHPStan\Reflection\NamespaceAnswerer $namespaceAnswerer): ?string; } reflectionProvider = $reflectionProvider; } public function getReflectionProvider(): ReflectionProvider { return $this->reflectionProvider; } } container = $container; } public function getReflectionProvider(): ReflectionProvider { return $this->container->getByType(ReflectionProvider::class); } } */ private array $knownClasses = []; /** @var array */ private array $unknownClasses = []; /** @var array */ private array $classes = []; /** @var array */ private array $classNames = []; public function __construct(ReflectionProvider $provider) { $this->provider = $provider; } public function hasClass(string $className): bool { if (isset($this->knownClasses[strtolower($className)])) { return \true; } if (isset($this->unknownClasses[$className])) { return \false; } $result = $this->provider->hasClass($className); if ($result) { $this->knownClasses[strtolower($className)] = \true; } else { $this->unknownClasses[$className] = \true; } return $result; } public function getClass(string $className): ClassReflection { return $this->classes[strtolower($className)] ??= $this->provider->getClass($className); } public function getClassName(string $className): string { return $this->classNames[strtolower($className)] ??= $this->provider->getClassName($className); } public function getAnonymousClassReflection(Node\Stmt\Class_ $classNode, Scope $scope): ClassReflection { return $this->provider->getAnonymousClassReflection($classNode, $scope); } public function getUniversalObjectCratesClasses(): array { return $this->provider->getUniversalObjectCratesClasses(); } 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): ConstantReflection { return $this->provider->getConstant($nameNode, $namespaceAnswerer); } public function resolveConstantName(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): ?string { return $this->provider->resolveConstantName($nameNode, $namespaceAnswerer); } } staticReflectionProvider = $staticReflectionProvider; } public function create(): ReflectionProvider { return new \PHPStan\Reflection\ReflectionProvider\MemoizingReflectionProvider($this->staticReflectionProvider); } } findMethod($classReflection, $methodName) !== null; } public function getMethod(ClassReflection $classReflection, string $methodName): ExtendedMethodReflection { $method = $this->findMethod($classReflection, $methodName); if ($method === null) { throw new ShouldNotHappenException(); } return $method; } private function findMethod(ClassReflection $classReflection, string $methodName): ?ExtendedMethodReflection { 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, static fn(Type $type, string $propertyName): TrinaryLogic => $type->hasProperty($propertyName), static fn(Type $type, string $propertyName): ExtendedPropertyReflection => $type->getProperty($propertyName, new OutOfClassScope())) !== null; } /** @deprecated Use getInstanceProperty or getStaticProperty */ public function getProperty(ClassReflection $classReflection, string $propertyName): ExtendedPropertyReflection { $property = $this->findProperty($classReflection, $propertyName, static fn(Type $type, string $propertyName): TrinaryLogic => $type->hasProperty($propertyName), static fn(Type $type, string $propertyName): ExtendedPropertyReflection => $type->getProperty($propertyName, new OutOfClassScope())); if ($property === null) { throw new ShouldNotHappenException(); } return $property; } public function hasInstanceProperty(ClassReflection $classReflection, string $propertyName): bool { return $this->findProperty($classReflection, $propertyName, static fn(Type $type, string $propertyName): TrinaryLogic => $type->hasInstanceProperty($propertyName), static fn(Type $type, string $propertyName): ExtendedPropertyReflection => $type->getInstanceProperty($propertyName, new OutOfClassScope())) !== null; } public function getInstanceProperty(ClassReflection $classReflection, string $propertyName): ExtendedPropertyReflection { $property = $this->findProperty($classReflection, $propertyName, static fn(Type $type, string $propertyName): TrinaryLogic => $type->hasInstanceProperty($propertyName), static fn(Type $type, string $propertyName): ExtendedPropertyReflection => $type->getInstanceProperty($propertyName, new OutOfClassScope())); if ($property === null) { throw new ShouldNotHappenException(); } return $property; } public function hasStaticProperty(ClassReflection $classReflection, string $propertyName): bool { return $this->findProperty($classReflection, $propertyName, static fn(Type $type, string $propertyName): TrinaryLogic => $type->hasStaticProperty($propertyName), static fn(Type $type, string $propertyName): ExtendedPropertyReflection => $type->getStaticProperty($propertyName, new OutOfClassScope())) !== null; } public function getStaticProperty(ClassReflection $classReflection, string $propertyName): ExtendedPropertyReflection { $property = $this->findProperty($classReflection, $propertyName, static fn(Type $type, string $propertyName): TrinaryLogic => $type->hasStaticProperty($propertyName), static fn(Type $type, string $propertyName): ExtendedPropertyReflection => $type->getStaticProperty($propertyName, new OutOfClassScope())); if ($property === null) { throw new ShouldNotHappenException(); } return $property; } /** * @param callable(Type, string): TrinaryLogic $propertyHasser * @param callable(Type, string): ExtendedPropertyReflection $propertyGetter */ private function findProperty(ClassReflection $classReflection, string $propertyName, callable $propertyHasser, callable $propertyGetter): ?ExtendedPropertyReflection { if (!$classReflection->isInterface()) { return null; } $requireExtendsTags = $classReflection->getRequireExtendsTags(); foreach ($requireExtendsTags as $requireExtendsTag) { $type = $requireExtendsTag->getType(); if (!$propertyHasser($type, $propertyName)->yes()) { continue; } return $propertyGetter($type, $propertyName); } $interfaces = $classReflection->getInterfaces(); foreach ($interfaces as $interface) { $property = $this->findProperty($interface, $propertyName, $propertyHasser, $propertyGetter); if ($property !== null) { return $property; } } return null; } } parametersAcceptor = $parametersAcceptor; $this->throwPoints = $throwPoints; $this->isPure = $isPure; $this->impurePoints = $impurePoints; $this->invalidateExpressions = $invalidateExpressions; $this->usedVariables = $usedVariables; $this->acceptsNamedArguments = $acceptsNamedArguments; $this->mustUseReturnValue = $mustUseReturnValue; $this->assertions = $assertions; } 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 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(): TrinaryLogic { return $this->acceptsNamedArguments; } public function mustUseReturnValue(): TrinaryLogic { return $this->mustUseReturnValue; } public function getAsserts(): \PHPStan\Reflection\Assertions { return $this->assertions ?? \PHPStan\Reflection\Assertions::createEmpty(); } } */ private array $passedArgs; /** @var list|null */ private ?array $parameters = null; private ?Type $returnTypeWithUnresolvableTemplateTypes = null; private ?Type $phpDocReturnTypeWithUnresolvableTemplateTypes = null; private ?Type $returnType = null; private ?Type $phpDocReturnType = null; /** * @param array $passedArgs */ public function __construct(\PHPStan\Reflection\ExtendedParametersAcceptor $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\ExtendedParameterReflection $param): \PHPStan\Reflection\ExtendedParameterReflection { $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 ExtendedDummyParameter($param->getName(), $paramType, $param->isOptional(), $param->passedByReference(), $param->isVariadic(), $param->getDefaultValue(), $param->getNativeType(), $param->getPhpDocType(), $paramOutType, $param->isImmediatelyInvokedCallable(), $closureThisType, $param->getAttributes()); }, $this->parametersAcceptor->getParameters()); $this->parameters = $parameters; } return $parameters; } public function isVariadic(): bool { return $this->parametersAcceptor->isVariadic(); } public function getReturnTypeWithUnresolvableTemplateTypes(): Type { return $this->returnTypeWithUnresolvableTemplateTypes ??= $this->resolveConditionalTypesForParameter($this->resolveResolvableTemplateTypes($this->parametersAcceptor->getReturnType(), TemplateTypeVariance::createCovariant())); } private function getPhpDocReturnTypeWithUnresolvableTemplateTypes(): Type { return $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 ($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)) { // Traverse children first, then convert — avoids infinite loop when // the passed argument contains ConditionalTypeForParameter with a colliding parameter name. $type = $traverse($type); if ($type instanceof ConditionalTypeForParameter) { return $type->toConditional($this->passedArgs[$type->getParameterName()]); } return $type; } return $traverse($type); }); } } |null */ private ?array $variants = null; /** @var list|null */ private ?array $namedArgumentVariants = null; private ?\PHPStan\Reflection\Assertions $asserts = null; /** * @var \PHPStan\Type\Type|false|null */ private $selfOutType = \false; private ?TrinaryLogic $hasSideEffects = null; public function __construct(\PHPStan\Reflection\ExtendedMethodReflection $reflection, TemplateTypeMap $resolvedTemplateTypeMap, TemplateTypeVarianceMap $callSiteVarianceMap) { $this->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\ExtendedParametersAcceptor { 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 ExtendedParametersAcceptor[] $variants * @return list */ 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 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 isBuiltin(): TrinaryLogic { $builtin = $this->reflection->isBuiltin(); if (is_bool($builtin)) { return TrinaryLogic::createFromBoolean($builtin); } return $builtin; } public function getThrowType(): ?Type { return $this->reflection->getThrowType(); } public function hasSideEffects(): TrinaryLogic { return $this->hasSideEffects ??= $this->reflection->hasSideEffects(); } public function isPure(): TrinaryLogic { return $this->reflection->isPure(); } public function getAsserts(): \PHPStan\Reflection\Assertions { return $this->asserts ??= $this->reflection->getAsserts()->mapTypes(fn(Type $type) => TemplateTypeHelper::resolveTemplateTypes($type, $this->resolvedTemplateTypeMap, $this->callSiteVarianceMap, TemplateTypeVariance::createInvariant())); } public function acceptsNamedArguments(): TrinaryLogic { 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; } public function getAttributes(): array { return $this->reflection->getAttributes(); } public function mustUseReturnValue(): TrinaryLogic { return $this->reflection->mustUseReturnValue(); } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return $this->reflection->getResolvedPhpDoc(); } } reflection = $reflection; $this->templateTypeMap = $templateTypeMap; $this->callSiteVarianceMap = $callSiteVarianceMap; } public function getName(): string { return $this->reflection->getName(); } public function getOriginalReflection(): \PHPStan\Reflection\ExtendedPropertyReflection { return $this->reflection; } public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection { return $this->reflection->getDeclaringClass(); } 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 hasPhpDocType(): bool { return $this->reflection->hasPhpDocType(); } public function getPhpDocType(): Type { return $this->reflection->getPhpDocType(); } public function hasNativeType(): bool { return $this->reflection->hasNativeType(); } public function getNativeType(): Type { return $this->reflection->getNativeType(); } 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(); } public function isAbstract(): TrinaryLogic { return $this->reflection->isAbstract(); } public function isFinalByKeyword(): TrinaryLogic { return $this->reflection->isFinalByKeyword(); } public function isFinal(): TrinaryLogic { return $this->reflection->isFinal(); } public function isVirtual(): TrinaryLogic { return $this->reflection->isVirtual(); } public function hasHook(string $hookType): bool { return $this->reflection->hasHook($hookType); } public function getHook(string $hookType): \PHPStan\Reflection\ExtendedMethodReflection { return new \PHPStan\Reflection\ResolvedMethodReflection($this->reflection->getHook($hookType), $this->templateTypeMap, $this->callSiteVarianceMap); } public function isProtectedSet(): bool { return $this->reflection->isProtectedSet(); } public function isPrivateSet(): bool { return $this->reflection->isPrivateSet(); } public function getAttributes(): array { return $this->reflection->getAttributes(); } public function isDummy(): TrinaryLogic { return $this->reflection->isDummy(); } } */ private array $parameters; private Type $returnType; private Type $nativeReturnType; private bool $variadic; /** * @param list $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 list */ 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; } } */ private static array $signatureMaps = []; /** @var array|null */ private static ?array $functionMetadata = null; public function __construct( \PHPStan\Reflection\SignatureMap\SignatureMapParser $parser, InitializerExprTypeResolver $initializerExprTypeResolver, PhpVersion $phpVersion, #[AutowiredParameter('%featureToggles.stricterFunctionMap%')] 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'); } if ($this->phpVersion->getVersionId() >= 80500) { $signatureMap = $this->computeSignatureMapFile($signatureMap, __DIR__ . '/../../../resources/functionMap_php85delta.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; $this->attributeReflectionFactory = $attributeReflectionFactory; } 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; $fileName = null; $attributes = []; try { $reflectionFunction = $this->reflector->reflectFunction($functionName); $reflectionFunctionAdapter = new ReflectionFunction($reflectionFunction); $attributes = $reflectionFunctionAdapter->getAttributes(); $returnsByReference = TrinaryLogic::createFromBoolean($reflectionFunctionAdapter->returnsReference()); $realFunctionName = $reflectionFunction->getName(); $isDeprecated = $reflectionFunction->isDeprecated(); if ($reflectionFunction->getFileName() !== null) { $fileName = $reflectionFunction->getFileName(); if (!$reflectionFunctionAdapter->isInternal() && !str_contains(strtolower($fileName), 'polyfill')) { return null; } $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(); } } } } catch (IdentifierNotFound|InvalidIdentifierName $e) { // pass } $functionSignaturesResult = $this->signatureMapProvider->getFunctionSignatures($lowerCasedFunctionName, null, $reflectionFunctionAdapter); $phpDoc = $this->stubPhpDocProvider->findFunctionPhpDoc($lowerCasedFunctionName, array_map(static fn(\PHPStan\Reflection\SignatureMap\ParameterSignature $parameter): string => $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 ExtendedFunctionVariant(TemplateTypeMap::createEmpty(), null, array_map(static function (\PHPStan\Reflection\SignatureMap\ParameterSignature $parameterSignature) use ($phpDoc): ExtendedNativeParameterReflection { $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 ExtendedNativeParameterReflection($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->attributeReflectionFactory->fromNativeReflection($attributes, InitializerExprContext::fromFunction($realFunctionName, $fileName))); $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; } } 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 array $methodNodes = []; /** @var array> */ private array $constantTypes = []; private Php8StubsMap $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 (!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); $this->findClassStubs($className); if (isset($this->methodNodes[$lowerClassName][$lowerMethodName])) { return $this->methodNodes[$lowerClassName][$lowerMethodName]; } return null; } private function findClassStubs(string $className): void { $lowerClassName = strtolower($className); if (isset($this->methodNodes[$lowerClassName]) || isset($this->constantTypes[$lowerClassName])) { return; } $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)); } $this->methodNodes[$lowerClassName] = []; $this->constantTypes[$lowerClassName] = []; // find and remember all methods/constants within the stubFile foreach ($class[0]->getNode()->stmts as $stmt) { if ($stmt instanceof ClassMethod) { if (!$this->isForCurrentVersion($stmt->attrGroups)) { continue; } $this->methodNodes[$lowerClassName][$stmt->name->toLowerString()] = [$stmt, $stubFile]; continue; } if (!$stmt instanceof ClassConst) { continue; } foreach ($stmt->consts as $const) { if ($stmt->type === null) { continue; } if (!$this->isForCurrentVersion($stmt->attrGroups)) { continue; } $this->constantTypes[$lowerClassName][$const->name->toLowerString()] = ParserNodeTypeToPHPStanType::resolve($stmt->type, 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() ?? $nativeParam->getDefaultValue(), $functionParam->getOutType() ?? $nativeParam->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 \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\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 fn(ParamTag $param): Type => $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); $phpDocParameterType = $phpDocParameterTypes[$name->name] ?? null; if ($param->default instanceof ConstFetch) { $constName = (string) $param->default->name; $loweredConstName = strtolower($constName); if ($loweredConstName === 'null') { $parameterType = TypeCombinator::addNull($parameterType); if ($phpDocParameterType !== null) { $phpDocParameterType = TypeCombinator::addNull($phpDocParameterType); } } } $parameters[] = new \PHPStan\Reflection\SignatureMap\ParameterSignature($name->name, $param->default !== null || $param->variadic, TypehintHelper::decideType($parameterType, $phpDocParameterType), $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); $this->findClassStubs($className); if (isset($this->constantTypes[$lowerClassName][$lowerConstantName])) { return $this->constantTypes[$lowerClassName][$lowerConstantName]; } return null; } } 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 list */ 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]; } } , 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; } 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; } } 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(): TrinaryLogic { return TrinaryLogic::createYes(); } public function mustUseReturnValue(): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getAsserts(): \PHPStan\Reflection\Assertions { return \PHPStan\Reflection\Assertions::createEmpty(); } } 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 { $selfOutType = $method->getSelfOutType() !== null ? $this->transformStaticType($method->getSelfOutType()) : null; $variantFn = function (ExtendedParametersAcceptor $acceptor) use (&$selfOutType): ExtendedParametersAcceptor { $originalReturnType = $acceptor->getReturnType(); $transformedReturnType = $this->transformStaticType($originalReturnType); if ($originalReturnType instanceof ThisType && $selfOutType !== null) { $returnType = TypeCombinator::intersect($selfOutType, $transformedReturnType); $selfOutType = $returnType; } else { $returnType = $transformedReturnType; } $phpDocReturnType = $acceptor->getPhpDocReturnType(); $nativeReturnType = $acceptor->getNativeReturnType(); return new ExtendedFunctionVariant($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), array_map(function (ExtendedParameterReflection $parameter): ExtendedParameterReflection { $originalType = $parameter->getType(); $transformedType = $this->transformStaticType($originalType); return new ExtendedDummyParameter($parameter->getName(), $transformedType, $parameter->isOptional(), $parameter->passedByReference(), $parameter->isVariadic(), $parameter->getDefaultValue(), $parameter->getNativeType(), $originalType->equals($parameter->getPhpDocType()) ? $transformedType : $this->transformStaticType($parameter->getPhpDocType()), $parameter->getOutType() !== null ? $this->transformStaticType($parameter->getOutType()) : null, $parameter->isImmediatelyInvokedCallable(), $parameter->getClosureThisType() !== null ? $this->transformStaticType($parameter->getClosureThisType()) : null, $parameter->getAttributes()); }, $acceptor->getParameters()), $acceptor->isVariadic(), $returnType, $originalReturnType->equals($phpDocReturnType) ? $transformedReturnType : $this->transformStaticType($phpDocReturnType), $originalReturnType->equals($nativeReturnType) ? $transformedReturnType : $this->transformStaticType($nativeReturnType), $acceptor->getCallSiteVarianceMap()); }; $variants = array_map($variantFn, $method->getVariants()); $namedArgumentVariants = $method->getNamedArgumentsVariants(); $namedArgumentVariants = $namedArgumentVariants !== null ? array_map($variantFn, $namedArgumentVariants) : null; $throwType = $method->getThrowType(); $throwType = $throwType !== null ? $this->transformStaticType($throwType) : null; return new ChangedTypeMethodReflection($declaringClass, $method, $variants, $namedArgumentVariants, $selfOutType, $throwType, $method->getAsserts()->mapTypes($this->transformStaticTypeCallback)); } private function transformStaticType(Type $type): Type { $callback = $this->transformStaticTypeCallback; return $callback($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 = $property->getReadableType(); $transformedReadableType = $this->transformStaticType($property->getReadableType()); $writableType = $property->getWritableType(); if ($readableType->equals($writableType)) { $transformedWritableType = $transformedReadableType; } else { $transformedWritableType = $this->transformStaticType($writableType); } $phpDocType = $property->getPhpDocType(); $transformedPhpDocType = $this->transformStaticType($phpDocType); $nativeType = $property->getNativeType(); if ($phpDocType->equals($nativeType)) { $transformedNativeType = $transformedPhpDocType; } else { $transformedNativeType = $this->transformStaticType($property->getNativeType()); } return new ChangedTypePropertyReflection($declaringClass, $property, $transformedReadableType, $transformedWritableType, $transformedPhpDocType, $transformedNativeType); } private function transformStaticType(Type $type): Type { $callback = $this->transformStaticTypeCallback; return $callback($type); } } 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 { $selfOutType = $method->getSelfOutType() !== null ? $this->transformStaticType($method->getSelfOutType()) : null; $variantFn = function (ExtendedParametersAcceptor $acceptor) use ($selfOutType): ExtendedParametersAcceptor { $originalReturnType = $acceptor->getReturnType(); if ($originalReturnType instanceof ThisType && $selfOutType !== null) { $returnType = $selfOutType; } else { $returnType = $this->transformStaticType($originalReturnType); } return new ExtendedFunctionVariant($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), array_map(fn(ExtendedParameterReflection $parameter): ExtendedParameterReflection => new ExtendedDummyParameter($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, $parameter->getAttributes()), $acceptor->getParameters()), $acceptor->isVariadic(), $returnType, $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; $throwType = $method->getThrowType(); $throwType = $throwType !== null ? $this->transformStaticType($throwType) : null; return new ChangedTypeMethodReflection($declaringClass, $method, $variants, $namedArgumentsVariants, $selfOutType, $throwType, $method->getAsserts()->mapTypes(fn(Type $type): Type => $this->transformStaticType($type))); } 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()); $phpDocType = $this->transformStaticType($property->getPhpDocType()); $nativeType = $this->transformStaticType($property->getNativeType()); return new ChangedTypePropertyReflection($declaringClass, $property, $readableType, $writableType, $phpDocType, $nativeType); } 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); }); } } methodName = $methodName; $this->methods = $methods; } public function getDeclaringClass(): ClassReflection { return $this->getMethodWithMostParameters()->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 { $returnTypes = []; $phpDocReturnTypes = []; $nativeReturnTypes = []; foreach ($this->methods as $method) { $variants = $method->getVariants(); foreach ($variants as $acceptor) { $returnTypes[] = $acceptor->getReturnType(); $phpDocReturnTypes[] = $acceptor->getPhpDocReturnType(); $nativeReturnTypes[] = $acceptor->getNativeReturnType(); } } $returnType = $returnTypes[0]; for ($i = 1, $count = count($returnTypes); $i < $count; $i++) { $returnType = TypeCombinator::intersect($returnType, $returnTypes[$i]); } $phpDocReturnType = $phpDocReturnTypes[0]; for ($i = 1, $count = count($phpDocReturnTypes); $i < $count; $i++) { $phpDocReturnType = TypeCombinator::intersect($phpDocReturnType, $phpDocReturnTypes[$i]); } $nativeReturnType = $nativeReturnTypes[0]; for ($i = 1, $count = count($nativeReturnTypes); $i < $count; $i++) { $nativeReturnType = TypeCombinator::intersect($nativeReturnType, $nativeReturnTypes[$i]); } return array_map(static fn(ExtendedParametersAcceptor $acceptor): ExtendedParametersAcceptor => new ExtendedFunctionVariant($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), $acceptor->getParameters(), $acceptor->isVariadic(), $returnType, $phpDocReturnType, $nativeReturnType, $acceptor->getCallSiteVarianceMap()), $this->getMethodWithMostParameters()->getVariants()); } public function getOnlyVariant(): ExtendedParametersAcceptor { $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 fn(MethodReflection $method): TrinaryLogic => $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 fn(MethodReflection $method): TrinaryLogic => $method->isFinal()); } public function isFinalByKeyword(): TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static fn(ExtendedMethodReflection $method): TrinaryLogic => $method->isFinalByKeyword()); } public function isInternal(): TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static fn(MethodReflection $method): TrinaryLogic => $method->isInternal()); } public function isBuiltin(): TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static fn(ExtendedMethodReflection $method): TrinaryLogic => is_bool($method->isBuiltin()) ? TrinaryLogic::createFromBoolean($method->isBuiltin()) : $method->isBuiltin()); } 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; } $result = $types[0]; for ($i = 1, $count = count($types); $i < $count; $i++) { $result = TypeCombinator::intersect($result, $types[$i]); } return $result; } public function hasSideEffects(): TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static fn(MethodReflection $method): TrinaryLogic => $method->hasSideEffects()); } public function isPure(): TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static fn(ExtendedMethodReflection $method): TrinaryLogic => $method->isPure()); } public function getDocComment(): ?string { return null; } public function getAsserts(): Assertions { $assertions = Assertions::createEmpty(); foreach ($this->methods as $method) { $assertions = $assertions->union($method->getAsserts()); } return $assertions; } public function acceptsNamedArguments(): TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static fn(MethodReflection $method): TrinaryLogic => $method->acceptsNamedArguments()); } public function getSelfOutType(): ?Type { return null; } public function returnsByReference(): TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static fn(ExtendedMethodReflection $method): TrinaryLogic => $method->returnsByReference()); } public function isAbstract(): TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static fn(ExtendedMethodReflection $method): TrinaryLogic => is_bool($method->isAbstract()) ? TrinaryLogic::createFromBoolean($method->isAbstract()) : $method->isAbstract()); } public function getAttributes(): array { return $this->getMethodWithMostParameters()->getAttributes(); } public function mustUseReturnValue(): TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static fn(ExtendedMethodReflection $method): TrinaryLogic => $method->mustUseReturnValue()); } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return $this->getMethodWithMostParameters()->getResolvedPhpDoc(); } /** * Since every intersected method should be compatible, * selects the method whose variant has the widest parameter list, * so intersection ordering does not affect call validation. */ private function getMethodWithMostParameters(): ExtendedMethodReflection { if ($this->methodWithMostParameters !== null) { return $this->methodWithMostParameters; } $methodWithMostParameters = $this->methods[0]; $maxParameters = 0; foreach ($this->methods as $method) { foreach ($method->getVariants() as $variant) { if (count($variant->getParameters()) <= $maxParameters) { continue; } $maxParameters = count($variant->getParameters()); $methodWithMostParameters = $method; } } $this->methodWithMostParameters = $methodWithMostParameters; return $methodWithMostParameters; } } properties = $properties; } public function getName(): string { return $this->properties[0]->getName(); } public function getDeclaringClass(): ClassReflection { return $this->properties[0]->getDeclaringClass(); } public function isStatic(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->isStatic()); } public function isPrivate(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->isPrivate()); } public function isPublic(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->isPublic()); } public function isDeprecated(): TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->properties, static fn(ExtendedPropertyReflection $propertyReflection): TrinaryLogic => $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 fn(ExtendedPropertyReflection $propertyReflection): TrinaryLogic => $propertyReflection->isInternal()); } public function getDocComment(): ?string { return null; } public function hasPhpDocType(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->hasPhpDocType()); } public function getPhpDocType(): Type { return $this->pairwiseIntersect(static fn(ExtendedPropertyReflection $property): Type => $property->getPhpDocType()); } public function hasNativeType(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->hasNativeType()); } public function getNativeType(): Type { return $this->pairwiseIntersect(static fn(ExtendedPropertyReflection $property): Type => $property->getNativeType()); } public function getReadableType(): Type { return $this->pairwiseIntersect(static fn(ExtendedPropertyReflection $property): Type => $property->getReadableType()); } public function getWritableType(): Type { return $this->pairwiseIntersect(static fn(ExtendedPropertyReflection $property): Type => $property->getWritableType()); } /** * @param callable(ExtendedPropertyReflection): Type $getType */ private function pairwiseIntersect(callable $getType): Type { $result = $getType($this->properties[0]); for ($i = 1, $count = count($this->properties); $i < $count; $i++) { $result = TypeCombinator::intersect($result, $getType($this->properties[$i])); } return $result; } public function canChangeTypeAfterAssignment(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->canChangeTypeAfterAssignment()); } public function isReadable(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->isReadable()); } public function isWritable(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->isWritable()); } /** * @param callable(ExtendedPropertyReflection): bool $cb */ private function computeResult(callable $cb): bool { $result = \false; foreach ($this->properties as $property) { $result = $result || $cb($property); } return $result; } public function isAbstract(): TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->properties, static fn(ExtendedPropertyReflection $propertyReflection): TrinaryLogic => $propertyReflection->isAbstract()); } public function isFinalByKeyword(): TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->properties, static fn(ExtendedPropertyReflection $propertyReflection): TrinaryLogic => $propertyReflection->isFinalByKeyword()); } public function isFinal(): TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->properties, static fn(ExtendedPropertyReflection $propertyReflection): TrinaryLogic => $propertyReflection->isFinal()); } public function isVirtual(): TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->properties, static fn(ExtendedPropertyReflection $propertyReflection): TrinaryLogic => $propertyReflection->isVirtual()); } public function hasHook(string $hookType): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->hasHook($hookType)); } public function getHook(string $hookType): ExtendedMethodReflection { $hooks = []; foreach ($this->properties as $property) { if (!$property->hasHook($hookType)) { continue; } $hooks[] = $property->getHook($hookType); } if (count($hooks) === 0) { throw new ShouldNotHappenException(); } if (count($hooks) === 1) { return $hooks[0]; } return new \PHPStan\Reflection\Type\IntersectionTypeMethodReflection($hooks[0]->getName(), $hooks); } public function isProtectedSet(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->isProtectedSet()); } public function isPrivateSet(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->isPrivateSet()); } public function getAttributes(): array { return $this->properties[0]->getAttributes(); } public function isDummy(): TrinaryLogic { // uses method typical for unions // because for this to return yes(), all methods should be dummy return TrinaryLogic::lazyExtremeIdentity($this->properties, static fn(ExtendedPropertyReflection $propertyReflection): TrinaryLogic => $propertyReflection->isDummy()); } } 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 fn(\PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection $prototype): \PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection => $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 fn(\PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection $prototype): MethodReflection => $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 fn(\PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection $prototype): \PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection => $prototype->withCalledOnType($type), $this->methodPrototypes)); } } propertyPrototypes = $propertyPrototypes; } public function doNotResolveTemplateTypeMapToBounds(): \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection { if ($this->cachedDoNotResolveTemplateTypeMapToBounds !== null) { return $this->cachedDoNotResolveTemplateTypeMapToBounds; } return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self(array_map(static fn(\PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection $prototype): \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection => $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 fn(\PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection $prototype): PropertyReflection => $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(array_map(static fn(\PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection $prototype): \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection => $prototype->withFechedOnType($type), $this->propertyPrototypes)); } } 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 fn(MethodReflection $method) => $method->getVariants(), $this->methods)); return [ParametersAcceptorSelector::combineAcceptors($variants)]; } public function getOnlyVariant(): ExtendedParametersAcceptor { return $this->getVariants()[0]; } public function getNamedArgumentsVariants(): ?array { return null; } public function isDeprecated(): TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static fn(MethodReflection $method): TrinaryLogic => $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 fn(MethodReflection $method): TrinaryLogic => $method->isFinal()); } public function isFinalByKeyword(): TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static fn(ExtendedMethodReflection $method): TrinaryLogic => $method->isFinalByKeyword()); } public function isInternal(): TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static fn(ExtendedMethodReflection $method): TrinaryLogic => $method->isInternal()); } public function isBuiltin(): TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static fn(ExtendedMethodReflection $method): TrinaryLogic => is_bool($method->isBuiltin()) ? TrinaryLogic::createFromBoolean($method->isBuiltin()) : $method->isBuiltin()); } 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 fn(MethodReflection $method): TrinaryLogic => $method->hasSideEffects()); } public function isPure(): TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static fn(ExtendedMethodReflection $method): TrinaryLogic => $method->isPure()); } public function getDocComment(): ?string { return null; } public function getAsserts(): Assertions { $assertions = Assertions::createEmpty(); foreach ($this->methods as $method) { $assertions = $assertions->intersect($method->getAsserts()); } return $assertions; } public function acceptsNamedArguments(): TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static fn(ExtendedMethodReflection $method): TrinaryLogic => $method->acceptsNamedArguments()); } public function getSelfOutType(): ?Type { return null; } public function returnsByReference(): TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static fn(ExtendedMethodReflection $method): TrinaryLogic => $method->returnsByReference()); } public function isAbstract(): TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static fn(ExtendedMethodReflection $method): TrinaryLogic => is_bool($method->isAbstract()) ? TrinaryLogic::createFromBoolean($method->isAbstract()) : $method->isAbstract()); } public function getAttributes(): array { return $this->methods[0]->getAttributes(); } public function mustUseReturnValue(): TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static fn(ExtendedMethodReflection $method): TrinaryLogic => $method->mustUseReturnValue()); } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return $this->methods[0]->getResolvedPhpDoc(); } } properties = $properties; } public function getName(): string { return $this->properties[0]->getName(); } public function getDeclaringClass(): ClassReflection { return $this->properties[0]->getDeclaringClass(); } public function isStatic(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->isStatic()); } public function isPrivate(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->isPrivate()); } public function isPublic(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->isPublic()); } public function isDeprecated(): TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->properties, static fn(ExtendedPropertyReflection $propertyReflection): TrinaryLogic => $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 fn(ExtendedPropertyReflection $propertyReflection): TrinaryLogic => $propertyReflection->isInternal()); } public function getDocComment(): ?string { return null; } public function hasPhpDocType(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->hasPhpDocType()); } public function getPhpDocType(): Type { return TypeCombinator::union(...array_map(static fn(ExtendedPropertyReflection $property): Type => $property->getPhpDocType(), $this->properties)); } public function hasNativeType(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->hasNativeType()); } public function getNativeType(): Type { return TypeCombinator::union(...array_map(static fn(ExtendedPropertyReflection $property): Type => $property->getNativeType(), $this->properties)); } public function getReadableType(): Type { return TypeCombinator::union(...array_map(static fn(ExtendedPropertyReflection $property): Type => $property->getReadableType(), $this->properties)); } public function getWritableType(): Type { return TypeCombinator::union(...array_map(static fn(ExtendedPropertyReflection $property): Type => $property->getWritableType(), $this->properties)); } public function canChangeTypeAfterAssignment(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->canChangeTypeAfterAssignment()); } public function isReadable(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->isReadable()); } public function isWritable(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->isWritable()); } /** * @param callable(ExtendedPropertyReflection): bool $cb */ private function computeResult(callable $cb): bool { $result = \true; foreach ($this->properties as $property) { $result = $result && $cb($property); } return $result; } public function isAbstract(): TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->properties, static fn(ExtendedPropertyReflection $propertyReflection): TrinaryLogic => $propertyReflection->isAbstract()); } public function isFinalByKeyword(): TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->properties, static fn(ExtendedPropertyReflection $propertyReflection): TrinaryLogic => $propertyReflection->isFinalByKeyword()); } public function isFinal(): TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->properties, static fn(ExtendedPropertyReflection $propertyReflection): TrinaryLogic => $propertyReflection->isFinal()); } public function isVirtual(): TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->properties, static fn(ExtendedPropertyReflection $propertyReflection): TrinaryLogic => $propertyReflection->isVirtual()); } public function hasHook(string $hookType): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->hasHook($hookType)); } public function getHook(string $hookType): ExtendedMethodReflection { $hooks = []; foreach ($this->properties as $property) { if (!$property->hasHook($hookType)) { continue; } $hooks[] = $property->getHook($hookType); } if (count($hooks) === 0) { throw new ShouldNotHappenException(); } if (count($hooks) === 1) { return $hooks[0]; } return new \PHPStan\Reflection\Type\UnionTypeMethodReflection($hooks[0]->getName(), $hooks); } public function isProtectedSet(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->isProtectedSet()); } public function isPrivateSet(): bool { return $this->computeResult(static fn(ExtendedPropertyReflection $property) => $property->isPrivateSet()); } public function getAttributes(): array { return $this->properties[0]->getAttributes(); } public function isDummy(): TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->properties, static fn(ExtendedPropertyReflection $propertyReflection): TrinaryLogic => $propertyReflection->isDummy()); } } 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 fn(\PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection $prototype): \PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection => $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 fn(\PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection $prototype): MethodReflection => $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 fn(\PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection $prototype): \PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection => $prototype->withCalledOnType($type), $this->methodPrototypes)); } } propertyPrototypes = $propertyPrototypes; } public function doNotResolveTemplateTypeMapToBounds(): \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection { if ($this->cachedDoNotResolveTemplateTypeMapToBounds !== null) { return $this->cachedDoNotResolveTemplateTypeMapToBounds; } return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self(array_map(static fn(\PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection $prototype): \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection => $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 fn(\PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection $prototype): PropertyReflection => $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(array_map(static fn(\PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection $prototype): \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection => $prototype->withFechedOnType($type), $this->propertyPrototypes)); } } 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\ExtendedParametersAcceptor) { $variants[] = $variant; continue; } $variants[] = new \PHPStan\Reflection\ExtendedFunctionVariant($variant->getTemplateTypeMap(), $variant->getResolvedTemplateTypeMap(), array_map(static fn(\PHPStan\Reflection\ParameterReflection $parameter): \PHPStan\Reflection\ExtendedParameterReflection => $parameter instanceof \PHPStan\Reflection\ExtendedParameterReflection ? $parameter : new ExtendedDummyParameter($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\ExtendedParametersAcceptor { 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 isBuiltin(): TrinaryLogic { return TrinaryLogic::createNo(); } 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(): TrinaryLogic { return TrinaryLogic::createFromBoolean($this->getDeclaringClass()->acceptsNamedArguments()); } public function getSelfOutType(): ?Type { return null; } public function returnsByReference(): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isAbstract(): TrinaryLogic { return TrinaryLogic::createNo(); } public function getAttributes(): array { return []; } public function mustUseReturnValue(): TrinaryLogic { // Align with the getAttributes() returning empty return TrinaryLogic::createNo(); } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return null; } } name = $name; $this->property = $property; } public function getName(): string { return $this->name; } 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 hasPhpDocType(): bool { return \false; } public function getPhpDocType(): Type { return new MixedType(); } public function hasNativeType(): bool { return \false; } public function getNativeType(): Type { return new MixedType(); } 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(); } public function isAbstract(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinalByKeyword(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinal(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isVirtual(): TrinaryLogic { return TrinaryLogic::createNo(); } public function hasHook(string $hookType): bool { return \false; } public function getHook(string $hookType): \PHPStan\Reflection\ExtendedMethodReflection { throw new ShouldNotHappenException(); } public function isProtectedSet(): bool { return \false; } public function isPrivateSet(): bool { return \false; } public function getAttributes(): array { return []; } public function isDummy(): TrinaryLogic { return TrinaryLogic::createNo(); } } */ #[RegisteredRule(0)] final class ApiClassConstFetchRule implements Rule { private \PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper; private ReflectionProvider $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]; } } */ #[RegisteredRule(0)] final class ApiClassExtendsRule implements Rule { private \PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper; private ReflectionProvider $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]; } } */ #[RegisteredRule(0)] final class ApiClassImplementsRule implements Rule { private \PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper; private ReflectionProvider $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(); $docBlock = $implementedClassReflection->getResolvedPhpDoc(); if ($docBlock === null) { return [$ruleError]; } foreach ($docBlock->getPhpDocNodes() as $phpDocNode) { if (count($phpDocNode->getTagsByName('@api-do-not-implement')) > 0) { return [$ruleError]; } } foreach ($docBlock->getPhpDocNodes() as $phpDocNode) { if (count($phpDocNode->getTagsByName('@api')) > 0) { return []; } } return [$ruleError]; } } */ #[RegisteredRule(0)] final class ApiInstanceofRule implements Rule { private \PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper; private ReflectionProvider $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->is(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()]; } } */ #[RegisteredRule(0)] final class ApiInstanceofTypeRule implements Rule { private ReflectionProvider $reflectionProvider; 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, 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', ]; /** @var array * @readonly */ private array $lowerMap; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; $lowerMap = []; foreach (self::MAP as $className => $method) { $lowerMap[strtolower($className)] = $method; } $this->lowerMap = $lowerMap; } public function getNodeType(): string { return Instanceof_::class; } public function processNode(Node $node, Scope $scope): array { if (!$node->class instanceof Node\Name) { return []; } if ($node->getAttribute(TypeTraverserInstanceofVisitor::ATTRIBUTE_NAME, \false) === \true) { return []; } $className = $scope->resolveName($node->class); $lowerClassName = strtolower($className); if (!array_key_exists($lowerClassName, $this->lowerMap)) { return []; } if ($scope->isInClass()) { $classReflection = $scope->getClassReflection(); if ($classReflection->implementsInterface(TypeTraverserCallable::class)) { return []; } } if ($this->reflectionProvider->hasClass($className)) { $classReflection = $this->reflectionProvider->getClass($className); if ($classReflection->is(AccessoryType::class)) { if ($className === $classReflection->getName()) { return []; } } } $tip = 'Learn more: https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated'; if ($this->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, $this->lowerMap[$lowerClassName]))->identifier('phpstanApi.instanceofType')->tip($tip)->build()]; } } */ #[RegisteredRule(0)] final class ApiInstantiationRule implements Rule { private \PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper; private ReflectionProvider $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 []; } } */ #[RegisteredRule(0)] final class ApiInterfaceExtendsRule implements Rule { private \PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper; private ReflectionProvider $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(); $docBlock = $extendedInterfaceReflection->getResolvedPhpDoc(); if ($docBlock === null) { return [$ruleError]; } foreach ($docBlock->getPhpDocNodes() as $phpDocNode) { if (count($phpDocNode->getTagsByName('@api-do-not-implement')) > 0) { return [$ruleError]; } } foreach ($docBlock->getPhpDocNodes() as $phpDocNode) { if (count($phpDocNode->getTagsByName('@api')) > 0) { return []; } } return [$ruleError]; } } */ #[RegisteredRule(0)] final class ApiMethodCallRule implements Rule { private \PHPStan\Rules\Api\ApiRuleHelper $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'); } } 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; } } */ #[RegisteredRule(0)] final class ApiStaticCallRule implements Rule { private \PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper; private ReflectionProvider $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(); if ($methodReflection->getName() !== '__construct') { $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'); } } */ #[RegisteredRule(0)] final class ApiTraitUseRule implements Rule { private \PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper; private ReflectionProvider $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; } } */ #[RegisteredRule(0)] final class GetTemplateTypeRule implements Rule { private ReflectionProvider $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; } } */ #[RegisteredRule(0)] final class NodeConnectingVisitorAttributesRule implements Rule { 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 []; } $messages = []; $argType = $scope->getType($args[0]->value); foreach ($argType->getConstantStrings() as $constantString) { $argValue = $constantString->getValue(); if (!in_array($argValue, ['parent', 'previous', 'next'], \true)) { continue; } if (!$scope->isInClass()) { continue; } $classReflection = $scope->getClassReflection(); $hasPhpStanInterface = \false; foreach (array_keys($classReflection->getInterfaces()) as $interfaceName) { if (!str_starts_with($interfaceName, 'PHPStan\\')) { continue; } $hasPhpStanInterface = \true; } if (!$hasPhpStanInterface) { continue; } $messages[] = RuleErrorBuilder::message(sprintf('Node attribute \'%s\' is no longer available.', $argValue))->identifier('phpParser.nodeConnectingAttribute')->tip('See: https://phpstan.org/blog/preprocessing-ast-for-custom-rules')->build(); } return $messages; } } */ #[RegisteredRule(0)] final class OldPhpParser4ClassRule implements Rule { private const NAME_MAPPING = [ // from https://github.com/nikic/PHP-Parser/blob/master/UPGRADE-5.0.md#renamed-nodes 'PhpParser\Node\Scalar\LNumber' => Node\Scalar\Int_::class, 'PhpParser\Node\Scalar\DNumber' => Node\Scalar\Float_::class, 'PhpParser\Node\Scalar\Encapsed' => Node\Scalar\InterpolatedString::class, 'PhpParser\Node\Scalar\EncapsedStringPart' => Node\InterpolatedStringPart::class, 'PhpParser\Node\Expr\ArrayItem' => Node\ArrayItem::class, 'PhpParser\Node\Expr\ClosureUse' => Node\ClosureUse::class, 'PhpParser\Node\Stmt\DeclareDeclare' => Node\DeclareItem::class, 'PhpParser\Node\Stmt\PropertyProperty' => Node\PropertyItem::class, 'PhpParser\Node\Stmt\StaticVar' => Node\StaticVar::class, 'PhpParser\Node\Stmt\UseUse' => Node\UseItem::class, ]; public function getNodeType(): string { return Name::class; } public function processNode(Node $node, Scope $scope): array { $nameMapping = array_change_key_case(self::NAME_MAPPING); $lowerName = $node->toLowerString(); if (!array_key_exists($lowerName, $nameMapping)) { return []; } $newName = $nameMapping[$lowerName]; 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('Class %s not found. It has been renamed to %s in PHP-Parser v5.', $node->toString(), $newName))->identifier('phpParser.classRenamed')->build()]; } } */ #[RegisteredRule(0)] final class PhpStanNamespaceIn3rdPartyPackageRule implements Rule { private \PHPStan\Rules\Api\ApiRuleHelper $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; } } } */ #[RegisteredRule(0)] final class RuntimeReflectionFunctionRule implements Rule { private ReflectionProvider $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()]; } } */ #[RegisteredRule(0)] final class RuntimeReflectionInstantiationRule implements Rule { private ReflectionProvider $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()]; } } deprecatesImplicitlyFloatConversionToInt()) { $types[] = new FloatType(); } if ($phpVersion === null || !$phpVersion->deprecatesNullArrayOffset()) { $types[] = new NullType(); } } return new UnionType($types); } public static function narrowOffsetKeyType(Type $varType, Type $keyType): ?Type { if (!$varType->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); } elseif ($varType->isList()->yes()) { return TypeCombinator::intersect($varIterableKeyType, $keyType); } return new MixedType(\false, new UnionType([new ArrayType(new MixedType(), new MixedType()), new ObjectWithoutClassType(), new ResourceType()])); } } */ #[RegisteredRule(3)] final class ArrayDestructuringRule implements Rule { private RuleLevelHelper $ruleLevelHelper; private \PHPStan\Rules\Arrays\NonexistentOffsetInArrayDimFetchCheck $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_) { return []; } return $this->getErrors($scope, $node->var, $node->expr); } /** * @return list */ private function getErrors(Scope $scope, Node\Expr\List_ $var, Expr $expr): array { $exprTypeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $expr, '', static fn(Type $varType): bool => $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\Int_($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_) { $i++; continue; } $errors = array_merge($errors, $this->getErrors($scope, $item->value, new Expr\ArrayDimFetch($expr, $keyExpr))); } return $errors; } } */ #[RegisteredRule(3)] final class ArrayUnpackingRule implements Rule { private PhpVersion $phpVersion; private RuleLevelHelper $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 fn(Type $type): bool => $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()]; } } */ #[RegisteredRule(4)] 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()]; } } */ #[RegisteredRule(0)] final class DuplicateKeysInLiteralArraysRule implements Rule { private ExprPrinter $exprPrinter; public function __construct(ExprPrinter $exprPrinter) { $this->exprPrinter = $exprPrinter; } public function getNodeType(): string { return LiteralArrayNode::class; } public function processNode(Node $node, Scope $scope): array { $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; $seenKeys = []; $seenUnions = []; 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); $arrayKeyValues = $keyType->toArrayKey()->getConstantScalarValues(); if (count($arrayKeyValues) === 1 && is_int($arrayKeyValues[0])) { $autoGeneratedIndex = $autoGeneratedIndex === null ? $arrayKeyValues[0] : max($autoGeneratedIndex, $arrayKeyValues[0]); } } $keyValues = $keyType->toArrayKey()->getConstantScalarValues(); if (count($keyValues) === 0) { $autoGeneratedIndex = \false; continue; } $duplicate = \false; $newValues = $keyValues; foreach ($newValues as $k => $newValue) { if (array_search($newValue, $seenKeys, \true) !== \false) { unset($newValues[$k]); } if ($newValues === []) { $duplicate = \true; break; } } if ($newValues !== []) { if (count($newValues) === 1) { $newValue = $newValues[array_key_first($newValues)]; foreach ($seenUnions as $k => $union) { $offset = array_search($newValue, $union, \true); if ($offset === \false) { continue; } unset($seenUnions[$k][$offset]); // turn a union into a seen key, when all its elements have been seen if (count($seenUnions[$k]) !== 1) { continue; } $seenKeys[] = $seenUnions[$k][array_key_first($seenUnions[$k])]; unset($seenUnions[$k]); } $seenKeys[] = $newValue; } else { $seenUnions[] = $newValues; } } foreach ($keyValues as $value) { // Prevent php warning by manually casting array keys if (is_bool($value) || is_float($value)) { $value = (int) $value; } elseif ($value === null) { $value = (string) $value; } $printedValue = $key !== null ? $this->exprPrinter->printExpr($key) : $value; $printedValues[$value][] = $printedValue; if (!isset($valueLines[$value])) { $valueLines[$value] = $item->getStartLine(); } if (!$duplicate) { 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; } } */ #[RegisteredRule(3)] final class InvalidKeyInArrayDimFetchRule implements Rule { private RuleLevelHelper $ruleLevelHelper; private PhpVersion $phpVersion; private bool $reportMaybes; private bool $reportNonIntStringArrayKey; public function __construct( RuleLevelHelper $ruleLevelHelper, PhpVersion $phpVersion, #[AutowiredParameter] bool $reportMaybes, #[AutowiredParameter] bool $reportNonIntStringArrayKey ) { $this->ruleLevelHelper = $ruleLevelHelper; $this->phpVersion = $phpVersion; $this->reportMaybes = $reportMaybes; $this->reportNonIntStringArrayKey = $reportNonIntStringArrayKey; } public function getNodeType(): string { return Node\Expr\ArrayDimFetch::class; } public function processNode(Node $node, Scope $scope): array { if ($node->dim === null) { return []; } $varType = $this->ruleLevelHelper->findTypeToCheck($scope, $node->var, '', static fn(Type $varType): bool => $varType->isArray()->no())->getType(); if ($varType instanceof ErrorType) { return []; } $isArray = $varType->isArray(); if ($isArray->no() || $isArray->maybe() && !$this->reportMaybes) { return []; } $allowedArrayKeys = \PHPStan\Rules\Arrays\AllowedArrayKeysTypes::getType($this->phpVersion, $this->reportNonIntStringArrayKey); $dimensionType = $this->ruleLevelHelper->findTypeToCheck($scope, $node->dim, '', static fn(Type $dimType): bool => $allowedArrayKeys->isSuperTypeOf($dimType)->yes())->getType(); if ($dimensionType instanceof ErrorType) { return []; } $isSuperType = $allowedArrayKeys->isSuperTypeOf($dimensionType); if ($isSuperType->yes() || $isSuperType->maybe() && !$this->reportMaybes) { return []; } return [RuleErrorBuilder::message(sprintf('%s array key type %s.', $isArray->yes() && $isSuperType->no() ? 'Invalid' : 'Possibly invalid', $dimensionType->describe(VerbosityLevel::typeOnly())))->identifier('offsetAccess.invalidOffset')->build()]; } } */ #[RegisteredRule(3)] final class InvalidKeyInArrayItemRule implements Rule { private RuleLevelHelper $ruleLevelHelper; private PhpVersion $phpVersion; private bool $reportNonIntStringArrayKey; public function __construct( RuleLevelHelper $ruleLevelHelper, PhpVersion $phpVersion, #[AutowiredParameter] bool $reportNonIntStringArrayKey ) { $this->ruleLevelHelper = $ruleLevelHelper; $this->phpVersion = $phpVersion; $this->reportNonIntStringArrayKey = $reportNonIntStringArrayKey; } public function getNodeType(): string { return Node\ArrayItem::class; } public function processNode(Node $node, Scope $scope): array { if ($node->key === null) { return []; } $allowedArrayKeys = \PHPStan\Rules\Arrays\AllowedArrayKeysTypes::getType($this->phpVersion, $this->reportNonIntStringArrayKey); $dimensionType = $this->ruleLevelHelper->findTypeToCheck($scope, $node->key, '', static fn(Type $dimType): bool => $allowedArrayKeys->isSuperTypeOf($dimType)->yes())->getType(); if ($dimensionType instanceof ErrorType) { return []; } $isSuperType = $allowedArrayKeys->isSuperTypeOf($dimensionType); if ($isSuperType->yes()) { return []; } return [RuleErrorBuilder::message(sprintf('%s array key type %s.', $isSuperType->no() ? 'Invalid' : 'Possibly invalid', $dimensionType->describe(VerbosityLevel::typeOnly())))->identifier('array.invalidKey')->build()]; } } */ #[RegisteredRule(3)] final class IterableInForeachRule implements Rule { private RuleLevelHelper $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 fn(Type $type): bool => $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()]; } } ruleLevelHelper = $ruleLevelHelper; $this->reportMaybes = $reportMaybes; $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 fn(Type $type): bool => $type->hasOffsetValueType($dimType)->yes()); $type = $typeResult->getType(); if ($type instanceof ErrorType) { return $typeResult->getUnknownClassErrors(); } if ($scope->isInExpressionAssign($var) || $scope->isUndefinedExpressionAllowed($var)) { return []; } $hasOffsetValueType = $type->hasOffsetValueType($dimType); if ($hasOffsetValueType->yes()) { return []; } if ($hasOffsetValueType->no()) { if ($type->isArray()->yes()) { $validArrayDimType = TypeCombinator::intersect(\PHPStan\Rules\Arrays\AllowedArrayKeysTypes::getType(), $dimType); if ($validArrayDimType instanceof NeverType) { // Already reported by InvalidKeyInArrayDimFetchRule return []; } } return [RuleErrorBuilder::message(sprintf('Offset %s does not exist on %s.', $dimType->describe(count($dimType->getConstantStrings()) > 0 ? VerbosityLevel::precise() : 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); } $validArrayDimType = $dimType instanceof MixedType ? $dimType : TypeCombinator::intersect(\PHPStan\Rules\Arrays\AllowedArrayKeysTypes::getType(), $dimType); foreach ($flattenedTypes as $innerType) { $dimTypeToCheck = $innerType->isArray()->yes() ? $validArrayDimType : $dimType; if ($this->reportPossiblyNonexistentGeneralArrayOffset && $innerType->isArray()->yes() && !$innerType->isConstantArray()->yes() && !$innerType->hasOffsetValueType($dimTypeToCheck)->yes()) { $report = \true; break; } if ($this->reportPossiblyNonexistentConstantArrayOffset && $innerType->isConstantArray()->yes() && !$innerType->hasOffsetValueType($dimTypeToCheck)->yes()) { $report = \true; break; } if ($dimTypeToCheck instanceof BenevolentUnionType) { $flattenedInnerTypes = [$dimTypeToCheck]; } else { $flattenedInnerTypes = TypeUtils::flattenTypes($dimTypeToCheck); } foreach ($flattenedInnerTypes as $innerDimType) { if ($innerType->hasOffsetValueType($innerDimType)->no()) { $report = \true; break 2; } } } if ($report) { return [RuleErrorBuilder::message(sprintf('Offset %s might not exist on %s.', $dimType->describe(count($dimType->getConstantStrings()) > 0 ? VerbosityLevel::precise() : VerbosityLevel::value()), $type->describe(VerbosityLevel::value())))->identifier('offsetAccess.notFound')->build()]; } } return []; } } */ #[RegisteredRule(3)] final class NonexistentOffsetInArrayDimFetchRule implements Rule { private RuleLevelHelper $ruleLevelHelper; private \PHPStan\Rules\Arrays\NonexistentOffsetInArrayDimFetchCheck $nonexistentOffsetInArrayDimFetchCheck; private bool $reportMaybes; public function __construct( RuleLevelHelper $ruleLevelHelper, \PHPStan\Rules\Arrays\NonexistentOffsetInArrayDimFetchCheck $nonexistentOffsetInArrayDimFetchCheck, #[AutowiredParameter] 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 ($this->isImplicitArrayCreation($node, $scope)->yes()) { return []; } 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 fn(Type $type): bool => $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(count($dimType->getConstantStrings()) > 0 ? VerbosityLevel::precise() : 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 []; } if ($node->dim instanceof Node\Expr\FuncCall && !$node->dim->isFirstClassCallable() && $node->dim->name instanceof Node\Name && in_array($node->dim->name->toLowerString(), ['array_key_first', 'array_key_last'], \true) && count($node->dim->getArgs()) >= 1) { $arrayArg = $node->dim->getArgs()[0]->value; $arrayType = $scope->getType($arrayArg); if ($arrayArg instanceof Node\Expr\Variable && $node->var instanceof Node\Expr\Variable && is_string($arrayArg->name) && $arrayArg->name === $node->var->name && $arrayType->isArray()->yes() && $arrayType->isIterableAtLeastOnce()->yes()) { return []; } } if ($node->dim instanceof Node\Expr\FuncCall && $node->dim->name instanceof Node\Name && $node->dim->name->toLowerString() === 'array_rand' && count($node->dim->getArgs()) >= 1) { $numArg = null; $arrayArg = $node->dim->getArgs()[0]->value; if (count($node->dim->getArgs()) > 1) { $numArg = $node->dim->getArgs()[1]->value; } $one = new ConstantIntegerType(1); $arrayType = $scope->getType($arrayArg); if ($arrayArg instanceof Node\Expr\Variable && $node->var instanceof Node\Expr\Variable && is_string($arrayArg->name) && $arrayArg->name === $node->var->name && $arrayType->isArray()->yes() && $arrayType->isIterableAtLeastOnce()->yes() && ($numArg === null || $one->isSuperTypeOf($scope->getType($numArg))->yes())) { return []; } } if ($node->dim instanceof Node\Expr\BinaryOp\Minus && $node->dim->left instanceof Node\Expr\FuncCall && $node->dim->left->name instanceof Node\Name && in_array($node->dim->left->name->toLowerString(), ['count', 'sizeof'], \true) && count($node->dim->left->getArgs()) >= 1 && $node->dim->right instanceof Node\Scalar\Int_ && $node->dim->right->value === 1) { $arrayArg = $node->dim->left->getArgs()[0]->value; $arrayType = $scope->getType($arrayArg); if ($arrayArg instanceof Node\Expr\Variable && $node->var instanceof Node\Expr\Variable && is_string($arrayArg->name) && $arrayArg->name === $node->var->name && $arrayType->isList()->yes() && $arrayType->isIterableAtLeastOnce()->yes()) { return []; } } return $this->nonexistentOffsetInArrayDimFetchCheck->check($scope, $node->var, $unknownClassPattern, $dimType); } private function isImplicitArrayCreation(Node\Expr\ArrayDimFetch $node, Scope $scope): TrinaryLogic { $varNode = $node->var; while ($varNode instanceof ArrayDimFetch) { $varNode = $varNode->var; } if (!$varNode instanceof Variable) { return TrinaryLogic::createNo(); } if (!is_string($varNode->name)) { return TrinaryLogic::createNo(); } return $scope->hasVariableType($varNode->name)->negate(); } } */ #[RegisteredRule(3)] final class OffsetAccessAssignOpRule implements Rule { private RuleLevelHelper $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()]; } } */ #[RegisteredRule(3)] final class OffsetAccessAssignmentRule implements Rule { private RuleLevelHelper $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()]; } } */ #[RegisteredRule(3)] final class OffsetAccessValueAssignmentRule implements Rule { private RuleLevelHelper $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()]; } } */ #[RegisteredRule(0)] 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()]; } } */ #[RegisteredRule(3)] final class UnpackIterableInArrayRule implements Rule { private RuleLevelHelper $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 fn(Type $type): bool => $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; } } 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($scope, [new \PHPStan\Rules\ClassNameNodePair($name, $attribute)], \PHPStan\Rules\ClassNameUsageLocation::from(\PHPStan\Rules\ClassNameUsageLocation::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', $attributeConstructor->acceptsNamedArguments(), '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.', '%s of attribute class ' . $attributeClassName . ' constructor expects %s, %s given.', '', // constructor does not have a return type '%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.', '%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.' ); foreach ($parameterErrors as $error) { $errors[] = $error; } } } return $errors; } } */ #[RegisteredRule(0)] final class DeprecatedCastRule implements Rule { private PhpVersion $phpVersion; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function getNodeType(): string { return Cast::class; } public function processNode(Node $node, Scope $scope): array { if (!$this->phpVersion->deprecatesNonStandardCasts()) { return []; } if ($node instanceof Cast\Int_) { $kind = $node->getAttribute('kind', Cast\Int_::KIND_INT); if ($kind === Cast\Int_::KIND_INTEGER) { return [RuleErrorBuilder::message('Non-standard (integer) cast is deprecated in PHP 8.5. Use (int) instead.')->identifier('cast.deprecated')->build()]; } return []; } if ($node instanceof Cast\Bool_) { $kind = $node->getAttribute('kind', Cast\Bool_::KIND_BOOL); if ($kind === Cast\Bool_::KIND_BOOLEAN) { return [RuleErrorBuilder::message('Non-standard (boolean) cast is deprecated in PHP 8.5. Use (bool) instead.')->identifier('cast.deprecated')->build()]; } return []; } if ($node instanceof Cast\Double) { $kind = $node->getAttribute('kind', Cast\Double::KIND_FLOAT); if ($kind === Cast\Double::KIND_DOUBLE) { return [RuleErrorBuilder::message('Non-standard (double) cast is deprecated in PHP 8.5. Use (float) instead.')->identifier('cast.deprecated')->build()]; } return []; } if ($node instanceof Cast\String_) { $kind = $node->getAttribute('kind', Cast\String_::KIND_STRING); if ($kind === Cast\String_::KIND_BINARY) { return [RuleErrorBuilder::message('Non-standard (binary) cast is deprecated in PHP 8.5. Use (string) instead.')->identifier('cast.deprecated')->build()]; } return []; } return []; } } */ #[RegisteredRule(2)] final class EchoRule implements Rule { private RuleLevelHelper $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 fn(Type $type): bool => !$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; } } */ #[RegisteredRule(2)] final class InvalidCastRule implements Rule { private ReflectionProvider $reflectionProvider; private RuleLevelHelper $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 []; } } */ #[RegisteredRule(2)] final class InvalidPartOfEncapsedStringRule implements Rule { private ExprPrinter $exprPrinter; private RuleLevelHelper $ruleLevelHelper; public function __construct(ExprPrinter $exprPrinter, RuleLevelHelper $ruleLevelHelper) { $this->exprPrinter = $exprPrinter; $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType(): string { return Node\Scalar\InterpolatedString::class; } public function processNode(Node $node, Scope $scope): array { $messages = []; foreach ($node->parts as $part) { if ($part instanceof Node\InterpolatedStringPart) { continue; } $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $part, '', static fn(Type $type): bool => !$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; } } */ #[RegisteredRule(2)] final class PrintRule implements Rule { private RuleLevelHelper $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 fn(Type $type): bool => !$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 []; } } */ #[RegisteredRule(0)] final class UnsetCastRule implements Rule { private PhpVersion $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()]; } } */ #[RegisteredRule(0)] final class VoidCastRule implements Rule { private PhpVersion $phpVersion; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function getNodeType(): string { return Node\Expr\Cast\Void_::class; } public function processNode(Node $node, Scope $scope): array { $errors = []; if (!$this->phpVersion->supportsVoidCast()) { $errors[] = RuleErrorBuilder::message('The (void) cast is supported only on PHP 8.5 and later.')->identifier('cast.voidNotSupported')->nonIgnorable()->build(); } if ($scope->isInFirstLevelStatement()) { return $errors; } $errors[] = RuleErrorBuilder::message('The (void) cast cannot be used within an expression.')->identifier('cast.void')->nonIgnorable()->build(); return $errors; } } 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() where the alias is a completely different name } if ($pair->getNode()->getAttribute(UseAliasVisitor::ATTRIBUTE_NAME) === \true) { continue; } 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 fn(ForbiddenClassNameExtension $extension): array => $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)); $pos = strpos($withoutPrefixClassName, '\\'); if ($pos === \false) { continue; } $withoutPrefixClassName = substr($withoutPrefixClassName, $pos); } if ($projectName === null) { continue; } $error = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Referencing prefixed %s class: %s.', $projectName, $className))->line($pair->getNode()->getStartLine())->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; } } classCaseSensitivityCheck = $classCaseSensitivityCheck; $this->classForbiddenNameCheck = $classForbiddenNameCheck; $this->reflectionProvider = $reflectionProvider; $this->container = $container; } /** * @param ClassNameNodePair[] $pairs * @return list */ public function checkClassNames(Scope $scope, array $pairs, ?\PHPStan\Rules\ClassNameUsageLocation $location, 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; } if ($location === null) { return $errors; } /** @var RestrictedClassNameUsageExtension[] $extensions */ $extensions = $this->extensions ??= $this->container->getServicesByTag(RestrictedClassNameUsageExtension::CLASS_NAME_EXTENSION_TAG); if ($extensions === []) { return $errors; } foreach ($pairs as $pair) { if (!$this->reflectionProvider->hasClass($pair->getClassName())) { continue; } $classReflection = $this->reflectionProvider->getClass($pair->getClassName()); foreach ($extensions as $extension) { $restrictedUsage = $extension->isRestrictedClassNameUsage($classReflection, $scope, $location); if ($restrictedUsage === null) { continue; } $errors[] = \PHPStan\Rules\RuleErrorBuilder::message($restrictedUsage->errorMessage)->identifier($restrictedUsage->identifier)->line($pair->getNode()->getStartLine())->build(); } } return $errors; } } className = $className; $this->node = $node; } /** * @return non-empty-string */ public function getClassName(): string { return $this->className; } public function getNode(): Node { return $this->node; } } value = $value; $this->data = $data; } /** * @param self::* $value * @param mixed[] $data */ public static function from(string $value, array $data = []): self { return new self($value, $data); } public function getMethod(): ?ExtendedMethodReflection { return $this->data['method'] ?? null; } public function getProperty(): ?ExtendedPropertyReflection { return $this->data['property'] ?? null; } public function getFunction(): ?FunctionReflection { return $this->data['function'] ?? null; } public function getPhpDocTagName(): ?string { return $this->data['phpDocTagName'] ?? null; } public function getAssertedExprString(): ?string { return $this->data['assertedExprString'] ?? null; } public function getClassConstant(): ?ClassConstantReflection { return $this->data['classConstant'] ?? null; } public function getCurrentClassName(): ?string { return $this->data['currentClassName'] ?? null; } public function getParameterName(): ?string { return $this->data['parameterName'] ?? null; } public function getTypeAliasName(): ?string { return $this->data['typeAliasName'] ?? null; } public function getMethodTagName(): ?string { return $this->data['methodTagName'] ?? null; } public function getPropertyTagName(): ?string { return $this->data['propertyTagName'] ?? null; } public function getTemplateTagName(): ?string { return $this->data['templateTagName'] ?? null; } public function isInAnomyousFunction(): bool { return $this->data['isInAnonymousFunction'] ?? \false; } public function createMessage(string $part): string { switch ($this->value) { case self::TRAIT_USE: if ($this->getCurrentClassName() !== null) { return sprintf('Usage of %s in class %s.', $part, $this->getCurrentClassName()); } return sprintf('Usage of %s.', $part); case self::STATIC_PROPERTY_ACCESS: $property = $this->getProperty(); if ($property !== null) { return sprintf('Access to static property $%s on %s.', $property->getName(), $part); } return sprintf('Access to static property on %s.', $part); case self::PHPDOC_TAG_ASSERT: $phpDocTagName = $this->getPhpDocTagName(); $assertExprString = $this->getAssertedExprString(); if ($phpDocTagName !== null && $assertExprString !== null) { return sprintf('PHPDoc tag %s for %s references %s.', $phpDocTagName, $assertExprString, $part); } return sprintf('Assert tag references %s.', $part); case self::ATTRIBUTE: return sprintf('Attribute references %s.', $part); case self::EXCEPTION_CATCH: return sprintf('Catching %s.', $part); case self::CLASS_CONSTANT_ACCESS: if ($this->getClassConstant() !== null) { return sprintf('Access to constant %s on %s.', $this->getClassConstant()->getName(), $part); } return sprintf('Access to constant on %s.', $part); case self::CLASS_IMPLEMENTS: if ($this->getCurrentClassName() !== null) { return sprintf('Class %s implements %s.', $this->getCurrentClassName(), $part); } return sprintf('Anonymous class implements %s.', $part); case self::ENUM_IMPLEMENTS: if ($this->getCurrentClassName() !== null) { return sprintf('Enum %s implements %s.', $this->getCurrentClassName(), $part); } return sprintf('Enum implements %s.', $part); case self::INTERFACE_EXTENDS: if ($this->getCurrentClassName() !== null) { return sprintf('Interface %s extends %s.', $this->getCurrentClassName(), $part); } return sprintf('Interface extends %s.', $part); case self::CLASS_EXTENDS: if ($this->getCurrentClassName() !== null) { return sprintf('Class %s extends %s.', $this->getCurrentClassName(), $part); } return sprintf('Anonymous class extends %s.', $part); case self::INSTANCEOF: return sprintf('Instanceof references %s.', $part); case self::PROPERTY_TYPE: $property = $this->getProperty(); if ($property !== null) { return sprintf('Property $%s references %s in its type.', $property->getName(), $part); } return sprintf('Property references %s in its type.', $part); case self::PARAMETER_TYPE: $parameterName = $this->getParameterName(); if ($parameterName !== null) { if ($this->isInAnomyousFunction()) { return sprintf('Parameter $%s of anonymous function has typehint with %s.', $parameterName, $part); } if ($this->getMethod() !== null) { if ($this->getCurrentClassName() !== null) { return sprintf('Parameter $%s of method %s::%s() has typehint with %s.', $parameterName, $this->getCurrentClassName(), $this->getMethod()->getName(), $part); } return sprintf('Parameter $%s of method %s() in anonymous class has typehint with %s.', $parameterName, $this->getMethod()->getName(), $part); } if ($this->getFunction() !== null) { return sprintf('Parameter $%s of function %s() has typehint with %s.', $parameterName, $this->getFunction()->getName(), $part); } return sprintf('Parameter $%s has typehint with %s.', $parameterName, $part); } return sprintf('Parameter has typehint with %s.', $part); case self::RETURN_TYPE: if ($this->isInAnomyousFunction()) { return sprintf('Return type of anonymous function has typehint with %s.', $part); } if ($this->getMethod() !== null) { if ($this->getCurrentClassName() !== null) { return sprintf('Return type of method %s::%s() has typehint with %s.', $this->getCurrentClassName(), $this->getMethod()->getName(), $part); } return sprintf('Return type of method %s() in anonymous class has typehint with %s.', $this->getMethod()->getName(), $part); } if ($this->getFunction() !== null) { return sprintf('Return type of function %s() has typehint with %s.', $this->getFunction()->getName(), $part); } return sprintf('Return type has typehint with %s.', $part); case self::PHPDOC_TAG_SELF_OUT: return sprintf('PHPDoc tag @phpstan-self-out references %s.', $part); case self::PHPDOC_TAG_VAR: return sprintf('PHPDoc tag @var references %s.', $part); case self::INSTANTIATION: return sprintf('Instantiation of %s.', $part); case self::TYPE_ALIAS: if ($this->getTypeAliasName() !== null) { return sprintf('Type alias %s references %s.', $this->getTypeAliasName(), $part); } return sprintf('Type alias references %s.', $part); case self::PHPDOC_TAG_METHOD: if ($this->getMethodTagName() !== null) { return sprintf('PHPDoc tag @method for %s() references %s.', $this->getMethodTagName(), $part); } return sprintf('PHPDoc tag @method references %s.', $part); case self::PHPDOC_TAG_MIXIN: return sprintf('PHPDoc tag @mixin references %s.', $part); case self::PHPDOC_TAG_PROPERTY: if ($this->getPropertyTagName() !== null) { return sprintf('PHPDoc tag @property for $%s references %s.', $this->getPropertyTagName(), $part); } return sprintf('PHPDoc tag @property references %s.', $part); case self::PHPDOC_TAG_REQUIRE_EXTENDS: return sprintf('PHPDoc tag @phpstan-require-extends references %s.', $part); case self::PHPDOC_TAG_REQUIRE_IMPLEMENTS: return sprintf('PHPDoc tag @phpstan-require-implements references %s.', $part); case self::PHPDOC_TAG_SEALED: return sprintf('PHPDoc tag @phpstan-sealed references %s.', $part); case self::STATIC_METHOD_CALL: $method = $this->getMethod(); if ($method !== null) { return sprintf('Call to static method %s() on %s.', $method->getName(), $part); } return sprintf('Call to static method on %s.', $part); case self::PHPDOC_TAG_TEMPLATE_BOUND: if ($this->getTemplateTagName() !== null) { return sprintf('PHPDoc tag @template %s bound references %s.', $this->getTemplateTagName(), $part); } return sprintf('PHPDoc tag @template bound references %s.', $part); case self::PHPDOC_TAG_TEMPLATE_DEFAULT: if ($this->getTemplateTagName() !== null) { return sprintf('PHPDoc tag @template %s default references %s.', $this->getTemplateTagName(), $part); } return sprintf('PHPDoc tag @template default references %s.', $part); } } public function createIdentifier(string $secondPart): string { if ($this->value === self::CLASS_IMPLEMENTS) { return sprintf('class.implements%s', ucfirst($secondPart)); } if ($this->value === self::ENUM_IMPLEMENTS) { return sprintf('enum.implements%s', ucfirst($secondPart)); } if ($this->value === self::INTERFACE_EXTENDS) { return sprintf('interface.extends%s', ucfirst($secondPart)); } if ($this->value === self::CLASS_EXTENDS) { return sprintf('class.extends%s', ucfirst($secondPart)); } if ($this->value === self::PHPDOC_TAG_TEMPLATE_BOUND) { return sprintf('generics.%sBound', $secondPart); } if ($this->value === self::PHPDOC_TAG_TEMPLATE_DEFAULT) { return sprintf('generics.%sDefault', $secondPart); } return sprintf('%s.%s', $this->value, $secondPart); } } */ #[RegisteredRule(2)] 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()]; } } */ #[RegisteredRule(0)] 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; } } */ #[RegisteredRule(0)] final class ClassAttributesRule implements Rule { private AttributesCheck $attributesCheck; public function __construct(AttributesCheck $attributesCheck) { $this->attributesCheck = $attributesCheck; } public function getNodeType(): string { return InClassNode::class; } public function processNode(Node $node, Scope $scope): array { $classReflection = $node->getClassReflection(); if (count($classReflection->getNativeReflection()->getAttributes('Deprecated')) > 0) { $typeName = strtolower($classReflection->getClassTypeDescription()); return [RuleErrorBuilder::message(sprintf('Attribute class Deprecated cannot be used with %s %s.', $typeName, $classReflection->getDisplayName()))->identifier(sprintf('%s.deprecatedAttribute', $typeName))->nonIgnorable()->build()]; } $classLikeNode = $node->getOriginalNode(); $errors = $this->attributesCheck->check($scope, $classLikeNode->attrGroups, Attribute::TARGET_CLASS, 'class'); if ($classReflection->isReadOnly() || $classReflection->isEnum() || $classReflection->isInterface()) { $typeName = 'readonly class'; $identifier = 'class.allowDynamicPropertiesReadonly'; if ($classReflection->isEnum()) { $typeName = 'enum'; $identifier = 'enum.allowDynamicProperties'; } if ($classReflection->isInterface()) { $typeName = 'interface'; $identifier = 'interface.allowDynamicProperties'; } if (count($classReflection->getNativeReflection()->getAttributes('AllowDynamicProperties')) > 0) { $errors[] = RuleErrorBuilder::message(sprintf('Attribute class AllowDynamicProperties cannot be used with %s.', $typeName))->identifier($identifier)->nonIgnorable()->build(); } } return $errors; } } */ #[RegisteredRule(0)] final class ClassConstantAttributesRule implements Rule { private AttributesCheck $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'); } } */ #[RegisteredRule(0)] final class ClassConstantRule implements Rule { private ReflectionProvider $reflectionProvider; private RuleLevelHelper $ruleLevelHelper; private ClassNameCheck $classCheck; private PhpVersion $phpVersion; private bool $checkNonStringableDynamicAccess; public function __construct( ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper, ClassNameCheck $classCheck, PhpVersion $phpVersion, #[AutowiredParameter('%featureToggles.checkNonStringableDynamicAccess%')] bool $checkNonStringableDynamicAccess ) { $this->reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; $this->classCheck = $classCheck; $this->phpVersion = $phpVersion; $this->checkNonStringableDynamicAccess = $checkNonStringableDynamicAccess; } public function getNodeType(): string { return ClassConstFetch::class; } public function processNode(Node $node, Scope $scope): array { $errors = []; if ($node->name instanceof Node\Identifier) { $constantNameScopes = [$node->name->name => $scope]; } else { $nameType = $scope->getType($node->name); $constantNameScopes = []; foreach ($nameType->getConstantStrings() as $constantString) { $name = $constantString->getValue(); $constantNameScopes[$name] = $scope->filterByTruthyValue(new Identical($node->name, new String_($name))); } if ($this->checkNonStringableDynamicAccess) { $nameTypeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $node->name, '', static fn(Type $type) => $type->isString()->yes()); $nameType = $nameTypeResult->getType(); if (!$nameType instanceof ErrorType && !$nameType->isString()->yes()) { $className = $node->class instanceof Name ? $scope->resolveName($node->class) : $scope->getType($node->class)->describe(VerbosityLevel::typeOnly()); $errors[] = RuleErrorBuilder::message(sprintf('Class constant name for %s must be a string, but %s was given.', $className, $nameType->describe(VerbosityLevel::precise())))->identifier('classConstant.nameNotString')->build(); } } } foreach ($constantNameScopes as $constantName => $constantScope) { $errors = array_merge($errors, $this->processSingleClassConstFetch($constantScope, $node, (string) $constantName)); } return $errors; } /** * @return list */ private function processSingleClassConstFetch(Scope $scope, ClassConstFetch $node, string $constantName): array { $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()]; } $classType = $scope->resolveTypeByName($class); if (strtolower($constantName) !== 'class') { foreach ($classType->getObjectClassReflections() as $classTypeReflection) { if (!$classTypeReflection->isTrait()) { continue; } return [RuleErrorBuilder::message(sprintf('Cannot access constant %s on trait %s.', $constantName, $classTypeReflection->getDisplayName()))->identifier('classConstant.onTrait')->build()]; } } $locationData = []; $locationClassReflection = $this->reflectionProvider->getClass($className); if ($locationClassReflection->hasConstant($constantName)) { $locationData['classConstant'] = $locationClassReflection->getConstant($constantName); } $messages = $this->classCheck->checkClassNames($scope, [new ClassNameNodePair($className, $class)], ClassNameUsageLocation::from(ClassNameUsageLocation::CLASS_CONSTANT_ACCESS, $locationData)); } 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 fn(Type $type): bool => $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; } } hasConsistentConstructor()) { if ($classReflection->hasConstructor()) { return $classReflection->getConstructor(); } return new DummyConstructorReflection($classReflection); } $parent = $classReflection->getParentClass(); if ($parent === null) { return null; } return $this->findConsistentConstructor($parent); } } */ #[ValidatesStubFiles] final class DuplicateClassDeclarationRule implements Rule { private Reflector $reflector; private RelativePathHelper $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 fn(ReflectionClass $class) => $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(fn(ReflectionClass $class) => sprintf('- %s:%d', $this->relativePathHelper->getRelativePath($class->getFileName() ?? 'unknown'), $class->getStartLine()), $filteredClasses))))->identifier(sprintf('%s.duplicate', $identifierType))->build()]; } } */ public function checkClassLike(ClassLike $classLike, string $displayName, string $identifierType): array { $errors = []; $declaredClassConstantsOrEnumCases = []; foreach ($classLike->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.', $displayName, $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.', $displayName, $classConstNode->name->name))->identifier(sprintf('%s.duplicateConstant', $identifierType))->line($classConstNode->getStartLine())->nonIgnorable()->build(); } else { $declaredClassConstantsOrEnumCases[$classConstNode->name->name] = \true; } } } } $declaredProperties = []; foreach ($classLike->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.', $displayName, $property->name->name))->identifier(sprintf('%s.duplicateProperty', $identifierType))->line($property->getStartLine())->nonIgnorable()->build(); } else { $declaredProperties[$property->name->name] = \true; } } } $declaredFunctions = []; foreach ($classLike->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.', $displayName, $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().', $displayName, $method->name->name))->identifier(sprintf('%s.duplicateMethod', $identifierType))->line($method->getStartLine())->nonIgnorable()->build(); } else { $declaredFunctions[strtolower($method->name->name)] = \true; } } return $errors; } } */ #[RegisteredRule(0)] #[ValidatesStubFiles] final class DuplicateDeclarationRule implements Rule { private \PHPStan\Rules\Classes\DuplicateDeclarationHelper $helper; public function __construct(\PHPStan\Rules\Classes\DuplicateDeclarationHelper $helper) { $this->helper = $helper; } public function getNodeType(): string { return InClassNode::class; } public function processNode(Node $node, Scope $scope): array { $classReflection = $node->getClassReflection(); return $this->helper->checkClassLike($node->getOriginalNode(), $classReflection->getDisplayName(), strtolower($classReflection->getClassTypeDescription())); } } */ #[RegisteredRule(0)] final class DuplicateTraitDeclarationRule implements Rule { private \PHPStan\Rules\Classes\DuplicateDeclarationHelper $helper; public function __construct(\PHPStan\Rules\Classes\DuplicateDeclarationHelper $helper) { $this->helper = $helper; } public function getNodeType(): string { return InTraitNode::class; } public function processNode(Node $node, Scope $scope): array { return $this->helper->checkClassLike($node->getOriginalNode(), $node->getTraitReflection()->getDisplayName(), 'trait'); } } */ #[RegisteredRule(0)] final class EnumSanityRule implements Rule { private InitializerExprTypeResolver $initializerExprTypeResolver; private const ALLOWED_MAGIC_METHODS = ['__call' => \true, '__callstatic' => \true, '__invoke' => \true]; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; } 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 ($enumNode->scalarType === null && $stmt->expr !== null) { $errors[] = RuleErrorBuilder::message(sprintf('Enum %s is not backed, but case %s has value %s.', $classReflection->getDisplayName(), $caseName, $this->initializerExprTypeResolver->getType($stmt->expr, InitializerExprContext::fromScope($scope))->describe(VerbosityLevel::value())))->identifier('enum.caseWithValue')->line($stmt->getStartLine())->nonIgnorable()->build(); } 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()) { $constantValues = $exprType->getConstantScalarValues(); if (count($constantValues) === 1) { $caseValue = $constantValues[0]; if (!is_string($caseValue) && !is_int($caseValue)) { throw new ShouldNotHappenException(); } if (!isset($enumCases[$caseValue])) { $enumCases[$caseValue] = []; } $enumCases[$caseValue][] = $caseName; } 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; } } */ #[RegisteredRule(0)] #[ValidatesStubFiles] final class ExistingClassInClassExtendsRule implements Rule { private ClassNameCheck $classCheck; private ReflectionProvider $reflectionProvider; private bool $discoveringSymbolsTip; public function __construct( ClassNameCheck $classCheck, ReflectionProvider $reflectionProvider, #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $this->classCheck = $classCheck; $this->reflectionProvider = $reflectionProvider; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } 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; $currentClassName = null; if (isset($node->namespacedName)) { $currentClassName = (string) $node->namespacedName; } $messages = $this->classCheck->checkClassNames($scope, [new ClassNameNodePair($extendedClassName, $node->extends)], ClassNameUsageLocation::from(ClassNameUsageLocation::CLASS_EXTENDS, ['currentClassName' => $currentClassName])); if (!$this->reflectionProvider->hasClass($extendedClassName)) { if (!$scope->isInClassExists($extendedClassName)) { $errorBuilder = RuleErrorBuilder::message(sprintf('%s extends unknown class %s.', $currentClassName !== null ? sprintf('Class %s', $currentClassName) : 'Anonymous class', $extendedClassName))->identifier('class.notFound')->nonIgnorable(); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $messages[] = $errorBuilder->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; } } */ #[RegisteredRule(0)] final class ExistingClassInInstanceOfRule implements Rule { private ReflectionProvider $reflectionProvider; private ClassNameCheck $classCheck; private bool $checkClassCaseSensitivity; private bool $discoveringSymbolsTip; public function __construct( ReflectionProvider $reflectionProvider, ClassNameCheck $classCheck, #[AutowiredParameter] bool $checkClassCaseSensitivity, #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $this->reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } 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 []; } $errorBuilder = RuleErrorBuilder::message(sprintf('Class %s not found.', $name))->identifier('class.notFound')->line($class->getStartLine()); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } return [$errorBuilder->build()]; } $errors = array_merge($errors, $this->classCheck->checkClassNames($scope, [new ClassNameNodePair($name, $class)], ClassNameUsageLocation::from(ClassNameUsageLocation::INSTANCEOF), $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; } } */ #[RegisteredRule(0)] #[ValidatesStubFiles] final class ExistingClassInTraitUseRule implements Rule { private ClassNameCheck $classCheck; private ReflectionProvider $reflectionProvider; private bool $discoveringSymbolsTip; public function __construct( ClassNameCheck $classCheck, ReflectionProvider $reflectionProvider, #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $this->classCheck = $classCheck; $this->reflectionProvider = $reflectionProvider; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } public function getNodeType(): string { return Node\Stmt\TraitUse::class; } public function processNode(Node $node, Scope $scope): array { if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } $classReflection = $scope->getClassReflection(); $messages = $this->classCheck->checkClassNames($scope, array_map(static fn(Node\Name $traitName): ClassNameNodePair => new ClassNameNodePair((string) $traitName, $traitName), $node->traits), ClassNameUsageLocation::from(ClassNameUsageLocation::TRAIT_USE, ['currentClassName' => $classReflection->isAnonymous() ? null : $classReflection->getName()])); 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)) { $errorBuilder = RuleErrorBuilder::message(sprintf('%s uses unknown trait %s.', $currentName, $traitName))->identifier('trait.notFound')->nonIgnorable(); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $messages[] = $errorBuilder->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; } } */ #[RegisteredRule(0)] #[ValidatesStubFiles] final class ExistingClassesInClassImplementsRule implements Rule { private ClassNameCheck $classCheck; private ReflectionProvider $reflectionProvider; private bool $discoveringSymbolsTip; public function __construct( ClassNameCheck $classCheck, ReflectionProvider $reflectionProvider, #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $this->classCheck = $classCheck; $this->reflectionProvider = $reflectionProvider; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } public function getNodeType(): string { return Node\Stmt\Class_::class; } public function processNode(Node $node, Scope $scope): array { $currentClassName = null; if (isset($node->namespacedName)) { $currentClassName = (string) $node->namespacedName; } $messages = $this->classCheck->checkClassNames($scope, array_map(static fn(Node\Name $interfaceName): ClassNameNodePair => new ClassNameNodePair((string) $interfaceName, $interfaceName), $node->implements), ClassNameUsageLocation::from(ClassNameUsageLocation::CLASS_IMPLEMENTS, ['currentClassName' => $currentClassName])); foreach ($node->implements as $implements) { $implementedClassName = (string) $implements; if (!$this->reflectionProvider->hasClass($implementedClassName)) { if (!$scope->isInClassExists($implementedClassName)) { $errorBuilder = RuleErrorBuilder::message(sprintf('%s implements unknown interface %s.', $currentClassName !== null ? sprintf('Class %s', $currentClassName) : 'Anonymous class', $implementedClassName))->identifier('interface.notFound')->nonIgnorable(); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $messages[] = $errorBuilder->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; } } */ #[RegisteredRule(0)] final class ExistingClassesInEnumImplementsRule implements Rule { private ClassNameCheck $classCheck; private ReflectionProvider $reflectionProvider; private bool $discoveringSymbolsTip; public function __construct( ClassNameCheck $classCheck, ReflectionProvider $reflectionProvider, #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $this->classCheck = $classCheck; $this->reflectionProvider = $reflectionProvider; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } public function getNodeType(): string { return Node\Stmt\Enum_::class; } public function processNode(Node $node, Scope $scope): array { $currentEnumName = (string) $node->namespacedName; $messages = $this->classCheck->checkClassNames($scope, array_map(static fn(Node\Name $interfaceName): ClassNameNodePair => new ClassNameNodePair((string) $interfaceName, $interfaceName), $node->implements), ClassNameUsageLocation::from(ClassNameUsageLocation::ENUM_IMPLEMENTS, ['currentClassName' => $currentEnumName])); foreach ($node->implements as $implements) { $implementedClassName = (string) $implements; if (!$this->reflectionProvider->hasClass($implementedClassName)) { if (!$scope->isInClassExists($implementedClassName)) { $errorBuilder = RuleErrorBuilder::message(sprintf('Enum %s implements unknown interface %s.', $currentEnumName, $implementedClassName))->identifier('interface.notFound')->nonIgnorable(); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $messages[] = $errorBuilder->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; } } */ #[RegisteredRule(0)] #[ValidatesStubFiles] final class ExistingClassesInInterfaceExtendsRule implements Rule { private ClassNameCheck $classCheck; private ReflectionProvider $reflectionProvider; private bool $discoveringSymbolsTip; public function __construct( ClassNameCheck $classCheck, ReflectionProvider $reflectionProvider, #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $this->classCheck = $classCheck; $this->reflectionProvider = $reflectionProvider; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } public function getNodeType(): string { return Node\Stmt\Interface_::class; } public function processNode(Node $node, Scope $scope): array { $currentInterfaceName = (string) $node->namespacedName; $messages = $this->classCheck->checkClassNames($scope, array_map(static fn(Node\Name $interfaceName): ClassNameNodePair => new ClassNameNodePair((string) $interfaceName, $interfaceName), $node->extends), ClassNameUsageLocation::from(ClassNameUsageLocation::INTERFACE_EXTENDS, ['currentClassName' => $currentInterfaceName])); foreach ($node->extends as $extends) { $extendedInterfaceName = (string) $extends; if (!$this->reflectionProvider->hasClass($extendedInterfaceName)) { if (!$scope->isInClassExists($extendedInterfaceName)) { $errorBuilder = RuleErrorBuilder::message(sprintf('Interface %s extends unknown interface %s.', $currentInterfaceName, $extendedInterfaceName))->identifier('interface.notFound')->nonIgnorable(); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $messages[] = $errorBuilder->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; } } */ #[RegisteredRule(4)] final class ImpossibleInstanceOfRule implements Rule { private RuleLevelHelper $ruleLevelHelper; private bool $treatPhpDocTypesAsCertain; private bool $reportAlwaysTrueInLastCondition; private bool $treatPhpDocTypesAsCertainTip; public function __construct( RuleLevelHelper $ruleLevelHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter] bool $reportAlwaysTrueInLastCondition, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->ruleLevelHelper = $ruleLevelHelper; $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 { 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 = new UnionType([new StringType(), new ObjectWithoutClassType()]); $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $node->class, '', static fn(Type $type): bool => !$allowed->isSuperTypeOf($type)->yes()); if (!$typeResult->getType() instanceof ErrorType && !$allowed->isSuperTypeOf($typeResult->getType())->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()]; } } $instanceofType = $this->treatPhpDocTypesAsCertain ? $scope->getType($node) : $scope->getNativeType($node); if (!$instanceofType 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 (!$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()]; } $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()]; } } */ #[RegisteredRule(0)] 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()]; } } */ #[RegisteredRule(0)] final class InstantiationRule implements Rule { private Container $container; private ReflectionProvider $reflectionProvider; private FunctionCallParametersCheck $check; private ClassNameCheck $classCheck; private \PHPStan\Rules\Classes\ConsistentConstructorHelper $consistentConstructorHelper; private bool $discoveringSymbolsTip; /** @var RestrictedMethodUsageExtension[] $extensions */ private ?array $extensions = null; public function __construct( Container $container, ReflectionProvider $reflectionProvider, FunctionCallParametersCheck $check, ClassNameCheck $classCheck, \PHPStan\Rules\Classes\ConsistentConstructorHelper $consistentConstructorHelper, #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $this->container = $container; $this->reflectionProvider = $reflectionProvider; $this->check = $check; $this->classCheck = $classCheck; $this->consistentConstructorHelper = $consistentConstructorHelper; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } 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() && $this->consistentConstructorHelper->findConsistentConstructor($classReflection) === null) { 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 []; } $errorBuilder = RuleErrorBuilder::message(sprintf('Instantiated class %s not found.', $class))->identifier('class.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } return [$errorBuilder->build()]; } $messages = $this->classCheck->checkClassNames($scope, [new ClassNameNodePair($class, $node->class)], ClassNameUsageLocation::from(ClassNameUsageLocation::INSTANTIATION)); $classReflection = $this->reflectionProvider->getClass($class); } if ($classReflection->isTrait() && $isName) { return [RuleErrorBuilder::message(sprintf('Cannot instantiate trait %s.', $classReflection->getDisplayName()))->identifier('new.trait')->build()]; } 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(); } /** @var RestrictedMethodUsageExtension[] $extensions */ $extensions = $this->extensions ??= $this->container->getServicesByTag(RestrictedMethodUsageExtension::METHOD_EXTENSION_TAG); foreach ($extensions as $extension) { $restrictedUsage = $extension->isRestrictedMethodUsage($constructorReflection, $scope); if ($restrictedUsage === null) { continue; } if ($classReflection->getName() !== $constructorReflection->getDeclaringClass()->getName()) { $rewrittenConstructorReflection = new RewrittenDeclaringClassMethodReflection($classReflection, $constructorReflection); $rewrittenRestrictedUsage = $extension->isRestrictedMethodUsage($rewrittenConstructorReflection, $scope); if ($rewrittenRestrictedUsage === null) { continue; } } $messages[] = RuleErrorBuilder::message($restrictedUsage->errorMessage)->identifier($restrictedUsage->identifier)->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, 'new', $constructorReflection->acceptsNamedArguments(), '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.', '%s of class ' . $classDisplayName . ' constructor expects %s, %s given.', '', // constructor does not have a return type ' %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.', '%s of class ' . $classDisplayName . ' constructor contains unresolvable type.', 'Class ' . $classDisplayName . ' constructor invoked with %s, but it\'s not allowed because of @no-named-arguments.' )); } /** * @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 fn(string $className) => [$className, \true], $classNames); } $type = $scope->getType($node->class); if ($type->isClassString()->yes()) { $concretes = array_filter($type->getClassStringObjectType()->getObjectClassReflections(), static fn(ClassReflection $classReflection): bool => !$classReflection->isAbstract() && !$classReflection->isInterface()); if (count($concretes) > 0) { return array_map(static fn(ClassReflection $classReflection): array => [$classReflection->getName(), \true], $concretes); } } return array_merge(array_map(static fn(ConstantStringType $type): array => [$type->getValue(), \true], $type->getConstantStrings()), array_map(static fn(string $name): array => [$name, \false], $type->getObjectClassNames())); } } */ #[RegisteredRule(0)] final class InvalidPromotedPropertiesRule implements Rule { private PhpVersion $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) { $hasPromotedProperties = \true; break; } if ($param->hooks === []) { 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->isFinal() && !$this->phpVersion->supportsFinalPromotedProperties()) { $errors[] = RuleErrorBuilder::message('Final promoted properties are supported only on PHP 8.5 and later.')->identifier('property.invalidPromoted')->nonIgnorable()->line($param->getStartLine())->build(); } 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; } } */ private array $globalTypeAliases; private ReflectionProvider $reflectionProvider; private TypeNodeResolver $typeNodeResolver; private MissingTypehintCheck $missingTypehintCheck; private ClassNameCheck $classCheck; private UnresolvableTypeHelper $unresolvableTypeHelper; private GenericObjectTypeCheck $genericObjectTypeCheck; private bool $checkMissingTypehints; private bool $checkClassCaseSensitivity; private bool $discoveringSymbolsTip; /** * @param array $globalTypeAliases */ public function __construct( #[AutowiredParameter('%typeAliases%')] array $globalTypeAliases, ReflectionProvider $reflectionProvider, TypeNodeResolver $typeNodeResolver, MissingTypehintCheck $missingTypehintCheck, ClassNameCheck $classCheck, UnresolvableTypeHelper $unresolvableTypeHelper, GenericObjectTypeCheck $genericObjectTypeCheck, #[AutowiredParameter] bool $checkMissingTypehints, #[AutowiredParameter] bool $checkClassCaseSensitivity, #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $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->discoveringSymbolsTip = $discoveringSymbolsTip; } /** * @return list */ public function check(Scope $scope, ClassReflection $reflection, ClassLike $node): array { $errors = []; foreach ($this->checkInTraitDefinitionContext($reflection) as $error) { $errors[] = $error; } foreach ($this->checkInTraitUseContext($scope, $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->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(Scope $scope, 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)) { $errorBuilder = RuleErrorBuilder::message(sprintf('Type alias %s contains unknown class %s.', $aliasName, $class))->identifier('class.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $errors[] = $errorBuilder->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($scope, [new ClassNameNodePair($class, $node)], ClassNameUsageLocation::from(ClassNameUsageLocation::TYPE_ALIAS, ['typeAliasName' => $aliasName]), $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; } } */ #[RegisteredRule(0)] #[ValidatesStubFiles] final class LocalTypeAliasesRule implements Rule { private \PHPStan\Rules\Classes\LocalTypeAliasesCheck $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($scope, $node->getClassReflection(), $node->getOriginalNode()); } } */ #[RegisteredRule(0)] #[ValidatesStubFiles] final class LocalTypeTraitAliasesRule implements Rule { private \PHPStan\Rules\Classes\LocalTypeAliasesCheck $check; private ReflectionProvider $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())); } } */ #[RegisteredRule(0)] #[ValidatesStubFiles] final class LocalTypeTraitUseAliasesRule implements Rule { private \PHPStan\Rules\Classes\LocalTypeAliasesCheck $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($scope, $node->getTraitReflection(), $node->getImplementingClassReflection(), $node->getOriginalNode()); } } reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->missingTypehintCheck = $missingTypehintCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->checkMissingTypehints = $checkMissingTypehints; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } /** * @return list */ public function check(Scope $scope, 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($scope, $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($scope, $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($scope, $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(Scope $scope, 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($scope, $classReflection, $methodName, $parameterDescription, $parameterTag->getType(), $node) as $error) { $errors[] = $error; } if ($parameterTag->getDefaultValue() === null) { continue; } $defaultValueDescription = sprintf('%s default value', $parameterDescription); foreach ($this->checkMethodTypeInTraitUseContext($scope, $classReflection, $methodName, $defaultValueDescription, $parameterTag->getDefaultValue(), $node) as $error) { $errors[] = $error; } } $returnTypeDescription = 'return type'; foreach ($this->checkMethodTypeInTraitUseContext($scope, $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(Scope $scope, ClassReflection $classReflection, string $methodName, string $description, Type $type, ClassLike $node): array { $errors = []; foreach ($type->getReferencedClasses() as $class) { if (!$this->reflectionProvider->hasClass($class)) { $errorBuilder = RuleErrorBuilder::message(sprintf('PHPDoc tag @method for method %s::%s() %s contains unknown class %s.', $classReflection->getDisplayName(), $methodName, $description, $class))->identifier('class.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $errors[] = $errorBuilder->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($scope, [new ClassNameNodePair($class, $node)], ClassNameUsageLocation::from(ClassNameUsageLocation::PHPDOC_TAG_METHOD, ['methodTagName' => $methodName]), $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))); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class MethodTagRule implements Rule { private \PHPStan\Rules\Classes\MethodTagCheck $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($scope, $node->getClassReflection(), $node->getOriginalNode()); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class MethodTagTraitRule implements Rule { private \PHPStan\Rules\Classes\MethodTagCheck $check; private ReflectionProvider $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())); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class MethodTagTraitUseRule implements Rule { private \PHPStan\Rules\Classes\MethodTagCheck $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($scope, $node->getTraitReflection(), $node->getImplementingClassReflection(), $node->getOriginalNode()); } } reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->missingTypehintCheck = $missingTypehintCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->checkMissingTypehints = $checkMissingTypehints; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } /** * @return list */ public function check(Scope $scope, ClassReflection $classReflection, ClassLike $node): array { $errors = []; foreach ($this->checkInTraitDefinitionContext($classReflection) as $error) { $errors[] = $error; } foreach ($this->checkInTraitUseContext($scope, $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->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(Scope $scope, 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)) { $errorBuilder = RuleErrorBuilder::message(sprintf('PHPDoc tag @mixin contains unknown class %s.', $class))->identifier('class.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $errors[] = $errorBuilder->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($scope, [new ClassNameNodePair($class, $node)], ClassNameUsageLocation::from(ClassNameUsageLocation::PHPDOC_TAG_MIXIN), $this->checkClassCaseSensitivity)); } } } return $errors; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class MixinRule implements Rule { private \PHPStan\Rules\Classes\MixinCheck $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($scope, $node->getClassReflection(), $node->getOriginalNode()); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class MixinTraitRule implements Rule { private \PHPStan\Rules\Classes\MixinCheck $check; private ReflectionProvider $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())); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class MixinTraitUseRule implements Rule { private \PHPStan\Rules\Classes\MixinCheck $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($scope, $node->getTraitReflection(), $node->getImplementingClassReflection(), $node->getOriginalNode()); } } */ final class NewStaticInAbstractClassStaticMethodRule 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->isAbstract()) { return []; } $inMethod = $scope->getFunction(); if (!$inMethod instanceof PhpMethodFromParserNodeReflection) { return []; } if (!$inMethod->isStatic()) { return []; } return [RuleErrorBuilder::message(sprintf('Unsafe usage of new static() in abstract class %s in static method %s().', $classReflection->getDisplayName(), $inMethod->getName()))->identifier('new.staticInAbstractClassStaticMethod')->tip(sprintf('Direct call to %s::%s() would crash because an abstract class cannot be instantiated.', $classReflection->getName(), $inMethod->getName()))->build()]; } } */ #[RegisteredRule(0)] final class NewStaticRule implements Rule { private PhpVersion $phpVersion; private \PHPStan\Rules\Classes\ConsistentConstructorHelper $consistentConstructorHelper; public function __construct(PhpVersion $phpVersion, \PHPStan\Rules\Classes\ConsistentConstructorHelper $consistentConstructorHelper) { $this->phpVersion = $phpVersion; $this->consistentConstructorHelper = $consistentConstructorHelper; } 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()]; $consistentConstructor = $this->consistentConstructorHelper->findConsistentConstructor($classReflection); if ($consistentConstructor !== null) { return []; } if (!$classReflection->hasConstructor()) { return $messages; } $constructor = $classReflection->getConstructor(); if ($constructor->getPrototype()->getDeclaringClass()->isInterface()) { return []; } foreach ($classReflection->getImmediateInterfaces() as $interface) { if ($interface->hasConstructor()) { return []; } } if ($constructor->isFinal()->yes()) { return []; } if ($constructor instanceof PhpMethodReflection) { $prototype = $constructor->getPrototype(); if ($prototype->isAbstract()) { return []; } } if ($this->phpVersion->supportsAbstractTraitMethods() && $scope->isInTrait()) { $traitReflection = $scope->getTraitReflection(); if ($traitReflection->hasConstructor()) { $isAbstract = $traitReflection->getConstructor()->isAbstract(); if ($isAbstract === \true || $isAbstract instanceof TrinaryLogic && $isAbstract->yes()) { return []; } } } return $messages; } } */ #[RegisteredRule(0)] 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 []; } } reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->missingTypehintCheck = $missingTypehintCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->checkMissingTypehints = $checkMissingTypehints; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } /** * @return list */ public function check(Scope $scope, 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($scope, $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(Scope $scope, 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($scope, $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(Scope $scope, ClassReflection $classReflection, string $propertyName, string $tagName, Type $type, ClassLike $node): array { $errors = []; foreach ($type->getReferencedClasses() as $class) { if (!$this->reflectionProvider->hasClass($class)) { $errorBuilder = RuleErrorBuilder::message(sprintf('PHPDoc tag %s for property %s::$%s contains unknown class %s.', $tagName, $classReflection->getDisplayName(), $propertyName, $class))->identifier('class.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $errors[] = $errorBuilder->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($scope, [new ClassNameNodePair($class, $node)], ClassNameUsageLocation::from(ClassNameUsageLocation::PHPDOC_TAG_PROPERTY, ['propertyTagName' => $propertyName]), $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))); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class PropertyTagRule implements Rule { private \PHPStan\Rules\Classes\PropertyTagCheck $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($scope, $node->getClassReflection(), $node->getOriginalNode()); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class PropertyTagTraitRule implements Rule { private \PHPStan\Rules\Classes\PropertyTagCheck $check; private ReflectionProvider $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())); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class PropertyTagTraitUseRule implements Rule { private \PHPStan\Rules\Classes\PropertyTagCheck $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($scope, $node->getTraitReflection(), $node->getImplementingClassReflection(), $node->getOriginalNode()); } } */ #[RegisteredRule(0)] final class ReadOnlyClassRule implements Rule { private PhpVersion $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()]; } } */ #[RegisteredRule(2)] 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(); foreach ($type->getObjectClassNames() as $className) { if ($classReflection->is($className)) { 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(); break; } } } foreach ($classReflection->getTraits(\true) as $trait) { $extendsTags = $trait->getRequireExtendsTags(); foreach ($extendsTags as $extendsTag) { $type = $extendsTag->getType(); foreach ($type->getObjectClassNames() as $className) { if ($classReflection->is($className)) { 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(); break; } } } return $errors; } } */ #[RegisteredRule(2)] 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; } } */ #[RegisteredRule(0)] 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 []; } } */ #[RegisteredRule(1)] final class UnusedConstructorParametersRule implements Rule { private UnusedFunctionParametersCheck $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 (!$method->isConstructor() || $originalNode->stmts === null) { return []; } if (count($originalNode->params) === 0) { return []; } if ($node->getClassReflection()->isAttributeClass()) { return []; } foreach ($node->getClassReflection()->getInterfaces() as $interface) { if ($interface->hasConstructor()) { 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): Variable { if (!$parameter->var instanceof Variable) { throw new ShouldNotHappenException(); } return $parameter->var; }, array_values(array_filter($originalNode->params, static fn(Param $parameter): bool => $parameter->flags === 0))), $originalNode->stmts, $message, 'constructor.unusedParameter'); } } */ #[RegisteredRule(4)] final class BooleanAndConstantConditionRule implements Rule { private \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper; private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; private bool $reportAlwaysTrueInLastCondition; private bool $treatPhpDocTypesAsCertainTip; public function __construct( \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter] bool $reportAlwaysTrueInLastCondition, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->helper = $helper; $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $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 = $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 $this->possiblyImpureTipHelper->addTip($scope, $originalNode->left, $ruleErrorBuilder); } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $originalNode->left); if ($booleanNativeType instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($scope, $originalNode->left, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $originalNode->left, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $originalNode->left, $ruleErrorBuilder); }; $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 $this->possiblyImpureTipHelper->addTip($rightScope, $originalNode->right, $ruleErrorBuilder); } $booleanNativeType = $this->helper->getNativeBooleanType($rightScope, $originalNode->right); if ($booleanNativeType instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($rightScope, $originalNode->right, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($rightScope, $originalNode->right, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($rightScope, $originalNode->right, $ruleErrorBuilder); }; $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 $this->possiblyImpureTipHelper->addTip($scope, $originalNode, $ruleErrorBuilder); } $booleanNativeType = $scope->getNativeType($originalNode); if ($booleanNativeType instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($scope, $originalNode, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $originalNode, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $originalNode, $ruleErrorBuilder); }; $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; } } */ #[RegisteredRule(4)] final class BooleanNotConstantConditionRule implements Rule { private \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper; private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; private bool $reportAlwaysTrueInLastCondition; private bool $treatPhpDocTypesAsCertainTip; public function __construct( \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter] bool $reportAlwaysTrueInLastCondition, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->helper = $helper; $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $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 $this->possiblyImpureTipHelper->addTip($scope, $node->expr, $ruleErrorBuilder); } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $node->expr); if ($booleanNativeType instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($scope, $node->expr, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $node->expr, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $node->expr, $ruleErrorBuilder); }; $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 []; } } */ #[RegisteredRule(4)] final class BooleanOrConstantConditionRule implements Rule { private \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper; private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; private bool $reportAlwaysTrueInLastCondition; private bool $treatPhpDocTypesAsCertainTip; public function __construct( \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter] bool $reportAlwaysTrueInLastCondition, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->helper = $helper; $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $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 = $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 $this->possiblyImpureTipHelper->addTip($scope, $originalNode->left, $ruleErrorBuilder); } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $originalNode->left); if ($booleanNativeType instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($scope, $originalNode->left, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $originalNode->left, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $originalNode->left, $ruleErrorBuilder); }; $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 $this->possiblyImpureTipHelper->addTip($rightScope, $originalNode->right, $ruleErrorBuilder); } $booleanNativeType = $this->helper->getNativeBooleanType($rightScope, $originalNode->right); if ($booleanNativeType instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($rightScope, $originalNode->right, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($rightScope, $originalNode->right, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($rightScope, $originalNode->right, $ruleErrorBuilder); }; $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 $this->possiblyImpureTipHelper->addTip($scope, $originalNode, $ruleErrorBuilder); } $booleanNativeType = $scope->getNativeType($originalNode); if ($booleanNativeType instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($scope, $originalNode, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $originalNode, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $originalNode, $ruleErrorBuilder); }; $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; } } impossibleCheckTypeHelper = $impossibleCheckTypeHelper; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; } private function shouldSkip(Scope $scope, Expr $expr): bool { if ($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) && !$expr->isFirstClassCallable()) { $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(); } } */ #[RegisteredRule(4)] final class ConstantLooseComparisonRule implements Rule { private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; private bool $reportAlwaysTrueInLastCondition; private bool $treatPhpDocTypesAsCertainTip; public function __construct( \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter] bool $reportAlwaysTrueInLastCondition, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $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->isTrue()->yes() && !$nodeType->isFalse()->yes()) { return []; } $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use ($scope, $node): RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } $instanceofTypeWithoutPhpDocs = $scope->getNativeType($node); if ($instanceofTypeWithoutPhpDocs->isTrue()->yes() || $instanceofTypeWithoutPhpDocs->isFalse()->yes()) { return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); }; if ($nodeType->isFalse()->yes()) { 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()]; } $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()]; } } */ #[RegisteredRule(4)] final class DoWhileLoopConstantConditionRule implements Rule { private \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper; private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; private bool $treatPhpDocTypesAsCertainTip; public function __construct( \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->helper = $helper; $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $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()) { if ($node->hasYield()) { return []; } foreach ($node->getExitPoints() as $exitPoint) { $statement = $exitPoint->getStatement(); if (!$statement instanceof Continue_) { return []; } if (!$statement->num instanceof Int_) { continue; } if ($statement->num->value > 1) { return []; } } } else { foreach ($node->getExitPoints() as $exitPoint) { $statement = $exitPoint->getStatement(); if ($statement instanceof Break_) { return []; } } } $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use ($scope, $node): RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $this->possiblyImpureTipHelper->addTip($scope, $node->getCond(), $ruleErrorBuilder); } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $node->getCond()); if ($booleanNativeType instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($scope, $node->getCond(), $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $node->getCond(), $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $node->getCond(), $ruleErrorBuilder); }; 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 []; } } */ #[RegisteredRule(4)] final class ElseIfConstantConditionRule implements Rule { private \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper; private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; private bool $reportAlwaysTrueInLastCondition; private bool $treatPhpDocTypesAsCertainTip; public function __construct( \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter] bool $reportAlwaysTrueInLastCondition, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->helper = $helper; $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $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 $this->possiblyImpureTipHelper->addTip($scope, $node->cond, $ruleErrorBuilder); } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $node->cond); if ($booleanNativeType instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($scope, $node->cond, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $node->cond, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $node->cond, $ruleErrorBuilder); }; $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 []; } } */ #[RegisteredRule(4)] final class IfConstantConditionRule implements Rule { private \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper; private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; private bool $treatPhpDocTypesAsCertainTip; public function __construct( \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->helper = $helper; $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $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 $this->possiblyImpureTipHelper->addTip($scope, $node->cond, $ruleErrorBuilder); } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $node->cond); if ($booleanNativeType instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($scope, $node->cond, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $node->cond, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $node->cond, $ruleErrorBuilder); }; 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 []; } } */ #[RegisteredRule(4)] final class ImpossibleCheckTypeFunctionCallRule implements Rule { private \PHPStan\Rules\Comparison\ImpossibleCheckTypeHelper $impossibleCheckTypeHelper; private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; private bool $reportAlwaysTrueInLastCondition; private bool $treatPhpDocTypesAsCertainTip; public function __construct( \PHPStan\Rules\Comparison\ImpossibleCheckTypeHelper $impossibleCheckTypeHelper, \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter] bool $reportAlwaysTrueInLastCondition, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->impossibleCheckTypeHelper = $impossibleCheckTypeHelper; $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $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 $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } $isAlways = $this->impossibleCheckTypeHelper->doNotTreatPhpDocTypesAsCertain()->findSpecifiedType($scope, $node); if ($isAlways !== null) { return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); }; 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()]; } $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()]; } } reflectionProvider = $reflectionProvider; $this->typeSpecifier = $typeSpecifier; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; } public function findSpecifiedType(Scope $scope, Expr $node): ?bool { if ($node instanceof FuncCall) { if ($node->isFirstClassCallable()) { return null; } $args = $node->getArgs(); $argsCount = count($args); if ($node->name instanceof Node\Name) { $functionName = strtolower((string) $node->name); if ($functionName === 'assert' && $argsCount >= 1) { $arg = $args[0]->value; $assertValue = ($this->treatPhpDocTypesAsCertain ? $scope->getType($arg) : $scope->getNativeType($arg))->toBoolean(); $assertValueIsTrue = $assertValue->isTrue()->yes(); if (!$assertValueIsTrue && !$assertValue->isFalse()->yes()) { return null; } return $assertValueIsTrue; } 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 = $args[1]->value; $haystackType = $this->treatPhpDocTypesAsCertain ? $scope->getType($haystackArg) : $scope->getNativeType($haystackArg); if ($haystackType instanceof MixedType) { return null; } if (!$haystackType->isArray()->yes()) { return null; } $needleArg = $args[0]->value; $needleType = $this->treatPhpDocTypesAsCertain ? $scope->getType($needleArg) : $scope->getNativeType($needleArg); $isStrictComparison = \false; if ($argsCount >= 3) { $strictNodeType = $scope->getType($args[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 (!$isNeedleSupertype->no()) { // Array might be empty, so in_array can 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; } $haystackArrayValueConstantScalarTypes = $haystackArrayValueType->getConstantScalarTypes(); if (count($haystackArrayValueConstantScalarTypes) > 1) { continue; } foreach ($haystackArrayValueConstantScalarTypes 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 = $args[0]->value; $objectType = $this->treatPhpDocTypesAsCertain ? $scope->getType($objectArg) : $scope->getNativeType($objectArg); if ($objectType instanceof ConstantStringType && !$this->reflectionProvider->hasClass($objectType->getValue())) { return \false; } $methodArg = $args[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; } } } } } } if (!$scope instanceof MutatingScope) { throw new ShouldNotHappenException(); } $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 = []; $assignedInCallVars = []; if ($node instanceof Expr\CallLike) { foreach ($node->getArgs() as $arg) { $expr = $arg->value; while ($expr instanceof Expr\Assign) { $expr = $expr->expr; } $assignedExpr = $expr; $expr = $arg->value; while ($expr instanceof Expr\Assign) { $assignedInCallVars[] = new Expr\Assign($expr->var, $assignedExpr, $expr->getAttributes()); $expr = $expr->expr; } } } 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]; foreach ($assignedInCallVars as $assignedInCallVar) { if ($sureType[0] !== $assignedInCallVar->var) { continue; } $argumentType = $scope->getType($assignedInCallVar->expr); } $results[] = $resultType->isSuperTypeOf($argumentType)->result; } 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()->result; } 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(fn(Arg $arg): string => ($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, \false); } private function determineContext(Scope $scope, Expr $node): TypeSpecifierContext { 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 = $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 = $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 = $parametersAcceptor->getReturnType(); return $returnType->isVoid()->yes() ? TypeSpecifierContext::createNull() : TypeSpecifierContext::createTruthy(); } } return TypeSpecifierContext::createTruthy(); } } */ #[RegisteredRule(4)] final class ImpossibleCheckTypeMethodCallRule implements Rule { private \PHPStan\Rules\Comparison\ImpossibleCheckTypeHelper $impossibleCheckTypeHelper; private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; private bool $reportAlwaysTrueInLastCondition; private bool $treatPhpDocTypesAsCertainTip; public function __construct( \PHPStan\Rules\Comparison\ImpossibleCheckTypeHelper $impossibleCheckTypeHelper, \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter] bool $reportAlwaysTrueInLastCondition, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->impossibleCheckTypeHelper = $impossibleCheckTypeHelper; $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $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 $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } $isAlways = $this->impossibleCheckTypeHelper->doNotTreatPhpDocTypesAsCertain()->findSpecifiedType($scope, $node); if ($isAlways !== null) { return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); }; 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()]; } $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()]; } 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; } } */ #[RegisteredRule(4)] final class ImpossibleCheckTypeStaticMethodCallRule implements Rule { private \PHPStan\Rules\Comparison\ImpossibleCheckTypeHelper $impossibleCheckTypeHelper; private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; private bool $reportAlwaysTrueInLastCondition; private bool $treatPhpDocTypesAsCertainTip; public function __construct( \PHPStan\Rules\Comparison\ImpossibleCheckTypeHelper $impossibleCheckTypeHelper, \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter] bool $reportAlwaysTrueInLastCondition, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->impossibleCheckTypeHelper = $impossibleCheckTypeHelper; $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $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 $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } $isAlways = $this->impossibleCheckTypeHelper->doNotTreatPhpDocTypesAsCertain()->findSpecifiedType($scope, $node); if ($isAlways !== null) { return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); }; 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()]; } $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()]; } /** * @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; } } */ #[RegisteredRule(4)] final class LogicalXorConstantConditionRule implements Rule { private \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper; private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; private bool $reportAlwaysTrueInLastCondition; private bool $treatPhpDocTypesAsCertainTip; public function __construct( \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter] bool $reportAlwaysTrueInLastCondition, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->helper = $helper; $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $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 $this->possiblyImpureTipHelper->addTip($scope, $node->left, $ruleErrorBuilder); } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $node->left); if ($booleanNativeType instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($scope, $node->left, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $node->left, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $node->left, $ruleErrorBuilder); }; $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 $this->possiblyImpureTipHelper->addTip($scope, $node->right, $ruleErrorBuilder); } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $node->right); if ($booleanNativeType instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($scope, $node->right, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $node->right, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $node->right, $ruleErrorBuilder); }; $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; } } */ #[RegisteredRule(4)] final class MatchExpressionRule implements Rule { private \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $constantConditionRuleHelper; private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; public function __construct( \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $constantConditionRuleHelper, \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain ) { $this->constantConditionRuleHelper = $constantConditionRuleHelper; $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $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) { 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()) { $errorBuilder = 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'); $this->possiblyImpureTipHelper->addTip($armConditionScope, $armConditionExpr, $errorBuilder); $errors[] = $errorBuilder->build(); continue; } if ($i === $armsCount - 1) { continue; } $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())); $errorBuilder = RuleErrorBuilder::message($message)->line($armLine)->identifier('match.alwaysTrue')->tip('Remove remaining cases below this one and this error will disappear too.'); $this->possiblyImpureTipHelper->addTip($armConditionScope, $armConditionExpr, $errorBuilder); $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 fn(string $class) => 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(); } } */ #[RegisteredRule(4)] final class NumberComparisonOperatorsConstantConditionRule implements Rule { private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; private bool $treatPhpDocTypesAsCertainTip; public function __construct( \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $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 $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } $booleanNativeType = $scope->getNativeType($node); if ($booleanNativeType instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); }; 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 []; } } possiblyImpureTip = $possiblyImpureTip; } /** * @template T of RuleError * @param RuleErrorBuilder $ruleErrorBuilder * @return RuleErrorBuilder */ public function addTip(Scope $scope, Expr $conditionExpr, RuleErrorBuilder $ruleErrorBuilder): RuleErrorBuilder { if (!$this->possiblyImpureTip) { return $ruleErrorBuilder; } if (!$scope instanceof MutatingScope) { return $ruleErrorBuilder; } $descriptions = $scope->findPossiblyImpureCallDescriptions($conditionExpr); if (count($descriptions) === 0) { return $ruleErrorBuilder; } return $ruleErrorBuilder->possiblyImpureTip($descriptions); } } */ #[RegisteredRule(4)] final class StrictComparisonOfDifferentTypesRule implements Rule { private RicherScopeGetTypeHelper $richerScopeGetTypeHelper; private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; private bool $reportAlwaysTrueInLastCondition; private bool $treatPhpDocTypesAsCertainTip; public function __construct( RicherScopeGetTypeHelper $richerScopeGetTypeHelper, \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter] bool $reportAlwaysTrueInLastCondition, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->richerScopeGetTypeHelper = $richerScopeGetTypeHelper; $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $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 (!$scope instanceof MutatingScope) { throw new ShouldNotHappenException(); } 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) { $ruleErrorBuilder = $ruleErrorBuilder->acceptsReasonsTip($reasons); return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertain) { return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } $instanceofTypeWithoutPhpDocs = $scope->getNativeType($node); if ($instanceofTypeWithoutPhpDocs instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $node, $ruleErrorBuilder); }; $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()]; } $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()]; } } */ #[RegisteredRule(4)] final class TernaryOperatorConstantConditionRule implements Rule { private \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper; private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; private bool $treatPhpDocTypesAsCertainTip; public function __construct( \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->helper = $helper; $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $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 $this->possiblyImpureTipHelper->addTip($scope, $node->cond, $ruleErrorBuilder); } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $node->cond); if ($booleanNativeType instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($scope, $node->cond, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $node->cond, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $node->cond, $ruleErrorBuilder); }; 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 []; } } */ #[RegisteredRule(2)] 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 []; } } */ #[RegisteredRule(4)] final class WhileLoopAlwaysFalseConditionRule implements Rule { private \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper; private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; private bool $treatPhpDocTypesAsCertainTip; public function __construct( \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->helper = $helper; $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $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 $this->possiblyImpureTipHelper->addTip($scope, $node->cond, $ruleErrorBuilder); } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $node->cond); if ($booleanNativeType instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($scope, $node->cond, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $node->cond, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $node->cond, $ruleErrorBuilder); }; return [$addTip(RuleErrorBuilder::message('While loop condition is always false.'))->line($node->cond->getStartLine())->identifier('while.alwaysFalse')->build()]; } return []; } } */ #[RegisteredRule(4)] final class WhileLoopAlwaysTrueConditionRule implements Rule { private \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper; private \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper; private bool $treatPhpDocTypesAsCertain; private bool $treatPhpDocTypesAsCertainTip; public function __construct( \PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, \PHPStan\Rules\Comparison\PossiblyImpureTipHelper $possiblyImpureTipHelper, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter('%tips.treatPhpDocTypesAsCertain%')] bool $treatPhpDocTypesAsCertainTip ) { $this->helper = $helper; $this->possiblyImpureTipHelper = $possiblyImpureTipHelper; $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 Int_) { 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()) { if ($node->hasYield()) { return []; } $ref = $scope->getFunction() ?? $scope->getAnonymousFunctionReflection(); if ($ref !== null && $ref->getReturnType() instanceof NeverType) { return []; } $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use ($scope, $originalNode): RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $this->possiblyImpureTipHelper->addTip($scope, $originalNode->cond, $ruleErrorBuilder); } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $originalNode->cond); if ($booleanNativeType instanceof ConstantBooleanType) { return $this->possiblyImpureTipHelper->addTip($scope, $originalNode->cond, $ruleErrorBuilder); } if (!$this->treatPhpDocTypesAsCertainTip) { return $this->possiblyImpureTipHelper->addTip($scope, $originalNode->cond, $ruleErrorBuilder); } $ruleErrorBuilder = $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); return $this->possiblyImpureTipHelper->addTip($scope, $originalNode->cond, $ruleErrorBuilder); }; return [$addTip(RuleErrorBuilder::message('While loop condition is always true.'))->line($originalNode->cond->getStartLine())->identifier('while.alwaysTrue')->build()]; } return []; } } */ #[RegisteredRule(0)] 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; } } */ #[RegisteredRule(0)] final class ConstantAttributesRule implements Rule { private AttributesCheck $attributesCheck; private PhpVersion $phpVersion; public function __construct(AttributesCheck $attributesCheck, PhpVersion $phpVersion) { $this->attributesCheck = $attributesCheck; $this->phpVersion = $phpVersion; } public function getNodeType(): string { return Node\Stmt\Const_::class; } public function processNode(Node $node, Scope $scope): array { if ($node->attrGroups === []) { return []; } if (!$this->phpVersion->supportsAttributesOnGlobalConstants()) { return [RuleErrorBuilder::message('Attributes on global constants are supported only on PHP 8.5 and later.')->identifier('constant.attributesNotSupported')->nonIgnorable()->build()]; } if (PHP_VERSION_ID < 80500) { // because of Attribute::TARGET_CONSTANT constant return [RuleErrorBuilder::message('ConstantAttributesRule requires PHP 8.5 runtime to check the code.')->identifier('constant.attributesRuleCannotRun')->nonIgnorable()->build()]; } return $this->attributesCheck->check($scope, $node->attrGroups, Attribute::TARGET_CONSTANT, 'constant'); } } */ #[RegisteredRule(1)] final class ConstantRule implements Rule { private bool $discoveringSymbolsTip; public function __construct( #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $this->discoveringSymbolsTip = $discoveringSymbolsTip; } public function getNodeType(): string { return Node\Expr\ConstFetch::class; } public function processNode(Node $node, Scope $scope): array { if (!$scope->hasConstant($node->name)) { $errorBuilder = RuleErrorBuilder::message(sprintf('Constant %s not found.', (string) $node->name))->identifier('constant.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } return [$errorBuilder->build()]; } return []; } } */ #[RegisteredRule(0)] final class DynamicClassConstantFetchRule implements Rule { private PhpVersion $phpVersion; private RuleLevelHelper $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 fn(Type $type): bool => $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()]; } } */ #[RegisteredRule(0)] final class FinalConstantRule implements Rule { private PhpVersion $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()]; } } */ #[RegisteredRule(0)] final class FinalPrivateConstantRule implements Rule { public function getNodeType(): string { return ClassConst::class; } public function processNode(Node $node, Scope $scope): array { if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } $classReflection = $scope->getClassReflection(); if (!$node->isFinal()) { return []; } if (!$node->isPrivate()) { return []; } $errors = []; foreach ($node->consts as $classConstNode) { $errors[] = RuleErrorBuilder::message(sprintf('Private constant %s::%s() cannot be final as it is never overridden by other classes.', $classReflection->getDisplayName(), $classConstNode->name->name))->identifier('classConstant.finalPrivate')->nonIgnorable()->build(); } return $errors; } } container = $container; } public function getExtensions(): array { return $this->extensions ??= $this->container->getServicesByTag(\PHPStan\Rules\Constants\AlwaysUsedClassConstantsExtensionProvider::EXTENSION_TAG); } } */ #[RegisteredRule(0)] 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 []; } } */ #[RegisteredRule(6)] final class MissingClassConstantTypehintRule implements Rule { private MissingTypehintCheck $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; } } */ #[RegisteredRule(0)] final class NativeTypedClassConstantRule implements Rule { private PhpVersion $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()]; } } */ #[RegisteredRule(0)] final class OverridingConstantRule implements Rule { private bool $checkPhpDocMethodSignatures; public function __construct( #[AutowiredParameter] 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 === null) { return []; } $constantReflection = $classReflection->getConstant($constantName); $errors = []; if ($prototype->isFinal()) { $errors[] = RuleErrorBuilder::message(sprintf('Constant %s::%s overrides final constant %s::%s.', $classReflection->getDisplayName(\false), $constantReflection->getName(), $prototype->getDeclaringClass()->getDisplayName(\false), $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(\false), $constantReflection->getName(), $prototype->getDeclaringClass()->getDisplayName(\false), $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(\false), $constantReflection->getName(), $prototype->getDeclaringClass()->getDisplayName(\false), $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(\false), $constantReflection->getName(), $prototypeNativeType->describe(VerbosityLevel::typeOnly()), $prototype->getDeclaringClass()->getDisplayName(\false), $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(\false), $constantReflection->getName(), $prototype->getDeclaringClass()->getDisplayName(\false), $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(\false), $constantReflection->getName(), $prototype->getValueType()->describe(VerbosityLevel::value()), $prototype->getDeclaringClass()->getDisplayName(\false), $prototype->getName()))->identifier('classConstant.type')->build(); } return $errors; } private function findPrototype(ClassReflection $classReflection, string $constantName): ?ClassConstantReflection { 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; } } */ #[RegisteredRule(2)] final class ValueAssignedToClassConstantRule implements Rule { private ConstantResolver $constantResolver; private bool $checkDynamicConstantNameValues; public function __construct( ConstantResolver $constantResolver, #[AutowiredParameter('%featureToggles.checkDynamicConstantNameValues%')] bool $checkDynamicConstantNameValues ) { $this->constantResolver = $constantResolver; $this->checkDynamicConstantNameValues = $checkDynamicConstantNameValues; } 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) { if (!$this->checkDynamicConstantNameValues) { return []; } $configuredType = $this->constantResolver->getConfiguredClassConstantType($classReflection->getName(), $constantName); if ($configuredType !== null) { $accepts = $configuredType->accepts($valueExprType, \true); if (!$accepts->yes()) { $verbosity = VerbosityLevel::getRecommendedLevelByType($configuredType, $valueExprType); return [RuleErrorBuilder::message(sprintf('Configuration defined type for constant %s::%s (%s) does not accept value %s.', $constantReflection->getDeclaringClass()->getDisplayName(), $constantName, $configuredType->describe(VerbosityLevel::typeOnly()), $valueExprType->describe($verbosity)))->acceptsReasonsTip($accepts->reasons)->identifier('classConstant.value')->build()]; } } return []; } $accepts = $nativeType->accepts($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->accepts($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 ValueAssignedToDefineRule implements Rule { private ConstantResolver $constantResolver; public function __construct(ConstantResolver $constantResolver) { $this->constantResolver = $constantResolver; } public function getNodeType(): string { return FuncCall::class; } public function processNode(Node $node, Scope $scope): array { if (!$node->name instanceof Node\Name) { return []; } if (strtolower((string) $node->name) !== 'define') { return []; } $args = $node->getArgs(); if (count($args) < 2) { return []; } $constantNameStrings = $scope->getType($args[0]->value)->getConstantStrings(); if (count($constantNameStrings) === 0) { return []; } $valueType = $scope->getType($args[1]->value); $errors = []; foreach ($constantNameStrings as $constantNameString) { $constantName = $constantNameString->getValue(); if ($constantName === '') { continue; } $configuredType = $this->constantResolver->getConfiguredGlobalConstantType($constantName); if ($configuredType === null) { continue; } $accepts = $configuredType->accepts($valueType, \true); if ($accepts->yes()) { continue; } $verbosity = VerbosityLevel::getRecommendedLevelByType($configuredType, $valueType); $errors[] = RuleErrorBuilder::message(sprintf('Configuration defined type for constant %s (%s) does not accept value %s.', $constantName, $configuredType->describe(VerbosityLevel::typeOnly()), $valueType->describe($verbosity)))->acceptsReasonsTip($accepts->reasons)->identifier('constant.defineValue')->build(); } return $errors; } } */ final class ValueAssignedToGlobalConstantRule implements Rule { private ConstantResolver $constantResolver; public function __construct(ConstantResolver $constantResolver) { $this->constantResolver = $constantResolver; } public function getNodeType(): string { return Node\Stmt\Const_::class; } public function processNode(Node $node, Scope $scope): array { $errors = []; foreach ($node->consts as $const) { if ($const->namespacedName !== null) { $constantName = $const->namespacedName->toString(); } else { $constantName = $const->name->toString(); } $configuredType = $this->constantResolver->getConfiguredGlobalConstantType($constantName); if ($configuredType === null) { continue; } $valueType = $scope->getType($const->value); $accepts = $configuredType->accepts($valueType, \true); if ($accepts->yes()) { continue; } $verbosity = VerbosityLevel::getRecommendedLevelByType($configuredType, $valueType); $errors[] = RuleErrorBuilder::message(sprintf('Configuration defined type for constant %s (%s) does not accept value %s.', $constantName, $configuredType->describe(VerbosityLevel::typeOnly()), $valueType->describe($verbosity)))->acceptsReasonsTip($accepts->reasons)->identifier('constant.value')->build(); } return $errors; } } */ final class DateIntervalInstantiationRule 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 []; } if (count($node->getArgs()) === 0 || strtolower((string) $node->class) !== 'dateinterval') { return []; } $arg = $scope->getType($node->getArgs()[0]->value); $errors = []; foreach ($arg->getConstantStrings() as $constantString) { $dateIntervalString = $constantString->getValue(); try { new DateInterval($dateIntervalString); } catch (Throwable $e) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Instantiating DateInterval with %s produces an error: %s', $dateIntervalString, $e->getMessage()))->identifier('new.dateInterval')->build(); } } return $errors; } } */ #[RegisteredRule(5)] 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; } } */ #[RegisteredRule(4)] 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; } } */ #[RegisteredRule(4)] 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; } } */ #[RegisteredRule(4)] 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); $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; } } */ #[RegisteredRule(4)] 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); $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; } } */ #[RegisteredCollector(4)] 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(); } } */ #[RegisteredCollector(4)] 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(); } } */ #[RegisteredCollector(4)] 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()]; } } */ #[RegisteredRule(4)] final class NoopRule implements Rule { private ExprPrinter $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\BinaryOp\Pipe) { $expr = $expr->right; } 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()]; } } */ #[RegisteredCollector(4)] final class PossiblyPureFuncCallCollector implements Collector { private ReflectionProvider $reflectionProvider; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } public function getNodeType(): string { return Expression::class; } public function processNode(Node $node, Scope $scope) { $expr = $node->expr; if ($expr instanceof Node\Expr\BinaryOp\Pipe) { if ($expr->right instanceof Node\Expr\FuncCall) { if (!$expr->right->isFirstClassCallable()) { return null; } $expr = new Node\Expr\FuncCall($expr->right->name, []); } elseif ($expr->right instanceof Node\Expr\ArrowFunction) { $expr = $expr->right->expr; } } if (!$expr instanceof Node\Expr\FuncCall) { return null; } if ($expr->isFirstClassCallable()) { return null; } if (!$expr->name instanceof Node\Name) { return null; } if (!$this->reflectionProvider->hasFunction($expr->name, $scope)) { return null; } $functionReflection = $this->reflectionProvider->getFunction($expr->name, $scope); if (!$functionReflection->isPure()->maybe()) { return null; } if (!$functionReflection->hasSideEffects()->maybe()) { return null; } return [$functionReflection->getName(), $node->getStartLine()]; } } , string, int}> */ #[RegisteredCollector(4)] final class PossiblyPureMethodCallCollector implements Collector { public function __construct() { } public function getNodeType(): string { return Expression::class; } public function processNode(Node $node, Scope $scope) { $expr = $node->expr; if ($expr instanceof Node\Expr\BinaryOp\Pipe) { if ($expr->right instanceof Node\Expr\MethodCall || $expr->right instanceof Node\Expr\NullsafeMethodCall) { if (!$expr->right->isFirstClassCallable()) { return null; } $expr = new Node\Expr\MethodCall($expr->right->var, $expr->right->name, []); } elseif ($expr->right instanceof Node\Expr\ArrowFunction) { $expr = $expr->right->expr; } } if (!$expr instanceof Node\Expr\MethodCall && !$expr instanceof Node\Expr\NullsafeMethodCall) { return null; } if ($expr->isFirstClassCallable()) { return null; } if (!$expr->name instanceof Node\Identifier) { return null; } $methodName = $expr->name->toString(); $calledOnType = $scope->getType($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()]; } } */ #[RegisteredCollector(4)] final class PossiblyPureNewCollector implements Collector { private ReflectionProvider $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()]; } } */ #[RegisteredCollector(4)] final class PossiblyPureStaticCallCollector implements Collector { public function __construct() { } public function getNodeType(): string { return Expression::class; } public function processNode(Node $node, Scope $scope) { $expr = $node->expr; if ($expr instanceof Node\Expr\BinaryOp\Pipe) { if ($expr->right instanceof Node\Expr\StaticCall) { if (!$expr->right->isFirstClassCallable()) { return null; } $expr = new Node\Expr\StaticCall($expr->right->class, $expr->right->name, []); } elseif ($expr->right instanceof Node\Expr\ArrowFunction) { $expr = $expr->right->expr; } } if (!$expr instanceof Node\Expr\StaticCall || $expr->isFirstClassCallable()) { return null; } if (!$expr->name instanceof Node\Identifier) { return null; } if (!$expr->class instanceof Node\Name) { return null; } $methodName = $expr->name->toString(); $calledOnType = $scope->resolveTypeByName($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()]; } } */ #[RegisteredRule(4)] 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()]; } } */ #[RegisteredRule(4)] final class UnusedPrivateConstantRule implements Rule { private AlwaysUsedClassConstantsExtensionProvider $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; } } */ #[RegisteredRule(4)] final class UnusedPrivateMethodRule implements Rule { private AlwaysUsedMethodExtensionProvider $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 fn(ConstantStringType $type): string => $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 []; } $inMethod = $arrayScope->getFunction(); if (!$inMethod instanceof MethodReflection) { continue; } if ($inMethod->getName() === $typeAndMethod->getMethod()) { continue; } $calledOnType = $typeAndMethod->getType(); $methodReflection = $arrayScope->getMethodReflection($calledOnType, $typeAndMethod->getMethod()); if ($methodReflection === null) { continue; } if ($methodReflection->getDeclaringClass()->getName() !== $classReflection->getName()) { 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; } } */ #[RegisteredRule(4)] final class UnusedPrivatePropertyRule implements Rule { private ReadWritePropertiesExtensionProvider $extensionProvider; /** * @var string[] */ private array $alwaysWrittenTags; /** * @var string[] */ private array $alwaysReadTags; private bool $checkUninitializedProperties; /** * @param string[] $alwaysWrittenTags * @param string[] $alwaysReadTags */ public function __construct( ReadWritePropertiesExtensionProvider $extensionProvider, #[AutowiredParameter('%propertyAlwaysWrittenTags%')] array $alwaysWrittenTags, #[AutowiredParameter('%propertyAlwaysReadTags%')] array $alwaysReadTags, #[AutowiredParameter] 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 = !$property->isReadable(); $alwaysWritten = !$property->isWritable(); 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, 'onlyReadable' => $property->isReadable() && !$property->isWritable(), 'onlyWritable' => $property->isWritable() && !$property->isReadable(), 'hasTrueRead' => $alwaysRead]; } foreach ($node->getPropertyUsages() as $usage) { $usageScope = $usage->getScope(); $fetch = $usage->getFetch(); if ($fetch->name instanceof Node\Identifier) { $propertyName = $fetch->name->toString(); $propertyNames = [$propertyName]; if ($usageScope->getFunction() !== null && $fetch instanceof Node\Expr\PropertyFetch && $fetch->var instanceof Node\Expr\Variable && is_string($fetch->var->name) && $fetch->var->name === 'this') { $methodReflection = $usageScope->getFunction(); if ($methodReflection instanceof PhpMethodFromParserNodeReflection && $methodReflection->isPropertyHook() && $methodReflection->getHookedPropertyName() === $propertyName && ($methodReflection->getPropertyHookName() === 'set' || $usage instanceof PropertyRead)) { continue; } } } else { $propertyNameType = $usageScope->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 fn(ConstantStringType $type): string => $type->getValue(), $strings); } if ($fetch instanceof Node\Expr\PropertyFetch) { $fetchedOnType = $usageScope->getType($fetch->var); } else if ($fetch->class instanceof Node\Name) { $fetchedOnType = $usageScope->resolveTypeByName($fetch->class); } else { $fetchedOnType = $usageScope->getType($fetch->class); } foreach ($propertyNames as $propertyName) { if (!array_key_exists($propertyName, $properties)) { continue; } $propertyNode = $properties[$propertyName]['node']; if ($propertyNode->isStatic()) { $propertyReflection = $usageScope->getStaticPropertyReflection($fetchedOnType, $propertyName); } else { $propertyReflection = $usageScope->getInstancePropertyReflection($fetchedOnType, $propertyName); } if ($propertyReflection === null) { if (!$classType->isSuperTypeOf($fetchedOnType)->no()) { if ($usage instanceof PropertyRead) { $properties[$propertyName]['read'] = \true; $properties[$propertyName]['hasTrueRead'] = \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; $properties[$propertyName]['hasTrueRead'] = \true; } else { $properties[$propertyName]['written'] = \true; } } continue; } if ($usage instanceof PropertyRead) { $properties[$propertyName]['read'] = \true; if (!$this->isPropertySelfWrite($usageScope, $propertyName, $propertyNode, $classReflection->getName())) { $properties[$propertyName]['hasTrueRead'] = \true; } } else { $properties[$propertyName]['written'] = \true; } } } foreach ($properties as $propertyName => $data) { if (!$data['read'] || $data['hasTrueRead']) { continue; } if (!$data['node']->isPromoted()) { continue; } $properties[$propertyName]['read'] = \false; } [$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 if ($data['onlyReadable']) { $errors[] = RuleErrorBuilder::message(sprintf('Readable %s is never read.', lcfirst($propertyName)))->line($propertyNode->getStartLine())->identifier('property.neverRead')->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)) { if ($data['onlyWritable']) { $errors[] = RuleErrorBuilder::message(sprintf('Writable %s is never written.', lcfirst($propertyName)))->line($propertyNode->getStartLine())->identifier('property.neverWritten')->build(); } else { $errors[] = RuleErrorBuilder::message(sprintf('%s is never written, only read.', $propertyName))->line($propertyNode->getStartLine())->identifier('property.onlyRead')->tip($tip)->build(); } } } return $errors; } private function isPropertySelfWrite(Scope $usageScope, string $propertyName, ClassPropertyNode $propertyNode, string $className): bool { if (!$propertyNode->isPromoted()) { return \false; } $callStack = $usageScope->getFunctionCallStackWithParameters(); if ($callStack === []) { return \false; } $lastCall = $callStack[count($callStack) - 1]; [$calleeReflection, $parameterReflection] = $lastCall; if (!$calleeReflection instanceof MethodReflection) { return \false; } if ($calleeReflection->getName() !== '__construct') { return \false; } if ($calleeReflection->getDeclaringClass()->getName() !== $className) { return \false; } if ($parameterReflection === null) { return \false; } return $parameterReflection->getName() === $propertyName; } } */ #[AutowiredService] final class DebugScopeRule implements Rule { private ReflectionProvider $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()]; } } */ #[AutowiredService] final class DumpNativeTypeRule implements Rule { private ReflectionProvider $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 []; } $args = $node->getArgs(); if (count($args) === 0) { return []; } $functionName = $this->reflectionProvider->resolveFunctionName($node->name, $scope); if ($functionName === null) { return []; } if (strtolower($functionName) !== 'phpstan\dumpnativetype') { return []; } $multipleArgs = count($args) > 1; $errors = []; foreach ($args as $i => $arg) { $errors[] = RuleErrorBuilder::message(sprintf($multipleArgs ? 'Dumped type #%d: %s' : 'Dumped type: %2$s', $i + 1, $scope->getNativeType($arg->value)->describe(VerbosityLevel::precise())))->nonIgnorable()->identifier('phpstan.dumpNativeType')->build(); } return $errors; } } */ #[AutowiredService] final class DumpPhpDocTypeRule implements Rule { private ReflectionProvider $reflectionProvider; private Printer $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 []; } $args = $node->getArgs(); if (count($args) === 0) { return []; } $functionName = $this->reflectionProvider->resolveFunctionName($node->name, $scope); if ($functionName === null) { return []; } if (strtolower($functionName) !== 'phpstan\dumpphpdoctype') { return []; } $multipleArgs = count($args) > 1; $errors = []; foreach ($args as $i => $arg) { $errors[] = RuleErrorBuilder::message(sprintf($multipleArgs ? 'Dumped type #%d: %s' : 'Dumped type: %2$s', $i + 1, $this->printer->print($scope->getType($arg->value)->toPhpDocNode())))->nonIgnorable()->identifier('phpstan.dumpPhpDocType')->build(); } return $errors; } } */ #[AutowiredService] final class DumpTypeRule implements Rule { private ReflectionProvider $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 []; } $args = $node->getArgs(); if (count($args) === 0) { return []; } $functionName = $this->reflectionProvider->resolveFunctionName($node->name, $scope); if ($functionName === null) { return []; } if (strtolower($functionName) !== 'phpstan\dumptype') { return []; } $multipleArgs = count($args) > 1; $errors = []; foreach ($args as $i => $arg) { $errors[] = RuleErrorBuilder::message(sprintf($multipleArgs ? 'Dumped type #%d: %s' : 'Dumped type: %2$s', $i + 1, $scope->getType($arg->value)->describe(VerbosityLevel::precise())))->nonIgnorable()->identifier('phpstan.dumpType')->build(); } return $errors; } } */ #[AutowiredService] final class FileAssertRule implements Rule { private ReflectionProvider $reflectionProvider; private TypeStringResolver $typeStringResolver; public function __construct(ReflectionProvider $reflectionProvider, TypeStringResolver $typeStringResolver) { $this->reflectionProvider = $reflectionProvider; $this->typeStringResolver = $typeStringResolver; } 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 (count($node->getArgs()) !== 2) { 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\assertSuperType') { return $this->processAssertSuperType($node->getArgs(), $scope); } if ($function->getName() === 'PHPStan\Testing\assertVariableCertainty') { return $this->processAssertVariableCertainty($node->getArgs(), $scope); } return []; } /** * @param array{Node\Arg, Node\Arg} $args * @return list */ private function processAssertType(array $args, Scope $scope): array { $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 array{Node\Arg, Node\Arg} $args * @return list */ private function processAssertNativeType(array $args, Scope $scope): array { $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 array{Node\Arg, Node\Arg} $args * @return list */ private function processAssertSuperType(array $args, Scope $scope): array { $expectedTypeStrings = $scope->getType($args[0]->value)->getConstantStrings(); if (count($expectedTypeStrings) !== 1) { return [RuleErrorBuilder::message('Expected super type must be a literal string.')->nonIgnorable()->identifier('phpstan.unknownExpectation')->build()]; } $expressionType = $scope->getType($args[1]->value); $expectedType = $this->typeStringResolver->resolve($expectedTypeStrings[0]->getValue()); if ($expectedType->isSuperTypeOf($expressionType)->yes()) { return []; } return [RuleErrorBuilder::message(sprintf('Expected subtype of %s, actual: %s', $expectedTypeStrings[0]->getValue(), $expressionType->describe(VerbosityLevel::precise())))->nonIgnorable()->identifier('phpstan.superType')->build()]; } /** * @param array{Node\Arg, Node\Arg} $args * @return list */ private function processAssertVariableCertainty(array $args, Scope $scope): array { $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()]; } } 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; } } */ #[RegisteredRule(0)] final class EnumCaseAttributesRule implements Rule { private AttributesCheck $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'); } } */ #[RegisteredRule(0)] final class EnumCaseOutsideEnumRule implements Rule { public function getNodeType(): string { return Node\Stmt\EnumCase::class; } public function processNode(Node $node, Scope $scope): array { if (!$scope->isInTrait() && $scope->isInClass() && $scope->getClassReflection()->isEnum()) { return []; } return [RuleErrorBuilder::message('Enum case can only be used in enums.')->nonIgnorable()->identifier('enum.caseOutsideOfEnum')->build()]; } } */ #[RegisteredRule(4)] final class CatchWithUnthrownExceptionRule implements Rule { private \PHPStan\Rules\Exceptions\ExceptionTypeResolver $exceptionTypeResolver; private bool $reportUncheckedExceptionDeadCatch; public function __construct( #[AutowiredParameter('@exceptionTypeResolver')] \PHPStan\Rules\Exceptions\ExceptionTypeResolver $exceptionTypeResolver, #[AutowiredParameter('%exceptions.reportUncheckedExceptionDeadCatch%')] 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()]; } } */ #[RegisteredRule(0)] final class CaughtExceptionExistenceRule implements Rule { private ReflectionProvider $reflectionProvider; private ClassNameCheck $classCheck; private bool $checkClassCaseSensitivity; private bool $discoveringSymbolsTip; public function __construct( ReflectionProvider $reflectionProvider, ClassNameCheck $classCheck, #[AutowiredParameter] bool $checkClassCaseSensitivity, #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $this->reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } 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; } $errorBuilder = RuleErrorBuilder::message(sprintf('Caught class %s not found.', $className))->line($class->getStartLine())->identifier('class.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $errors[] = $errorBuilder->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($scope, [new ClassNameNodePair($className, $class)], ClassNameUsageLocation::from(ClassNameUsageLocation::EXCEPTION_CATCH), $this->checkClassCaseSensitivity)); } return $errors; } } 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->is($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->is($checkedExceptionClass)) { continue; } return \true; } return count($this->checkedExceptionRegexes) === 0 && count($this->checkedExceptionClasses) === 0; } } */ final class MethodThrowTypeCovarianceRule implements Rule { private ParentMethodHelper $parentMethodHelper; private bool $implicitThrows; public function __construct(ParentMethodHelper $parentMethodHelper, bool $implicitThrows) { $this->parentMethodHelper = $parentMethodHelper; $this->implicitThrows = $implicitThrows; } 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 ($method->isPrivate()) { return []; } $throwType = $method->getThrowType(); if ($throwType === null) { if ($this->implicitThrows) { $throwType = new ObjectType(Throwable::class); } else { $throwType = new VoidType(); } } if ($throwType->isVoid()->yes()) { return []; } $errors = []; foreach ($this->parentMethodHelper->collectParentMethods($methodName, $method->getDeclaringClass()) as [$parentMethod, $parentMethodDeclaringClass]) { $parentThrowType = $parentMethod->getThrowType(); $explicitParentThrowsVoid = \true; if ($parentThrowType === null) { if ($this->implicitThrows) { $parentThrowType = new ObjectType(Throwable::class); } else { $parentThrowType = new VoidType(); $explicitParentThrowsVoid = \false; } } else { $explicitParentThrowsVoid = $parentThrowType->isVoid()->yes(); } if ($parentThrowType->isVoid()->yes()) { if ($explicitParentThrowsVoid) { $errors[] = RuleErrorBuilder::message(sprintf('Method %s::%s() should not throw %s because parent method %s::%s() has PHPDoc tag @throws void.', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $throwType->describe(VerbosityLevel::typeOnly()), $parentMethodDeclaringClass->getDisplayName(), $parentMethod->getName()))->identifier('throws.shouldBeVoid')->build(); } else { $errors[] = RuleErrorBuilder::message(sprintf('Method %s::%s() should not throw %s because parent method %s::%s() does not have PHPDoc tag @throws.', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $throwType->describe(VerbosityLevel::typeOnly()), $parentMethodDeclaringClass->getDisplayName(), $parentMethod->getName()))->identifier('throws.notCovariantWithImplicitVoid')->build(); } continue; } if ($parentThrowType->isSuperTypeOf($throwType)->yes()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @throws type %s of method %s::%s() should be covariant with PHPDoc @throws type %s of method %s::%s().', $throwType->describe(VerbosityLevel::typeOnly()), $method->getDeclaringClass()->getDisplayName(), $method->getName(), $parentThrowType->describe(VerbosityLevel::typeOnly()), $parentMethodDeclaringClass->getDisplayName(), $parentMethod->getName()))->identifier('throws.notCovariant')->build(); } return $errors; } } */ final class MissingCheckedExceptionInFunctionThrowsRule implements Rule { private \PHPStan\Rules\Exceptions\MissingCheckedExceptionInThrowsCheck $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 MissingCheckedExceptionInMethodThrowsRule implements Rule { private \PHPStan\Rules\Exceptions\MissingCheckedExceptionInThrowsCheck $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; } } */ final class MissingCheckedExceptionInPropertyHookThrowsRule implements Rule { private \PHPStan\Rules\Exceptions\MissingCheckedExceptionInThrowsCheck $check; public function __construct(\PHPStan\Rules\Exceptions\MissingCheckedExceptionInThrowsCheck $check) { $this->check = $check; } public function getNodeType(): string { return PropertyHookReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope): array { $statementResult = $node->getStatementResult(); $hookReflection = $node->getHookReflection(); if (!$hookReflection->isPropertyHook()) { throw new ShouldNotHappenException(); } $errors = []; foreach ($this->check->check($hookReflection->getThrowType(), $statementResult->getThrowPoints()) as [$className, $throwPointNode]) { $errors[] = RuleErrorBuilder::message(sprintf('%s hook for property %s::$%s throws checked exception %s but it\'s missing from the PHPDoc @throws tag.', ucfirst($hookReflection->getPropertyHookName()), $hookReflection->getDeclaringClass()->getDisplayName(), $hookReflection->getHookedPropertyName(), $className))->line($throwPointNode->getStartLine())->identifier('missingType.checkedException')->build(); } 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(), fn(string $objectClassName) => TrinaryLogic::createFromBoolean($this->exceptionTypeResolver->isCheckedException($objectClassName, $throwPoint->getScope()))); if ($isCheckedException->no()) { continue; } $classes[] = [$throwPointType->describe(VerbosityLevel::typeOnly()), $throwPoint->getNode()]; } } return $classes; } } */ #[RegisteredRule(0)] final class NoncapturingCatchRule implements Rule { public function getNodeType(): string { return Node\Stmt\Catch_::class; } /** * @param Node\Stmt\Catch_ $node */ public function processNode(Node $node, Scope $scope): array { if ($scope->getPhpVersion()->supportsNoncapturingCatches()->yes()) { 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()]; } } */ #[RegisteredRule(4)] 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\Expression && $stmt->expr instanceof Node\Expr\Throw_) { return 'throw'; } if ($stmt instanceof Node\Stmt\Continue_) { return 'continue'; } if ($stmt instanceof Node\Stmt\Break_) { return 'break'; } return 'exit point'; } } */ #[RegisteredRule(3)] final class ThrowExprTypeRule implements Rule { private RuleLevelHelper $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 fn(Type $type): bool => $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()]; } } */ #[RegisteredRule(0)] final class ThrowExpressionRule implements Rule { private PhpVersion $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 []; } if ($node->getAttribute(StandaloneThrowExprVisitor::ATTRIBUTE_NAME) === \true) { return []; } return [RuleErrorBuilder::message('Throw expression is supported only on PHP 8.0 and later.')->nonIgnorable()->identifier('throw.notSupported')->build()]; } } */ #[RegisteredRule(3)] final class ThrowsVoidFunctionWithExplicitThrowPointRule implements Rule { private \PHPStan\Rules\Exceptions\ExceptionTypeResolver $exceptionTypeResolver; private bool $missingCheckedExceptionInThrows; public function __construct( #[AutowiredParameter('@exceptionTypeResolver')] \PHPStan\Rules\Exceptions\ExceptionTypeResolver $exceptionTypeResolver, #[AutowiredParameter('%exceptions.check.missingCheckedExceptionInThrows%')] 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(), fn(string $objectClassName) => 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; } } */ #[RegisteredRule(3)] final class ThrowsVoidMethodWithExplicitThrowPointRule implements Rule { private \PHPStan\Rules\Exceptions\ExceptionTypeResolver $exceptionTypeResolver; private bool $missingCheckedExceptionInThrows; public function __construct( #[AutowiredParameter('@exceptionTypeResolver')] \PHPStan\Rules\Exceptions\ExceptionTypeResolver $exceptionTypeResolver, #[AutowiredParameter('%exceptions.check.missingCheckedExceptionInThrows%')] 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(), fn(string $objectClassName) => 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; } } */ #[RegisteredRule(3)] final class ThrowsVoidPropertyHookWithExplicitThrowPointRule implements Rule { private \PHPStan\Rules\Exceptions\ExceptionTypeResolver $exceptionTypeResolver; private bool $missingCheckedExceptionInThrows; public function __construct( #[AutowiredParameter('@exceptionTypeResolver')] \PHPStan\Rules\Exceptions\ExceptionTypeResolver $exceptionTypeResolver, #[AutowiredParameter('%exceptions.check.missingCheckedExceptionInThrows%')] bool $missingCheckedExceptionInThrows ) { $this->exceptionTypeResolver = $exceptionTypeResolver; $this->missingCheckedExceptionInThrows = $missingCheckedExceptionInThrows; } public function getNodeType(): string { return PropertyHookReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope): array { $statementResult = $node->getStatementResult(); $hookReflection = $node->getHookReflection(); if ($hookReflection->getThrowType() === null || !$hookReflection->getThrowType()->isVoid()->yes()) { return []; } if ($hookReflection->getPropertyHookName() === null) { throw new ShouldNotHappenException(); } $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(), fn(string $objectClassName) => TrinaryLogic::createFromBoolean($this->exceptionTypeResolver->isCheckedException($objectClassName, $throwPoint->getScope()))); if ($isCheckedException->yes()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('%s hook for property %s::$%s throws exception %s but the PHPDoc contains @throws void.', ucfirst($hookReflection->getPropertyHookName()), $hookReflection->getDeclaringClass()->getDisplayName(), $hookReflection->getHookedPropertyName(), $throwPointType->describe(VerbosityLevel::typeOnly())))->line($throwPoint->getNode()->getStartLine())->identifier('throws.void')->build(); } } return $errors; } } */ final class TooWideFunctionThrowTypeRule implements Rule { private \PHPStan\Rules\Exceptions\TooWideThrowTypeCheck $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 TooWideMethodThrowTypeRule implements Rule { private FileTypeMapper $fileTypeMapper; private \PHPStan\Rules\Exceptions\TooWideThrowTypeCheck $check; private bool $checkProtectedAndPublicMethods; private bool $tooWideImplicitThrows; public function __construct(FileTypeMapper $fileTypeMapper, \PHPStan\Rules\Exceptions\TooWideThrowTypeCheck $check, bool $checkProtectedAndPublicMethods, bool $tooWideImplicitThrows) { $this->fileTypeMapper = $fileTypeMapper; $this->check = $check; $this->checkProtectedAndPublicMethods = $checkProtectedAndPublicMethods; $this->tooWideImplicitThrows = $tooWideImplicitThrows; } public function getNodeType(): string { return MethodReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope): array { $statementResult = $node->getStatementResult(); $method = $node->getMethodReflection(); $isFirstDeclaration = $method->getPrototype()->getDeclaringClass() === $method->getDeclaringClass(); if (!$method->isPrivate()) { if (!$method->getDeclaringClass()->isFinal() && !$method->isFinal()->yes()) { if (!$this->checkProtectedAndPublicMethods) { return []; } if ($isFirstDeclaration) { return []; } } } $throwType = $method->getThrowType(); if ($throwType === null) { return []; } $unusedThrowClasses = $this->check->check($throwType, $statementResult->getThrowPoints()); if (count($unusedThrowClasses) === 0) { return []; } $isThrowTypeExplicit = $this->isThrowTypeExplicit($node->getDocComment(), $scope, $node->getClassReflection(), $method->getName()); if (!$isThrowTypeExplicit && !$this->tooWideImplicitThrows) { return []; } $throwClasses = array_map(static fn($type) => $type->describe(VerbosityLevel::typeOnly()), TypeUtils::flattenTypes($throwType)); $usedClasses = array_diff($throwClasses, $unusedThrowClasses); $errors = []; foreach ($unusedThrowClasses as $throwClass) { $builder = RuleErrorBuilder::message(sprintf('Method %s::%s() has %s in PHPDoc @throws tag but it\'s not thrown.', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $throwClass))->identifier('throws.unusedType'); if (!$isThrowTypeExplicit) { $builder->tip(sprintf('You can narrow the thrown type with PHPDoc tag @throws %s.', count($usedClasses) === 0 ? 'void' : implode('|', $usedClasses))); } $errors[] = $builder->build(); } return $errors; } private function isThrowTypeExplicit(?Doc $docComment, Scope $scope, ClassReflection $classReflection, string $methodName): bool { if ($docComment === null) { return \false; } $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), $classReflection->getName(), $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, $methodName, $docComment->getText()); return $resolvedPhpDoc->getThrowsTag() !== null; } } */ final class TooWidePropertyHookThrowTypeRule implements Rule { private \PHPStan\Rules\Exceptions\TooWideThrowTypeCheck $check; private bool $checkProtectedAndPublicMethods; public function __construct(\PHPStan\Rules\Exceptions\TooWideThrowTypeCheck $check, bool $checkProtectedAndPublicMethods) { $this->check = $check; $this->checkProtectedAndPublicMethods = $checkProtectedAndPublicMethods; } public function getNodeType(): string { return PropertyHookReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope): array { $statementResult = $node->getStatementResult(); $hookReflection = $node->getHookReflection(); if ($hookReflection->getPropertyHookName() === null) { throw new ShouldNotHappenException(); } $propertyReflection = $node->getPropertyReflection(); $throwType = $hookReflection->getThrowType(); if ($throwType === null) { return []; } if (!$propertyReflection->isPrivate() && !$propertyReflection->getDeclaringClass()->isFinal() && !$propertyReflection->isFinal()->yes() && !$hookReflection->isFinal()->yes() && !$this->checkProtectedAndPublicMethods) { return []; } $errors = []; foreach ($this->check->check($throwType, $statementResult->getThrowPoints()) as $throwClass) { $errors[] = RuleErrorBuilder::message(sprintf('%s hook for property %s::$%s has %s in PHPDoc @throws tag but it\'s not thrown.', ucfirst($hookReflection->getPropertyHookName()), $hookReflection->getDeclaringClass()->getDisplayName(), $hookReflection->getHookedPropertyName(), $throwClass))->identifier('throws.unusedType')->build(); } return $errors; } } implicitThrows = $implicitThrows; } /** * @param ThrowPoint[] $throwPoints * @return string[] */ public function check(Type $throwType, array $throwPoints): array { if ($throwType->isVoid()->yes()) { return []; } $throwPointType = TypeCombinator::union(...array_map(function (ThrowPoint $throwPoint): Type { if (!$this->implicitThrows && !$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; } } */ private array $unknownClassErrors; private ?string $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; } } ruleLevelHelper = $ruleLevelHelper; $this->nullsafeCheck = $nullsafeCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->propertyReflectionFinder = $propertyReflectionFinder; $this->reflectionProvider = $reflectionProvider; $this->checkArgumentTypes = $checkArgumentTypes; $this->checkArgumentsPassedByReference = $checkArgumentsPassedByReference; $this->checkExtraArguments = $checkExtraArguments; $this->checkMissingTypehints = $checkMissingTypehints; } /** * @param 'attribute'|'callable'|'method'|'staticMethod'|'function'|'new' $nodeType * @return list * @param \PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\New_ $funcCall */ public function check(ParametersAcceptor $parametersAcceptor, Scope $scope, bool $isBuiltin, $funcCall, string $nodeType, TrinaryLogic $acceptsNamedArguments, string $singleInsufficientParameterMessage, string $pluralInsufficientParametersMessage, string $singleInsufficientParameterInVariadicFunctionMessage, string $pluralInsufficientParametersInVariadicFunctionMessage, string $singleInsufficientParameterWithOptionalParametersMessage, string $pluralInsufficientParametersWithOptionalParametersMessage, string $wrongArgumentTypeMessage, string $voidReturnTypeUsed, string $parameterPassedByReferenceMessage, string $unresolvableTemplateTypeMessage, string $missingParameterMessage, string $unknownParameterMessage, string $unresolvableReturnTypeMessage, string $unresolvableParameterTypeMessage, string $namedArgumentMessage): array { if ($funcCall instanceof Node\Expr\MethodCall || $funcCall instanceof Node\Expr\StaticCall || $funcCall instanceof Node\Expr\FuncCall) { $funcCallLine = $funcCall->name->getStartLine(); } else { $funcCallLine = $funcCall->getStartLine(); } $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) { $argumentName = null; if ($arg->name !== null) { $hasNamedArguments = \true; $argumentName = $arg->name->toString(); } 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) { if ($argumentName === null || !$scope->getPhpVersion()->supportsNamedArgumentAfterUnpackedArgument()->yes()) { $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; } if ($arg->unpack) { $type = $scope->getType($arg->value); $arrays = $type->getConstantArrays(); if (count($arrays) > 0) { $maxKeys = null; foreach ($arrays as $array) { $countType = $array->getArraySize(); if ($countType instanceof ConstantIntegerType) { $keysCount = $countType->getValue(); } elseif ($countType instanceof IntegerRangeType) { $keysCount = $countType->getMax(); if ($keysCount === null) { throw new ShouldNotHappenException(); } } else { throw new ShouldNotHappenException(); } if ($maxKeys !== null && $keysCount >= $maxKeys) { continue; } $maxKeys = $keysCount; } for ($j = 0; $j < $maxKeys; $j++) { $types = []; $commonKey = null; $isOptionalKey = \false; foreach ($arrays as $constantArray) { $isOptionalKey = in_array($j, $constantArray->getOptionalKeys(), \true); $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; } if ($isOptionalKey && $keyArgumentName === null) { continue; } $arguments[] = [$arg->value, TypeCombinator::union(...$types), \false, $keyArgumentName, $arg->getStartLine()]; } if (count($arguments) === 0 && $type->isIterableAtLeastOnce()->yes()) { $arguments[] = [$arg->value, $type->getIterableValueType(), \true, null, $arg->getStartLine()]; } } else { $arguments[] = [$arg->value, $type->getIterableValueType(), \true, null, $arg->getStartLine()]; } continue; } $arguments[] = [$arg->value, null, \false, $argumentName, $arg->getStartLine()]; } if ($hasNamedArguments && !$scope->getPhpVersion()->supportsNamedArguments()->yes() && !(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($funcCallLine)->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 ? $singleInsufficientParameterMessage : $pluralInsufficientParametersMessage, $invokedParametersCount, $functionParametersMinCount))->identifier('arguments.count')->line($funcCallLine)->build(); } elseif ($functionParametersMaxCount === -1 && $invokedParametersCount < $functionParametersMinCount) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($invokedParametersCount === 1 ? $singleInsufficientParameterInVariadicFunctionMessage : $pluralInsufficientParametersInVariadicFunctionMessage, $invokedParametersCount, $functionParametersMinCount))->identifier('arguments.count')->line($funcCallLine)->build(); } elseif ($functionParametersMaxCount !== -1) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($invokedParametersCount === 1 ? $singleInsufficientParameterWithOptionalParametersMessage : $pluralInsufficientParametersWithOptionalParametersMessage, $invokedParametersCount, $functionParametersMinCount, $functionParametersMaxCount))->identifier('arguments.count')->line($funcCallLine)->build(); } } } if (!$funcCall instanceof Node\Expr\New_ && !$scope->isInFirstLevelStatement() && $scope->getKeepVoidType($funcCall)->isVoid()->yes()) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message($voidReturnTypeUsed)->identifier(sprintf('%s.void', $nodeType))->line($funcCallLine)->build(); } [$addedErrors, $argumentsWithParameters] = $this->processArguments($parametersAcceptor, $funcCallLine, $isBuiltin, $arguments, $hasNamedArguments, $missingParameterMessage, $unknownParameterMessage); 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 fn(Type $type): bool => $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) { $rememberTypes = !$argumentValue instanceof Expr\Closure && !$argumentValue instanceof Expr\ArrowFunction; $scope = $scope->pushInFunctionCall(null, $parameter, $rememberTypes); } $argumentValueType = $scope->getType($argumentValue); if ($scope instanceof MutatingScope) { $scope = $scope->popInFunctionCall(); } } if (!$acceptsNamedArguments->yes()) { if ($argumentName !== null) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($namedArgumentMessage, 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($namedArgumentMessage, 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 && !$argumentValueType instanceof ErrorType) { // @see https://github.com/php/php-src/issues/21568#issuecomment-4148832540 $isStrictTypes = $scope->isDeclareStrictTypes() && (!$isBuiltin || !$parameterType->isCallable()->yes()); $accepts = $this->ruleLevelHelper->accepts($parameterType, $argumentValueType, $isStrictTypes); if (!$accepts->result) { $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($parameterType, $argumentValueType); $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($wrongArgumentTypeMessage, $this->describeParameter($parameter, $argumentName ?? $i + 1), $parameterType->describe($verbosityLevel), $argumentValueType->describe($verbosityLevel)))->identifier('argument.type')->line($argumentLine)->acceptsReasonsTip($accepts->reasons)->build(); } } if ($originalParameter !== null && !$this->unresolvableTypeHelper->containsUnresolvableType($originalParameter->getType()) && $this->unresolvableTypeHelper->containsUnresolvableType($parameterType)) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($unresolvableParameterTypeMessage, $this->describeParameter($parameter, $argumentName === null ? $i + 1 : null)))->identifier('argument.unresolvableType')->line($argumentLine)->build(); } if ($parameter instanceof ExtendedParameterReflection && $parameter->getClosureThisType() !== null && ($argumentValue instanceof Expr\Closure || $argumentValue instanceof Expr\ArrowFunction) && $argumentValue->static) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($wrongArgumentTypeMessage, $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($parameterPassedByReferenceMessage, $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()) { if ($nativePropertyReflection->isStatic()) { $errorFormat = 'static readonly property %s::$%s'; } else { $errorFormat = 'readonly property %s::$%s'; } } elseif ($nativePropertyReflection->isReadOnlyByPhpDoc()) { if ($nativePropertyReflection->isStatic()) { $errorFormat = 'static @readonly property %s::$%s'; } else { $errorFormat = '@readonly property %s::$%s'; } } else { continue; } $propertyDescription = sprintf($errorFormat, $propertyReflection->getDeclaringClass()->getDisplayName(), $propertyReflection->getName()); $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('%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; } if ($this->callReturnsByReference($argumentValue, $scope)) { continue; } $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($parameterPassedByReferenceMessage, $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($unresolvableTemplateTypeMessage, $name))->identifier('argument.templateType')->line($funcCallLine)->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($unresolvableReturnTypeMessage)->identifier(sprintf('%s.unresolvableReturnType', $nodeType))->line($funcCallLine)->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 = []; $isNativelyVariadic = \false; foreach ($parameters as $i => $parameter) { $parametersByName[$parameter->getName()] = $parameter; $originalParametersByName[$parameter->getName()] = $originalParameters[$i]; if ($parameter->isVariadic()) { $isNativelyVariadic = \true; continue; } $unusedParametersByName[$parameter->getName()] = $parameter; } $newArguments = []; $namedArgumentAlreadyOccurred = \false; $namedArgumentsForVariadicParameter = []; 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 = array_last($parameters); $originalParameter = array_last($originalParameters); 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; if (!$isNativelyVariadic || $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; } $parametersCount = count($parameters); $parameter = $parameters[$parametersCount - 1]; $originalParameter = $originalParameters[$parametersCount - 1]; if (isset($namedArgumentsForVariadicParameter[$argumentName])) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Named parameter $%s overwrites previous argument.', $argumentName))->identifier('argument.duplicate')->line($argumentLine)->build(); } $namedArgumentsForVariadicParameter[$argumentName] = \true; } 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]; } /** * @param int|string|null $positionOrNamed */ private function describeParameter(ParameterReflection $parameter, $positionOrNamed): string { $parts = []; if (is_int($positionOrNamed)) { $parts[] = 'Parameter #' . $positionOrNamed; } elseif ($parameter->isVariadic() && is_string($positionOrNamed)) { $parts[] = 'Named argument ' . $positionOrNamed . ' for variadic parameter'; } else { $parts[] = 'Parameter'; } $name = $parameter->getName(); if ($name !== '') { $parts[] = ($parameter->isVariadic() ? '...$' : '$') . $name; } return implode(' ', $parts); } private function callReturnsByReference(Expr $expr, Scope $scope): bool { if ($expr instanceof Node\Expr\MethodCall) { if (!$expr->name instanceof Node\Identifier) { return \false; } $calledOnType = $scope->getType($expr->var); $methodReflection = $scope->getMethodReflection($calledOnType, $expr->name->name); if ($methodReflection === null) { return \false; } return $methodReflection->returnsByReference()->yes(); } if ($expr instanceof Node\Expr\StaticCall) { if (!$expr->name instanceof Node\Identifier) { return \false; } if ($expr->class instanceof Node\Name) { $calledOnType = $scope->resolveTypeByName($expr->class); } else { $calledOnType = $scope->getType($expr->class); } $methodReflection = $scope->getMethodReflection($calledOnType, $expr->name->name); if ($methodReflection === null) { return \false; } return $methodReflection->returnsByReference()->yes(); } if ($expr instanceof Node\Expr\FuncCall) { if ($expr->name instanceof Node\Name) { if ($this->reflectionProvider->hasFunction($expr->name, $scope)) { $functionReflection = $this->reflectionProvider->getFunction($expr->name, $scope); return $functionReflection->returnsByReference()->yes(); } } } return \false; } } reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->phpVersion = $phpVersion; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->checkThisOnly = $checkThisOnly; } /** * @return list */ public function checkFunction(Scope $scope, Function_ $function, PhpFunctionFromParserNodeReflection $functionReflection, string $parameterMessage, string $returnMessage, string $unionTypesMessage, string $templateTypeMissingInParameterMessage, string $unresolvableParameterTypeMessage, string $unresolvableReturnTypeMessage, string $noDiscardVoidReturnMessage): array { return $this->checkParametersAcceptor($scope, $functionReflection, $function, $parameterMessage, $returnMessage, $unionTypesMessage, $templateTypeMissingInParameterMessage, $unresolvableParameterTypeMessage, $unresolvableReturnTypeMessage, $noDiscardVoidReturnMessage); } /** * @param Node\Param[] $parameters * @param Node\Identifier|Node\Name|Node\ComplexType|null $returnTypeNode * @param Node\AttributeGroup[] $attribGroups * @return list */ public function checkAnonymousFunction(Scope $scope, array $parameters, $returnTypeNode, array $attribGroups, string $parameterMessage, string $returnMessage, string $unionTypesMessage, string $unresolvableParameterTypeMessage, string $unresolvableReturnTypeMessage, string $noDiscardReturnTypeMessage): 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; } } $anonParamOriginalCasePairs = $this->getOriginalClassNamePairsFromTypeNode($param->type); $errors = array_merge($errors, $this->classCheck->checkClassNames($scope, array_map(static function (string $class) use ($param, $anonParamOriginalCasePairs): \PHPStan\Rules\ClassNameNodePair { $lowerClass = strtolower($class); if (isset($anonParamOriginalCasePairs[$lowerClass])) { return $anonParamOriginalCasePairs[$lowerClass]; } return new \PHPStan\Rules\ClassNameNodePair($class, $param->type); }, $type->getReferencedClasses()), \PHPStan\Rules\ClassNameUsageLocation::from(\PHPStan\Rules\ClassNameUsageLocation::PARAMETER_TYPE, ['parameterName' => $param->var->name, 'isInAnonymousFunction' => \true]), $this->checkClassCaseSensitivity)); } if ($this->phpVersion->deprecatesRequiredParameterAfterOptional()) { $errors = array_merge($errors, $this->checkRequiredParameterAfterOptional($parameters)); } if ($returnTypeNode === null) { return $errors; } if ($returnTypeNode instanceof Identifier && in_array($returnTypeNode->toLowerString(), ['void', 'never'], \true)) { foreach ($attribGroups as $attribGroup) { foreach ($attribGroup->attrs as $attrib) { if (strtolower($attrib->name->name) === 'nodiscard') { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($noDiscardReturnTypeMessage, $returnTypeNode->toString()))->line($returnTypeNode->getStartLine())->identifier('attribute.target')->build(); break 2; } } } } 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->getStartLine())->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; } } $anonReturnOriginalCasePairs = $this->getOriginalClassNamePairsFromTypeNode($returnTypeNode); $errors = array_merge($errors, $this->classCheck->checkClassNames($scope, array_map(static function (string $class) use ($returnTypeNode, $anonReturnOriginalCasePairs): \PHPStan\Rules\ClassNameNodePair { $lowerClass = strtolower($class); if (isset($anonReturnOriginalCasePairs[$lowerClass])) { return $anonReturnOriginalCasePairs[$lowerClass]; } return new \PHPStan\Rules\ClassNameNodePair($class, $returnTypeNode); }, $returnType->getReferencedClasses()), \PHPStan\Rules\ClassNameUsageLocation::from(\PHPStan\Rules\ClassNameUsageLocation::RETURN_TYPE, ['isInAnonymousFunction' => \true]), $this->checkClassCaseSensitivity)); return $errors; } /** * @return list * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\PropertyHook $methodNode */ public function checkClassMethod(Scope $scope, PhpMethodFromParserNodeReflection $methodReflection, $methodNode, string $parameterMessage, string $returnMessage, string $unionTypesMessage, string $templateTypeMissingInParameterMessage, string $unresolvableParameterTypeMessage, string $unresolvableReturnTypeMessage, string $selfOutMessage, string $noDiscardVoidReturnMessage): array { $errors = $this->checkParametersAcceptor($scope, $methodReflection, $methodNode, $parameterMessage, $returnMessage, $unionTypesMessage, $templateTypeMissingInParameterMessage, $unresolvableParameterTypeMessage, $unresolvableReturnTypeMessage, $noDiscardVoidReturnMessage); $selfOutType = $methodReflection->getSelfOutType(); if ($selfOutType !== null) { $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($scope, array_map(static fn(string $class): \PHPStan\Rules\ClassNameNodePair => new \PHPStan\Rules\ClassNameNodePair($class, $methodNode), $selfOutTypeReferencedClasses), \PHPStan\Rules\ClassNameUsageLocation::from(\PHPStan\Rules\ClassNameUsageLocation::PHPDOC_TAG_SELF_OUT), $this->checkClassCaseSensitivity)); } return $errors; } /** * @return list * @param \PHPStan\Reflection\Php\PhpMethodFromParserNodeReflection|\PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection $parametersAcceptor */ private function checkParametersAcceptor(Scope $scope, $parametersAcceptor, FunctionLike $functionNode, string $parameterMessage, string $returnMessage, string $unionTypesMessage, string $templateTypeMissingInParameterMessage, string $unresolvableParameterTypeMessage, string $unresolvableReturnTypeMessage, string $noDiscardReturnTypeMessage): 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; }; $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(); } $locationData = ['parameterName' => $parameter->getName()]; if ($parametersAcceptor instanceof PhpMethodFromParserNodeReflection) { $locationData['method'] = $parametersAcceptor; if (!$parametersAcceptor->getDeclaringClass()->isAnonymous()) { $locationData['currentClassName'] = $parametersAcceptor->getDeclaringClass()->getName(); } } else { $locationData['function'] = $parametersAcceptor; } $originalCasePairs = $this->getOriginalClassNamePairsFromTypeNode($parameterNodeCallback()->type); $errors = array_merge($errors, $this->classCheck->checkClassNames($scope, array_map(static function (string $class) use ($parameterNodeCallback, $originalCasePairs): \PHPStan\Rules\ClassNameNodePair { $lowerClass = strtolower($class); if (isset($originalCasePairs[$lowerClass])) { return $originalCasePairs[$lowerClass]; } return new \PHPStan\Rules\ClassNameNodePair($class, $parameterNodeCallback()); }, $referencedClasses), \PHPStan\Rules\ClassNameUsageLocation::from(\PHPStan\Rules\ClassNameUsageLocation::PARAMETER_TYPE, $locationData), $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(), $scope->isInClass() ? $scope->getClassReflection() : null); if ($this->unresolvableTypeHelper->containsUnresolvableType($nativeReturnType)) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message($unresolvableReturnTypeMessage)->nonIgnorable()->line($returnTypeNode->getStartLine())->identifier('return.unresolvableNativeType')->build(); } } if ($parametersAcceptor->mustUseReturnValue()->yes()) { $returnType = $parametersAcceptor->getReturnType(); if ($returnType->isVoid()->yes() || $returnType instanceof NeverType && $returnType->isExplicit()) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($noDiscardReturnTypeMessage, $returnType->describe(VerbosityLevel::typeOnly())))->line($returnTypeNode->getStartLine())->identifier('attribute.target')->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(); } $locationData = []; if ($parametersAcceptor instanceof PhpMethodFromParserNodeReflection) { $locationData['method'] = $parametersAcceptor; if (!$parametersAcceptor->getDeclaringClass()->isAnonymous()) { $locationData['currentClassName'] = $parametersAcceptor->getDeclaringClass()->getName(); } } else { $locationData['function'] = $parametersAcceptor; } $returnOriginalCasePairs = $this->getOriginalClassNamePairsFromTypeNode($functionNode->getReturnType()); $errors = array_merge($errors, $this->classCheck->checkClassNames($scope, array_map(static function (string $class) use ($returnTypeNode, $returnOriginalCasePairs): \PHPStan\Rules\ClassNameNodePair { $lowerClass = strtolower($class); if (isset($returnOriginalCasePairs[$lowerClass])) { return $returnOriginalCasePairs[$lowerClass]; } return new \PHPStan\Rules\ClassNameNodePair($class, $returnTypeNode); }, $returnTypeReferencedClasses), \PHPStan\Rules\ClassNameUsageLocation::from(\PHPStan\Rules\ClassNameUsageLocation::RETURN_TYPE, $locationData), $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 fn($type): bool => $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 non-empty-string[] */ private function getParameterReferencedClasses(ParameterReflection $parameter): array { if (!$parameter instanceof ExtendedParameterReflection) { return $parameter->getType()->getReferencedClasses(); } if ($this->checkThisOnly) { return $parameter->getNativeType()->getReferencedClasses(); } $moreClasses = []; 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 non-empty-string[] */ private function getReturnTypeReferencedClasses(ParametersAcceptor $parametersAcceptor): array { if (!$parametersAcceptor instanceof ExtendedParametersAcceptor) { return $parametersAcceptor->getReturnType()->getReferencedClasses(); } if ($this->checkThisOnly) { return $parametersAcceptor->getNativeReturnType()->getReferencedClasses(); } return array_merge($parametersAcceptor->getNativeReturnType()->getReferencedClasses(), $parametersAcceptor->getPhpDocReturnType()->getReferencedClasses()); } /** * @param \PhpParser\Node\Identifier|\PhpParser\Node\Name|\PhpParser\Node\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 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; } } } 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(); } /** * @return array * @param \PhpParser\Node\Identifier|\PhpParser\Node\Name|\PhpParser\Node\ComplexType|null $typeNode */ private function getOriginalClassNamePairsFromTypeNode($typeNode): array { if ($typeNode === null) { return []; } if ($typeNode instanceof Name) { $originalName = $typeNode->getAttribute('originalName'); if (!$originalName instanceof Name) { return []; } $resolvedName = $typeNode->toString(); $originalParts = $originalName->getParts(); $resolvedParts = $typeNode->getParts(); $originalPartsCount = count($originalParts); $resolvedPartsCount = count($resolvedParts); if ($originalPartsCount <= $resolvedPartsCount) { $prefixParts = array_slice($resolvedParts, 0, $resolvedPartsCount - $originalPartsCount); $originalCaseClassName = implode('\\', array_merge($prefixParts, $originalParts)); } else { $originalCaseClassName = $originalName->toString(); } if ($originalCaseClassName === $resolvedName) { return []; } return [strtolower($resolvedName) => new \PHPStan\Rules\ClassNameNodePair($originalCaseClassName, $typeNode)]; } if ($typeNode instanceof NullableType) { return $this->getOriginalClassNamePairsFromTypeNode($typeNode->type); } if ($typeNode instanceof UnionType || $typeNode instanceof IntersectionType) { $pairs = []; foreach ($typeNode->types as $innerType) { $pairs += $this->getOriginalClassNamePairsFromTypeNode($innerType); } return $pairs; } return []; } } 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->accepts($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 []; } } */ #[RegisteredRule(5)] final class ArrayFilterRule implements Rule { private ReflectionProvider $reflectionProvider; private bool $treatPhpDocTypesAsCertain; private bool $treatPhpDocTypesAsCertainTip; public function __construct( ReflectionProvider $reflectionProvider, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter('%tips.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 []; } } */ #[RegisteredRule(5)] final class ArrayValuesRule implements Rule { /** * @readonly */ private ReflectionProvider $reflectionProvider; /** * @readonly */ private bool $treatPhpDocTypesAsCertain; private bool $treatPhpDocTypesAsCertainTip; public function __construct( ReflectionProvider $reflectionProvider, #[AutowiredParameter] bool $treatPhpDocTypesAsCertain, #[AutowiredParameter('%tips.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_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 []; } } */ #[RegisteredRule(0)] final class ArrowFunctionAttributesRule implements Rule { private AttributesCheck $attributesCheck; public function __construct(AttributesCheck $attributesCheck) { $this->attributesCheck = $attributesCheck; } public function getNodeType(): string { return InArrowFunctionNode::class; } public function processNode(Node $node, Scope $scope): array { return $this->attributesCheck->check($scope, $node->getOriginalNode()->attrGroups, Attribute::TARGET_FUNCTION, 'function'); } } */ #[RegisteredRule(0)] final class ArrowFunctionReturnNullsafeByRefRule implements Rule { private NullsafeCheck $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()]; } } */ #[RegisteredRule(3)] final class ArrowFunctionReturnTypeRule implements Rule { private FunctionReturnTypeCheck $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(); } $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()); } } */ #[RegisteredRule(2)] final class CallCallablesRule implements Rule { private FunctionCallParametersCheck $check; private RuleLevelHelper $ruleLevelHelper; private bool $reportMaybes; public function __construct( FunctionCallParametersCheck $check, RuleLevelHelper $ruleLevelHelper, #[AutowiredParameter] 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 fn(Type $type): bool => $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 = TrinaryLogic::createYes(); foreach ($parametersAcceptors as $parametersAcceptor) { $acceptsNamedArguments = $acceptsNamedArguments->and($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, 'callable', $acceptsNamedArguments, 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.', '%s of ' . $callableDescription . ' expects %s, %s given.', 'Result of ' . $callableDescription . ' (void) is used.', '%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.', '%s of ' . $callableDescription . ' contains unresolvable type.', ucfirst($callableDescription) . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.')); } } */ #[RegisteredRule(0)] final class CallToFunctionParametersRule implements Rule { private ReflectionProvider $reflectionProvider; private FunctionCallParametersCheck $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', $function->acceptsNamedArguments(), '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.', '%s of function ' . $functionName . ' expects %s, %s given.', 'Result of function ' . $functionName . ' (void) is used.', '%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.', '%s of function ' . $functionName . ' contains unresolvable type.', 'Function ' . $functionName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.'); } } */ #[RegisteredRule(0)] final class CallToFunctionStatementWithNoDiscardRule implements Rule { private ReflectionProvider $reflectionProvider; private PhpVersion $phpVersion; public function __construct(ReflectionProvider $reflectionProvider, PhpVersion $phpVersion) { $this->reflectionProvider = $reflectionProvider; $this->phpVersion = $phpVersion; } public function getNodeType(): string { return Node\Stmt\Expression::class; } public function processNode(Node $node, Scope $scope): array { $funcCall = $node->expr; $isInVoidCast = \false; if ($funcCall instanceof Node\Expr\Cast\Void_) { $isInVoidCast = \true; $funcCall = $funcCall->expr; } if ($funcCall instanceof Node\Expr\BinaryOp\Pipe) { if ($funcCall->right instanceof Node\Expr\FuncCall) { if (!$funcCall->right->isFirstClassCallable()) { return []; } $funcCall = new Node\Expr\FuncCall($funcCall->right->name, []); } elseif ($funcCall->right instanceof Node\Expr\ArrowFunction) { $funcCall = $funcCall->right->expr; } } if (!$funcCall instanceof Node\Expr\FuncCall) { return []; } if ($funcCall->isFirstClassCallable()) { return []; } if (!$this->phpVersion->supportsNoDiscardAttribute()) { return []; } if ($funcCall->name instanceof Node\Name) { if (!$this->reflectionProvider->hasFunction($funcCall->name, $scope)) { return []; } $function = $this->reflectionProvider->getFunction($funcCall->name, $scope); $mustUseReturnValue = $function->mustUseReturnValue(); if ($isInVoidCast) { if ($mustUseReturnValue->no()) { return [RuleErrorBuilder::message(sprintf('Call to function %s() in (void) cast but function allows discarding return value.', $function->getName()))->identifier('function.inVoidCast')->build()]; } return []; } if (!$mustUseReturnValue->yes()) { return []; } return [RuleErrorBuilder::message(sprintf('Call to function %s() on a separate line discards return value.', $function->getName()))->identifier('function.resultDiscarded')->nonIgnorable()->build()]; } $callableType = $scope->getType($funcCall->name); if (!$callableType->isCallable()->yes()) { return []; } $mustUseReturnValue = TrinaryLogic::createNo(); foreach ($callableType->getCallableParametersAcceptors($scope) as $callableParametersAcceptor) { $mustUseReturnValue = $mustUseReturnValue->or($callableParametersAcceptor->mustUseReturnValue()); } if ($isInVoidCast) { if ($mustUseReturnValue->no()) { return [RuleErrorBuilder::message(sprintf('Call to callable %s in (void) cast but callable allows discarding return value.', $callableType->describe(VerbosityLevel::value())))->identifier('callable.inVoidCast')->build()]; } return []; } if (!$mustUseReturnValue->yes()) { return []; } return [RuleErrorBuilder::message(sprintf('Call to callable %s on a separate line discards return value.', $callableType->describe(VerbosityLevel::value())))->identifier('callable.resultDiscarded')->nonIgnorable()->build()]; } } */ #[RegisteredRule(4)] final class CallToFunctionStatementWithoutSideEffectsRule implements Rule { private ReflectionProvider $reflectionProvider; public const PHPSTAN_TESTING_FUNCTIONS = ['PHPStan\dumpNativeType', 'PHPStan\dumpType', 'PHPStan\dumpPhpDocType', 'PHPStan\debugScope', 'PHPStan\Testing\assertType', 'PHPStan\Testing\assertNativeType', 'PHPStan\Testing\assertSuperType', 'PHPStan\Testing\assertVariableCertainty']; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } public function getNodeType(): string { return NoopExpressionNode::class; } public function processNode(Node $node, Scope $scope): array { $expr = $node->getOriginalExpr(); if ($expr instanceof Node\Expr\BinaryOp\Pipe) { $expr = $expr->right; } if (!$expr instanceof Node\Expr\FuncCall) { return []; } $funcCall = $expr; if (!$funcCall->name instanceof Node\Name) { return []; } if (!$this->reflectionProvider->hasFunction($funcCall->name, $scope)) { return []; } $function = $this->reflectionProvider->getFunction($funcCall->name, $scope); if (count($function->getAsserts()->getAsserts()) > 0) { return []; } $functionName = $function->getName(); if (in_array($functionName, self::PHPSTAN_TESTING_FUNCTIONS, \true)) { 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()]; } } */ #[RegisteredRule(0)] final class CallToNonExistentFunctionRule implements Rule { private ReflectionProvider $reflectionProvider; private bool $checkFunctionNameCase; private bool $discoveringSymbolsTip; public function __construct( ReflectionProvider $reflectionProvider, #[AutowiredParameter] bool $checkFunctionNameCase, #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $this->reflectionProvider = $reflectionProvider; $this->checkFunctionNameCase = $checkFunctionNameCase; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } 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 []; } $errorBuilder = RuleErrorBuilder::message(sprintf('Function %s not found.', (string) $node->name))->identifier('function.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } return [$errorBuilder->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 []; } } */ #[RegisteredRule(5)] final class CallUserFuncRule implements Rule { private ReflectionProvider $reflectionProvider; private FunctionCallParametersCheck $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); $functionName = $functionReflection->getName(); if ($functionName === 'call_user_func') { $result = ArgumentsNormalizer::reorderCallUserFuncArguments($node, $scope); } elseif ($functionName === 'call_user_func_array') { $result = ArgumentsNormalizer::reorderCallUserFuncArrayArguments($node, $scope); } else { return []; } if ($result === null) { return []; } [$parametersAcceptor, $funcCall, $acceptsNamedArguments] = $result; $callableDescription = sprintf('callable passed to %s()', $functionName); return $this->check->check($parametersAcceptor, $scope, \false, $funcCall, 'function', $acceptsNamedArguments, 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.', '%s of ' . $callableDescription . ' expects %s, %s given.', 'Result of ' . $callableDescription . ' (void) is used.', '%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.', '%s of ' . $callableDescription . ' contains unresolvable type.', ucfirst($callableDescription) . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.'); } } */ #[RegisteredRule(0)] final class ClosureAttributesRule implements Rule { private AttributesCheck $attributesCheck; public function __construct(AttributesCheck $attributesCheck) { $this->attributesCheck = $attributesCheck; } public function getNodeType(): string { return InClosureNode::class; } public function processNode(Node $node, Scope $scope): array { return $this->attributesCheck->check($scope, $node->getOriginalNode()->attrGroups, Attribute::TARGET_FUNCTION, 'function'); } } */ #[RegisteredRule(3)] final class ClosureReturnTypeRule implements Rule { private FunctionReturnTypeCheck $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 []; } $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; } } */ #[RegisteredRule(0)] final class DefineParametersRule implements Rule { private PhpVersion $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()]; } } */ #[ValidatesStubFiles] final class DuplicateFunctionDeclarationRule implements Rule { private Reflector $reflector; private RelativePathHelper $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(fn(ReflectionFunction $function) => sprintf('- %s:%d', $this->relativePathHelper->getRelativePath($function->getFileName() ?? 'unknown'), $function->getStartLine()), $filteredFunctions))))->identifier('function.duplicate')->build()]; } } */ #[RegisteredRule(0)] final class ExistingClassesInArrowFunctionTypehintsRule implements Rule { private FunctionDefinitionCheck $check; private PhpVersion $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(), $node->getAttrGroups(), '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.', 'Attribute NoDiscard cannot be used on %s anonymous function.')); } } */ #[RegisteredRule(0)] final class ExistingClassesInClosureTypehintsRule implements Rule { private FunctionDefinitionCheck $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(), $node->getAttrGroups(), '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.', 'Attribute NoDiscard cannot be used on %s anonymous function.'); } } */ #[RegisteredRule(0)] #[ValidatesStubFiles] final class ExistingClassesInTypehintsRule implements Rule { private FunctionDefinitionCheck $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($scope, $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), sprintf('Attribute NoDiscard cannot be used on %%s function %s().', $functionName)); } } */ #[RegisteredRule(0)] final class FilterVarRule implements Rule { private ReflectionProvider $reflectionProvider; private FilterFunctionReturnTypeHelper $filterFunctionReturnTypeHelper; private PhpVersion $phpVersion; public function __construct(ReflectionProvider $reflectionProvider, FilterFunctionReturnTypeHelper $filterFunctionReturnTypeHelper, PhpVersion $phpVersion) { $this->reflectionProvider = $reflectionProvider; $this->filterFunctionReturnTypeHelper = $filterFunctionReturnTypeHelper; $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->reflectionProvider->resolveFunctionName($node->name, $scope) !== 'filter_var') { return []; } $args = $node->getArgs(); if (count($args) < 3) { return []; } if (!$this->phpVersion->hasFilterThrowOnFailureConstant() || !$this->reflectionProvider->hasConstant(new Name\FullyQualified('FILTER_THROW_ON_FAILURE'), null)) { return []; } $flagsType = $scope->getType($args[2]->value); if ($this->filterFunctionReturnTypeHelper->hasFlag('FILTER_NULL_ON_FAILURE', $flagsType)->and($this->filterFunctionReturnTypeHelper->hasFlag('FILTER_THROW_ON_FAILURE', $flagsType))->yes()) { return [RuleErrorBuilder::message('Cannot use both FILTER_NULL_ON_FAILURE and FILTER_THROW_ON_FAILURE.')->identifier('filterVar.nullOnFailureAndThrowOnFailure')->build()]; } return []; } } */ #[RegisteredRule(0)] final class FunctionAttributesRule implements Rule { private AttributesCheck $attributesCheck; public function __construct(AttributesCheck $attributesCheck) { $this->attributesCheck = $attributesCheck; } public function getNodeType(): string { return InFunctionNode::class; } public function processNode(Node $node, Scope $scope): array { return $this->attributesCheck->check($scope, $node->getOriginalNode()->attrGroups, Attribute::TARGET_FUNCTION, 'function'); } } */ #[RegisteredRule(0)] final class FunctionCallableRule implements Rule { private ReflectionProvider $reflectionProvider; private RuleLevelHelper $ruleLevelHelper; private PhpVersion $phpVersion; private bool $checkFunctionNameCase; private bool $reportMaybes; public function __construct( ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper, PhpVersion $phpVersion, #[AutowiredParameter] bool $checkFunctionNameCase, #[AutowiredParameter] 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 fn(Type $type): bool => $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 []; } } */ #[RegisteredRule(5)] final class ImplodeParameterCastableToStringRule implements Rule { private ReflectionProvider $reflectionProvider; private ParameterCastableToStringCheck $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 fn(Type $t) => $t->toString(), $functionName, $argName); if ($error === null) { continue; } $errors[] = $error; } return $errors; } } */ #[RegisteredRule(2)] 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->accepts($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; } } */ #[RegisteredRule(2)] 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->accepts($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; } } */ #[RegisteredRule(2)] 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->accepts($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; } } */ #[RegisteredRule(0)] 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()]; } } */ #[RegisteredRule(0)] 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 fn($name) => $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; } } */ #[RegisteredRule(0)] final class InvalidParameterNameRule implements Rule { public function getNodeType(): string { return Node\Param::class; } public function processNode(Node $node, Scope $scope): array { if (!$node->var instanceof Node\Expr\Variable) { return []; } if (!is_string($node->var->name)) { return []; } $variableName = $node->var->name; if (in_array($variableName, Scope::SUPERGLOBAL_VARIABLES, \true)) { return [RuleErrorBuilder::message(sprintf('Superglobal variable $%s cannot be used as a parameter.', $variableName))->identifier('parameter.superglobal')->nonIgnorable()->build()]; } if ($variableName === 'this') { return [RuleErrorBuilder::message('Cannot use $this as parameter.')->identifier('parameter.this')->nonIgnorable()->build()]; } return []; } } */ #[RegisteredRule(6)] #[ValidatesStubFiles] final class MissingFunctionParameterTypehintRule implements Rule { private MissingTypehintCheck $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(); $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 ($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; } } */ #[RegisteredRule(6)] #[ValidatesStubFiles] final class MissingFunctionReturnTypehintRule implements Rule { private MissingTypehintCheck $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; } } */ #[RegisteredRule(0)] final class ParamAttributesRule implements Rule { private AttributesCheck $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 ParameterCastableToNumberRule implements Rule { private ReflectionProvider $reflectionProvider; private ParameterCastableToStringCheck $parameterCastableToStringCheck; private PhpVersion $phpVersion; public function __construct(ReflectionProvider $reflectionProvider, ParameterCastableToStringCheck $parameterCastableToStringCheck, PhpVersion $phpVersion) { $this->reflectionProvider = $reflectionProvider; $this->parameterCastableToStringCheck = $parameterCastableToStringCheck; $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->reflectionProvider->hasFunction($node->name, $scope)) { return []; } $functionReflection = $this->reflectionProvider->getFunction($node->name, $scope); $functionName = $functionReflection->getName(); if (!in_array($functionName, ['array_sum', 'array_product'], \true)) { return []; } $origArgs = $node->getArgs(); if (count($origArgs) !== 1) { return []; } $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $origArgs, $functionReflection->getVariants(), $functionReflection->getNamedArgumentsVariants()); $errorMessage = 'Parameter %s of function %s expects an array of values castable to number, %s given.'; $functionParameters = $parametersAcceptor->getParameters(); $castFn = $this->phpVersion->supportsObjectsInArraySumProduct() ? static fn(Type $t) => $t->toNumber() : static fn(Type $t) => !$t instanceof MixedType && !$t->isObject()->no() ? new ErrorType() : $t->toNumber(); $error = $this->parameterCastableToStringCheck->checkParameter($origArgs[0], $scope, $errorMessage, $castFn, $functionName, $this->parameterCastableToStringCheck->getParameterName($origArgs[0], 0, $functionParameters[0] ?? null)); return $error !== null ? [$error] : []; } } */ #[RegisteredRule(5)] final class ParameterCastableToStringRule implements Rule { private ReflectionProvider $reflectionProvider; private ParameterCastableToStringCheck $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.'; 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 = []; $functionParameters = $parametersAcceptor->getParameters(); foreach ($argsToCheck as $argIdx => $arg) { $error = $this->parameterCastableToStringCheck->checkParameter($arg, $scope, $errorMessage, static fn(Type $t) => $t->toString(), $functionName, $this->parameterCastableToStringCheck->getParameterName($arg, $argIdx, $functionParameters[$argIdx] ?? null)); if ($error === null) { continue; } $errors[] = $error; } return $errors; } } */ #[RegisteredRule(0)] final class PrintfArrayParametersRule implements Rule { private \PHPStan\Rules\Functions\PrintfHelper $printfHelper; private ReflectionProvider $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(); $count = $this->printfHelper->getPrintfPlaceholdersCount($format); if ($count === null) { return [RuleErrorBuilder::message(sprintf('Call to %s contains an invalid placeholder.', $name))->identifier(sprintf('argument.%s', $name))->build()]; } $placeHoldersCounts[] = $count; } 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 \PHPStan\Type\Constant\ConstantIntegerType|\PHPStan\Type\IntegerRangeType $placeHoldersCount * @param \PHPStan\Type\Constant\ConstantIntegerType|\PHPStan\Type\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(); } } [bs%s]|l?[cdeEgfFGouxX])'; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function getPrintfPlaceholdersCount(string $format): ?int { return $this->getPlaceholdersCount(self::PRINTF_SPECIFIER_PATTERN, $format); } /** @phpstan-return array> parameter index => placeholders */ public function getPrintfPlaceholders(string $format): ?array { return $this->parsePlaceholders(self::PRINTF_SPECIFIER_PATTERN, $format); } public function getScanfPlaceholdersCount(string $format): ?int { try { $result = @sscanf('', '%*n' . $format); } catch (ValueError $e) { return null; } if ($result === null) { return null; } return count($result); } /** * @phpstan-return array>|null parameter index => placeholders */ private function parsePlaceholders(string $specifiersPattern, string $format): ?array { $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 []; } $placeholders = array_filter($matches, static fn(array $match): bool => strlen($match['before']) % 2 === 0); $result = []; $parsedPlaceholders = []; $parameterIdx = 0; $placeholderNumber = 0; foreach ($placeholders as $placeholder) { $placeholderNumber++; $showValueSuffix = \false; if (isset($placeholder['width']) && $placeholder['width'] !== '') { $parsedPlaceholders[] = new \PHPStan\Rules\Functions\PrintfPlaceholder(sprintf('"%s" (width)', $placeholder[0]), $parameterIdx++, $placeholderNumber, 'strict-int'); $showValueSuffix = \true; } if (isset($placeholder['precision']) && $placeholder['precision'] !== '') { $parsedPlaceholders[] = new \PHPStan\Rules\Functions\PrintfPlaceholder(sprintf('"%s" (precision)', $placeholder[0]), $parameterIdx++, $placeholderNumber, 'strict-int'); $showValueSuffix = \true; } $specifier = $placeholder['specifier'] ?? ''; if ($specifier === '') { // A placeholder is invalid. return null; } $parsedPlaceholders[] = new \PHPStan\Rules\Functions\PrintfPlaceholder(sprintf('"%s"', $placeholder[0]) . ($showValueSuffix ? ' (value)' : ''), isset($placeholder['position']) && $placeholder['position'] !== '' ? $placeholder['position'] - 1 : $parameterIdx++, $placeholderNumber, $this->getAcceptingTypeBySpecifier($specifier)); } foreach ($parsedPlaceholders as $placeholder) { $result[$placeholder->parameterIndex][] = $placeholder; } return $result; } /** @phpstan-return 'string'|'int'|'float'|'mixed' */ private function getAcceptingTypeBySpecifier(string $specifier): string { if ($specifier === 's') { return 'string'; } if (in_array($specifier, ['d', 'u', 'c', 'o', 'x', 'X', 'b'], \true)) { return 'int'; } if (in_array($specifier, ['e', 'E', 'f', 'F', 'g', 'G', 'h', 'H'], \true)) { return 'float'; } return 'mixed'; } private function getPlaceholdersCount(string $specifiersPattern, string $format): ?int { $placeholdersMap = $this->parsePlaceholders($specifiersPattern, $format); if ($placeholdersMap === null) { return null; } $paramIndices = array_keys($placeholdersMap); return $paramIndices === [] ? 0 : max($paramIndices) + 1; } } */ final class PrintfParameterTypeRule implements Rule { private \PHPStan\Rules\Functions\PrintfHelper $printfHelper; private ReflectionProvider $reflectionProvider; private RuleLevelHelper $ruleLevelHelper; private bool $checkStrictPrintfPlaceholderTypes; private const FORMAT_ARGUMENT_POSITIONS = ['printf' => 0, 'sprintf' => 0, 'fprintf' => 1]; private const MINIMUM_NUMBER_OF_ARGUMENTS = ['printf' => 1, 'sprintf' => 1, 'fprintf' => 2]; public function __construct(\PHPStan\Rules\Functions\PrintfHelper $printfHelper, ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper, bool $checkStrictPrintfPlaceholderTypes) { $this->printfHelper = $printfHelper; $this->reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; $this->checkStrictPrintfPlaceholderTypes = $checkStrictPrintfPlaceholderTypes; } 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); $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); $formatArgTypeStrings = $formatArgType->getConstantStrings(); // Let's start simple for now. if (count($formatArgTypeStrings) !== 1) { return []; } $formatString = $formatArgTypeStrings[0]; $format = $formatString->getValue(); $placeholderMap = $this->printfHelper->getPrintfPlaceholders($format); if ($placeholderMap === null) { // Already reported by PrintfParametersRule. return []; } $errors = []; $typeAllowedByCallToFunctionParametersRule = new UnionType([new StringAlwaysAcceptingObjectWithToStringType(), new IntegerType(), new FloatType(), new BooleanType(), new NullType()]); // Type on the left can go to the type on the right, but not vice versa. $allowedTypeNameMap = $this->checkStrictPrintfPlaceholderTypes ? ['strict-int' => 'int', 'int' => 'int', 'float' => 'float', 'string' => 'string', 'mixed' => 'string'] : [ 'strict-int' => 'int', 'int' => 'castable to int', 'float' => 'castable to float', // These are here just for completeness. They won't be used because, these types are already enforced by // CallToFunctionParametersRule. 'string' => 'castable to string', 'mixed' => 'castable to string', ]; for ($i = $formatArgumentPosition + 1, $j = 0; $i < $argsCount; $i++, $j++) { // Some arguments may be skipped entirely. foreach ($placeholderMap[$j] ?? [] as $placeholder) { $argType = $this->ruleLevelHelper->findTypeToCheck($scope, $args[$i]->value, '', fn(Type $t) => $placeholder->doesArgumentTypeMatchPlaceholder($t, $this->checkStrictPrintfPlaceholderTypes))->getType(); if ($argType instanceof ErrorType || $placeholder->doesArgumentTypeMatchPlaceholder($argType, $this->checkStrictPrintfPlaceholderTypes)) { continue; } // This is already reported by CallToFunctionParametersRule if (!$this->ruleLevelHelper->accepts($typeAllowedByCallToFunctionParametersRule, $argType, $scope->isDeclareStrictTypes())->result) { continue; } if (!array_key_exists($placeholder->acceptingType, $allowedTypeNameMap)) { throw new ShouldNotHappenException(); } $errors[] = RuleErrorBuilder::message(sprintf('Parameter #%d of function %s is expected to be %s by placeholder #%d (%s), %s given.', $i + 1, $name, $allowedTypeNameMap[$placeholder->acceptingType], $placeholder->placeholderNumber, $placeholder->label, $argType->describe(VerbosityLevel::typeOnly())))->identifier('argument.type')->build(); } } return $errors; } } */ #[RegisteredRule(0)] final class PrintfParametersRule implements Rule { private \PHPStan\Rules\Functions\PrintfHelper $printfHelper; private ReflectionProvider $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 ($tempPlaceHoldersCount === null) { return [RuleErrorBuilder::message(sprintf('Call to %s contains an invalid placeholder.', $name))->identifier(sprintf('argument.%s', $name))->build()]; } 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 []; } } label = $label; $this->parameterIndex = $parameterIndex; $this->placeholderNumber = $placeholderNumber; $this->acceptingType = $acceptingType; } public function doesArgumentTypeMatchPlaceholder(Type $argumentType, bool $strictPlaceholderTypes): bool { switch ($this->acceptingType) { case 'strict-int': return (new IntegerType())->accepts($argumentType, \true)->yes(); case 'int': return $strictPlaceholderTypes ? (new IntegerType())->accepts($argumentType, \true)->yes() : !$argumentType->toInteger() instanceof ErrorType; case 'float': return $strictPlaceholderTypes ? (new UnionType([ new FloatType(), // numeric-string is allowed for consistency with phpstan-strict-rules. new IntersectionType([new StringType(), new AccessoryNumericStringType()]), ]))->accepts($argumentType, \true)->yes() : !$argumentType->toFloat() instanceof ErrorType; case 'string': case 'mixed': // The function signature already limits the parameters to stringable types, so there's // no point in checking string again here. return !$strictPlaceholderTypes || (new UnionType([ new StringAlwaysAcceptingObjectWithToStringType(), // float also accepts int. new FloatType(), // null is allowed for consistency with phpstan-strict-rules (e.g. $string . $null). new NullType(), ]))->accepts($argumentType, \true)->yes(); // Without this PHPStan with PHP 7.4 reports "...should return bool but return statement is missing." // Presumably, because promoted properties are turned into regular properties and the phpdoc isn't applied to the property. default: throw new ShouldNotHappenException('Unexpected type ' . $this->acceptingType); } } } */ #[RegisteredRule(5)] final class RandomIntParametersRule implements Rule { private ReflectionProvider $reflectionProvider; private PhpVersion $phpVersion; private bool $reportMaybes; public function __construct( ReflectionProvider $reflectionProvider, PhpVersion $phpVersion, #[AutowiredParameter] bool $reportMaybes ) { $this->reflectionProvider = $reflectionProvider; $this->phpVersion = $phpVersion; $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 = $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, $this->phpVersion); if ($isSmaller->maybe() && $this->reportMaybes) { if ($minType instanceof IntegerRangeType && ($minType->getMin() === null || $minType->getMax() === null) || $maxType instanceof IntegerRangeType && ($maxType->getMin() === null || $maxType->getMax() === null)) { return []; } } 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 []; } } */ #[RegisteredRule(0)] 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; } } */ #[RegisteredRule(0)] final class ReturnNullsafeByRefRule implements Rule { private NullsafeCheck $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; } } */ #[RegisteredRule(3)] final class ReturnTypeRule implements Rule { private FunctionReturnTypeCheck $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()); } } */ #[RegisteredRule(5)] final class SortParameterCastableToStringRule implements Rule { private ReflectionProvider $reflectionProvider; private ParameterCastableToStringCheck $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()); $normalizedFuncCall = ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $node); if ($normalizedFuncCall === null) { return []; } $normalizedArgs = $normalizedFuncCall->getArgs(); if (!array_key_exists(0, $normalizedArgs)) { return []; } $functionParameters = $parametersAcceptor->getParameters(); $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 fn(Type $t) => $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 fn(Type $t) => $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; } } */ #[RegisteredRule(1)] final class UnusedClosureUsesRule implements Rule { private UnusedFunctionParametersCheck $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 fn(Node\ClosureUse $use): Node\Expr\Variable => $use->var, $node->uses), $node->stmts, 'Anonymous function has an unused use $%s.', 'closure.unusedUse'); } } */ #[RegisteredRule(4)] final class UselessFunctionReturnValueRule implements Rule { private ReflectionProvider $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 []; } } */ #[RegisteredRule(0)] 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; } } */ #[RegisteredRule(3)] final class YieldFromTypeRule implements Rule { private RuleLevelHelper $ruleLevelHelper; private bool $reportMaybes; public function __construct( RuleLevelHelper $ruleLevelHelper, #[AutowiredParameter] 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->accepts($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->accepts($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; } } */ #[RegisteredRule(3)] final class YieldInGeneratorRule implements Rule { private bool $reportMaybes; public function __construct( #[AutowiredParameter] 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()]; } } */ #[RegisteredRule(3)] final class YieldTypeRule implements Rule { private RuleLevelHelper $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->accepts($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->accepts($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; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class ClassAncestorsRule implements Rule { private \PHPStan\Rules\Generics\GenericAncestorsCheck $genericAncestorsCheck; private \PHPStan\Rules\Generics\CrossCheckInterfacesHelper $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 fn(ExtendsTag $tag): Type => $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 fn(ImplementsTag $tag): Type => $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); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class ClassTemplateTypeRule implements Rule { private \PHPStan\Rules\Generics\TemplateTypeCheck $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)); } } */ 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; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class EnumAncestorsRule implements Rule { private \PHPStan\Rules\Generics\GenericAncestorsCheck $genericAncestorsCheck; private \PHPStan\Rules\Generics\CrossCheckInterfacesHelper $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 fn(ExtendsTag $tag): Type => $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 fn(ImplementsTag $tag): Type => $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 enum %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); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] 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()]; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class FunctionSignatureVarianceRule implements Rule { private \PHPStan\Rules\Generics\VarianceCheck $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'); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class FunctionTemplateTypeRule implements Rule { private FileTypeMapper $fileTypeMapper; private \PHPStan\Rules\Generics\TemplateTypeCheck $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)); } } reflectionProvider = $reflectionProvider; $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->varianceCheck = $varianceCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->skipCheckGenericClasses = $skipCheckGenericClasses; $this->checkMissingTypehints = $checkMissingTypehints; } /** * @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 fn(Name $nameNode): string => $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->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 ($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->checkMissingTypehints) { 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 fn(Type $type) => $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; } } */ 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 fn(Type $type) => $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())) { if ($classReflection->getName() !== ReflectionClass::class || $templateType->getName() !== 'T') { $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; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class InterfaceAncestorsRule implements Rule { private \PHPStan\Rules\Generics\GenericAncestorsCheck $genericAncestorsCheck; private \PHPStan\Rules\Generics\CrossCheckInterfacesHelper $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 fn(ExtendsTag $tag): Type => $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 fn(ImplementsTag $tag): Type => $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); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class InterfaceTemplateTypeRule implements Rule { private \PHPStan\Rules\Generics\TemplateTypeCheck $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)); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class MethodSignatureVarianceRule implements Rule { private \PHPStan\Rules\Generics\VarianceCheck $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'); } } 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; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class MethodTagTemplateTypeRule implements Rule { private \PHPStan\Rules\Generics\MethodTagTemplateTypeCheck $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()); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class MethodTagTemplateTypeTraitRule implements Rule { private \PHPStan\Rules\Generics\MethodTagTemplateTypeCheck $check; private ReflectionProvider $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()); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class MethodTemplateTypeRule implements Rule { private FileTypeMapper $fileTypeMapper; private \PHPStan\Rules\Generics\TemplateTypeCheck $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; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class PropertyVarianceRule implements Rule { private \PHPStan\Rules\Generics\VarianceCheck $varianceCheck; public function __construct(\PHPStan\Rules\Generics\VarianceCheck $varianceCheck) { $this->varianceCheck = $varianceCheck; } 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 = $this->hasRestrictedWriteAccess($node) ? TemplateTypeVariance::createCovariant() : TemplateTypeVariance::createInvariant(); return $this->varianceCheck->check($variance, $propertyReflection->getReadableType(), sprintf('in property %s::$%s', SprintfHelper::escapeFormatString($classReflection->getDisplayName()), SprintfHelper::escapeFormatString($node->getName()))); } private function hasRestrictedWriteAccess(ClassPropertyNode $node): bool { if ($node->isReadOnly() || $node->isReadOnlyByPhpDoc()) { return \true; } if ($node->isPrivateSet()) { return \true; } $hooks = $node->getHooks(); if ($hooks === []) { return \false; } foreach ($hooks as $hook) { if ($hook->name->name === 'set') { return \false; } } return \true; } } 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 fn(string $referencedClass): ClassNameNodePair => new ClassNameNodePair($referencedClass, $node), $boundType->getReferencedClasses()); $messages = array_merge($messages, $this->classCheck->checkClassNames($scope, $classNameNodePairs, ClassNameUsageLocation::from(ClassNameUsageLocation::PHPDOC_TAG_TEMPLATE_BOUND, ['templateTagName' => $templateTagName]), $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 && $boundTypeClass !== NullType::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 fn(string $referencedClass): ClassNameNodePair => new ClassNameNodePair($referencedClass, $node), $defaultType->getReferencedClasses()); $messages = array_merge($messages, $this->classCheck->checkClassNames($scope, $classNameNodePairs, ClassNameUsageLocation::from(ClassNameUsageLocation::PHPDOC_TAG_TEMPLATE_DEFAULT, ['templateTagName' => $templateTagName]), $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; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class TraitTemplateTypeRule implements Rule { private FileTypeMapper $fileTypeMapper; private \PHPStan\Rules\Generics\TemplateTypeCheck $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)); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class UsedTraitsRule implements Rule { private FileTypeMapper $fileTypeMapper; private \PHPStan\Rules\Generics\GenericAncestorsCheck $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 fn(UsesTag $tag): Type => $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)); } } */ public function checkParametersAcceptor(ExtendedParametersAcceptor $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 = 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; } $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()); } } */ #[RegisteredRule(0)] 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; } } helper = $helper; } public function isRestrictedClassConstantUsage(ClassConstantReflection $constantReflection, Scope $scope): ?RestrictedUsage { $isConstantInternal = $constantReflection->isInternal()->yes(); $declaringClass = $constantReflection->getDeclaringClass(); $isDeclaringClassInternal = $declaringClass->isInternal(); if (!$isConstantInternal && !$isDeclaringClassInternal) { return null; } $declaringClassName = $declaringClass->getName(); if (!$this->helper->shouldBeReported($scope, $declaringClassName)) { return null; } $namespace = array_slice(explode('\\', $declaringClassName), 0, -1)[0] ?? null; if ($namespace === null) { if (!$isConstantInternal) { return RestrictedUsage::create(sprintf('Access to constant %s of internal %s %s.', $constantReflection->getName(), strtolower($constantReflection->getDeclaringClass()->getClassTypeDescription()), $constantReflection->getDeclaringClass()->getDisplayName()), sprintf('classConstant.internal%s', $constantReflection->getDeclaringClass()->getClassTypeDescription())); } return RestrictedUsage::create(sprintf('Access to internal constant %s::%s.', $constantReflection->getDeclaringClass()->getDisplayName(), $constantReflection->getName()), 'classConstant.internal'); } if (!$isConstantInternal) { return RestrictedUsage::create(sprintf('Access to constant %s of internal %s %s from outside its root namespace %s.', $constantReflection->getName(), strtolower($constantReflection->getDeclaringClass()->getClassTypeDescription()), $constantReflection->getDeclaringClass()->getDisplayName(), $namespace), sprintf('classConstant.internal%s', $constantReflection->getDeclaringClass()->getClassTypeDescription())); } return RestrictedUsage::create(sprintf('Access to internal constant %s::%s from outside its root namespace %s.', $constantReflection->getDeclaringClass()->getDisplayName(), $constantReflection->getName(), $namespace), 'classConstant.internal'); } } helper = $helper; } public function isRestrictedClassNameUsage(ClassReflection $classReflection, Scope $scope, ClassNameUsageLocation $location): ?RestrictedUsage { if (!$classReflection->isInternal()) { return null; } if (!$this->helper->shouldBeReported($scope, $classReflection->getName())) { return null; } if ($location->value === ClassNameUsageLocation::STATIC_METHOD_CALL) { $method = $location->getMethod(); if ($method !== null) { if ($method->isInternal()->yes() || $method->getDeclaringClass()->isInternal()) { return null; } } } if ($location->value === ClassNameUsageLocation::STATIC_PROPERTY_ACCESS) { $property = $location->getProperty(); if ($property !== null) { if ($property->isInternal()->yes() || $property->getDeclaringClass()->isInternal()) { return null; } } } if ($location->value === ClassNameUsageLocation::CLASS_CONSTANT_ACCESS) { $constant = $location->getClassConstant(); if ($constant !== null) { if ($constant->isInternal()->yes() || $constant->getDeclaringClass()->isInternal()) { return null; } } } return RestrictedUsage::create($location->createMessage(sprintf('internal %s %s', strtolower($classReflection->getClassTypeDescription()), $classReflection->getDisplayName())), $location->createIdentifier(sprintf('internal%s', $classReflection->getClassTypeDescription()))); } } helper = $helper; } public function isRestrictedFunctionUsage(FunctionReflection $functionReflection, Scope $scope): ?RestrictedUsage { if (!$functionReflection->isInternal()->yes()) { return null; } if (!$this->helper->shouldBeReported($scope, $functionReflection->getName())) { return null; } $namespace = array_slice(explode('\\', $functionReflection->getName()), 0, -1)[0] ?? null; if ($namespace === null) { return RestrictedUsage::create(sprintf('Call to internal function %s().', $functionReflection->getName()), 'function.internal'); } return RestrictedUsage::create(sprintf('Call to internal function %s() from outside its root namespace %s.', $functionReflection->getName(), $namespace), 'function.internal'); } } helper = $helper; } public function isRestrictedMethodUsage(ExtendedMethodReflection $methodReflection, Scope $scope): ?RestrictedUsage { $isMethodInternal = $methodReflection->isInternal()->yes(); $declaringClass = $methodReflection->getDeclaringClass(); $isDeclaringClassInternal = $declaringClass->isInternal(); if (!$isMethodInternal && !$isDeclaringClassInternal) { return null; } $declaringClassName = $declaringClass->getName(); if (!$this->helper->shouldBeReported($scope, $declaringClassName)) { return null; } $namespace = array_slice(explode('\\', $declaringClassName), 0, -1)[0] ?? null; if ($namespace === null) { if (!$isMethodInternal) { return RestrictedUsage::create(sprintf('Call to %smethod %s() of internal %s %s.', $methodReflection->isStatic() ? 'static ' : '', $methodReflection->getName(), strtolower($methodReflection->getDeclaringClass()->getClassTypeDescription()), $methodReflection->getDeclaringClass()->getDisplayName()), sprintf('%s.internal%s', $methodReflection->isStatic() ? 'staticMethod' : 'method', $methodReflection->getDeclaringClass()->getClassTypeDescription())); } return RestrictedUsage::create(sprintf('Call to internal %smethod %s::%s().', $methodReflection->isStatic() ? 'static ' : '', $methodReflection->getDeclaringClass()->getDisplayName(), $methodReflection->getName()), sprintf('%s.internal', $methodReflection->isStatic() ? 'staticMethod' : 'method')); } if (!$isMethodInternal) { return RestrictedUsage::create(sprintf('Call to %smethod %s() of internal %s %s from outside its root namespace %s.', $methodReflection->isStatic() ? 'static ' : '', $methodReflection->getName(), strtolower($methodReflection->getDeclaringClass()->getClassTypeDescription()), $methodReflection->getDeclaringClass()->getDisplayName(), $namespace), sprintf('%s.internal%s', $methodReflection->isStatic() ? 'staticMethod' : 'method', $methodReflection->getDeclaringClass()->getClassTypeDescription())); } return RestrictedUsage::create(sprintf('Call to internal %smethod %s::%s() from outside its root namespace %s.', $methodReflection->isStatic() ? 'static ' : '', $methodReflection->getDeclaringClass()->getDisplayName(), $methodReflection->getName(), $namespace), sprintf('%s.internal', $methodReflection->isStatic() ? 'staticMethod' : 'method')); } } helper = $helper; } public function isRestrictedPropertyUsage(ExtendedPropertyReflection $propertyReflection, Scope $scope): ?RestrictedUsage { $isPropertyInternal = $propertyReflection->isInternal()->yes(); $declaringClass = $propertyReflection->getDeclaringClass(); $isDeclaringClassInternal = $declaringClass->isInternal(); if (!$isPropertyInternal && !$isDeclaringClassInternal) { return null; } $declaringClassName = $declaringClass->getName(); if (!$this->helper->shouldBeReported($scope, $declaringClassName)) { return null; } $namespace = array_slice(explode('\\', $declaringClassName), 0, -1)[0] ?? null; if ($namespace === null) { if (!$isPropertyInternal) { return RestrictedUsage::create(sprintf('Access to %sproperty $%s of internal %s %s.', $propertyReflection->isStatic() ? 'static ' : '', $propertyReflection->getName(), strtolower($propertyReflection->getDeclaringClass()->getClassTypeDescription()), $propertyReflection->getDeclaringClass()->getDisplayName()), sprintf('%s.internal%s', $propertyReflection->isStatic() ? 'staticProperty' : 'property', $propertyReflection->getDeclaringClass()->getClassTypeDescription())); } return RestrictedUsage::create(sprintf('Access to internal %sproperty %s::$%s.', $propertyReflection->isStatic() ? 'static ' : '', $propertyReflection->getDeclaringClass()->getDisplayName(), $propertyReflection->getName()), sprintf('%s.internal', $propertyReflection->isStatic() ? 'staticProperty' : 'property')); } if (!$isPropertyInternal) { return RestrictedUsage::create(sprintf('Access to %sproperty $%s of internal %s %s from outside its root namespace %s.', $propertyReflection->isStatic() ? 'static ' : '', $propertyReflection->getName(), strtolower($propertyReflection->getDeclaringClass()->getClassTypeDescription()), $propertyReflection->getDeclaringClass()->getDisplayName(), $namespace), sprintf('%s.internal%s', $propertyReflection->isStatic() ? 'staticProperty' : 'property', $propertyReflection->getDeclaringClass()->getClassTypeDescription())); } return RestrictedUsage::create(sprintf('Access to internal %sproperty %s::$%s from outside its root namespace %s.', $propertyReflection->isStatic() ? 'static ' : '', $propertyReflection->getDeclaringClass()->getDisplayName(), $propertyReflection->getName(), $namespace), sprintf('%s.internal', $propertyReflection->isStatic() ? 'staticProperty' : 'property')); } } getNamespace(); if ($currentNamespace === null) { $classReflection = $scope->getClassReflection(); if ($classReflection === null) { return \true; } return $classReflection->getName() !== $name; } $currentNamespace = explode('\\', $currentNamespace)[0]; $namespace = array_slice(explode('\\', $name), 0, -1)[0] ?? null; return !str_starts_with($namespace . '\\', $currentNamespace . '\\'); } } propertyDescriptor = $propertyDescriptor; $this->propertyReflectionFinder = $propertyReflectionFinder; $this->checkAdvancedIsset = $checkAdvancedIsset; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; } /** * @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->getScopeType($expr) : $scope->getScopeNativeType($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->getScopeType($expr->var) : $scope->getScopeNativeType($expr->var); if (!$type->isOffsetAccessible()->yes()) { return $error ?? $this->checkUndefined($expr->var, $scope, $operatorDescription, $identifier); } $dimType = $this->treatPhpDocTypesAsCertain ? $scope->getScopeType($expr->dim) : $scope->getScopeNativeType($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 ??= $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->toMutatingScope()); 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; } if ($propertyReflection->hasNativeType() && !$propertyReflection->isVirtual()->yes()) { if ($expr instanceof Node\Expr\PropertyFetch && $expr->name instanceof Node\Identifier && $expr->var instanceof Expr\Variable && $expr->var->name === 'this' && $scope->hasExpressionType(new PropertyInitializationExpr($propertyReflection->getName()))->yes()) { return $this->generateError($propertyReflection->getNativeType(), sprintf('%s %s', $this->propertyDescriptor->describeProperty($propertyReflection, $scope, $expr), $operatorDescription), static function (Type $type) use ($typeMessageCallback): ?string { $originalMessage = $typeMessageCallback($type); if ($originalMessage === null) { return null; } if (str_starts_with($originalMessage, 'is not')) { return sprintf('%s nor uninitialized', $originalMessage); } return sprintf('%s and initialized', $originalMessage); }, $identifier, 'initializedProperty'); } if (!$scope->hasExpressionType($expr)->yes()) { $nativeReflection = $propertyReflection->getNativeReflection(); if ($nativeReflection !== null && !$nativeReflection->getNativeReflection()->hasDefaultValue() && (!$nativeReflection->isPromoted() || !$nativeReflection->isReadOnly() && !$nativeReflection->isHooked())) { return null; } } } $propertyDescription = $this->propertyDescriptor->describeProperty($propertyReflection, $scope, $expr); $propertyType = $propertyReflection->getWritableType(); 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 (!$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->getScopeType($expr) : $scope->getScopeNativeType($expr), sprintf('Expression %s', $operatorDescription), $typeMessageCallback, $identifier, 'expr'); if ($error !== null) { return $error; } if ($expr instanceof Expr\NullsafePropertyFetch) { 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->getScopeType($expr->var) : $scope->getScopeNativeType($expr->var); $dimType = $this->treatPhpDocTypesAsCertain ? $scope->getScopeType($expr->dim) : $scope->getScopeNativeType($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'|'initializedProperty' $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(); } } */ #[RegisteredRule(0)] 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\Int_) { $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 === 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 (in_array($parentStmtType, [Stmt\For_::class, Stmt\Foreach_::class, Stmt\Do_::class, Stmt\While_::class, Stmt\Switch_::class], \true)) { $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 []; } } */ #[RegisteredRule(0)] final class DeclareStrictTypesRule implements Rule { /** * @readonly */ private ExprPrinter $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\Int_ || !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()]; } } */ #[RegisteredRule(0)] final class RequireFileExistsRule implements Rule { private string $currentWorkingDirectory; public function __construct( #[AutowiredParameter] 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; } } 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; } } */ #[RegisteredRule(0)] 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 []; } } */ #[RegisteredRule(0)] 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()]; } } */ #[RegisteredRule(0)] final class CallMethodsRule implements Rule { private \PHPStan\Rules\Methods\MethodCallCheck $methodCallCheck; private FunctionCallParametersCheck $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 { $errors = []; if ($node->name instanceof Node\Identifier) { $methodNameScopes = [$node->name->name => $scope]; } else { $nameType = $scope->getType($node->name); $methodNameScopes = []; foreach ($nameType->getConstantStrings() as $constantString) { $name = $constantString->getValue(); $methodNameScopes[$name] = $scope->filterByTruthyValue(new Identical($node->name, new String_($name))); } } foreach ($methodNameScopes as $methodName => $methodScope) { $errors = array_merge($errors, $this->processSingleMethodCall($methodScope, $node, (string) $methodName)); } return $errors; } /** * @return list */ private function processSingleMethodCall(Scope $scope, MethodCall $node, string $methodName): array { [$errors, $methodReflection] = $this->methodCallCheck->check($scope, $methodName, $node->var, $node->name); 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', $methodReflection->acceptsNamedArguments(), '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.', '%s of method ' . $messagesMethodName . ' expects %s, %s given.', 'Result of method ' . $messagesMethodName . ' (void) is used.', '%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.', '%s of method ' . $messagesMethodName . ' contains unresolvable type.', 'Method ' . $messagesMethodName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.')); } } */ #[RegisteredRule(2)] 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 []; } if ($scope->isInClass() && $scope->getClassReflection()->isFinal()) { return []; } $classType = $scope->resolveTypeByName($className); if (!$classType->hasMethod($methodName)->yes()) { return []; } $method = $classType->getMethod($methodName, $scope); if (!$method->isPrivate()) { return []; } return [RuleErrorBuilder::message(sprintf('Unsafe call to private method %s::%s() through static::.', $method->getDeclaringClass()->getDisplayName(), $method->getName()))->line($node->name->getStartLine())->identifier('staticClassAccess.privateMethod')->build()]; } } */ #[RegisteredRule(0)] final class CallStaticMethodsRule implements Rule { private \PHPStan\Rules\Methods\StaticMethodCallCheck $methodCallCheck; private FunctionCallParametersCheck $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 { $errors = []; if ($node->name instanceof Node\Identifier) { $methodNameScopes = [$node->name->name => $scope]; } else { $nameType = $scope->getType($node->name); $methodNameScopes = []; foreach ($nameType->getConstantStrings() as $constantString) { $name = $constantString->getValue(); $methodNameScopes[$name] = $scope->filterByTruthyValue(new Identical($node->name, new String_($name))); } } foreach ($methodNameScopes as $methodName => $methodScope) { $errors = array_merge($errors, $this->processSingleMethodCall($methodScope, $node, (string) $methodName)); } return $errors; } /** * @return list */ private function processSingleMethodCall(Scope $scope, StaticCall $node, string $methodName): array { [$errors, $method] = $this->methodCallCheck->check($scope, $methodName, $node->class, $node->name); 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, 'staticMethod', $method->acceptsNamedArguments(), $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.', '%s of ' . $lowercasedMethodName . ' expects %s, %s given.', 'Result of ' . $lowercasedMethodName . ' (void) is used.', '%s of ' . $lowercasedMethodName . ' is passed by reference, so it expects variables only.', 'Unable to resolve the template type %s in call to ' . $lowercasedMethodName, 'Missing parameter $%s in call to ' . $lowercasedMethodName . '.', 'Unknown parameter $%s in call to ' . $lowercasedMethodName . '.', 'Return type of call to ' . $lowercasedMethodName . ' contains unresolvable type.', '%s of ' . $lowercasedMethodName . ' contains unresolvable type.', $displayMethodName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.')); return $errors; } } */ #[RegisteredRule(4)] final class CallToConstructorStatementWithoutSideEffectsRule implements Rule { private ReflectionProvider $reflectionProvider; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } 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()) { return [RuleErrorBuilder::message(sprintf('Call to new %s() on a separate line has no effect.', $classReflection->getDisplayName()))->identifier('new.resultUnused')->build()]; } $constructor = $classReflection->getConstructor(); if (count($constructor->getAsserts()->getAsserts()) > 0) { return []; } $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()]; } } */ #[RegisteredRule(0)] final class CallToMethodStatementWithNoDiscardRule implements Rule { private RuleLevelHelper $ruleLevelHelper; private PhpVersion $phpVersion; public function __construct(RuleLevelHelper $ruleLevelHelper, PhpVersion $phpVersion) { $this->ruleLevelHelper = $ruleLevelHelper; $this->phpVersion = $phpVersion; } public function getNodeType(): string { return Node\Stmt\Expression::class; } public function processNode(Node $node, Scope $scope): array { $methodCall = $node->expr; $isInVoidCast = \false; if ($methodCall instanceof Node\Expr\Cast\Void_) { $isInVoidCast = \true; $methodCall = $methodCall->expr; } if ($methodCall instanceof Node\Expr\BinaryOp\Pipe) { if ($methodCall->right instanceof Node\Expr\MethodCall || $methodCall->right instanceof Node\Expr\NullsafeMethodCall) { if (!$methodCall->right->isFirstClassCallable()) { return []; } $methodCall = new Node\Expr\MethodCall($methodCall->right->var, $methodCall->right->name, []); } elseif ($methodCall->right instanceof Node\Expr\ArrowFunction) { $methodCall = $methodCall->right->expr; } } if (!$methodCall instanceof Node\Expr\MethodCall && !$methodCall instanceof Node\Expr\NullsafeMethodCall) { return []; } if (!$methodCall->name instanceof Node\Identifier) { return []; } if ($methodCall->isFirstClassCallable()) { return []; } if (!$this->phpVersion->supportsNoDiscardAttribute()) { return []; } $methodName = $methodCall->name->toString(); $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope($scope, $methodCall->var), '', static fn(Type $type): bool => $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); $mustUseReturnValue = $method->mustUseReturnValue(); if ($isInVoidCast) { if ($mustUseReturnValue->no()) { return [RuleErrorBuilder::message(sprintf('Call to %s %s::%s() in (void) cast but method allows discarding return value.', $method->isStatic() ? 'static method' : 'method', $method->getDeclaringClass()->getDisplayName(), $method->getName()))->identifier('method.inVoidCast')->build()]; } return []; } if (!$mustUseReturnValue->yes()) { return []; } return [RuleErrorBuilder::message(sprintf('Call to %s %s::%s() on a separate line discards return value.', $method->isStatic() ? 'static method' : 'method', $method->getDeclaringClass()->getDisplayName(), $method->getName()))->identifier('method.resultDiscarded')->nonIgnorable()->build()]; } } */ #[RegisteredRule(4)] final class CallToMethodStatementWithoutSideEffectsRule implements Rule { private RuleLevelHelper $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\BinaryOp\Pipe) { $methodCall = $methodCall->right; } if ($methodCall instanceof Node\Expr\NullsafeMethodCall) { if (!$methodCall->name instanceof Node\Identifier) { return []; } $scope = $scope->filterByTruthyValue(new Node\Expr\BinaryOp\NotIdentical($methodCall->var, new Node\Expr\ConstFetch(new Node\Name('null')))); } elseif ($methodCall instanceof Node\Expr\MethodCall) { if (!$methodCall->name instanceof Node\Identifier) { return []; } } else { return []; } $methodName = $methodCall->name->toString(); $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope($scope, $methodCall->var), '', static fn(Type $type): bool => $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); if (count($method->getAsserts()->getAsserts()) > 0) { 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('method.resultUnused')->build()]; } } */ #[RegisteredRule(0)] final class CallToStaticMethodStatementWithNoDiscardRule implements Rule { private RuleLevelHelper $ruleLevelHelper; private ReflectionProvider $reflectionProvider; private PhpVersion $phpVersion; public function __construct(RuleLevelHelper $ruleLevelHelper, ReflectionProvider $reflectionProvider, PhpVersion $phpVersion) { $this->ruleLevelHelper = $ruleLevelHelper; $this->reflectionProvider = $reflectionProvider; $this->phpVersion = $phpVersion; } public function getNodeType(): string { return Node\Stmt\Expression::class; } public function processNode(Node $node, Scope $scope): array { $methodCall = $node->expr; $isInVoidCast = \false; if ($methodCall instanceof Node\Expr\Cast\Void_) { $isInVoidCast = \true; $methodCall = $methodCall->expr; } if ($methodCall instanceof Node\Expr\BinaryOp\Pipe) { if ($methodCall->right instanceof Node\Expr\StaticCall) { if (!$methodCall->right->isFirstClassCallable()) { return []; } $methodCall = new Node\Expr\StaticCall($methodCall->right->class, $methodCall->right->name, []); } elseif ($methodCall->right instanceof Node\Expr\ArrowFunction) { $methodCall = $methodCall->right->expr; } } if (!$methodCall instanceof Node\Expr\StaticCall) { return []; } if (!$methodCall->name instanceof Node\Identifier) { return []; } if ($methodCall->isFirstClassCallable()) { return []; } if (!$this->phpVersion->supportsNoDiscardAttribute()) { return []; } $methodName = $methodCall->name->toString(); if ($methodCall->class instanceof Node\Name) { $className = $scope->resolveName($methodCall->class); if (!$this->reflectionProvider->hasClass($className)) { return []; } $calledOnType = new ObjectType($className); } else { $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope($scope, $methodCall->class), '', static fn(Type $type): bool => $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); $mustUseReturnValue = $method->mustUseReturnValue(); if ($isInVoidCast) { if ($mustUseReturnValue->no()) { return [RuleErrorBuilder::message(sprintf('Call to %s %s::%s() in (void) cast but method allows discarding return value.', $method->isStatic() ? 'static method' : 'method', $method->getDeclaringClass()->getDisplayName(), $method->getName()))->identifier('staticMethod.inVoidCast')->build()]; } return []; } if (!$mustUseReturnValue->yes()) { return []; } return [RuleErrorBuilder::message(sprintf('Call to %s %s::%s() on a separate line discards return value.', $method->isStatic() ? 'static method' : 'method', $method->getDeclaringClass()->getDisplayName(), $method->getName()))->identifier('staticMethod.resultDiscarded')->nonIgnorable()->build()]; } } */ #[RegisteredRule(4)] final class CallToStaticMethodStatementWithoutSideEffectsRule implements Rule { private RuleLevelHelper $ruleLevelHelper; private ReflectionProvider $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\BinaryOp\Pipe) { $staticCall = $staticCall->right; } 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 fn(Type $type): bool => $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 []; } if (count($method->getAsserts()->getAsserts()) > 0) { 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()]; } } */ #[RegisteredRule(0)] final class ConsistentConstructorDeclarationRule implements Rule { public function getNodeType(): string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope): array { $method = $node->getMethodReflection(); if (strtolower($method->getName()) !== '__construct') { return []; } $classReflection = $node->getClassReflection(); if (!$classReflection->hasConsistentConstructor()) { return []; } if ($classReflection->isFinal()) { return []; } if (!$method->isPrivate()) { return []; } return [RuleErrorBuilder::message('Private constructor cannot be enforced as consistent for child classes.')->identifier('consistentConstructor.private')->build()]; } } */ #[RegisteredRule(0)] final class ConsistentConstructorRule implements Rule { private ConsistentConstructorHelper $consistentConstructorHelper; private \PHPStan\Rules\Methods\MethodParameterComparisonHelper $methodParameterComparisonHelper; private \PHPStan\Rules\Methods\MethodVisibilityComparisonHelper $methodVisibilityComparisonHelper; public function __construct(ConsistentConstructorHelper $consistentConstructorHelper, \PHPStan\Rules\Methods\MethodParameterComparisonHelper $methodParameterComparisonHelper, \PHPStan\Rules\Methods\MethodVisibilityComparisonHelper $methodVisibilityComparisonHelper) { $this->consistentConstructorHelper = $consistentConstructorHelper; $this->methodParameterComparisonHelper = $methodParameterComparisonHelper; $this->methodVisibilityComparisonHelper = $methodVisibilityComparisonHelper; } 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 []; } $parentConstructor = $this->consistentConstructorHelper->findConsistentConstructor($parent); if ($parentConstructor === null) { return []; } return array_merge($this->methodParameterComparisonHelper->compare($parentConstructor, $parentConstructor->getDeclaringClass(), $method, \true), $this->methodVisibilityComparisonHelper->compare($parentConstructor, $parentConstructor->getDeclaringClass(), $method)); } } */ #[RegisteredRule(0)] 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()]; } } extensions = $extensions; } public function getExtensions(): array { return $this->extensions; } } */ #[RegisteredRule(0)] #[ValidatesStubFiles] final class ExistingClassesInTypehintsRule implements Rule { private FunctionDefinitionCheck $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($scope, $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), sprintf('Attribute NoDiscard cannot be used on %%s method %s::%s().', $className, $methodName)); } } */ #[RegisteredRule(0)] final class FinalPrivateMethodRule implements Rule { public function getNodeType(): string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope): array { $method = $node->getMethodReflection(); if ($method->getName() === '__construct') { return []; } if ($scope->getPhpVersion()->producesWarningForFinalPrivateMethods()->no()) { 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()]; } } */ #[RegisteredRule(2)] 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->accepts($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; } } container = $container; } public function getExtensions(): array { return $this->extensions ??= $this->container->getServicesByTag(static::EXTENSION_TAG); } } */ #[RegisteredRule(0)] final class MethodAttributesRule implements Rule { private AttributesCheck $attributesCheck; public function __construct(AttributesCheck $attributesCheck) { $this->attributesCheck = $attributesCheck; } public function getNodeType(): string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope): array { return $this->attributesCheck->check($scope, $node->getOriginalNode()->attrGroups, Attribute::TARGET_METHOD, 'method'); } } reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; $this->checkFunctionNameCase = $checkFunctionNameCase; $this->reportMagicMethods = $reportMagicMethods; } /** * @return array{list, ExtendedMethodReflection|null} * @param \PhpParser\Node\Identifier|\PhpParser\Node\Expr $astName */ public function check(Scope $scope, string $methodName, Expr $var, $astName): array { $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope($scope, $var), sprintf('Call to method %s() on an unknown class %%s.', SprintfHelper::escapeFormatString($methodName)), static fn(Type $type): bool => $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->isClassString()->yes()) { return [[RuleErrorBuilder::message(sprintf('Cannot call method %s() on %s.', $methodName, $typeForDescribe->describe(VerbosityLevel::typeOnly())))->line($astName->getStartLine())->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()))->line($astName->getStartLine())->identifier('method.private')->build()], $methodReflection]; } $parentClassReflection = $parentClassReflection->getParentClass(); } } if ($astName instanceof Expr) { $methodExistsExpr = new Expr\FuncCall(new FullyQualified('method_exists'), [new Arg($var), new Arg($astName)]); if ($scope->getType($methodExistsExpr)->isTrue()->yes()) { return [[], null]; } } return [[RuleErrorBuilder::message(sprintf('Call to an undefined method %s::%s().', $typeForDescribe->describe(VerbosityLevel::typeOnly()), $methodName))->line($astName->getStartLine())->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()))->line($astName->getStartLine())->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))->line($astName->getStartLine())->identifier('method.nameCase')->build(); } return [$errors, $methodReflection]; } } */ #[RegisteredRule(0)] final class MethodCallableRule implements Rule { private \PHPStan\Rules\Methods\MethodCallCheck $methodCallCheck; private PhpVersion $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(); return $this->methodCallCheck->check($scope, $methodNameName, $node->getVar(), $node->getName())[0]; } } phpVersion = $phpVersion; } /** * @return list */ public function compare(ExtendedMethodReflection $prototype, ClassReflection $prototypeDeclaringClass, PhpMethodFromParserNodeReflection $method, bool $ignorable): 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(\true), $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(\true), $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(\true), $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(\true), $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(\true), $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(\true), $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(\true), $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(\true), $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(\true), $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(\true), $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(); } return $messages; } private 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 instanceof ConstantArrayType) { return \true; } if ($prototypeParameterType->isObject()->yes() && $prototypeParameterType->getObjectClassNames() === [Traversable::class]) { return \true; } } return \false; } return $methodParameterType->isSuperTypeOf($prototypeParameterType)->yes(); } } phpVersion = $phpVersion; $this->phpClassReflectionExtension = $phpClassReflectionExtension; } /** * Finds the prototype method that a class method should be validated against. * Returns two prototypes with different purposes: * - Signature prototype: Used for validating method signature (parameters, return type, ...). * - Inheritance prototype: Used for validating inheritance rules (final keyword, override attribute, ...). * Also, return a bool to precise if the visibility of the prototype needs to be respected. * * @return array{ExtendedMethodReflection, ClassReflection, bool, ExtendedMethodReflection, ClassReflection}|null */ public 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, $method, $method->getDeclaringClass()]; } } 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(); $prototype = $this->phpClassReflectionExtension->createUserlandMethodReflection($trait, $classReflection, $methodReflection, $declaringTrait->getName()); return [$prototype, $declaringTrait, \false, $prototype, $declaringTrait]; } } } $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; } } $prototype = $method; if (strtolower($method->getName()) === '__construct') { foreach ($parentClass->getInterfaces() as $interface) { if ($interface->hasNativeMethod($method->getName())) { $prototype = $interface->getNativeMethod($method->getName()); break; } } } return [$prototype, $prototype->getDeclaringClass(), \true, $method, $declaringClass]; } } */ final class MethodSignatureRule implements Rule { private \PHPStan\Rules\Methods\ParentMethodHelper $parentMethodHelper; private bool $reportMaybes; private bool $reportStatic; private bool $reportMethodPurityOverride; public function __construct(\PHPStan\Rules\Methods\ParentMethodHelper $parentMethodHelper, bool $reportMaybes, bool $reportStatic, bool $reportMethodPurityOverride) { $this->parentMethodHelper = $parentMethodHelper; $this->reportMaybes = $reportMaybes; $this->reportStatic = $reportStatic; $this->reportMethodPurityOverride = $reportMethodPurityOverride; } 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->parentMethodHelper->collectParentMethods($methodName, $method->getDeclaringClass()) as [$parentMethod, $parentMethodDeclaringClass]) { if ($this->reportMethodPurityOverride && $method->isPure()->no() && $parentMethod->isPure()->yes()) { $errors[] = RuleErrorBuilder::message(sprintf('Impure method %s::%s() overrides pure method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $parentMethodDeclaringClass->getDisplayName(), $parentMethod->getName()))->identifier('method.impure')->build(); } $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(); } $methodParameters = $method->getParameters(); $parentVariantParameters = $parentVariant->getParameters(); $parameterResults = $this->checkParameterTypeCompatibility($declaringClass, $methodParameters, $parentVariantParameters); foreach ($parameterResults as $parameterIndex => [$parameterResult, $parameterType, $parentParameterType]) { if ($parameterResult->yes()) { continue; } if (!$parameterResult->no() && !$this->reportMaybes) { continue; } $parameter = $methodParameters[$parameterIndex]; $parentParameter = $parentVariantParameters[$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 array{TrinaryLogic, Type, Type} */ private function checkReturnTypeCompatibility(ClassReflection $declaringClass, ExtendedParametersAcceptor $currentVariant, ExtendedParametersAcceptor $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)->result, TypehintHelper::decideType($currentVariant->getNativeReturnType(), $currentVariant->getPhpDocReturnType()), $originalParentReturnType]; } /** * @param ExtendedParameterReflection[] $parameters * @param ExtendedParameterReflection[] $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)->result, 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); }); } } */ public function compare(ExtendedMethodReflection $prototype, ClassReflection $prototypeDeclaringClass, PhpMethodFromParserNodeReflection $method): array { /** @var list $messages */ $messages = []; 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(\true), $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(\true), $prototype->getName()))->nonIgnorable()->identifier('method.visibility')->build(); } return $messages; } } */ #[RegisteredRule(0)] 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()]; } } */ #[RegisteredRule(0)] final class MissingMagicSerializationMethodsRule implements Rule { private PhpVersion $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; } } */ #[RegisteredRule(0)] 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; } } */ #[RegisteredRule(6)] #[ValidatesStubFiles] final class MissingMethodParameterTypehintRule implements Rule { private MissingTypehintCheck $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(); $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 ($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; } } */ #[RegisteredRule(6)] #[ValidatesStubFiles] final class MissingMethodReturnTypehintRule implements Rule { private MissingTypehintCheck $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; } } */ #[RegisteredRule(6)] #[ValidatesStubFiles] final class MissingMethodSelfOutTypeRule implements Rule { private MissingTypehintCheck $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; } } */ #[RegisteredRule(4)] final class NullsafeMethodCallRule implements Rule { public function getNodeType(): string { return Node\Expr\NullsafeMethodCall::class; } public function processNode(Node $node, Scope $scope): array { $calledOnType = $scope->getScopeType($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())))->line($node->name->getStartLine())->identifier('nullsafe.neverNull')->build()]; } } */ #[RegisteredRule(0)] #[ValidatesStubFiles] final class OverridingMethodRule implements Rule { private PhpVersion $phpVersion; private \PHPStan\Rules\Methods\MethodSignatureRule $methodSignatureRule; private bool $checkPhpDocMethodSignatures; private \PHPStan\Rules\Methods\MethodParameterComparisonHelper $methodParameterComparisonHelper; private \PHPStan\Rules\Methods\MethodVisibilityComparisonHelper $methodVisibilityComparisonHelper; private \PHPStan\Rules\Methods\MethodPrototypeFinder $methodPrototypeFinder; private bool $checkMissingOverrideMethodAttribute; public function __construct( PhpVersion $phpVersion, \PHPStan\Rules\Methods\MethodSignatureRule $methodSignatureRule, #[AutowiredParameter] bool $checkPhpDocMethodSignatures, \PHPStan\Rules\Methods\MethodParameterComparisonHelper $methodParameterComparisonHelper, \PHPStan\Rules\Methods\MethodVisibilityComparisonHelper $methodVisibilityComparisonHelper, \PHPStan\Rules\Methods\MethodPrototypeFinder $methodPrototypeFinder, #[AutowiredParameter] bool $checkMissingOverrideMethodAttribute ) { $this->phpVersion = $phpVersion; $this->methodSignatureRule = $methodSignatureRule; $this->checkPhpDocMethodSignatures = $checkPhpDocMethodSignatures; $this->methodParameterComparisonHelper = $methodParameterComparisonHelper; $this->methodVisibilityComparisonHelper = $methodVisibilityComparisonHelper; $this->methodPrototypeFinder = $methodPrototypeFinder; $this->checkMissingOverrideMethodAttribute = $checkMissingOverrideMethodAttribute; } public function getNodeType(): string { return InClassMethodNode::class; } /** * @param \PHPStan\Analyser\Scope&\PHPStan\Analyser\NodeCallbackInvoker $scope */ public function processNode(Node $node, \PHPStan\Analyser\Scope $scope): array { $method = $node->getMethodReflection(); $prototypeData = $this->methodPrototypeFinder->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(\true), $parentConstructor->getName()))->nonIgnorable()->identifier('method.parentMethodFinal')->build()], $node, $scope); } if ($parentConstructor->isFinal()->yes()) { return $this->addErrors([RuleErrorBuilder::message(sprintf('Method %s::%s() overrides @final method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $parent->getDisplayName(\true), $parentConstructor->getName()))->identifier('method.parentMethodFinalByPhpDoc')->build()], $node, $scope); } } } if ($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')->fixNode($node->getOriginalNode(), function (Node\Stmt\ClassMethod $method) { $method->attrGroups = $this->filterOverrideAttribute($method->attrGroups); return $method; })->build()]; } return []; } [$prototype, $prototypeDeclaringClass, $checkVisibility, $inheritancePrototype, $inheritancePrototypeDeclaringClass] = $prototypeData; $messages = []; if ($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(), $inheritancePrototypeDeclaringClass->getDisplayName(\true), $inheritancePrototype->getName()))->identifier('method.missingOverride')->fixNode($node->getOriginalNode(), static function (Node\Stmt\ClassMethod $method) { $method->attrGroups[] = new Node\AttributeGroup([new Attribute(new Node\Name\FullyQualified('Override'))]); return $method; })->build(); } if ($inheritancePrototype->isFinalByKeyword()->yes()) { $messages[] = RuleErrorBuilder::message(sprintf('Method %s::%s() overrides final method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $inheritancePrototypeDeclaringClass->getDisplayName(\true), $inheritancePrototype->getName()))->nonIgnorable()->identifier('method.parentMethodFinal')->build(); } elseif ($inheritancePrototype->isFinal()->yes()) { $messages[] = RuleErrorBuilder::message(sprintf('Method %s::%s() overrides @final method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $inheritancePrototypeDeclaringClass->getDisplayName(\true), $inheritancePrototype->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(\true), $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(\true), $prototype->getName()))->nonIgnorable()->identifier('method.static')->build(); } if ($checkVisibility) { $messages = array_merge($messages, $this->methodVisibilityComparisonHelper->compare($prototype, $prototypeDeclaringClass, $method)); } $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(\true), $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, \false)); if (!$prototypeVariant instanceof ExtendedFunctionVariant) { return $this->addErrors($messages, $node, $scope); } $prototypeReturnType = $prototypeVariant->getNativeReturnType(); $reportReturnType = \true; if ($this->phpVersion->hasTentativeReturnTypes()) { $reportReturnType = !$realPrototype instanceof MethodPrototypeReflection || $realPrototype->getTentativeReturnType() === null || (is_bool($prototype->isBuiltin()) ? !$prototype->isBuiltin() : $prototype->isBuiltin()->no()); } else if ($realPrototype instanceof MethodPrototypeReflection && $realPrototype->isInternal()) { if ((is_bool($prototype->isBuiltin()) ? $prototype->isBuiltin() : $prototype->isBuiltin()->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 && (is_bool($prototype->isBuiltin()) ? $prototype->isBuiltin() : $prototype->isBuiltin()->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(\true), $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(\true), $prototype->getName()))->nonIgnorable()->identifier('method.childReturnType')->build(); } } return $this->addErrors($messages, $node, $scope); } /** * @param Node\AttributeGroup[] $attrGroups * @return Node\AttributeGroup[] */ private function filterOverrideAttribute(array $attrGroups): array { foreach ($attrGroups as $i => $attrGroup) { foreach ($attrGroup->attrs as $j => $attr) { if ($attr->name->toLowerString() !== 'override') { continue; } unset($attrGroup->attrs[$j]); if (count($attrGroup->attrs) !== 0) { continue; } unset($attrGroups[$i]); } } return $attrGroups; } /** * @param list $errors * @return list * @param \PHPStan\Analyser\Scope&\PHPStan\Analyser\NodeCallbackInvoker $scope */ private function addErrors(array $errors, InClassMethodNode $classMethod, \PHPStan\Analyser\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; } } phpClassReflectionExtension = $phpClassReflectionExtension; } /** * @return list */ public 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()]; } foreach ($class->getTraits(\true) as $trait) { $nativeTraitReflection = $trait->getNativeReflection(); if (!$nativeTraitReflection->hasMethod($methodName)) { continue; } $methodReflection = $nativeTraitReflection->getMethod($methodName); $isAbstract = $methodReflection->isAbstract(); if (!$isAbstract) { continue; } // Skip traits that inherited the method from a sub-trait // The actual declaring trait will be processed separately if ($methodReflection->getBetterReflection()->getDeclaringClass()->getName() !== $trait->getName()) { continue; } $declaringTrait = $trait->getNativeMethod($methodName)->getDeclaringClass(); $parentMethods[] = [$this->phpClassReflectionExtension->createUserlandMethodReflection($trait, $class, $methodReflection, $declaringTrait->getName()), $declaringTrait]; } return $parentMethods; } } */ #[RegisteredRule(3)] final class ReturnTypeRule implements Rule { private FunctionReturnTypeCheck $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 []; } if ($method->isPropertyHook()) { $methodDescription = sprintf('%s hook for property %s::$%s', ucfirst($method->getPropertyHookName()), $method->getDeclaringClass()->getDisplayName(), $method->getHookedPropertyName()); } else { $methodDescription = sprintf('Method %s::%s()', $method->getDeclaringClass()->getDisplayName(), $method->getName()); } $returnType = $method->getReturnType(); $errors = $this->returnTypeCheck->checkReturnType($scope, $returnType, $node->expr, $node, sprintf('%s should return %%s but empty return statement found.', $methodDescription), sprintf('%s with return type void returns %%s but should not return anything.', $methodDescription), sprintf('%s should return %%s but returns %%s.', $methodDescription), sprintf('%s should never return but return statement found.', $methodDescription), $method->isGenerator()); if (count($errors) === 1 && $errors[0]->getIdentifier() === 'return.type' && !$errors[0] instanceof TipRuleError && $errors[0] instanceof LineRuleError && $method->getDeclaringClass()->is(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; } } reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; $this->classCheck = $classCheck; $this->checkFunctionNameCase = $checkFunctionNameCase; $this->discoveringSymbolsTip = $discoveringSymbolsTip; $this->reportMagicMethods = $reportMagicMethods; } /** * @param Name|Expr $class * @return array{list, ExtendedMethodReflection|null} * @param \PhpParser\Node\Identifier|\PhpParser\Node\Expr $astName */ public function check(Scope $scope, string $methodName, $class, $astName): 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))->line($astName->getStartLine())->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))->line($astName->getStartLine())->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()))->line($astName->getStartLine())->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]; } $errorBuilder = RuleErrorBuilder::message(sprintf('Call to static method %s() on an unknown class %s.', $methodName, $className))->line($astName->getStartLine())->identifier('class.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } return [[$errorBuilder->build()], null]; } $locationData = []; $locationClassReflection = $this->reflectionProvider->getClass($className); if ($locationClassReflection->hasMethod($methodName)) { $locationData['method'] = $locationClassReflection->getMethod($methodName, $scope); } $errors = $this->classCheck->checkClassNames($scope, [new ClassNameNodePair($className, $class)], ClassNameUsageLocation::from(ClassNameUsageLocation::STATIC_METHOD_CALL, $locationData)); $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 fn(Type $type): bool => $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())))->line($astName->getStartLine())->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))->line($astName->getStartLine())->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 fn(string $objectClassName) => TrinaryLogic::createFromBoolean($scope->isInClass() && $scope->getClassReflection()->is($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()))->line($astName->getStartLine())->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()))->line($astName->getStartLine())->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()))->line($astName->getStartLine())->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))->line($astName->getStartLine())->identifier('staticMethod.nameCase')->build(); } return [$errors, $method]; } } */ #[RegisteredRule(0)] final class StaticMethodCallableRule implements Rule { private \PHPStan\Rules\Methods\StaticMethodCallCheck $methodCallCheck; private PhpVersion $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(); return $this->methodCallCheck->check($scope, $methodNameName, $node->getClass(), $node->getName())[0]; } } */ #[RegisteredRule(0)] final class MissingReturnRule implements Rule { private bool $checkExplicitMixedMissingReturn; private bool $checkPhpDocMissingReturn; public function __construct( #[AutowiredParameter] bool $checkExplicitMixedMissingReturn, #[AutowiredParameter] 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 PhpMethodFromParserNodeReflection) { if (!$scopeFunction->isPropertyHook()) { $description = sprintf('Method %s::%s()', $scopeFunction->getDeclaringClass()->getDisplayName(), $scopeFunction->getName()); } else { $description = sprintf('%s hook for property %s::$%s', ucfirst($scopeFunction->getPropertyHookName()), $scopeFunction->getDeclaringClass()->getDisplayName(), $scopeFunction->getHookedPropertyName()); } } 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()]; } } checkMissingCallableSignature = $checkMissingCallableSignature; $this->skipCheckGenericClasses = $skipCheckGenericClasses; $this->checkGenericIterableClasses = $checkGenericIterableClasses; } /** * @return Type[] */ public function getIterableTypesWithMissingValueTypehint(Type $type): array { $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 IntersectionType && $type->isCallable()->yes() && $type->isArray()->yes()) { $nonArrayInner = []; foreach ($type->getTypes() as $innerType) { if ($innerType->isArray()->yes()) { continue; } $nonArrayInner[] = $innerType; } if (count($nonArrayInner) === 1) { return $traverse($nonArrayInner[0]); } return $traverse(new IntersectionType($nonArrayInner)); } 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 { $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 ($classReflection->getName() === Traversable::class || !$this->checkGenericIterableClasses && 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 fn(Type $type) => $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; } } */ #[RegisteredRule(0)] 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->getStartLine())->nonIgnorable()->build()]; } $usedNames[$lowerNamespace][] = $name; return []; } return []; } /** * @param Node\UseItem[] $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->getStartLine())->nonIgnorable()->build(); continue; } $usedNames[$lowerNamespace][] = $useAlias; } return $errors; } /** * @param \PhpParser\Node\Stmt\Use_|\PhpParser\Node\Stmt\GroupUse|\PhpParser\Node\UseItem $use */ private function shouldBeIgnored($use): bool { return in_array($use->type, [Use_::TYPE_FUNCTION, Use_::TYPE_CONSTANT], \true); } } */ #[RegisteredRule(0)] final class ExistingNamesInGroupUseRule implements Rule { private ReflectionProvider $reflectionProvider; private ClassNameCheck $classCheck; private bool $checkFunctionNameCase; private bool $discoveringSymbolsTip; public function __construct( ReflectionProvider $reflectionProvider, ClassNameCheck $classCheck, #[AutowiredParameter] bool $checkFunctionNameCase, #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $this->reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->checkFunctionNameCase = $checkFunctionNameCase; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } 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($scope, $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)) { $errorBuilder = RuleErrorBuilder::message(sprintf('Used constant %s not found.', (string) $name))->line($name->getStartLine())->identifier('constant.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } return $errorBuilder->build(); } return null; } private function checkFunction(Node\Name $name): ?IdentifierRuleError { if (!$this->reflectionProvider->hasFunction($name, null)) { $errorBuilder = RuleErrorBuilder::message(sprintf('Used function %s not found.', (string) $name))->line($name->getStartLine())->identifier('function.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } return $errorBuilder->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(Scope $scope, Node\Name $name): ?IdentifierRuleError { $errors = $this->classCheck->checkClassNames($scope, [new ClassNameNodePair((string) $name, $name)], null); if (count($errors) === 0) { return null; } elseif (count($errors) === 1) { return $errors[0]; } throw new ShouldNotHappenException(); } } */ #[RegisteredRule(0)] final class ExistingNamesInUseRule implements Rule { private ReflectionProvider $reflectionProvider; private ClassNameCheck $classCheck; private bool $checkFunctionNameCase; private bool $discoveringSymbolsTip; public function __construct( ReflectionProvider $reflectionProvider, ClassNameCheck $classCheck, #[AutowiredParameter] bool $checkFunctionNameCase, #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $this->reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->checkFunctionNameCase = $checkFunctionNameCase; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } 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($scope, $node->uses); } /** * @param Node\UseItem[] $uses * @return list */ private function checkConstants(array $uses): array { $errors = []; foreach ($uses as $use) { if ($this->reflectionProvider->hasConstant($use->name, null)) { continue; } $errorBuilder = RuleErrorBuilder::message(sprintf('Used constant %s not found.', (string) $use->name))->line($use->name->getStartLine())->identifier('constant.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $errors[] = $errorBuilder->build(); } return $errors; } /** * @param Node\UseItem[] $uses * @return list */ private function checkFunctions(array $uses): array { $errors = []; foreach ($uses as $use) { if (!$this->reflectionProvider->hasFunction($use->name, null)) { $errorBuilder = RuleErrorBuilder::message(sprintf('Used function %s not found.', (string) $use->name))->line($use->name->getStartLine())->identifier('function.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $errors[] = $errorBuilder->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\UseItem[] $uses * @return list */ private function checkClasses(Scope $scope, array $uses): array { return $this->classCheck->checkClassNames($scope, array_map(static fn(Node\UseItem $use): ClassNameNodePair => new ClassNameNodePair((string) $use->name, $use->name), $uses), null); } } 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_) { 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; } } */ #[RegisteredRule(0)] final class BacktickRule implements Rule { private PhpVersion $phpVersion; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function getNodeType(): string { return ShellExec::class; } public function processNode(Node $node, Scope $scope): array { if (!$this->phpVersion->deprecatesBacktickOperator()) { return []; } $argExpr = null; foreach ($node->parts as $part) { if ($part instanceof Node\InterpolatedStringPart) { $expr = new Node\Scalar\String_($part->value); } else { $expr = $part; } if ($argExpr === null) { $argExpr = $expr; continue; } $argExpr = new Node\Expr\BinaryOp\Concat($argExpr, $expr); } if ($argExpr === null) { throw new ShouldNotHappenException(); } return [RuleErrorBuilder::message('Backtick operator is deprecated in PHP 8.5. Use shell_exec() function call instead.')->identifier('backtick.deprecated')->fixNode($node, static fn() => new Node\Expr\FuncCall(new Node\Name('shell_exec'), [new Node\Arg($argExpr)]))->build()]; } } */ #[RegisteredRule(0)] final class InvalidAssignVarRule implements Rule { private NullsafeCheck $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_) { foreach ($expr->items as $item) { if ($item === null) { continue; } if (!$this->containsNonAssignableExpression($item->value)) { continue; } return \true; } return \false; } return \true; } } */ #[RegisteredRule(2)] final class InvalidBinaryOperationRule implements Rule { private ExprPrinter $exprPrinter; private RuleLevelHelper $ruleLevelHelper; public function __construct(ExprPrinter $exprPrinter, RuleLevelHelper $ruleLevelHelper) { $this->exprPrinter = $exprPrinter; $this->ruleLevelHelper = $ruleLevelHelper; } 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 ($node instanceof Node\Expr\AssignOp) { $identifier = 'assignOp'; $left = $node->var; $right = $node->expr; } else { $identifier = 'binaryOp'; $left = $node->left; $right = $node->right; } if ($node instanceof Node\Expr\AssignOp\Concat || $node instanceof Node\Expr\BinaryOp\Concat) { $callback = static fn(Type $type): bool => !$type->toString() instanceof ErrorType; } elseif ($node instanceof Node\Expr\AssignOp\Plus || $node instanceof Node\Expr\BinaryOp\Plus) { $callback = static fn(Type $type): bool => !$type->toNumber() instanceof ErrorType || $type->isArray()->yes(); } else { $callback = static fn(Type $type): bool => !$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 ($node instanceof Node\Expr\AssignOp) { $newNode = clone $node; $newNode->setAttribute('phpstan_cache_printer', null); $newNode->var = new TypeExpr($leftType); $newNode->expr = new TypeExpr($rightType); $newLeft = $newNode->var; $newRight = $newNode->expr; } else { $newNode = clone $node; $newNode->setAttribute('phpstan_cache_printer', null); $newNode->left = new TypeExpr($leftType); $newNode->right = new TypeExpr($rightType); $newLeft = $newNode->left; $newRight = $newNode->right; } if (!$scope->getType($newNode) instanceof ErrorType) { return []; } $leftPrinted = $this->exprPrinter->printExpr($newLeft); $rightPrinted = $this->exprPrinter->printExpr($newRight); $opLeftSideTrimmed = substr($this->exprPrinter->printExpr($newNode), strlen($leftPrinted) + 1); $pos = strpos($opLeftSideTrimmed, $rightPrinted); if ($pos === \false) { throw new ShouldNotHappenException(); } return [RuleErrorBuilder::message(sprintf('Binary operation "%s" between %s and %s results in an error.', substr($opLeftSideTrimmed, 0, $pos - 1), $scope->getType($left)->describe(VerbosityLevel::value()), $scope->getType($right)->describe(VerbosityLevel::value())))->line($left->getStartLine())->identifier(sprintf('%s.invalid', $identifier))->build()]; } } */ #[RegisteredRule(2)] final class InvalidComparisonOperationRule implements Rule { private RuleLevelHelper $ruleLevelHelper; private OperatorTypeSpecifyingExtensionRegistryProvider $operatorTypeSpecifyingExtensionRegistryProvider; private bool $checkExtensionsForComparisonOperators; public function __construct( RuleLevelHelper $ruleLevelHelper, OperatorTypeSpecifyingExtensionRegistryProvider $operatorTypeSpecifyingExtensionRegistryProvider, #[AutowiredParameter('%featureToggles.checkExtensionsForComparisonOperators%')] bool $checkExtensionsForComparisonOperators ) { $this->ruleLevelHelper = $ruleLevelHelper; $this->operatorTypeSpecifyingExtensionRegistryProvider = $operatorTypeSpecifyingExtensionRegistryProvider; $this->checkExtensionsForComparisonOperators = $checkExtensionsForComparisonOperators; } 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 []; } $isLeftNumberType = $this->isNumberType($scope, $node->left); $isRightNumberType = $this->isNumberType($scope, $node->right); if ($isLeftNumberType === $isRightNumberType) { return []; } $result = $this->operatorTypeSpecifyingExtensionRegistryProvider->getRegistry()->callOperatorTypeSpecifyingExtensions($node, $scope->getType($node->left), $scope->getType($node->right)); if ($result !== null) { if (!$result instanceof ErrorType) { return []; } if ($this->checkExtensionsForComparisonOperators) { return $this->createError($node, $scope); } } if ($isLeftNumberType && ($this->isPossiblyNullableObjectType($scope, $node->right) || $this->isPossiblyNullableArrayType($scope, $node->right)) || $isRightNumberType && ($this->isPossiblyNullableObjectType($scope, $node->left) || $this->isPossiblyNullableArrayType($scope, $node->left))) { return $this->createError($node, $scope); } return []; } private function isNumberType(Scope $scope, Node\Expr $expr): bool { $acceptedType = new UnionType([new IntegerType(), new FloatType()]); $onlyNumber = static fn(Type $type): bool => $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 { $type = $scope->getType($expr); $acceptedType = new UnionType([new ObjectWithoutClassType(), new NullType()]); return !$type->isNull()->yes() && $acceptedType->isSuperTypeOf($type)->yes(); } private function isPossiblyNullableArrayType(Scope $scope, Node\Expr $expr): bool { $type = $scope->getType($expr); $acceptedType = new UnionType([new ArrayType(new MixedType(), new MixedType()), new NullType()]); return !$type->isNull()->yes() && $acceptedType->isSuperTypeOf($type)->yes(); } /** @return list */ private function createError(Node\Expr\BinaryOp $node, Scope $scope): array { 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()]; } } */ #[RegisteredRule(0)] final class InvalidIncDecOperationRule implements Rule { private RuleLevelHelper $ruleLevelHelper; private PhpVersion $phpVersion; public function __construct(RuleLevelHelper $ruleLevelHelper, PhpVersion $phpVersion) { $this->ruleLevelHelper = $ruleLevelHelper; $this->phpVersion = $phpVersion; } 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()]; } $string = new StringType(); $deprecatedString = \false; if ($this->phpVersion->deprecatesDecOnNonNumericString() && ($node instanceof Node\Expr\PreDec || $node instanceof Node\Expr\PostDec) || $this->phpVersion->deprecatesIncOnNonNumericString() && ($node instanceof Node\Expr\PreInc || $node instanceof Node\Expr\PostInc)) { $string = new IntersectionType([$string, new AccessoryNumericStringType()]); $deprecatedString = \true; } $allowedTypes = [new FloatType(), new IntegerType(), $string, new ObjectType('SimpleXMLElement'), new ObjectType('GMP')]; $deprecatedNull = \false; if (!$this->phpVersion->deprecatesDecOnNonNumericString() || $node instanceof Node\Expr\PreInc || $node instanceof Node\Expr\PostInc) { $allowedTypes[] = new NullType(); } else { $deprecatedNull = \true; } $deprecatedBool = \false; if (!$this->phpVersion->deprecatesDecOnNonNumericString()) { $allowedTypes[] = new BooleanType(); } else { $deprecatedBool = \true; } if ($this->phpVersion->supportsBcMathNumberOperatorOverloading()) { $allowedTypes[] = new ObjectType('BcMath\Number'); } $allowedTypes = new UnionType($allowedTypes); $varType = $this->ruleLevelHelper->findTypeToCheck($scope, $node->var, '', static fn(Type $type): bool => $allowedTypes->isSuperTypeOf($type)->yes())->getType(); if ($varType instanceof ErrorType || $allowedTypes->isSuperTypeOf($varType)->yes()) { return []; } $errorBuilder = RuleErrorBuilder::message(sprintf('Cannot use %s on %s.', $operatorString, $varType->describe(VerbosityLevel::value())))->line($node->var->getStartLine())->identifier(sprintf('%s.type', $nodeType)); if (!$varType->isString()->no() && $deprecatedString) { $errorBuilder->addTip(sprintf('Operator %s is deprecated for non-numeric-strings. Either narrow the type to numeric-string, or use %s().', $operatorString, $node instanceof Node\Expr\PreDec || $node instanceof Node\Expr\PostDec ? 'str_decrement' : 'str_increment')); } if (!$varType->isNull()->no() && $deprecatedNull) { $errorBuilder->addTip(sprintf('Operator %s is deprecated for null.', $operatorString)); } if (!$varType->isBoolean()->no() && $deprecatedBool) { $errorBuilder->addTip(sprintf('Operator %s is deprecated for %s.', $operatorString, TypeCombinator::intersect($varType, new BooleanType())->describe(VerbosityLevel::value()))); } return [$errorBuilder->build()]; } } */ #[RegisteredRule(2)] final class InvalidUnaryOperationRule implements Rule { private RuleLevelHelper $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } 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 ($node instanceof Node\Expr\BitwiseNot) { $callback = static fn(Type $type): bool => $type->isString()->yes() || $type->isInteger()->yes() || $type->isFloat()->yes(); } else { $callback = static fn(Type $type): bool => !$type->toNumber() instanceof ErrorType; } $exprType = $this->ruleLevelHelper->findTypeToCheck($scope, $node->expr, '', $callback)->getType(); if ($exprType instanceof ErrorType) { return []; } $newNode = clone $node; $newNode->setAttribute('phpstan_cache_printer', null); $newNode->expr = new TypeExpr($exprType); if (!$scope->getType($newNode) 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()]; } } */ #[RegisteredRule(0)] final class PipeOperatorRule implements Rule { private RuleLevelHelper $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType(): string { return Node\Expr\BinaryOp\Pipe::class; } public function processNode(Node $node, Scope $scope): array { $rightType = $this->ruleLevelHelper->findTypeToCheck($scope, $node->right, '', static fn(Type $type) => $type->isCallable()->yes())->getType(); if ($rightType instanceof ErrorType) { return []; } if (!$rightType->isCallable()->yes()) { return []; } $acceptors = $rightType->getCallableParametersAcceptors($scope); foreach ($acceptors as $acceptor) { foreach ($acceptor->getParameters() as $parameter) { if ($parameter->passedByReference()->no()) { break; } return [RuleErrorBuilder::message(sprintf('Parameter #1%s of callable on the right side of pipe operator is passed by reference.', $parameter->getName() !== '' ? ' $' . $parameter->getName() : ''))->line($node->right->getStartLine())->identifier('pipe.byRef')->build()]; } } return []; } } 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; } $arrayTypeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $parameter->value, '', static fn(Type $type): bool => $type->isArray()->yes()); $arrayType = $arrayTypeResult->getType(); if (!$arrayType->isArray()->yes()) { return null; } $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, new TypeExpr($arrayType->getIterableValueType()), '', static fn(Type $type): bool => !$castFn($type) instanceof ErrorType); if (!$castFn($typeResult->getType()) instanceof ErrorType) { return null; } return \PHPStan\Rules\RuleErrorBuilder::message(sprintf($errorMessageTemplate, $parameterName, $functionName, $arrayTypeResult->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); } } reflectionProvider = $reflectionProvider; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->classCheck = $classCheck; $this->missingTypehintCheck = $missingTypehintCheck; $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->checkMissingTypehints = $checkMissingTypehints; } /** * @return list * @param \PhpParser\Node\Stmt\Function_|\PhpParser\Node\Stmt\ClassMethod $node * @param \PHPStan\Reflection\ExtendedMethodReflection|\PHPStan\Reflection\FunctionReflection $reflection */ public function check(Scope $scope, $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); } $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 = $scope->getType($assertedExpr); $assertedExprString = $assert->getParameter()->describe(); if ($assertedExprType instanceof ErrorType) { $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->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(); } } 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($scope, [new ClassNameNodePair($class, $node)], ClassNameUsageLocation::from(ClassNameUsageLocation::PHPDOC_TAG_ASSERT, ['phpDocTagName' => $tagName, 'assertedExprString' => $assertedExprString]), $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; } } */ public function check(ExtendedParametersAcceptor $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; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class FunctionAssertRule implements Rule { private \PHPStan\Rules\PhpDoc\AssertRuleHelper $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($scope, $node->getOriginalNode(), $function, $variants[0]); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class FunctionConditionalReturnTypeRule implements Rule { private \PHPStan\Rules\PhpDoc\ConditionalReturnTypeRuleHelper $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]); } } 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; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class IncompatibleClassConstantPhpDocTypeRule implements Rule { private GenericObjectTypeCheck $genericObjectTypeCheck; private \PHPStan\Rules\PhpDoc\UnresolvableTypeHelper $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))); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class IncompatibleParamImmediatelyInvokedCallableRule implements Rule { private FileTypeMapper $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; } } genericObjectTypeCheck = $genericObjectTypeCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->genericCallableRuleHelper = $genericCallableRuleHelper; } /** * @param array $nativeParameterTypes * @param array $byRefParameters * @return list */ public function check(Scope $scope, Node $node, ResolvedPhpDocBlock $resolvedPhpDoc, string $functionName, array $nativeParameterTypes, array $byRefParameters, Type $nativeReturnType): array { $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 { $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; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class IncompatiblePhpDocTypeRule implements Rule { private FileTypeMapper $fileTypeMapper; private \PHPStan\Rules\PhpDoc\IncompatiblePhpDocTypeCheck $check; public function __construct(FileTypeMapper $fileTypeMapper, \PHPStan\Rules\PhpDoc\IncompatiblePhpDocTypeCheck $check) { $this->fileTypeMapper = $fileTypeMapper; $this->check = $check; } 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()); return $this->check->check($scope, $node, $resolvedPhpDoc, $functionName, $this->getNativeParameterTypes($node, $scope), $this->getByRefParameters($node), $this->getNativeReturnType($node, $scope)); } /** * @return array */ 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); } } */ #[RegisteredRule(2)] final class IncompatiblePropertyHookPhpDocTypeRule implements Rule { private FileTypeMapper $fileTypeMapper; private \PHPStan\Rules\PhpDoc\IncompatiblePhpDocTypeCheck $check; public function __construct(FileTypeMapper $fileTypeMapper, \PHPStan\Rules\PhpDoc\IncompatiblePhpDocTypeCheck $check) { $this->fileTypeMapper = $fileTypeMapper; $this->check = $check; } public function getNodeType(): string { return InPropertyHookNode::class; } public function processNode(Node $node, Scope $scope): array { $docComment = $node->getDocComment(); if ($docComment === null) { return []; } $hookReflection = $node->getHookReflection(); $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), $node->getClassReflection()->getName(), $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, $hookReflection->getName(), $docComment->getText()); return $this->check->check($scope, $node, $resolvedPhpDoc, $hookReflection->getName(), $this->getNativeParameterTypes($hookReflection), $this->getByRefParameters($hookReflection), $hookReflection->getNativeReturnType()); } /** * @return array */ private function getNativeParameterTypes(PhpMethodFromParserNodeReflection $node): array { $parameters = []; foreach ($node->getParameters() as $parameter) { $parameters[$parameter->getName()] = $parameter->getNativeType(); } return $parameters; } /** * @return array */ private function getByRefParameters(PhpMethodFromParserNodeReflection $node): array { $parameters = []; foreach ($node->getParameters() as $parameter) { $parameters[$parameter->getName()] = \false; } return $parameters; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class IncompatiblePropertyPhpDocTypeRule implements Rule { private GenericObjectTypeCheck $genericObjectTypeCheck; private \PHPStan\Rules\PhpDoc\UnresolvableTypeHelper $unresolvableTypeHelper; private \PHPStan\Rules\PhpDoc\GenericCallableRuleHelper $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 = $node->getNativeType(); if ($nativeType !== null) { $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; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class IncompatibleSelfOutTypeRule implements Rule { private \PHPStan\Rules\PhpDoc\UnresolvableTypeHelper $unresolvableTypeHelper; private GenericObjectTypeCheck $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))); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class InvalidPHPStanDocTagRule implements Rule { private Lexer $phpDocLexer; private PhpDocParser $phpDocParser; 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-sealed', '@phpstan-param-immediately-invoked-callable', '@phpstan-param-later-invoked-callable', '@phpstan-param-closure-this', '@phpstan-all-methods-pure', '@phpstan-all-methods-impure']; public function __construct(Lexer $phpDocLexer, PhpDocParser $phpDocParser) { $this->phpDocLexer = $phpDocLexer; $this->phpDocParser = $phpDocParser; } public function getNodeType(): string { return NodeAbstract::class; } public function processNode(Node $node, Scope $scope): array { // mirrored with InvalidPhpDocTagValueRule if ($node instanceof VirtualNode) { return []; } if (!$node instanceof Node\Stmt && !$node instanceof Node\PropertyHook) { return []; } if ($node instanceof Node\Stmt\Expression) { if (!$node->expr instanceof Node\Expr\Assign && !$node->expr instanceof Node\Expr\AssignRef && !$node->expr instanceof Node\Expr\AssignOp) { 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; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class InvalidPhpDocTagValueRule implements Rule { private Lexer $phpDocLexer; private PhpDocParser $phpDocParser; public function __construct(Lexer $phpDocLexer, PhpDocParser $phpDocParser) { $this->phpDocLexer = $phpDocLexer; $this->phpDocParser = $phpDocParser; } public function getNodeType(): string { return NodeAbstract::class; } public function processNode(Node $node, Scope $scope): array { // mirrored with InvalidPHPStanDocTagRule if ($node instanceof VirtualNode) { return []; } if (!$node instanceof Node\Stmt && !$node instanceof Node\PropertyHook) { return []; } if ($node instanceof Node\Stmt\Expression) { if (!$node->expr instanceof Node\Expr\Assign && !$node->expr instanceof Node\Expr\AssignRef && !$node->expr instanceof Node\Expr\AssignOp) { 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, $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, $phpDocTag->value->exception->getMessage()))->line(\PHPStan\Rules\PhpDoc\PhpDocLineHelper::detectLine($node, $phpDocTag))->identifier('phpDoc.parseError')->build(); } return $errors; } } */ #[RegisteredRule(2)] final class InvalidPhpDocVarTagTypeRule implements Rule { private FileTypeMapper $fileTypeMapper; private ReflectionProvider $reflectionProvider; private ClassNameCheck $classCheck; private GenericObjectTypeCheck $genericObjectTypeCheck; private MissingTypehintCheck $missingTypehintCheck; private \PHPStan\Rules\PhpDoc\UnresolvableTypeHelper $unresolvableTypeHelper; private bool $checkClassCaseSensitivity; private bool $checkMissingVarTagTypehint; private bool $discoveringSymbolsTip; public function __construct( FileTypeMapper $fileTypeMapper, ReflectionProvider $reflectionProvider, ClassNameCheck $classCheck, GenericObjectTypeCheck $genericObjectTypeCheck, MissingTypehintCheck $missingTypehintCheck, \PHPStan\Rules\PhpDoc\UnresolvableTypeHelper $unresolvableTypeHelper, #[AutowiredParameter] bool $checkClassCaseSensitivity, #[AutowiredParameter] bool $checkMissingVarTagTypehint, #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $this->fileTypeMapper = $fileTypeMapper; $this->reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->missingTypehintCheck = $missingTypehintCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->checkMissingVarTagTypehint = $checkMissingVarTagTypehint; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } 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\ClassConst && !$node instanceof Node\Stmt\Const_ && !$node instanceof Node\Stmt\ClassLike && !$node instanceof Node\Stmt\Function_ && !$node instanceof Node\Stmt\ClassMethod)) { 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(); } 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(); } } $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))); $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; } $errorBuilder = RuleErrorBuilder::message(sprintf(sprintf('%s contains unknown class %%s.', $identifier), $referencedClass))->identifier('class.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $errors[] = $errorBuilder->build(); } $errors = array_merge($errors, $this->classCheck->checkClassNames($scope, array_map(static fn(string $class): ClassNameNodePair => new ClassNameNodePair($class, $node), $referencedClasses), ClassNameUsageLocation::from(ClassNameUsageLocation::PHPDOC_TAG_VAR), $this->checkClassCaseSensitivity)); } return $errors; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class InvalidThrowsPhpDocValueRule implements Rule { private FileTypeMapper $fileTypeMapper; public function __construct(FileTypeMapper $fileTypeMapper) { $this->fileTypeMapper = $fileTypeMapper; } public function getNodeType(): string { return NodeAbstract::class; } public function processNode(Node $node, Scope $scope): array { if ($node instanceof Node\Stmt) { if ($node instanceof Node\Stmt\ClassLike || $node instanceof Node\Stmt\Function_ || $node instanceof Node\Stmt\ClassMethod) { return []; // is handled by virtual nodes } } elseif (!$node instanceof InPropertyHookNode) { return []; } $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(); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class MethodAssertRule implements Rule { private \PHPStan\Rules\PhpDoc\AssertRuleHelper $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($scope, $node->getOriginalNode(), $method, $variants[0]); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class MethodConditionalReturnTypeRule implements Rule { private \PHPStan\Rules\PhpDoc\ConditionalReturnTypeRuleHelper $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]); } } getAttribute('startLine'); $phpDoc = $node->getDocComment(); if ($phpDocTagLine === null || $phpDoc === null) { return $node->getStartLine(); } return $phpDoc->getStartLine() + $phpDocTagLine - 1; } } reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } /** * @param array $extendsTags * @return list */ public function checkExtendsTags(Scope $scope, 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(); $classNames = $type->getObjectClassNames(); if (count($classNames) === 0) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-extends contains non-object type %s.', $type->describe(VerbosityLevel::typeOnly())))->identifier('requireExtends.nonObject')->build(); continue; } foreach ($classNames as $class) { if (!$this->reflectionProvider->hasClass($class)) { $errorBuilder = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-extends contains unknown class %s.', $class))->identifier('class.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $errors[] = $errorBuilder->build(); continue; } $reflection = $this->reflectionProvider->getClass($class); if ($reflection->isInterface()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-extends cannot contain an interface %s, expected a class.', $class))->tip('If you meant an interface, use @phpstan-require-implements instead.')->identifier('requireExtends.interface')->build(); } elseif (!$reflection->isClass()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-extends cannot contain non-class type %s.', $class))->identifier(sprintf('requireExtends.%s', strtolower($reflection->getClassTypeDescription())))->build(); } elseif ($reflection->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($scope, [new ClassNameNodePair($class, $node)], ClassNameUsageLocation::from(ClassNameUsageLocation::PHPDOC_TAG_REQUIRE_EXTENDS), $this->checkClassCaseSensitivity)); } } } return $errors; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class RequireExtendsDefinitionClassRule implements Rule { private \PHPStan\Rules\PhpDoc\RequireExtendsCheck $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($scope, $node, $extendsTags); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class RequireExtendsDefinitionTraitRule implements Rule { private ReflectionProvider $reflectionProvider; private \PHPStan\Rules\PhpDoc\RequireExtendsCheck $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($scope, $node, $extendsTags); } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] 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()]; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class RequireImplementsDefinitionTraitRule implements Rule { private ReflectionProvider $reflectionProvider; private ClassNameCheck $classCheck; private bool $checkClassCaseSensitivity; private bool $discoveringSymbolsTip; public function __construct( ReflectionProvider $reflectionProvider, ClassNameCheck $classCheck, #[AutowiredParameter] bool $checkClassCaseSensitivity, #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $this->reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } 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(); $classNames = $type->getObjectClassNames(); if (count($classNames) === 0) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-implements contains non-object type %s.', $type->describe(VerbosityLevel::typeOnly())))->identifier('requireImplements.nonObject')->build(); continue; } foreach ($classNames as $class) { if (!$this->reflectionProvider->hasClass($class)) { $errorBuilder = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-implements contains unknown class %s.', $class))->identifier('class.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $errors[] = $errorBuilder->build(); continue; } $reflection = $this->reflectionProvider->getClass($class); if (!$reflection->isInterface()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-implements cannot contain non-interface type %s.', $class))->identifier(sprintf('requireImplements.%s', strtolower($reflection->getClassTypeDescription())))->build(); } else { $errors = array_merge($errors, $this->classCheck->checkClassNames($scope, [new ClassNameNodePair($class, $node)], ClassNameUsageLocation::from(ClassNameUsageLocation::PHPDOC_TAG_REQUIRE_IMPLEMENTS), $this->checkClassCaseSensitivity)); } } } return $errors; } } */ #[RegisteredRule(2)] #[ValidatesStubFiles] final class SealedDefinitionClassRule implements Rule { private ReflectionProvider $reflectionProvider; private ClassNameCheck $classCheck; private bool $checkClassCaseSensitivity; private bool $discoveringSymbolsTip; public function __construct( ReflectionProvider $reflectionProvider, ClassNameCheck $classCheck, #[AutowiredParameter] bool $checkClassCaseSensitivity, #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $this->reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } public function getNodeType(): string { return InClassNode::class; } public function processNode(Node $node, Scope $scope): array { $classReflection = $node->getClassReflection(); $sealedTags = $classReflection->getSealedTags(); if (count($sealedTags) === 0) { return []; } if ($classReflection->isEnum()) { return [RuleErrorBuilder::message('PHPDoc tag @phpstan-sealed is only valid on class or interface.')->identifier('sealed.onEnum')->build()]; } $errors = []; foreach ($sealedTags as $sealedTag) { $type = $sealedTag->getType(); $classNames = $type->getObjectClassNames(); if (count($classNames) === 0) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-sealed contains non-object type %s.', $type->describe(VerbosityLevel::typeOnly())))->identifier('sealed.nonObject')->build(); continue; } foreach ($classNames as $class) { if (!$this->reflectionProvider->hasClass($class)) { $errorBuilder = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-sealed contains unknown class %s.', $class))->identifier('class.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $errors[] = $errorBuilder->build(); continue; } $errors = array_merge($errors, $this->classCheck->checkClassNames($scope, [new ClassNameNodePair($class, $node)], ClassNameUsageLocation::from(ClassNameUsageLocation::PHPDOC_TAG_SEALED), $this->checkClassCaseSensitivity)); } } return $errors; } } */ #[RegisteredRule(0)] #[ValidatesStubFiles] final class SealedDefinitionTraitRule implements Rule { private ReflectionProvider $reflectionProvider; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } 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()); $sealedTags = $traitReflection->getSealedTags(); if (count($sealedTags) === 0) { return []; } return [RuleErrorBuilder::message('PHPDoc tag @phpstan-sealed is only valid on class or interface.')->identifier('sealed.onTrait')->build()]; } } isExplicit()) { $containsUnresolvable = \true; } return $containsUnresolvable ? $type : $traverse($type); }); return $containsUnresolvable; } } */ #[RegisteredRule(2)] final class VarTagChangedExpressionTypeRule implements Rule { private \PHPStan\Rules\PhpDoc\VarTagTypeRuleHelper $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()); } } typeNodeResolver = $typeNodeResolver; $this->fileTypeMapper = $fileTypeMapper; $this->reflectionProvider = $reflectionProvider; $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\Int_($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->getScopeNativeType($expr); $containsPhpStanType = $this->containsPhpStanType($varTagType); $isValidSuperTypeOfExpr = $this->isValidSuperTypeOfExpr($scope, $expr, $exprNativeType, $varTagType); if (!$isValidSuperTypeOfExpr->yes()) { $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)))->acceptsReasonsTip($isValidSuperTypeOfExpr->reasons)->identifier('varTag.nativeType')->build(); } elseif ($this->checkTypeAgainstPhpDocType || $containsPhpStanType) { $exprType = $scope->getScopeType($expr); $isValidSuperTypeOfExpr = $this->isValidSuperTypeOfExpr($scope, $expr, $exprType, $varTagType); if (!$isValidSuperTypeOfExpr->yes()) { $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)))->acceptsReasonsTip($isValidSuperTypeOfExpr->reasons)->identifier('varTag.type')->build(); } } if ($containsPhpStanType && count($errors) === 0) { $exprType = $scope->getScopeType($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(); if (!$this->reflectionProvider->hasClass(Type::class)) { return \false; } $typeClass = $this->reflectionProvider->getClass(Type::class); foreach ($classReflections as $classReflection) { if (!$classReflection->isSubclassOfClass($typeClass)) { continue; } return \true; } return \false; } private function isValidSuperTypeOfExpr(Scope $scope, Node\Expr $expr, Type $type, Type $varTagType): IsSuperTypeOfResult { 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->isValidSuperType($scope, $type, $varTagType); } private function isValidSuperType(Scope $scope, Type $type, Type $varTagType, int $depth = 0): IsSuperTypeOfResult { if ($this->strictWideningCheck) { return $this->isSuperTypeOfVarType($scope, $type, $varTagType); } $type = TypeTraverser::map($type, static function (Type $type, callable $traverse): Type { if ($type instanceof GenericObjectType) { $type = $type->changeVariances(array_map(static fn(TemplateTypeVariance $variance) => $variance->invariant() ? TemplateTypeVariance::createCovariant() : $variance, $type->getVariances())); } return $traverse($type); }); 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()) { $isAtLeastMaybeSuperTypeOf = $this->isAtLeastMaybeSuperTypeOfVarType($scope, $type, $varTagType); if ($isAtLeastMaybeSuperTypeOf->no()) { return $isAtLeastMaybeSuperTypeOf; } $innerType = $type->getIterableValueType(); $innerVarTagType = $varTagType->getIterableValueType(); if ($type->equals($innerType) || $varTagType->equals($innerVarTagType)) { return $this->isSuperTypeOfVarType($scope, $innerType, $innerVarTagType); } return $this->isValidSuperType($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): IsSuperTypeOfResult { if ($type->isSuperTypeOf($varTagType)->yes()) { return IsSuperTypeOfResult::createYes(); } try { $type = $this->typeNodeResolver->resolve($type->toPhpDocNode(), $this->createNameScope($scope)); } catch (NameScopeAlreadyBeingCreatedException $e) { return IsSuperTypeOfResult::createYes(); } return $type->isSuperTypeOf($varTagType); } private function isAtLeastMaybeSuperTypeOfVarType(Scope $scope, Type $type, Type $varTagType): IsSuperTypeOfResult { if (!$type->isSuperTypeOf($varTagType)->no()) { return IsSuperTypeOfResult::createYes(); } try { $type = $this->typeNodeResolver->resolve($type->toPhpDocNode(), $this->createNameScope($scope)); } catch (NameScopeAlreadyBeingCreatedException $e) { return IsSuperTypeOfResult::createYes(); } $isSuperTypeOf = $type->isSuperTypeOf($varTagType); if (!$isSuperTypeOf->no()) { return IsSuperTypeOfResult::createYes(); } return $isSuperTypeOf; } /** * @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(); } } */ #[RegisteredRule(2)] final class WrongVariableNameInVarTagRule implements Rule { private FileTypeMapper $fileTypeMapper; private \PHPStan\Rules\PhpDoc\VarTagTypeRuleHelper $varTagTypeRuleHelper; public function __construct(FileTypeMapper $fileTypeMapper, \PHPStan\Rules\PhpDoc\VarTagTypeRuleHelper $varTagTypeRuleHelper) { $this->fileTypeMapper = $fileTypeMapper; $this->varTagTypeRuleHelper = $varTagTypeRuleHelper; } 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\ClassConst && !$node instanceof Node\Stmt\Const_ && !$node instanceof Node\Stmt\ClassLike && !$node instanceof Node\Stmt\Function_ && !$node instanceof Node\Stmt\ClassMethod)) { return []; } if ($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) { if ($node->expr instanceof Expr\Throw_) { return $this->processStmt($scope, $varTags, $node->expr); } return $this->processExpression($scope, $node->expr, $varTags); } if ($node instanceof Node\Stmt\Return_) { return $this->processStmt($scope, $varTags, $node->expr); } if ($node instanceof Node\Stmt\Global_) { return $this->processGlobal($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); 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(); } } if (count($errors) === 0) { foreach ($this->varTagTypeRuleHelper->checkVarType($scope, $var, $expr, $varTags, $assignedVariables) as $error) { $errors[] = $error; } } 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_) { $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 fn(string $name): string => sprintf('$%s', $name), $variableNames))))->identifier('varTag.differentVariable')->build(); } 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 || $expr instanceof Node\Expr\AssignOp) { return $this->processAssign($scope, $expr->var, $expr->expr, $varTags); } return $this->processStmt($scope, $varTags, null); } /** * @param Node\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 fn(string $name): string => sprintf('$%s', $name), $variableNames))))->identifier('varTag.differentVariable')->build(); } 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(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 fn(string $name): string => sprintf('$%s', $name), array_keys($variableNames)))))->identifier('varTag.differentVariable')->build(); } return $errors; } } */ final class FunctionNeverRule implements Rule { private \PHPStan\Rules\Playground\NeverRuleHelper $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()]; } } */ final class MethodNeverRule implements Rule { private \PHPStan\Rules\Playground\NeverRuleHelper $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()]; } } |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()) { $executionEndNode = $executionEnd->getNode(); if (!$executionEndNode instanceof Node\Stmt\Expression) { $other[] = $executionEnd->getNode(); continue; } if ($executionEndNode->expr instanceof Node\Expr\Throw_) { continue; } $other[] = $executionEnd->getNode(); continue; } return \false; } return $other; } } */ 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 PhpdocCommentRule implements Rule { public function getNodeType(): string { return Node\Stmt::class; } public function processNode(Node $node, Scope $scope): array { if ($node instanceof VirtualNode) { return []; } $comments = $node->getComments(); $errors = []; foreach ($comments as $comment) { foreach (['/**', '//', '#'] as $startTag) { if (str_starts_with($comment->getText(), $startTag)) { continue 2; } } if (Strings::match($comment->getText(), '{(\s|^)@\w+(\s|$)}') === null) { continue; } $errors[] = RuleErrorBuilder::message('Comment contains PHPDoc tag but does not start with /** prefix.')->identifier('phpstanPlayground.phpDoc')->build(); } return $errors; } } */ final class PromoteParameterRule implements Rule { /** * @var Rule */ private Rule $rule; private Container $container; /** * @var class-string */ private string $nodeType; private bool $parameterValue; private string $parameterName; /** @var Rule|false|null */ private $originalRule = null; /** * @param Rule $rule * @param class-string $nodeType */ public function __construct(Rule $rule, Container $container, string $nodeType, bool $parameterValue, string $parameterName) { $this->rule = $rule; $this->container = $container; $this->nodeType = $nodeType; $this->parameterValue = $parameterValue; $this->parameterName = $parameterName; } public function getNodeType(): string { return $this->nodeType; } /** * @return Rule|null */ private function getOriginalRule(): ?Rule { if ($this->originalRule === \false) { return null; } if ($this->originalRule !== null) { return $this->originalRule; } $originalRule = null; try { /** @var Rule $originalRule */ $originalRule = $this->container->getByType(get_class($this->rule)); $taggedRules = $this->container->getServicesByTag(LazyRegistry::RULE_TAG); $found = \false; foreach ($taggedRules as $rule) { if ($originalRule !== $rule) { continue; } $found = \true; break; } if (!$found) { $originalRule = null; } } catch (MissingServiceException $e) { // pass } if ($originalRule === null) { $this->originalRule = \false; return null; } return $this->originalRule = $originalRule; } /** * @param \PHPStan\Analyser\Scope&\PHPStan\Analyser\NodeCallbackInvoker $scope */ public function processNode(Node $node, \PHPStan\Analyser\Scope $scope): array { if ($this->parameterValue) { return []; } if ($this->nodeType !== $this->rule->getNodeType()) { return []; } $originalRule = $this->getOriginalRule(); if ($originalRule !== null) { $originalRuleErrors = $originalRule->processNode($node, $scope); if (count($originalRuleErrors) > 0) { return []; } } $errors = []; foreach ($this->rule->processNode($node, $scope) as $error) { $builder = RuleErrorBuilder::message($error->getMessage())->identifier('phpstanPlayground.configParameter')->tip(sprintf('This error would be reported if the %s: true parameter was enabled in your %%configurationFile%%.', $this->parameterName)); if ($error instanceof LineRuleError) { $builder->line($error->getLine()); } if ($error instanceof FixableNodeRuleError) { $builder->fixNode($error->getOriginalNode(), $error->getNewNodeCallable()); } $errors[] = $builder->build(); } return $errors; } } */ final class StaticVarWithoutTypeRule implements Rule { private FileTypeMapper $fileTypeMapper; public function __construct(FileTypeMapper $fileTypeMapper) { $this->fileTypeMapper = $fileTypeMapper; } public function getNodeType(): string { return Node\Stmt\Static_::class; } public function processNode(Node $node, Scope $scope): array { $docComment = $node->getDocComment(); $ruleError = RuleErrorBuilder::message('Static variable needs to be typed with PHPDoc @var tag.')->identifier('phpstanPlayground.staticWithoutType')->build(); if ($docComment === null) { return [$ruleError]; } $variableNames = []; foreach ($node->vars as $var) { if (!is_string($var->var->name)) { throw new ShouldNotHappenException(); } $variableNames[] = $var->var->name; } $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()); $varTags = []; foreach ($resolvedPhpDoc->getVarTags() as $key => $varTag) { $varTags[$key] = $varTag; } if (count($varTags) === 0) { return [$ruleError]; } if (count($variableNames) === 1 && count($varTags) === 1 && isset($varTags[0])) { return []; } foreach ($variableNames as $variableName) { if (isset($varTags[$variableName])) { continue; } return [$ruleError]; } return []; } } */ #[RegisteredRule(2)] 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->hasStaticProperty($propertyName)->yes()) { return []; } $property = $classType->getStaticProperty($propertyName, $scope); if (!$property->isPrivate()) { 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))->line($node->name->getStartLine())->identifier('staticClassAccess.privateProperty')->build()]; } } reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; $this->phpVersion = $phpVersion; $this->reportMagicProperties = $reportMagicProperties; $this->checkDynamicProperties = $checkDynamicProperties; $this->checkNonStringableDynamicAccess = $checkNonStringableDynamicAccess; } /** * @return list */ public function check(PropertyFetch $node, Scope $scope, bool $write): array { $errors = []; if ($node->name instanceof Identifier) { $names = [$node->name->name]; } else { $names = array_map(static fn(ConstantStringType $type): string => $type->getValue(), $scope->getType($node->name)->getConstantStrings()); if (!$write && $this->checkNonStringableDynamicAccess) { $nameTypeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $node->name, '', static fn(Type $type) => !$type->toString() instanceof ErrorType && $type->toString()->isString()->yes()); $nameType = $nameTypeResult->getType(); if (!$nameType instanceof ErrorType && ($nameType->toString() instanceof ErrorType || !$nameType->toString()->isString()->yes())) { $originalNameType = $scope->getType($node->name); $className = $scope->getType($node->var)->describe(VerbosityLevel::typeOnly()); $errors[] = RuleErrorBuilder::message(sprintf('Property name for %s must be a string, but %s was given.', $className, $originalNameType->describe(VerbosityLevel::precise())))->line($node->name->getStartLine())->identifier('property.nameNotString')->build(); } } } foreach ($names as $name) { $errors = array_merge($errors, $this->processSingleProperty($scope, $node, $name, $write)); } return $errors; } /** * @return list */ private function processSingleProperty(Scope $scope, PropertyFetch $node, string $name, bool $write): 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 fn(Type $type): bool => $type->canAccessProperties()->yes() && ($type->hasInstanceProperty($name)->yes() || $type->hasStaticProperty($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())))->line($node->name->getStartLine())->identifier('property.nonObject')->build()]; } $has = $type->hasInstanceProperty($name); $hasStatic = $type->hasStaticProperty($name); if ($has->maybe() && !$hasStatic->yes()) { if ($scope->isUndefinedExpressionAllowed($node)) { if (!$this->checkDynamicProperties) { return []; } if ($type->getObjectClassNames() === []) { return []; } $maybePropertyReflection = $this->pickProperty($scope, $type, $name); if ($maybePropertyReflection !== null && $maybePropertyReflection->isDummy()->no()) { 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->hasInstanceProperty($name)) { if ($write) { if ($scope->canWriteProperty($parentClassReflection->getInstanceProperty($name, $scope))) { return []; } } elseif ($scope->canReadProperty($parentClassReflection->getInstanceProperty($name, $scope))) { return []; } return [RuleErrorBuilder::message(sprintf('Access to private property $%s of parent class %s.', $name, $parentClassReflection->getDisplayName()))->line($node->name->getStartLine())->identifier('property.private')->build()]; } $parentClassReflection = $parentClassReflection->getParentClass(); } } if ($node->name instanceof Expr) { $propertyExistsExpr = new FuncCall(new FullyQualified('property_exists'), [new Arg($node->var), new Arg($node->name)]); if ($scope->getType($propertyExistsExpr)->isTrue()->yes()) { return []; } } if ($hasStatic->yes()) { return [RuleErrorBuilder::message(sprintf('Non-static access to static property %s::$%s.', $type->getStaticProperty($name, $scope)->getDeclaringClass()->getDisplayName(), $name))->line($node->name->getStartLine())->identifier('staticProperty.nonStaticAccess')->build()]; } $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->getInstanceProperty($name, $scope); if ($write) { if ($scope->canWriteProperty($propertyReflection)) { return []; } } elseif ($scope->canReadProperty($propertyReflection)) { return []; } if (!$this->phpVersion->supportsAsymmetricVisibility() || !$write || !$propertyReflection->isPrivateSet() && !$propertyReflection->isProtectedSet()) { if ($scope->isUndefinedExpressionAllowed($node) && !$propertyReflection->getDeclaringClass()->isFinal()) { return []; } return [RuleErrorBuilder::message(sprintf('Access to %s property %s::$%s.', $propertyReflection->isPrivate() ? 'private' : 'protected', $type->describe(VerbosityLevel::typeOnly()), $name))->line($node->name->getStartLine())->identifier(sprintf('property.%s', $propertyReflection->isPrivate() ? 'private' : 'protected'))->build()]; } return [RuleErrorBuilder::message(sprintf('Assign to %s property %s::$%s.', $propertyReflection->isPrivateSet() ? 'private(set)' : 'protected(set)', $type->describe(VerbosityLevel::typeOnly()), $name))->line($node->name->getStartLine())->identifier(sprintf('assign.property%s', $propertyReflection->isPrivateSet() ? 'PrivateSet' : 'ProtectedSet'))->build()]; } private function pickProperty(Scope $scope, Type $type, string $name): ?ExtendedPropertyReflection { $types = []; if ($type instanceof UnionType) { foreach ($type->getTypes() as $innerType) { if ($innerType->hasInstanceProperty($name)->no()) { continue; } $types[] = $innerType; } } if (count($types) === 0) { try { return $type->getInstanceProperty($name, $scope); } catch (MissingPropertyFromReflectionException $e) { return null; } } if (count($types) === 1) { try { return $types[0]->getInstanceProperty($name, $scope); } catch (MissingPropertyFromReflectionException $e) { return null; } } $unionType = new UnionType($types); try { return $unionType->getInstanceProperty($name, $scope); } catch (MissingPropertyFromReflectionException $e) { return null; } } } */ #[RegisteredRule(0)] final class AccessPropertiesInAssignRule implements Rule { private \PHPStan\Rules\Properties\AccessPropertiesCheck $check; public function __construct(\PHPStan\Rules\Properties\AccessPropertiesCheck $check) { $this->check = $check; } 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->check->check($node->getPropertyFetch(), $scope, \true); } } */ #[RegisteredRule(0)] final class AccessPropertiesRule implements Rule { private \PHPStan\Rules\Properties\AccessPropertiesCheck $check; public function __construct(\PHPStan\Rules\Properties\AccessPropertiesCheck $check) { $this->check = $check; } public function getNodeType(): string { return PropertyFetch::class; } public function processNode(Node $node, Scope $scope): array { return $this->check->check($node, $scope, \false); } } reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; $this->classCheck = $classCheck; $this->phpVersion = $phpVersion; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } /** * @return list */ public function check(StaticPropertyFetch $node, Scope $scope, bool $write): array { if ($node->name instanceof Node\VarLikeIdentifier) { $names = [$node->name->name]; } else { $names = array_map(static fn(ConstantStringType $type): string => $type->getValue(), $scope->getType($node->name)->getConstantStrings()); } $errors = []; foreach ($names as $name) { $errors = array_merge($errors, $this->processSingleProperty($scope, $node, $name, $write)); } return $errors; } /** * @return list */ private function processSingleProperty(Scope $scope, StaticPropertyFetch $node, string $name, bool $write): 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))->line($node->name->getStartLine())->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))->line($node->name->getStartLine())->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()))->line($node->name->getStartLine())->identifier('class.noParent')->build()]; } $classType = $scope->resolveTypeByName($node->class); } else { if (!$this->reflectionProvider->hasClass($class)) { if ($scope->isInClassExists($class)) { return []; } $errorBuilder = RuleErrorBuilder::message(sprintf('Access to static property $%s on an unknown class %s.', $name, $class))->line($node->name->getStartLine())->identifier('class.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } return [$errorBuilder->build()]; } $locationData = []; $locationClassReflection = $this->reflectionProvider->getClass($class); if ($locationClassReflection->hasStaticProperty($name)) { $locationData['property'] = $locationClassReflection->getStaticProperty($name); } $messages = $this->classCheck->checkClassNames($scope, [new ClassNameNodePair($class, $node->class)], ClassNameUsageLocation::from(ClassNameUsageLocation::STATIC_PROPERTY_ACCESS, $locationData)); $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 fn(Type $type): bool => $type->canAccessProperties()->yes() && $type->hasStaticProperty($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())))->line($node->name->getStartLine())->identifier('staticProperty.nonObject')->build()]); } $has = $classType->hasStaticProperty($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->hasStaticProperty($name)) { if ($write) { if ($scope->canWriteProperty($parentClassReflection->getStaticProperty($name))) { return []; } } elseif ($scope->canReadProperty($parentClassReflection->getStaticProperty($name))) { return []; } return [RuleErrorBuilder::message(sprintf('Access to private static property $%s of parent class %s.', $name, $parentClassReflection->getDisplayName()))->line($node->name->getStartLine())->identifier('staticProperty.private')->build()]; } $parentClassReflection = $parentClassReflection->getParentClass(); } } if ($classType->hasInstanceProperty($name)->yes()) { $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.', $classType->getInstanceProperty($name, $scope)->getDeclaringClass()->getDisplayName(), $name))->line($node->name->getStartLine())->identifier('property.staticAccess')->build()]); } return array_merge($messages, [RuleErrorBuilder::message(sprintf('Access to an undefined static property %s::$%s.', $typeForDescribe->describe(VerbosityLevel::typeOnly()), $name))->line($node->name->getStartLine())->identifier('staticProperty.notFound')->build()]); } $property = $classType->getStaticProperty($name, $scope); if ($write) { if ($scope->canWriteProperty($property)) { return $messages; } } elseif ($scope->canReadProperty($property)) { return $messages; } if (!$this->phpVersion->supportsAsymmetricVisibilityForStaticProperties() || !$write || !$property->isPrivateSet() && !$property->isProtectedSet()) { return array_merge($messages, [RuleErrorBuilder::message(sprintf('Access to %s property $%s of class %s.', $property->isPrivate() ? 'private' : 'protected', $name, $property->getDeclaringClass()->getDisplayName()))->line($node->name->getStartLine())->identifier(sprintf('staticProperty.%s', $property->isPrivate() ? 'private' : 'protected'))->build()]); } return array_merge($messages, [RuleErrorBuilder::message(sprintf('Access to %s property $%s of class %s.', $property->isPrivateSet() ? 'private(set)' : 'protected(set)', $name, $property->getDeclaringClass()->getDisplayName()))->line($node->name->getStartLine())->identifier(sprintf('assign.staticProperty%s', $property->isPrivateSet() ? 'PrivateSet' : 'ProtectedSet'))->build()]); } } */ #[RegisteredRule(0)] final class AccessStaticPropertiesInAssignRule implements Rule { private \PHPStan\Rules\Properties\AccessStaticPropertiesCheck $check; public function __construct(\PHPStan\Rules\Properties\AccessStaticPropertiesCheck $check) { $this->check = $check; } 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->check->check($node->getPropertyFetch(), $scope, \true); } } */ #[RegisteredRule(0)] final class AccessStaticPropertiesRule implements Rule { private \PHPStan\Rules\Properties\AccessStaticPropertiesCheck $check; public function __construct(\PHPStan\Rules\Properties\AccessStaticPropertiesCheck $check) { $this->check = $check; } public function getNodeType(): string { return StaticPropertyFetch::class; } public function processNode(Node $node, Scope $scope): array { return $this->check->check($node, $scope, \false); } } */ #[RegisteredRule(3)] final class DefaultValueTypesAssignedToPropertiesRule implements Rule { private RuleLevelHelper $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->hasNativeType()) { if ($default instanceof Node\Expr\ConstFetch && $default->name->toLowerString() === 'null') { return []; } } $defaultValueType = $scope->getType($default); $accepts = $this->ruleLevelHelper->accepts($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()]; } } extensions = $extensions; } /** * @return ReadWritePropertiesExtension[] */ public function getExtensions(): array { return $this->extensions; } } */ #[RegisteredRule(0)] #[ValidatesStubFiles] final class ExistingClassesInPropertiesRule implements Rule { private ReflectionProvider $reflectionProvider; private ClassNameCheck $classCheck; private UnresolvableTypeHelper $unresolvableTypeHelper; private PhpVersion $phpVersion; private bool $checkClassCaseSensitivity; private bool $checkThisOnly; private bool $discoveringSymbolsTip; public function __construct( ReflectionProvider $reflectionProvider, ClassNameCheck $classCheck, UnresolvableTypeHelper $unresolvableTypeHelper, PhpVersion $phpVersion, #[AutowiredParameter] bool $checkClassCaseSensitivity, #[AutowiredParameter] bool $checkThisOnly, #[AutowiredParameter('%tips.discoveringSymbols%')] bool $discoveringSymbolsTip ) { $this->reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->phpVersion = $phpVersion; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->checkThisOnly = $checkThisOnly; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } 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; } $errorBuilder = RuleErrorBuilder::message(sprintf('Property %s::$%s has unknown class %s as its type.', $propertyReflection->getDeclaringClass()->getDisplayName(), $node->getName(), $referencedClass))->identifier('class.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $errors[] = $errorBuilder->build(); } $errors = array_merge($errors, $this->classCheck->checkClassNames($scope, array_map(static fn(string $class): ClassNameNodePair => new ClassNameNodePair($class, $node), $referencedClasses), ClassNameUsageLocation::from(ClassNameUsageLocation::PROPERTY_TYPE, ['property' => $propertyReflection]), $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; } } */ #[RegisteredRule(0)] final class ExistingClassesInPropertyHookTypehintsRule implements Rule { private FunctionDefinitionCheck $check; public function __construct(FunctionDefinitionCheck $check) { $this->check = $check; } public function getNodeType(): string { return InPropertyHookNode::class; } public function processNode(Node $node, Scope $scope): array { $hookReflection = $node->getHookReflection(); if (!$hookReflection->isPropertyHook()) { throw new ShouldNotHappenException(); } $className = SprintfHelper::escapeFormatString($node->getClassReflection()->getDisplayName()); $hookName = $hookReflection->getPropertyHookName(); $propertyName = SprintfHelper::escapeFormatString($hookReflection->getHookedPropertyName()); $originalHookNode = $node->getOriginalNode(); if ($hookReflection->getPropertyHookName() === 'set' && $originalHookNode->params === []) { $originalHookNode = clone $originalHookNode; $originalHookNode->params = [new Node\Param(new Variable('value'), null, null)]; } return $this->check->checkClassMethod( $scope, $hookReflection, $originalHookNode, sprintf('Parameter $%%s of %s hook for property %s::$%s has invalid type %%s.', $hookName, $className, $propertyName), sprintf('%s hook for property %s::$%s has invalid return type %%s.', ucfirst($hookName), $className, $propertyName), sprintf('%s hook for property %s::$%s uses native union types but they\'re supported only on PHP 8.0 and later.', $hookName, $className, $propertyName), sprintf('Template type %%s of %s hook for property %s::$%s is not referenced in a parameter.', $hookName, $className, $propertyName), sprintf('Parameter $%%s of %s hook for property %s::$%s has unresolvable native type.', $hookName, $className, $propertyName), sprintf('%s hook for property %s::$%s has unresolvable native return type.', ucfirst($hookName), $className, $propertyName), sprintf('%s hook for property %s::$%s has invalid @phpstan-self-out type %%s.', ucfirst($hookName), $className, $propertyName), // Should be impossible, property hooks do not support return types sprintf('Impossible condition: Attribute NoDiscard cannot be used on void %s hook for property %s::$%s.', ucfirst($hookName), $className, $propertyName) ); } } 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 hasPhpDocType(): bool { return $this->originalPropertyReflection->hasPhpDocType(); } public function getPhpDocType(): Type { return $this->originalPropertyReflection->getPhpDocType(); } public function hasNativeType(): bool { return $this->originalPropertyReflection->hasNativeType(); } public function getNativeType(): Type { return $this->originalPropertyReflection->getNativeType(); } 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 getNativeReflection(): ?PhpPropertyReflection { $reflection = $this->originalPropertyReflection; while ($reflection instanceof WrapperPropertyReflection) { $reflection = $reflection->getOriginalReflection(); } if (!$reflection instanceof PhpPropertyReflection) { return null; } return $reflection; } public function isAbstract(): TrinaryLogic { return $this->originalPropertyReflection->isAbstract(); } public function isFinalByKeyword(): TrinaryLogic { return $this->originalPropertyReflection->isFinalByKeyword(); } public function isFinal(): TrinaryLogic { return $this->originalPropertyReflection->isFinal(); } public function isVirtual(): TrinaryLogic { return $this->originalPropertyReflection->isVirtual(); } public function hasHook(string $hookType): bool { return $this->originalPropertyReflection->hasHook($hookType); } public function getHook(string $hookType): ExtendedMethodReflection { return $this->originalPropertyReflection->getHook($hookType); } public function isProtectedSet(): bool { return $this->originalPropertyReflection->isProtectedSet(); } public function isPrivateSet(): bool { return $this->originalPropertyReflection->isPrivateSet(); } public function getAttributes(): array { return $this->originalPropertyReflection->getAttributes(); } public function isDummy(): TrinaryLogic { return $this->originalPropertyReflection->isDummy(); } } */ #[RegisteredRule(3)] final class GetNonVirtualPropertyHookReadRule implements Rule { public function getNodeType(): string { return ClassPropertiesNode::class; } public function processNode(Node $node, Scope $scope): array { $reads = []; $classReflection = $node->getClassReflection(); foreach ($node->getPropertyUsages() as $propertyUsage) { if (!$propertyUsage instanceof PropertyRead) { continue; } $fetch = $propertyUsage->getFetch(); if (!$fetch instanceof Node\Expr\PropertyFetch) { continue; } if (!$fetch->name instanceof Node\Identifier) { continue; } $propertyName = $fetch->name->toString(); if (!$fetch->var instanceof Node\Expr\Variable || $fetch->var->name !== 'this') { continue; } $usageScope = $propertyUsage->getScope(); $inFunction = $usageScope->getFunction(); if (!$inFunction instanceof PhpMethodFromParserNodeReflection) { continue; } if (!$inFunction->isPropertyHook()) { continue; } if ($inFunction->getPropertyHookName() !== 'get') { continue; } if ($propertyName !== $inFunction->getHookedPropertyName()) { continue; } $reads[$propertyName] = \true; } $errors = []; foreach ($node->getProperties() as $propertyNode) { $hasGetHook = \false; foreach ($propertyNode->getHooks() as $hook) { if ($hook->name->toLowerString() !== 'get') { continue; } if ($hook->body === null) { continue; } $hasGetHook = \true; break; } if (!$hasGetHook) { continue; } if (array_key_exists($propertyNode->getName(), $reads)) { continue; } $propertyReflection = $classReflection->getNativeProperty($propertyNode->getName()); if ($propertyReflection->isVirtual()->yes()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Get hook for non-virtual property %s::$%s does not read its value.', $classReflection->getDisplayName(), $propertyNode->getName()))->line($this->getGetHookLine($propertyNode))->identifier('propertyGetHook.noRead')->build(); } return $errors; } private function getGetHookLine(ClassPropertyNode $propertyNode): int { $getHook = null; foreach ($propertyNode->getHooks() as $hook) { if ($hook->name->toLowerString() !== 'get') { continue; } $getHook = $hook; break; } if ($getHook === null) { return $propertyNode->getStartLine(); } return $getHook->getStartLine(); } } */ #[RegisteredRule(0)] 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()]; } } container = $container; } public function getExtensions(): array { return $this->extensions ??= $this->container->getServicesByTag(\PHPStan\Rules\Properties\ReadWritePropertiesExtensionProvider::EXTENSION_TAG); } } */ #[RegisteredRule(6)] #[ValidatesStubFiles] final class MissingPropertyTypehintRule implements Rule { private MissingTypehintCheck $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; } } */ #[RegisteredRule(0)] final class MissingReadOnlyByPhpDocPropertyAssignRule implements Rule { private ConstructorsHelper $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; } } */ #[RegisteredRule(0)] final class MissingReadOnlyPropertyAssignRule implements Rule { private ConstructorsHelper $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; } } */ #[RegisteredRule(4)] 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->getScopeType($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())))->line($node->name->getStartLine())->identifier('nullsafe.neverNull')->build()]; } } */ #[RegisteredRule(0)] final class OverridingPropertyRule implements Rule { private PhpVersion $phpVersion; private bool $checkPhpDocMethodSignatures; private bool $reportMaybes; private ?bool $checkMissingOverridePropertyAttribute; private bool $checkMissingOverrideMethodAttribute; public function __construct( PhpVersion $phpVersion, #[AutowiredParameter] bool $checkPhpDocMethodSignatures, #[AutowiredParameter('%reportMaybesInPropertyPhpDocTypes%')] bool $reportMaybes, #[AutowiredParameter] ?bool $checkMissingOverridePropertyAttribute, #[AutowiredParameter] bool $checkMissingOverrideMethodAttribute ) { $this->phpVersion = $phpVersion; $this->checkPhpDocMethodSignatures = $checkPhpDocMethodSignatures; $this->reportMaybes = $reportMaybes; $this->checkMissingOverridePropertyAttribute = $checkMissingOverridePropertyAttribute; $this->checkMissingOverrideMethodAttribute = $checkMissingOverrideMethodAttribute; } 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) { if ($this->hasOverrideAttribute($node->getAttrGroups())) { $originalNode = $node->getOriginalNode(); if ($originalNode instanceof Node\Stmt\Property) { /** @var Node\Stmt\Property $originalNode */ $originalNode = $originalNode->getAttribute('originalPropertyStmt'); } return [RuleErrorBuilder::message(sprintf('Property %s::$%s has #[\Override] attribute but does not override any property.', $node->getClassReflection()->getDisplayName(), $node->getName()))->nonIgnorable()->identifier('property.override')->fixNode($originalNode, function ($property) { $property->attrGroups = $this->filterOverrideAttribute($property->attrGroups); return $property; })->build()]; } return []; } $errors = []; if (($this->checkMissingOverridePropertyAttribute === \true || $this->checkMissingOverridePropertyAttribute === null && $this->checkMissingOverrideMethodAttribute && $this->phpVersion->supportsOverrideAttributeOnProperty()) && !$scope->isInTrait() && !$this->hasOverrideAttribute($node->getAttrGroups())) { $originalNode = $node->getOriginalNode(); if ($originalNode instanceof Node\Stmt\Property) { /** @var Node\Stmt\Property $originalNode */ $originalNode = $originalNode->getAttribute('originalPropertyStmt'); } $errors[] = RuleErrorBuilder::message(sprintf('Property %s::$%s overrides property %s::$%s but is missing the #[\Override] attribute.', $node->getClassReflection()->getDisplayName(), $node->getName(), $prototype->getDeclaringClass()->getDisplayName(), $prototype->getName()))->identifier('property.missingOverride')->fixNode($originalNode, static function ($property) { $property->attrGroups[] = new Node\AttributeGroup([new Attribute(new Node\Name\FullyQualified('Override'))]); return $property; })->build(); } 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()) { if (!$this->phpVersion->supportsPropertyHooks() || $prototype->isWritable()) { $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(); } } $propertyReflection = $classReflection->getNativeProperty($node->getName()); if ($this->phpVersion->supportsPropertyHooks()) { if ($prototype->isReadable()) { if (!$propertyReflection->isReadable()) { $errors[] = RuleErrorBuilder::message(sprintf('Property %s::$%s overriding readable property %s::$%s also has to be readable.', $classReflection->getDisplayName(), $node->getName(), $prototype->getDeclaringClass()->getDisplayName(), $node->getName()))->identifier('property.notReadable')->nonIgnorable()->build(); } } if ($prototype->isWritable()) { if (!$propertyReflection->isWritable()) { $errors[] = RuleErrorBuilder::message(sprintf('Property %s::$%s overriding writable property %s::$%s also has to be writable.', $classReflection->getDisplayName(), $node->getName(), $prototype->getDeclaringClass()->getDisplayName(), $node->getName()))->identifier('property.notWritable')->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(); } if ($prototype->isFinalByKeyword()->yes()) { $errors[] = RuleErrorBuilder::message(sprintf('Property %s::$%s overrides final property %s::$%s.', $classReflection->getDisplayName(), $node->getName(), $prototype->getDeclaringClass()->getDisplayName(), $node->getName()))->identifier('property.parentPropertyFinal')->nonIgnorable()->build(); } elseif ($prototype->isFinal()->yes()) { $errors[] = RuleErrorBuilder::message(sprintf('Property %s::$%s overrides @final property %s::$%s.', $classReflection->getDisplayName(), $node->getName(), $prototype->getDeclaringClass()->getDisplayName(), $node->getName()))->identifier('property.parentPropertyFinalByPhpDoc')->build(); } $typeErrors = []; $nativeType = $node->getNativeType(); if ($prototype->hasNativeType()) { if ($nativeType === 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 if (!$prototype->getNativeType()->equals($nativeType)) { if ($this->phpVersion->supportsPropertyHooks() && ($prototype->isVirtual()->yes() || $prototype->isAbstract()->yes()) && (!$prototype->isReadable() || !$prototype->isWritable())) { if (!$prototype->isReadable()) { if (!$nativeType->isSuperTypeOf($prototype->getNativeType())->yes()) { $typeErrors[] = RuleErrorBuilder::message(sprintf('Type %s of property %s::$%s is not contravariant with 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 (!$prototype->getNativeType()->isSuperTypeOf($nativeType)->yes()) { $typeErrors[] = RuleErrorBuilder::message(sprintf('Type %s of property %s::$%s is not covariant with 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(); } } else { $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 ($nativeType !== null) { $typeErrors[] = RuleErrorBuilder::message(sprintf('Property %s::$%s (%s) overriding property %s::$%s should not have a native type.', $classReflection->getDisplayName(), $node->getName(), $nativeType->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; } if ($prototype->getReadableType()->equals($propertyReflection->getReadableType())) { return $errors; } $verbosity = VerbosityLevel::getRecommendedLevelByType($prototype->getReadableType(), $propertyReflection->getReadableType()); if ($this->phpVersion->supportsPropertyHooks() && ($prototype->isVirtual()->yes() || $prototype->isAbstract()->yes()) && (!$prototype->isReadable() || !$prototype->isWritable())) { if (!$prototype->isReadable()) { if (!$propertyReflection->getReadableType()->isSuperTypeOf($prototype->getReadableType())->yes()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc type %s of property %s::$%s is not contravariant with 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", 'https://phpstan.org/user-guide/stub-files'))->build(); } } elseif (!$prototype->getReadableType()->isSuperTypeOf($propertyReflection->getReadableType())->yes()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc type %s of property %s::$%s is not covariant with 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", 'https://phpstan.org/user-guide/stub-files'))->build(); } return $errors; } $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 $this->findPrototypeInInterfaces($classReflection, $propertyName); } if (!$parentClass->hasNativeProperty($propertyName)) { return $this->findPrototypeInInterfaces($classReflection, $propertyName); } $property = $parentClass->getNativeProperty($propertyName); if ($property->isPrivate()) { return $this->findPrototypeInInterfaces($classReflection, $propertyName); } return $property; } private function findPrototypeInInterfaces(ClassReflection $classReflection, string $propertyName): ?PhpPropertyReflection { foreach ($classReflection->getInterfaces() as $interface) { if (!$interface->hasNativeProperty($propertyName)) { continue; } return $interface->getNativeProperty($propertyName); } return null; } /** * @param Node\AttributeGroup[] $attrGroups * @return Node\AttributeGroup[] */ private function filterOverrideAttribute(array $attrGroups): array { foreach ($attrGroups as $i => $attrGroup) { foreach ($attrGroup->attrs as $j => $attr) { if ($attr->name->toLowerString() !== 'override') { continue; } unset($attrGroup->attrs[$j]); if (count($attrGroup->attrs) !== 0) { continue; } unset($attrGroups[$i]); } } return $attrGroups; } /** * @param Node\AttributeGroup[] $attrGroups */ private function hasOverrideAttribute(array $attrGroups): bool { foreach ($attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { if ($attr->name->toLowerString() === 'override') { return \true; } } } return \false; } } */ #[RegisteredRule(0)] final class PropertiesInInterfaceRule implements Rule { private PhpVersion $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->getClassReflection()->isInterface()) { return []; } if (!$this->phpVersion->supportsPropertyHooks()) { return [RuleErrorBuilder::message('Interfaces can include properties only on PHP 8.4 and later.')->nonIgnorable()->identifier('property.inInterface')->build()]; } if (!$node->hasHooks()) { return [RuleErrorBuilder::message('Interfaces can only include hooked properties.')->nonIgnorable()->identifier('property.nonHookedInInterface')->build()]; } if (!$node->isPublic()) { return [RuleErrorBuilder::message('Interfaces cannot include non-public properties.')->nonIgnorable()->identifier('property.nonPublicInInterface')->build()]; } if ($node->isReadOnly()) { return [RuleErrorBuilder::message('Interfaces cannot include readonly hooked properties.')->nonIgnorable()->identifier('property.readOnlyInInterface')->build()]; } if ($node->isStatic()) { return [RuleErrorBuilder::message('Hooked properties cannot be static.')->nonIgnorable()->identifier('property.hookedStatic')->build()]; } if ($node->isAbstract()) { return [RuleErrorBuilder::message('Property in interface cannot be explicitly abstract.')->nonIgnorable()->identifier('property.abstractInInterface')->build()]; } if ($node->isFinal()) { return [RuleErrorBuilder::message('Interfaces cannot include final properties.')->nonIgnorable()->identifier('property.finalInInterface')->build()]; } foreach ($node->getHooks() as $hook) { if (!$hook->isFinal()) { continue; } return [RuleErrorBuilder::message('Property hook cannot be both abstract and final.')->nonIgnorable()->identifier('property.abstractFinalHook')->build()]; } if ($this->hasAnyHookBody($node)) { return [RuleErrorBuilder::message('Interfaces cannot include property hooks with bodies.')->nonIgnorable()->identifier('property.hookBodyInInterface')->build()]; } return []; } private function hasAnyHookBody(ClassPropertyNode $node): bool { foreach ($node->getHooks() as $hook) { if ($hook->body !== null) { return \true; } } return \false; } } */ #[RegisteredRule(0)] final class PropertyAssignRefRule implements Rule { private PhpVersion $phpVersion; private \PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder; public function __construct(PhpVersion $phpVersion, \PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder) { $this->phpVersion = $phpVersion; $this->propertyReflectionFinder = $propertyReflectionFinder; } public function getNodeType(): string { return Node\Expr\AssignRef::class; } public function processNode(Node $node, Scope $scope): array { if (!$this->phpVersion->supportsAsymmetricVisibility()) { return []; } if (!$node->expr instanceof Node\Expr\PropertyFetch) { return []; } $propertyFetch = $node->expr; $errors = []; $reflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($propertyFetch, $scope); foreach ($reflections as $propertyReflection) { $nativeReflection = $propertyReflection->getNativeReflection(); if ($nativeReflection === null) { continue; } if ($scope->canWriteProperty($propertyReflection)) { continue; } $declaringClass = $nativeReflection->getDeclaringClass(); $errors[] = RuleErrorBuilder::message(sprintf('Property %s::$%s with %s visibility is assigned by reference.', $declaringClass->getDisplayName(), $propertyReflection->getName(), $propertyReflection->isPrivateSet() ? 'private(set)' : ($propertyReflection->isProtectedSet() ? 'protected(set)' : ($propertyReflection->isPrivate() ? 'private' : 'protected'))))->identifier('property.assignByRef')->build(); } return $errors; } } */ #[RegisteredRule(0)] final class PropertyAttributesRule implements Rule { private AttributesCheck $attributesCheck; private PhpVersion $phpVersion; public function __construct(AttributesCheck $attributesCheck, PhpVersion $phpVersion) { $this->attributesCheck = $attributesCheck; $this->phpVersion = $phpVersion; } public function getNodeType(): string { return ClassPropertyNode::class; } public function processNode(Node $node, Scope $scope): array { if (!$this->phpVersion->supportsOverrideAttributeOnProperty()) { $propertyReflection = $node->getClassReflection()->getNativeProperty($node->getName()); if (count($propertyReflection->getNativeReflection()->getAttributes('Override')) > 0) { return [RuleErrorBuilder::message('Attribute class Override can be used with properties only on PHP 8.5 and later.')->identifier('property.overrideAttribute')->nonIgnorable()->build()]; } } if ($node->isPromoted()) { return []; } return $this->attributesCheck->check($scope, $node->getAttrGroups(), Attribute::TARGET_PROPERTY, '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); } } */ #[RegisteredRule(0)] final class PropertyHookAttributesRule implements Rule { private AttributesCheck $attributesCheck; public function __construct(AttributesCheck $attributesCheck) { $this->attributesCheck = $attributesCheck; } public function getNodeType(): string { return InPropertyHookNode::class; } public function processNode(Node $node, Scope $scope): array { $attrGroups = $node->getOriginalNode()->attrGroups; $errors = $this->attributesCheck->check($scope, $attrGroups, Attribute::TARGET_METHOD, 'method'); foreach ($attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attribute) { $name = $attribute->name->toString(); if (strtolower($name) === 'nodiscard') { $errors[] = RuleErrorBuilder::message(sprintf('Attribute class %s cannot be used on property hooks.', $name))->identifier('attribute.target')->line($attribute->getStartLine())->nonIgnorable()->build(); break; } } } return $errors; } } */ #[RegisteredRule(0)] final class PropertyInClassRule implements Rule { private PhpVersion $phpVersion; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function getNodeType(): string { return ClassPropertyNode::class; } public function processNode(Node $node, Scope $scope): array { $classReflection = $node->getClassReflection(); if (!$classReflection->isClass()) { return []; } if ($node->isFinal() && !$this->phpVersion->supportsFinalProperties()) { return [RuleErrorBuilder::message('Final properties are supported only on PHP 8.4 and later.')->nonIgnorable()->identifier('property.final')->build()]; } if ($node->isAbstract()) { if (!$node->hasHooks()) { return [RuleErrorBuilder::message('Only hooked properties can be declared abstract.')->nonIgnorable()->identifier('property.abstractNonHooked')->build()]; } if (!$this->isAtLeastOneHookBodyEmpty($node)) { return [RuleErrorBuilder::message('Abstract properties must specify at least one abstract hook.')->nonIgnorable()->identifier('property.abstractWithoutAbstractHook')->build()]; } if (!$classReflection->isAbstract()) { return [RuleErrorBuilder::message('Non-abstract classes cannot include abstract properties.')->nonIgnorable()->identifier('property.abstract')->build()]; } } elseif (!$this->doAllHooksHaveBody($node)) { return [RuleErrorBuilder::message('Non-abstract properties cannot include hooks without bodies.')->nonIgnorable()->identifier('property.hookWithoutBody')->build()]; } if ($node->isPrivate()) { if ($node->isAbstract()) { return [RuleErrorBuilder::message('Property cannot be both abstract and private.')->nonIgnorable()->identifier('property.abstractPrivate')->build()]; } if ($node->isFinal()) { return [RuleErrorBuilder::message('Property cannot be both final and private.')->nonIgnorable()->identifier('property.finalPrivate')->build()]; } foreach ($node->getHooks() as $hook) { if (!$hook->isFinal()) { continue; } return [RuleErrorBuilder::message('Private property cannot have a final hook.')->nonIgnorable()->identifier('property.finalPrivateHook')->build()]; } } if ($node->isAbstract()) { if ($node->isFinal()) { return [RuleErrorBuilder::message('Property cannot be both abstract and final.')->nonIgnorable()->identifier('property.abstractFinal')->build()]; } foreach ($node->getHooks() as $hook) { if ($hook->body !== null) { continue; } if (!$hook->isFinal()) { continue; } return [RuleErrorBuilder::message('Property cannot be both abstract and final.')->nonIgnorable()->identifier('property.abstractFinal')->build()]; } } if ($node->isReadOnly()) { if ($node->hasHooks()) { return [RuleErrorBuilder::message('Hooked properties cannot be readonly.')->nonIgnorable()->identifier('property.hookReadOnly')->build()]; } } if ($node->isStatic()) { if ($node->hasHooks()) { return [RuleErrorBuilder::message('Hooked properties cannot be static.')->nonIgnorable()->identifier('property.hookedStatic')->build()]; } if (!$this->phpVersion->supportsAsymmetricVisibilityForStaticProperties() && ($node->isPrivateSet() || $node->isProtectedSet() || $node->isPublicSet())) { return [RuleErrorBuilder::message('Asymmetric visibility for static properties is supported only on PHP 8.5 and later.')->nonIgnorable()->identifier('property.staticAsymmetricVisibility')->build()]; } } if ($node->isVirtual()) { if ($node->getDefault() !== null) { return [RuleErrorBuilder::message('Virtual hooked properties cannot have a default value.')->nonIgnorable()->identifier('property.virtualDefault')->build()]; } } if (!$this->phpVersion->supportsPropertyHooks()) { if ($node->hasHooks()) { return [RuleErrorBuilder::message('Property hooks are supported only on PHP 8.4 and later.')->nonIgnorable()->identifier('property.hooksNotSupported')->build()]; } return []; } return []; } private function doAllHooksHaveBody(ClassPropertyNode $node): bool { foreach ($node->getHooks() as $hook) { if ($hook->body === null) { return \false; } } return \true; } private function isAtLeastOneHookBodyEmpty(ClassPropertyNode $node): bool { foreach ($node->getHooks() as $hook) { if ($hook->body === null) { return \true; } } return \false; } } name instanceof Node\Identifier) { $names = [$propertyFetch->name->name]; } else { $names = array_map(static fn(ConstantStringType $name): string => $name->getValue(), $scope->getType($propertyFetch->name)->getConstantStrings()); } $reflections = []; $propertyHolderType = $scope->getType($propertyFetch->var); foreach ($names as $name) { $reflection = $this->findInstancePropertyReflection($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 fn(ConstantStringType $name): string => $name->getValue(), $scope->getType($propertyFetch->name)->getConstantStrings()); } $reflections = []; foreach ($names as $name) { $reflection = $this->findStaticPropertyReflection($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) { $propertyHolderType = $scope->getType($propertyFetch->var); if ($propertyFetch->name instanceof Node\Identifier) { return $this->findInstancePropertyReflection($propertyHolderType, $propertyFetch->name->name, $scope); } $nameType = $scope->getType($propertyFetch->name); $nameTypeConstantStrings = $nameType->getConstantStrings(); if (count($nameTypeConstantStrings) === 1) { return $this->findInstancePropertyReflection($propertyHolderType, $nameTypeConstantStrings[0]->getValue(), $scope); } return null; } 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->findStaticPropertyReflection($propertyHolderType, $propertyFetch->name->name, $scope); } private function findInstancePropertyReflection(Type $propertyHolderType, string $propertyName, Scope $scope): ?\PHPStan\Rules\Properties\FoundPropertyReflection { if (!$propertyHolderType->hasInstanceProperty($propertyName)->yes()) { return null; } $originalProperty = $propertyHolderType->getInstanceProperty($propertyName, $scope); return new \PHPStan\Rules\Properties\FoundPropertyReflection($originalProperty, $scope, $propertyName, $originalProperty->getReadableType(), $originalProperty->getWritableType()); } private function findStaticPropertyReflection(Type $propertyHolderType, string $propertyName, Scope $scope): ?\PHPStan\Rules\Properties\FoundPropertyReflection { if (!$propertyHolderType->hasStaticProperty($propertyName)->yes()) { return null; } $originalProperty = $propertyHolderType->getStaticProperty($propertyName, $scope); return new \PHPStan\Rules\Properties\FoundPropertyReflection($originalProperty, $scope, $propertyName, $originalProperty->getReadableType(), $originalProperty->getWritableType()); } } */ #[RegisteredRule(3)] final class ReadOnlyByPhpDocPropertyAssignRefRule implements Rule { private \PHPStan\Rules\Properties\PropertyReflectionFinder $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->canWriteProperty($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; } } */ #[RegisteredRule(3)] final class ReadOnlyByPhpDocPropertyAssignRule implements Rule { private \PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder; private ConstructorsHelper $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 []; } $inCloneWith = (bool) $propertyFetch->getAttribute('inCloneWith', \false); if ($inCloneWith) { return []; } $inFunction = $scope->getFunction(); if ($inFunction instanceof PhpMethodFromParserNodeReflection && $inFunction->isPropertyHook() && $propertyFetch->var instanceof Node\Expr\Variable && $propertyFetch->var->name === 'this' && $propertyFetch->name instanceof Node\Identifier && $inFunction->getHookedPropertyName() === $propertyFetch->name->toString()) { return []; } $errors = []; $reflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($propertyFetch, $scope); foreach ($reflections as $propertyReflection) { $nativeReflection = $propertyReflection->getNativeReflection(); if ($nativeReflection === null) { continue; } if (!$scope->canWriteProperty($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()))->line($propertyFetch->name->getStartLine())->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()))->line($propertyFetch->name->getStartLine())->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()))->line($propertyFetch->name->getStartLine())->identifier('property.readOnlyByPhpDocAssignNotOnThis')->build(); } continue; } if ($nativeReflection->isAllowedPrivateMutation()) { continue; } $assignedExpr = $node->getAssignedExpr(); if (($assignedExpr instanceof SetOffsetValueTypeExpr || $assignedExpr instanceof UnsetOffsetExpr) && (new ObjectType(ArrayAccess::class))->isSuperTypeOf($scope->getType($assignedExpr->getVar()))->yes()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('@readonly property %s::$%s is assigned outside of the constructor.', $declaringClass->getDisplayName(), $propertyReflection->getName()))->line($propertyFetch->name->getStartLine())->identifier('property.readOnlyByPhpDocAssignNotInConstructor')->build(); } return $errors; } } */ #[RegisteredRule(0)] 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; } } */ #[RegisteredRule(3)] final class ReadOnlyPropertyAssignRefRule implements Rule { private \PHPStan\Rules\Properties\PropertyReflectionFinder $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) { return []; } $propertyFetch = $node->expr; $errors = []; $reflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($propertyFetch, $scope); foreach ($reflections as $propertyReflection) { $nativeReflection = $propertyReflection->getNativeReflection(); if ($nativeReflection === null) { continue; } if (!$scope->canWriteProperty($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; } } */ #[RegisteredRule(3)] final class ReadOnlyPropertyAssignRule implements Rule { private \PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder; private ConstructorsHelper $constructorsHelper; private PhpVersion $phpVersion; public function __construct(\PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder, ConstructorsHelper $constructorsHelper, PhpVersion $phpVersion) { $this->propertyReflectionFinder = $propertyReflectionFinder; $this->constructorsHelper = $constructorsHelper; $this->phpVersion = $phpVersion; } 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 []; } $inCloneWith = (bool) $propertyFetch->getAttribute('inCloneWith', \false); if ($inCloneWith) { return []; } $errors = []; $reflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($propertyFetch, $scope); foreach ($reflections as $propertyReflection) { $nativeReflection = $propertyReflection->getNativeReflection(); if ($nativeReflection === null) { continue; } if (!$scope->canWriteProperty($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()))->line($propertyFetch->name->getStartLine())->identifier('property.readOnlyAssignOutOfClass')->build(); continue; } $scopeClassReflection = $scope->getClassReflection(); if ($scopeClassReflection->getName() !== $declaringClass->getName()) { $allowedInSubclass = $this->phpVersion->supportsAsymmetricVisibility() && !$propertyReflection->isPrivateSet() && $scopeClassReflection->isSubclassOfClass($propertyReflection->getDeclaringClass()); if (!$allowedInSubclass) { $errors[] = RuleErrorBuilder::message(sprintf('Readonly property %s::$%s is assigned outside of its declaring class.', $declaringClass->getDisplayName(), $propertyReflection->getName()))->line($propertyFetch->name->getStartLine())->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()))->line($propertyFetch->name->getStartLine())->identifier('property.readOnlyAssignNotOnThis')->build(); } continue; } $assignedExpr = $node->getAssignedExpr(); if (($assignedExpr instanceof SetOffsetValueTypeExpr || $assignedExpr instanceof UnsetOffsetExpr) && (new ObjectType(ArrayAccess::class))->isSuperTypeOf($scope->getType($assignedExpr->getVar()))->yes()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Readonly property %s::$%s is assigned outside of the constructor.', $declaringClass->getDisplayName(), $propertyReflection->getName()))->line($propertyFetch->name->getStartLine())->identifier('property.readOnlyAssignNotInConstructor')->build(); } return $errors; } } */ #[RegisteredRule(0)] final class ReadOnlyPropertyRule implements Rule { private PhpVersion $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; } } */ #[RegisteredRule(0)] final class ReadingWriteOnlyPropertiesRule implements Rule { private \PHPStan\Rules\Properties\PropertyDescriptor $propertyDescriptor; private \PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder; private RuleLevelHelper $ruleLevelHelper; private bool $checkThisOnly; public function __construct( \PHPStan\Rules\Properties\PropertyDescriptor $propertyDescriptor, \PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder, RuleLevelHelper $ruleLevelHelper, #[AutowiredParameter] 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->canReadProperty($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 []; } } */ #[RegisteredRule(3)] final class SetNonVirtualPropertyHookAssignRule implements Rule { public function getNodeType(): string { return PropertyHookReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope): array { $hookNode = $node->getPropertyHookNode(); if ($hookNode->name->toLowerString() !== 'set') { return []; } $hookReflection = $node->getHookReflection(); if (!$hookReflection->isPropertyHook()) { throw new ShouldNotHappenException(); } $propertyName = $hookReflection->getHookedPropertyName(); $classReflection = $node->getClassReflection(); $propertyReflection = $node->getPropertyReflection(); if ($propertyReflection->isVirtual()->yes()) { return []; } $finalHookScope = null; foreach ($node->getExecutionEnds() as $executionEnd) { $statementResult = $executionEnd->getStatementResult(); $endNode = $executionEnd->getNode(); if ($statementResult->isAlwaysTerminating()) { if ($endNode instanceof Node\Stmt\Expression) { $exprType = $statementResult->getScope()->getType($endNode->expr); if ($exprType instanceof NeverType && $exprType->isExplicit()) { continue; } } } if ($finalHookScope === null) { $finalHookScope = $statementResult->getScope(); continue; } $finalHookScope = $finalHookScope->mergeWith($statementResult->getScope()); } foreach ($node->getReturnStatements() as $returnStatement) { if ($finalHookScope === null) { $finalHookScope = $returnStatement->getScope(); continue; } $finalHookScope = $finalHookScope->mergeWith($returnStatement->getScope()); } if ($finalHookScope === null) { return []; } $initExpr = new PropertyInitializationExpr($propertyName); $hasInit = $finalHookScope->hasExpressionType($initExpr); if ($hasInit->yes()) { return []; } return [RuleErrorBuilder::message(sprintf('Set hook for non-virtual property %s::$%s does not %sassign value to it.', $classReflection->getDisplayName(), $propertyName, $hasInit->maybe() ? 'always ' : ''))->identifier('propertySetHook.noAssign')->build()]; } } */ #[RegisteredRule(0)] final class SetPropertyHookParameterRule implements Rule { private MissingTypehintCheck $missingTypehintCheck; private bool $checkPhpDocMethodSignatures; private bool $checkMissingTypehints; public function __construct( MissingTypehintCheck $missingTypehintCheck, #[AutowiredParameter] bool $checkPhpDocMethodSignatures, #[AutowiredParameter] bool $checkMissingTypehints ) { $this->missingTypehintCheck = $missingTypehintCheck; $this->checkPhpDocMethodSignatures = $checkPhpDocMethodSignatures; $this->checkMissingTypehints = $checkMissingTypehints; } public function getNodeType(): string { return InPropertyHookNode::class; } public function processNode(Node $node, Scope $scope): array { $hookReflection = $node->getHookReflection(); if (!$hookReflection->isPropertyHook()) { return []; } if ($hookReflection->getPropertyHookName() !== 'set') { return []; } $propertyReflection = $node->getPropertyReflection(); $parameters = $hookReflection->getParameters(); if (!isset($parameters[0])) { throw new ShouldNotHappenException(); } $classReflection = $node->getClassReflection(); $errors = []; $parameter = $parameters[0]; if (!$propertyReflection->hasNativeType()) { if ($parameter->hasNativeType()) { $errors[] = RuleErrorBuilder::message(sprintf('Parameter $%s of set hook has a native type but the property %s::$%s does not.', $parameter->getName(), $classReflection->getDisplayName(), $hookReflection->getHookedPropertyName()))->identifier('propertySetHook.nativeParameterType')->nonIgnorable()->build(); } } elseif (!$parameter->hasNativeType()) { $errors[] = RuleErrorBuilder::message(sprintf('Parameter $%s of set hook does not have a native type but the property %s::$%s does.', $parameter->getName(), $classReflection->getDisplayName(), $hookReflection->getHookedPropertyName()))->identifier('propertySetHook.nativeParameterType')->nonIgnorable()->build(); } else if (!$parameter->getNativeType()->isSuperTypeOf($propertyReflection->getNativeType())->yes()) { $errors[] = RuleErrorBuilder::message(sprintf('Native type %s of set hook parameter $%s is not contravariant with native type %s of property %s::$%s.', $parameter->getNativeType()->describe(VerbosityLevel::typeOnly()), $parameter->getName(), $propertyReflection->getNativeType()->describe(VerbosityLevel::typeOnly()), $classReflection->getDisplayName(), $hookReflection->getHookedPropertyName()))->identifier('propertySetHook.nativeParameterType')->nonIgnorable()->build(); } if (!$this->checkPhpDocMethodSignatures || count($errors) > 0) { return $errors; } $parameterType = $parameter->getType(); if (!$parameterType->isSuperTypeOf($propertyReflection->getReadableType())->yes()) { $errors[] = RuleErrorBuilder::message(sprintf('Type %s of set hook parameter $%s is not contravariant with type %s of property %s::$%s.', $parameterType->describe(VerbosityLevel::value()), $parameter->getName(), $propertyReflection->getReadableType()->describe(VerbosityLevel::value()), $classReflection->getDisplayName(), $hookReflection->getHookedPropertyName()))->identifier('propertySetHook.parameterType')->build(); } if (!$this->checkMissingTypehints) { return $errors; } if ($parameter->getNativeType()->equals($propertyReflection->getReadableType())) { return $errors; } foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($parameterType) as $iterableType) { $iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly()); $errors[] = RuleErrorBuilder::message(sprintf('Set hook for property %s::$%s has parameter $%s with no value type specified in iterable type %s.', $classReflection->getDisplayName(), $hookReflection->getHookedPropertyName(), $parameter->getName(), $iterableTypeDescription))->tip(MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP)->identifier('missingType.iterableValue')->build(); } foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($parameterType) as [$name, $genericTypeNames]) { $errors[] = RuleErrorBuilder::message(sprintf('Set hook for property %s::$%s has parameter $%s with generic %s but does not specify its types: %s', $classReflection->getDisplayName(), $hookReflection->getHookedPropertyName(), $parameter->getName(), $name, $genericTypeNames))->identifier('missingType.generics')->build(); } foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($parameterType) as $callableType) { $errors[] = RuleErrorBuilder::message(sprintf('Set hook for property %s::$%s has parameter $%s with no signature specified for %s.', $classReflection->getDisplayName(), $hookReflection->getHookedPropertyName(), $parameter->getName(), $callableType->describe(VerbosityLevel::typeOnly())))->identifier('missingType.callable')->build(); } return $errors; } } */ #[RegisteredRule(3)] final class TypesAssignedToPropertiesRule implements Rule { private RuleLevelHelper $ruleLevelHelper; private \PHPStan\Rules\Properties\PropertyReflectionFinder $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 { $propertyFetch = $node->getPropertyFetch(); $propertyReflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($propertyFetch, $scope); $errors = []; foreach ($propertyReflections as $propertyReflection) { $errors = array_merge($errors, $this->processSingleProperty($propertyReflection, $propertyFetch, $node->getAssignedExpr())); } return $errors; } /** * @return list * @param \PhpParser\Node\Expr\PropertyFetch|\PhpParser\Node\Expr\StaticPropertyFetch $fetch */ private function processSingleProperty(\PHPStan\Rules\Properties\FoundPropertyReflection $propertyReflection, $fetch, Node\Expr $assignedExpr): array { if (!$propertyReflection->isWritable()) { return []; } $scope = $propertyReflection->getScope(); $inFunction = $scope->getFunction(); if ($fetch instanceof PropertyFetch && $fetch->var instanceof Node\Expr\Variable && is_string($fetch->var->name) && $fetch->var->name === 'this' && $fetch->name instanceof Node\Identifier && $inFunction instanceof PhpMethodFromParserNodeReflection && $inFunction->isPropertyHook() && $inFunction->getHookedPropertyName() === $fetch->name->toString()) { $propertyType = $propertyReflection->getReadableType(); } else { $propertyType = $propertyReflection->getWritableType(); } $assignedValueType = $scope->getType($assignedExpr); $accepts = $this->ruleLevelHelper->accepts($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)))->line($assignedExpr->getStartLine())->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); } } */ final class UninitializedPropertyRule implements Rule { private ConstructorsHelper $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; } } */ #[RegisteredRule(0)] final class WritingToReadOnlyPropertiesRule implements Rule { private RuleLevelHelper $ruleLevelHelper; private \PHPStan\Rules\Properties\PropertyDescriptor $propertyDescriptor; private \PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder; private bool $checkThisOnly; public function __construct( RuleLevelHelper $ruleLevelHelper, \PHPStan\Rules\Properties\PropertyDescriptor $propertyDescriptor, \PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder, #[AutowiredParameter] 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->canWriteProperty($propertyReflection)) { return []; } if (!$propertyReflection->isWritable()) { $propertyDescription = $this->propertyDescriptor->describeProperty($propertyReflection, $scope, $propertyFetch); return [RuleErrorBuilder::message(sprintf('%s is not writable.', $propertyDescription))->line($propertyFetch->name->getStartLine())->identifier('assign.propertyReadOnly')->build()]; } return []; } } * @param \PHPStan\Reflection\FunctionReflection|\PHPStan\Reflection\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(); } $throwType = $functionReflection->getThrowType(); if ($returnType->isVoid()->yes() && !$isConstructor && ($throwType === null || $throwType->isVoid()->yes()) && $functionReflection->getAsserts()->getAll() === []) { $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 && (!$functionReflection instanceof ExtendedMethodReflection || $functionReflection->isFinal()->yes() || $functionReflection->getDeclaringClass()->isFinal())) { $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; } } */ #[RegisteredRule(2)] final class PureFunctionRule implements Rule { private \PHPStan\Rules\Pure\FunctionPurityCheck $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); } } */ #[RegisteredRule(2)] final class PureMethodRule implements Rule { private \PHPStan\Rules\Pure\FunctionPurityCheck $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()); } } */ #[RegisteredRule(0)] final class RegularExpressionPatternRule implements Rule { private RegexExpressionHelper $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; } } */ #[RegisteredRule(5)] final class RegularExpressionQuotingRule implements Rule { private ReflectionProvider $reflectionProvider; private RegexExpressionHelper $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, fn(string $delimiter): bool => !$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(); } } $nodeType * @return array> */ public function getRules(string $nodeType): array; } */ #[AutowiredService] final class RestrictedClassConstantUsageRule implements Rule { private Container $container; private ReflectionProvider $reflectionProvider; private RuleLevelHelper $ruleLevelHelper; /** @var RestrictedClassConstantUsageExtension[] $extensions */ private ?array $extensions = null; public function __construct(Container $container, ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper) { $this->container = $container; $this->reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType(): string { return Node\Expr\ClassConstFetch::class; } /** * @api */ public function processNode(Node $node, Scope $scope): array { if (!$node->name instanceof Identifier) { return []; } /** @var RestrictedClassConstantUsageExtension[] $extensions */ $extensions = $this->extensions ??= $this->container->getServicesByTag(\PHPStan\Rules\RestrictedUsage\RestrictedClassConstantUsageExtension::CLASS_CONSTANT_EXTENSION_TAG); if ($extensions === []) { return []; } $constantName = $node->name->name; $referencedClasses = []; if ($node->class instanceof Name) { $referencedClasses[] = $scope->resolveName($node->class); } else { $classTypeResult = $this->ruleLevelHelper->findTypeToCheck( $scope, $node->class, '', // We don't care about the error message static fn(Type $type): bool => $type->canAccessConstants()->yes() && $type->hasConstant($constantName)->yes() ); if ($classTypeResult->getType() instanceof ErrorType) { return []; } $referencedClasses = $classTypeResult->getReferencedClasses(); } $errors = []; foreach ($referencedClasses as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $classReflection = $this->reflectionProvider->getClass($referencedClass); if (!$classReflection->hasConstant($constantName)) { continue; } $constantReflection = $classReflection->getConstant($constantName); foreach ($extensions as $extension) { $restrictedUsage = $extension->isRestrictedClassConstantUsage($constantReflection, $scope); if ($restrictedUsage === null) { continue; } if ($classReflection->getName() !== $constantReflection->getDeclaringClass()->getName()) { $rewrittenConstantReflection = new \PHPStan\Rules\RestrictedUsage\RewrittenDeclaringClassClassConstantReflection($classReflection, $constantReflection); $rewrittenRestrictedUsage = $extension->isRestrictedClassConstantUsage($rewrittenConstantReflection, $scope); if ($rewrittenRestrictedUsage === null) { continue; } } $errors[] = RuleErrorBuilder::message($restrictedUsage->errorMessage)->identifier($restrictedUsage->identifier)->build(); } } return $errors; } } */ #[AutowiredService] final class RestrictedFunctionCallableUsageRule implements Rule { private Container $container; private ReflectionProvider $reflectionProvider; /** @var RestrictedFunctionUsageExtension[] $extensions */ private ?array $extensions = null; public function __construct(Container $container, ReflectionProvider $reflectionProvider) { $this->container = $container; $this->reflectionProvider = $reflectionProvider; } public function getNodeType(): string { return FunctionCallableNode::class; } /** * @api */ public function processNode(Node $node, Scope $scope): array { if (!$node->getName() instanceof Name) { return []; } if (!$this->reflectionProvider->hasFunction($node->getName(), $scope)) { return []; } $functionReflection = $this->reflectionProvider->getFunction($node->getName(), $scope); /** @var RestrictedFunctionUsageExtension[] $extensions */ $extensions = $this->extensions ??= $this->container->getServicesByTag(\PHPStan\Rules\RestrictedUsage\RestrictedFunctionUsageExtension::FUNCTION_EXTENSION_TAG); $errors = []; foreach ($extensions as $extension) { $restrictedUsage = $extension->isRestrictedFunctionUsage($functionReflection, $scope); if ($restrictedUsage === null) { continue; } $errors[] = RuleErrorBuilder::message($restrictedUsage->errorMessage)->identifier($restrictedUsage->identifier)->build(); } return $errors; } } */ #[AutowiredService] final class RestrictedFunctionUsageRule implements Rule { private Container $container; private ReflectionProvider $reflectionProvider; /** @var RestrictedFunctionUsageExtension[] $extensions */ private ?array $extensions = null; public function __construct(Container $container, ReflectionProvider $reflectionProvider) { $this->container = $container; $this->reflectionProvider = $reflectionProvider; } public function getNodeType(): string { return Node\Expr\FuncCall::class; } /** * @api */ public function processNode(Node $node, Scope $scope): array { if (!$node->name instanceof Name) { return []; } if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { return []; } $functionReflection = $this->reflectionProvider->getFunction($node->name, $scope); /** @var RestrictedFunctionUsageExtension[] $extensions */ $extensions = $this->extensions ??= $this->container->getServicesByTag(\PHPStan\Rules\RestrictedUsage\RestrictedFunctionUsageExtension::FUNCTION_EXTENSION_TAG); $errors = []; foreach ($extensions as $extension) { $restrictedUsage = $extension->isRestrictedFunctionUsage($functionReflection, $scope); if ($restrictedUsage === null) { continue; } $errors[] = RuleErrorBuilder::message($restrictedUsage->errorMessage)->identifier($restrictedUsage->identifier)->build(); } return $errors; } } */ #[AutowiredService] final class RestrictedMethodCallableUsageRule implements Rule { private Container $container; private ReflectionProvider $reflectionProvider; /** @var RestrictedMethodUsageExtension[] $extensions */ private ?array $extensions = null; public function __construct(Container $container, ReflectionProvider $reflectionProvider) { $this->container = $container; $this->reflectionProvider = $reflectionProvider; } public function getNodeType(): string { return MethodCallableNode::class; } /** * @api */ public function processNode(Node $node, Scope $scope): array { if (!$node->getName() instanceof Identifier) { return []; } /** @var RestrictedMethodUsageExtension[] $extensions */ $extensions = $this->extensions ??= $this->container->getServicesByTag(\PHPStan\Rules\RestrictedUsage\RestrictedMethodUsageExtension::METHOD_EXTENSION_TAG); if ($extensions === []) { return []; } $methodName = $node->getName()->name; $methodCalledOnType = $scope->getType($node->getVar()); $referencedClasses = $methodCalledOnType->getObjectClassNames(); $errors = []; foreach ($referencedClasses as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $classReflection = $this->reflectionProvider->getClass($referencedClass); if (!$classReflection->hasMethod($methodName)) { continue; } $methodReflection = $classReflection->getMethod($methodName, $scope); foreach ($extensions as $extension) { $restrictedUsage = $extension->isRestrictedMethodUsage($methodReflection, $scope); if ($restrictedUsage === null) { continue; } $errors[] = RuleErrorBuilder::message($restrictedUsage->errorMessage)->identifier($restrictedUsage->identifier)->build(); } } return $errors; } } */ #[AutowiredService] final class RestrictedMethodUsageRule implements Rule { private Container $container; private ReflectionProvider $reflectionProvider; /** @var RestrictedMethodUsageExtension[] $extensions */ private ?array $extensions = null; public function __construct(Container $container, ReflectionProvider $reflectionProvider) { $this->container = $container; $this->reflectionProvider = $reflectionProvider; } public function getNodeType(): string { return MethodCall::class; } /** * @api */ public function processNode(Node $node, Scope $scope): array { if (!$node->name instanceof Identifier) { return []; } /** @var RestrictedMethodUsageExtension[] $extensions */ $extensions = $this->extensions ??= $this->container->getServicesByTag(\PHPStan\Rules\RestrictedUsage\RestrictedMethodUsageExtension::METHOD_EXTENSION_TAG); if ($extensions === []) { return []; } $methodName = $node->name->name; $methodCalledOnType = $scope->getType($node->var); $referencedClasses = $methodCalledOnType->getObjectClassNames(); $errors = []; foreach ($referencedClasses as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $classReflection = $this->reflectionProvider->getClass($referencedClass); if (!$classReflection->hasMethod($methodName)) { continue; } $methodReflection = $classReflection->getMethod($methodName, $scope); foreach ($extensions as $extension) { $restrictedUsage = $extension->isRestrictedMethodUsage($methodReflection, $scope); if ($restrictedUsage === null) { continue; } $errors[] = RuleErrorBuilder::message($restrictedUsage->errorMessage)->identifier($restrictedUsage->identifier)->build(); } } return $errors; } } */ #[AutowiredService] final class RestrictedPropertyUsageRule implements Rule { private Container $container; private ReflectionProvider $reflectionProvider; /** @var RestrictedPropertyUsageExtension[] $extensions */ private ?array $extensions = null; public function __construct(Container $container, ReflectionProvider $reflectionProvider) { $this->container = $container; $this->reflectionProvider = $reflectionProvider; } public function getNodeType(): string { return Node\Expr\PropertyFetch::class; } /** * @api */ public function processNode(Node $node, Scope $scope): array { if (!$node->name instanceof Identifier) { return []; } /** @var RestrictedPropertyUsageExtension[] $extensions */ $extensions = $this->extensions ??= $this->container->getServicesByTag(\PHPStan\Rules\RestrictedUsage\RestrictedPropertyUsageExtension::PROPERTY_EXTENSION_TAG); if ($extensions === []) { return []; } $propertyName = $node->name->name; $propertyCalledOnType = $scope->getType($node->var); $referencedClasses = $propertyCalledOnType->getObjectClassNames(); $errors = []; foreach ($referencedClasses as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $classReflection = $this->reflectionProvider->getClass($referencedClass); if (!$classReflection->hasInstanceProperty($propertyName)) { continue; } $propertyReflection = $classReflection->getInstanceProperty($propertyName, $scope); foreach ($extensions as $extension) { $restrictedUsage = $extension->isRestrictedPropertyUsage($propertyReflection, $scope); if ($restrictedUsage === null) { continue; } $errors[] = RuleErrorBuilder::message($restrictedUsage->errorMessage)->identifier($restrictedUsage->identifier)->build(); } } return $errors; } } */ #[AutowiredService] final class RestrictedStaticMethodCallableUsageRule implements Rule { private Container $container; private ReflectionProvider $reflectionProvider; private RuleLevelHelper $ruleLevelHelper; /** @var RestrictedMethodUsageExtension[] $extensions */ private ?array $extensions = null; public function __construct(Container $container, ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper) { $this->container = $container; $this->reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType(): string { return StaticMethodCallableNode::class; } /** * @api */ public function processNode(Node $node, Scope $scope): array { if (!$node->getName() instanceof Identifier) { return []; } /** @var RestrictedMethodUsageExtension[] $extensions */ $extensions = $this->extensions ??= $this->container->getServicesByTag(\PHPStan\Rules\RestrictedUsage\RestrictedMethodUsageExtension::METHOD_EXTENSION_TAG); if ($extensions === []) { return []; } $methodName = $node->getName()->name; $referencedClasses = []; if ($node->getClass() instanceof Name) { $referencedClasses[] = $scope->resolveName($node->getClass()); } else { $classTypeResult = $this->ruleLevelHelper->findTypeToCheck( $scope, $node->getClass(), '', // We don't care about the error message static fn(Type $type): bool => $type->canCallMethods()->yes() && $type->hasMethod($methodName)->yes() ); if ($classTypeResult->getType() instanceof ErrorType) { return []; } $referencedClasses = $classTypeResult->getReferencedClasses(); } $errors = []; foreach ($referencedClasses as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $classReflection = $this->reflectionProvider->getClass($referencedClass); if (!$classReflection->hasMethod($methodName)) { continue; } $methodReflection = $classReflection->getMethod($methodName, $scope); foreach ($extensions as $extension) { $restrictedUsage = $extension->isRestrictedMethodUsage($methodReflection, $scope); if ($restrictedUsage === null) { continue; } if ($classReflection->getName() !== $methodReflection->getDeclaringClass()->getName()) { $rewrittenMethodReflection = new \PHPStan\Rules\RestrictedUsage\RewrittenDeclaringClassMethodReflection($classReflection, $methodReflection); $rewrittenRestrictedUsage = $extension->isRestrictedMethodUsage($rewrittenMethodReflection, $scope); if ($rewrittenRestrictedUsage === null) { continue; } } $errors[] = RuleErrorBuilder::message($restrictedUsage->errorMessage)->identifier($restrictedUsage->identifier)->build(); } } return $errors; } } */ #[AutowiredService] final class RestrictedStaticMethodUsageRule implements Rule { private Container $container; private ReflectionProvider $reflectionProvider; private RuleLevelHelper $ruleLevelHelper; /** @var RestrictedMethodUsageExtension[] $extensions */ private ?array $extensions = null; public function __construct(Container $container, ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper) { $this->container = $container; $this->reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType(): string { return Node\Expr\StaticCall::class; } /** * @api */ public function processNode(Node $node, Scope $scope): array { if (!$node->name instanceof Identifier) { return []; } /** @var RestrictedMethodUsageExtension[] $extensions */ $extensions = $this->extensions ??= $this->container->getServicesByTag(\PHPStan\Rules\RestrictedUsage\RestrictedMethodUsageExtension::METHOD_EXTENSION_TAG); if ($extensions === []) { return []; } $methodName = $node->name->name; $referencedClasses = []; if ($node->class instanceof Name) { $referencedClasses[] = $scope->resolveName($node->class); } else { $classTypeResult = $this->ruleLevelHelper->findTypeToCheck( $scope, $node->class, '', // We don't care about the error message static fn(Type $type): bool => $type->canCallMethods()->yes() && $type->hasMethod($methodName)->yes() ); if ($classTypeResult->getType() instanceof ErrorType) { return []; } $referencedClasses = $classTypeResult->getReferencedClasses(); } $errors = []; foreach ($referencedClasses as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $classReflection = $this->reflectionProvider->getClass($referencedClass); if (!$classReflection->hasMethod($methodName)) { continue; } $methodReflection = $classReflection->getMethod($methodName, $scope); foreach ($extensions as $extension) { $restrictedUsage = $extension->isRestrictedMethodUsage($methodReflection, $scope); if ($restrictedUsage === null) { continue; } if ($classReflection->getName() !== $methodReflection->getDeclaringClass()->getName()) { $rewrittenMethodReflection = new \PHPStan\Rules\RestrictedUsage\RewrittenDeclaringClassMethodReflection($classReflection, $methodReflection); $rewrittenRestrictedUsage = $extension->isRestrictedMethodUsage($rewrittenMethodReflection, $scope); if ($rewrittenRestrictedUsage === null) { continue; } } $errors[] = RuleErrorBuilder::message($restrictedUsage->errorMessage)->identifier($restrictedUsage->identifier)->build(); } } return $errors; } } */ #[AutowiredService] final class RestrictedStaticPropertyUsageRule implements Rule { private Container $container; private ReflectionProvider $reflectionProvider; private RuleLevelHelper $ruleLevelHelper; /** @var RestrictedPropertyUsageExtension[] $extensions */ private ?array $extensions = null; public function __construct(Container $container, ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper) { $this->container = $container; $this->reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType(): string { return Node\Expr\StaticPropertyFetch::class; } /** * @api */ public function processNode(Node $node, Scope $scope): array { if (!$node->name instanceof Identifier) { return []; } /** @var RestrictedPropertyUsageExtension[] $extensions */ $extensions = $this->extensions ??= $this->container->getServicesByTag(\PHPStan\Rules\RestrictedUsage\RestrictedPropertyUsageExtension::PROPERTY_EXTENSION_TAG); if ($extensions === []) { return []; } $propertyName = $node->name->name; $referencedClasses = []; if ($node->class instanceof Name) { $referencedClasses[] = $scope->resolveName($node->class); } else { $classTypeResult = $this->ruleLevelHelper->findTypeToCheck( $scope, $node->class, '', // We don't care about the error message static fn(Type $type): bool => $type->canAccessProperties()->yes() && $type->hasInstanceProperty($propertyName)->yes() ); if ($classTypeResult->getType() instanceof ErrorType) { return []; } $referencedClasses = $classTypeResult->getReferencedClasses(); } $errors = []; foreach ($referencedClasses as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $classReflection = $this->reflectionProvider->getClass($referencedClass); if (!$classReflection->hasStaticProperty($propertyName)) { continue; } $propertyReflection = $classReflection->getStaticProperty($propertyName); foreach ($extensions as $extension) { $restrictedUsage = $extension->isRestrictedPropertyUsage($propertyReflection, $scope); if ($restrictedUsage === null) { continue; } if ($classReflection->getName() !== $propertyReflection->getDeclaringClass()->getName()) { $rewrittenPropertyReflection = new \PHPStan\Rules\RestrictedUsage\RewrittenDeclaringClassPropertyReflection($classReflection, $propertyReflection); $rewrittenRestrictedUsage = $extension->isRestrictedPropertyUsage($rewrittenPropertyReflection, $scope); if ($rewrittenRestrictedUsage === null) { continue; } } $errors[] = RuleErrorBuilder::message($restrictedUsage->errorMessage)->identifier($restrictedUsage->identifier)->build(); } } return $errors; } } errorMessage = $errorMessage; $this->identifier = $identifier; } public static function create(string $errorMessage, string $identifier): self { return new self($errorMessage, $identifier); } } */ #[AutowiredService] final class RestrictedUsageOfDeprecatedStringCastRule implements Rule { private Container $container; private ReflectionProvider $reflectionProvider; /** @var RestrictedMethodUsageExtension[] $extensions */ private ?array $extensions = null; public function __construct(Container $container, ReflectionProvider $reflectionProvider) { $this->container = $container; $this->reflectionProvider = $reflectionProvider; } public function getNodeType(): string { return Cast\String_::class; } public function processNode(Node $node, Scope $scope): array { /** @var RestrictedMethodUsageExtension[] $extensions */ $extensions = $this->extensions ??= $this->container->getServicesByTag(\PHPStan\Rules\RestrictedUsage\RestrictedMethodUsageExtension::METHOD_EXTENSION_TAG); if ($extensions === []) { return []; } $exprType = $scope->getType($node->expr); $referencedClasses = $exprType->getObjectClassNames(); $errors = []; foreach ($referencedClasses as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $classReflection = $this->reflectionProvider->getClass($referencedClass); if (!$classReflection->hasNativeMethod('__toString')) { continue; } $methodReflection = $classReflection->getNativeMethod('__toString'); foreach ($extensions as $extension) { $restrictedUsage = $extension->isRestrictedMethodUsage($methodReflection, $scope); if ($restrictedUsage === null) { continue; } $errors[] = RuleErrorBuilder::message($restrictedUsage->errorMessage)->identifier($restrictedUsage->identifier)->build(); } } return $errors; } } declaringClass = $declaringClass; $this->constantReflection = $constantReflection; } public function getValueExpr(): Expr { return $this->constantReflection->getValueExpr(); } public function isFinal(): bool { return $this->constantReflection->isFinal(); } public function isFinalByKeyword(): bool { return $this->constantReflection->isFinalByKeyword(); } public function hasPhpDocType(): bool { return $this->constantReflection->hasPhpDocType(); } public function getPhpDocType(): ?Type { return $this->constantReflection->getPhpDocType(); } public function hasNativeType(): bool { return $this->constantReflection->hasNativeType(); } public function getNativeType(): ?Type { return $this->constantReflection->getNativeType(); } public function getAttributes(): array { return $this->constantReflection->getAttributes(); } public function getDeclaringClass(): ClassReflection { return $this->declaringClass; } public function isStatic(): bool { return $this->constantReflection->isStatic(); } public function isPrivate(): bool { return $this->constantReflection->isPrivate(); } public function isPublic(): bool { return $this->constantReflection->isPublic(); } public function getDocComment(): ?string { return $this->constantReflection->getDocComment(); } public function getName(): string { return $this->constantReflection->getName(); } public function getValueType(): Type { return $this->constantReflection->getValueType(); } public function isDeprecated(): TrinaryLogic { return $this->constantReflection->isDeprecated(); } public function getDeprecatedDescription(): ?string { return $this->constantReflection->getDeprecatedDescription(); } public function isInternal(): TrinaryLogic { return $this->constantReflection->isInternal(); } public function getFileName(): ?string { return $this->constantReflection->getFileName(); } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return $this->constantReflection->getResolvedPhpDoc(); } } declaringClass = $declaringClass; $this->methodReflection = $methodReflection; } public function getDeclaringClass(): ClassReflection { return $this->declaringClass; } public function isStatic(): bool { return $this->methodReflection->isStatic(); } public function isPrivate(): bool { return $this->methodReflection->isPrivate(); } public function isPublic(): bool { return $this->methodReflection->isPublic(); } public function getDocComment(): ?string { return $this->methodReflection->getDocComment(); } public function getVariants(): array { return $this->methodReflection->getVariants(); } public function getOnlyVariant(): ExtendedParametersAcceptor { return $this->methodReflection->getOnlyVariant(); } public function getNamedArgumentsVariants(): ?array { return $this->methodReflection->getNamedArgumentsVariants(); } public function acceptsNamedArguments(): TrinaryLogic { return $this->methodReflection->acceptsNamedArguments(); } public function getAsserts(): Assertions { return $this->methodReflection->getAsserts(); } public function getSelfOutType(): ?Type { return $this->methodReflection->getSelfOutType(); } public function returnsByReference(): TrinaryLogic { return $this->methodReflection->returnsByReference(); } public function isFinalByKeyword(): TrinaryLogic { return $this->methodReflection->isFinalByKeyword(); } /** * @return \PHPStan\TrinaryLogic|bool */ public function isAbstract() { return $this->methodReflection->isAbstract(); } /** * @return \PHPStan\TrinaryLogic|bool */ public function isBuiltin() { return $this->methodReflection->isBuiltin(); } public function isPure(): TrinaryLogic { return $this->methodReflection->isPure(); } public function getAttributes(): array { return $this->methodReflection->getAttributes(); } public function getName(): string { return $this->methodReflection->getName(); } public function getPrototype(): ClassMemberReflection { return $this->methodReflection->getPrototype(); } public function isDeprecated(): TrinaryLogic { return $this->methodReflection->isDeprecated(); } public function getDeprecatedDescription(): ?string { return $this->methodReflection->getDeprecatedDescription(); } public function isFinal(): TrinaryLogic { return $this->methodReflection->isFinal(); } public function isInternal(): TrinaryLogic { return $this->methodReflection->isInternal(); } public function getThrowType(): ?Type { return $this->methodReflection->getThrowType(); } public function hasSideEffects(): TrinaryLogic { return $this->methodReflection->hasSideEffects(); } public function mustUseReturnValue(): TrinaryLogic { return $this->methodReflection->mustUseReturnValue(); } public function getResolvedPhpDoc(): ?ResolvedPhpDocBlock { return $this->methodReflection->getResolvedPhpDoc(); } } declaringClass = $declaringClass; $this->propertyReflection = $propertyReflection; } public function getDeclaringClass(): ClassReflection { return $this->declaringClass; } public function isStatic(): bool { return $this->propertyReflection->isStatic(); } public function isPrivate(): bool { return $this->propertyReflection->isPrivate(); } public function isPublic(): bool { return $this->propertyReflection->isPublic(); } public function getDocComment(): ?string { return $this->propertyReflection->getDocComment(); } public function getName(): string { return $this->propertyReflection->getName(); } public function hasPhpDocType(): bool { return $this->propertyReflection->hasPhpDocType(); } public function getPhpDocType(): Type { return $this->propertyReflection->getPhpDocType(); } public function hasNativeType(): bool { return $this->propertyReflection->hasNativeType(); } public function getNativeType(): Type { return $this->propertyReflection->getNativeType(); } public function isAbstract(): TrinaryLogic { return $this->propertyReflection->isAbstract(); } public function isFinalByKeyword(): TrinaryLogic { return $this->propertyReflection->isFinalByKeyword(); } public function isFinal(): TrinaryLogic { return $this->propertyReflection->isFinal(); } public function isVirtual(): TrinaryLogic { return $this->propertyReflection->isVirtual(); } public function hasHook(string $hookType): bool { return $this->propertyReflection->hasHook($hookType); } public function getHook(string $hookType): ExtendedMethodReflection { return $this->propertyReflection->getHook($hookType); } public function isProtectedSet(): bool { return $this->propertyReflection->isProtectedSet(); } public function isPrivateSet(): bool { return $this->propertyReflection->isPrivateSet(); } public function getAttributes(): array { return $this->propertyReflection->getAttributes(); } public function getReadableType(): Type { return $this->propertyReflection->getReadableType(); } public function getWritableType(): Type { return $this->propertyReflection->getWritableType(); } public function canChangeTypeAfterAssignment(): bool { return $this->propertyReflection->canChangeTypeAfterAssignment(); } public function isReadable(): bool { return $this->propertyReflection->isReadable(); } public function isWritable(): bool { return $this->propertyReflection->isWritable(); } public function isDeprecated(): TrinaryLogic { return $this->propertyReflection->isDeprecated(); } public function getDeprecatedDescription(): ?string { return $this->propertyReflection->getDeprecatedDescription(); } public function isInternal(): TrinaryLogic { return $this->propertyReflection->isInternal(); } public function isDummy(): TrinaryLogic { return $this->propertyReflection->isDummy(); } } */ public function getNodeType(): string; /** * @param TNodeType $node * @return list * @param \PHPStan\Analyser\Scope&\PHPStan\Analyser\NodeCallbackInvoker $scope */ public function processNode(Node $node, \PHPStan\Analyser\Scope $scope): array; } */ private array $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', // property name 'string', // native type '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, []], self::TYPE_FIXABLE_NODE => [\PHPStan\Rules\FixableNodeRuleError::class, [['originalNode', '\PhpParser\Node', '\PhpParser\Node'], ['newNodeCallable', null, 'callable(\PhpParser\Node): \PhpParser\Node']]]]; } /** * @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%.'); } /** * @param list $callDescriptions * @phpstan-this-out self * @return self */ public function possiblyImpureTip(array $callDescriptions): self { foreach ($callDescriptions as $callDescription) { $this->addTip(sprintf('If %s is impure, add @phpstan-impure PHPDoc tag above its declaration. Learn more: https://phpstan.org/blog/remembering-and-forgetting-returned-values', $callDescription)); } return $this; } /** * 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; } /** * @internal Experimental * @template TNode of Node * @param TNode $node * @param callable(TNode): Node $cb * @phpstan-this-out self * @return self */ public function fixNode(Node $node, callable $cb): self { $this->properties['originalNode'] = $node; $this->properties['newNodeCallable'] = $cb; $this->type |= self::TYPE_FIXABLE_NODE; 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 fn(string $tip) => sprintf('• %s', $tip), $this->tips)); } } return $ruleError; } } message; } } 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; } /** * @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 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 getTip(): string { return $this->tip; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } } message; } public function getLine(): int { return $this->line; } 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; } 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 getLine(): int { return $this->line; } 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; } /** * @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; } /** * @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 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 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; } public function getIdentifier(): string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } } message; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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 getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getFile(): string { return $this->file; } public function getFileDescription(): string { return $this->fileDescription; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getLine(): int { return $this->line; } public function getFile(): string { return $this->file; } public function getFileDescription(): string { return $this->fileDescription; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getTip(): string { return $this->tip; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getLine(): int { return $this->line; } public function getTip(): string { return $this->tip; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getFile(): string { return $this->file; } public function getFileDescription(): string { return $this->fileDescription; } public function getTip(): string { return $this->tip; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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 getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getIdentifier(): string { return $this->identifier; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getLine(): int { return $this->line; } public function getIdentifier(): string { return $this->identifier; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getFile(): string { return $this->file; } public function getFileDescription(): string { return $this->fileDescription; } public function getIdentifier(): string { return $this->identifier; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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 getFile(): string { return $this->file; } public function getFileDescription(): string { return $this->fileDescription; } public function getIdentifier(): string { return $this->identifier; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getTip(): string { return $this->tip; } public function getIdentifier(): string { return $this->identifier; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getLine(): int { return $this->line; } public function getTip(): string { return $this->tip; } public function getIdentifier(): string { return $this->identifier; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getLine(): int { return $this->line; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getFile(): string { return $this->file; } public function getFileDescription(): string { return $this->fileDescription; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getTip(): string { return $this->tip; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getIdentifier(): string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getLine(): int { return $this->line; } public function getIdentifier(): string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getTip(): string { return $this->tip; } public function getIdentifier(): string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getTip(): string { return $this->tip; } public function getIdentifier(): string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getLine(): int { return $this->line; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getFile(): string { return $this->file; } public function getFileDescription(): string { return $this->fileDescription; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getLine(): int { return $this->line; } public function getFile(): string { return $this->file; } public function getFileDescription(): string { return $this->fileDescription; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getTip(): string { return $this->tip; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getLine(): int { return $this->line; } public function getTip(): string { return $this->tip; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getFile(): string { return $this->file; } public function getFileDescription(): string { return $this->fileDescription; } public function getTip(): string { return $this->tip; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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 getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getIdentifier(): string { return $this->identifier; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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 getIdentifier(): string { return $this->identifier; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getFile(): string { return $this->file; } public function getFileDescription(): string { return $this->fileDescription; } public function getIdentifier(): string { return $this->identifier; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getTip(): string { return $this->tip; } public function getIdentifier(): string { return $this->identifier; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getLine(): int { return $this->line; } public function getTip(): string { return $this->tip; } public function getIdentifier(): string { return $this->identifier; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getLine(): int { return $this->line; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getFile(): string { return $this->file; } public function getFileDescription(): string { return $this->fileDescription; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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 getFile(): string { return $this->file; } public function getFileDescription(): string { return $this->fileDescription; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getTip(): string { return $this->tip; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getLine(): int { return $this->line; } public function getTip(): string { return $this->tip; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getIdentifier(): string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getLine(): int { return $this->line; } public function getIdentifier(): string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getTip(): string { return $this->tip; } public function getIdentifier(): string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } message; } public function getTip(): string { return $this->tip; } public function getIdentifier(): string { return $this->identifier; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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; } public function getOriginalNode(): Node { return $this->originalNode; } /** * @return callable(Node): Node */ public function getNewNodeCallable(): callable { return $this->newNodeCallable; } } 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 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; } 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; } /** * @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; } /** * @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 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 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 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 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; } /** * @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; } /** * @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 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 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; } public function getIdentifier(): string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } } message; } } message; } public function getLine(): int { return $this->line; } } 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; } } 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; } } 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; } } 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 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 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 getTip(): string { return $this->tip; } public function getIdentifier(): string { return $this->identifier; } } message; } public function getTip(): string { return $this->tip; } } 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 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; } 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 getLine(): int { return $this->line; } /** * @return mixed[] */ public function getMetadata(): array { return $this->metadata; } } reflectionProvider = $reflectionProvider; $this->checkNullables = $checkNullables; $this->checkThisOnly = $checkThisOnly; $this->checkUnionTypes = $checkUnionTypes; $this->checkExplicitMixed = $checkExplicitMixed; $this->checkImplicitMixed = $checkImplicitMixed; $this->checkBenevolentUnionTypes = $checkBenevolentUnionTypes; $this->discoveringSymbolsTip = $discoveringSymbolsTip; } /** @api */ public function isThis(Expr $expression): bool { return $expression instanceof Expr\Variable && $expression->name === 'this'; } 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->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($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($acceptedType->getReturnType()), $acceptedType->isVariadic(), $acceptedType->getTemplateTypeMap(), $acceptedType->getResolvedTemplateTypeMap(), $acceptedType->getCallSiteVarianceMap(), $acceptedType->getTemplateTags(), $acceptedType->getThrowPoints(), $acceptedType->getImpurePoints(), $acceptedType->getInvalidateExpressions(), $acceptedType->getUsedVariables(), $acceptedType->acceptsNamedArguments(), $acceptedType->mustUseReturnValue()); } 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($acceptedType); }); return [$this->transformCommonType($acceptedType), $checkForUnion]; } /** @api */ public function accepts(Type $acceptingType, Type $acceptedType, bool $strictTypes): \PHPStan\Rules\RuleLevelHelperAcceptsResult { [$acceptedType, $checkForUnion] = $this->transformAcceptedType($acceptingType, $acceptedType); $acceptingType = $this->transformCommonType($acceptingType); $accepts = $acceptingType->accepts($acceptedType, $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() && !$unionTypeCriteriaCallback(new NullType())) { $type = TypeCombinator::removeNull($type); } 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); } if ($type instanceof MixedType || $type instanceof NeverType) { return new \PHPStan\Rules\FoundTypeResult(new ErrorType(), [], [], null); } $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; } $errorBuilder = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($unknownClassErrorPattern, $referencedClass))->line($var->getStartLine())->identifier('class.notFound'); if ($this->discoveringSymbolsTip) { $errorBuilder->discoveringSymbolsTip(); } $errors[] = $errorBuilder->build(); } } if (count($errors) > 0 || $hasClassExistsClass) { return new \PHPStan\Rules\FoundTypeResult(new ErrorType(), [], $errors, null); } if (!$this->checkUnionTypes && $type->isObject()->yes() && count($type->getObjectClassNames()) === 0) { return new \PHPStan\Rules\FoundTypeResult(new ErrorType(), [], [], null); } 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 = []; $changed = \false; foreach ($type->getTypes() as $innerType) { if ($innerType instanceof TemplateMixedType) { $changed = \true; $newTypes[] = $this->findTypeToCheckImplementation($scope, $var, $innerType->toStrictMixedType(), $unknownClassErrorPattern, $unionTypeCriteriaCallback)->getType(); continue; } $newTypes[] = $innerType; } if ($changed) { return new \PHPStan\Rules\FoundTypeResult(TypeCombinator::intersect(...$newTypes), $directClassNames, [], null); } } $tip = null; if ($type instanceof UnionType && count($type->getTypes()) === 2 && $type->isObject()->yes() && $type->getTypes()[0]->getObjectClassNames() === ['PhpParser\Node\Arg'] && $type->getTypes()[1]->getObjectClassNames() === ['PhpParser\Node\VariadicPlaceholder'] && !$unionTypeCriteriaCallback($type)) { $tip = 'Use ->getArgs() instead of ->args.'; } return new \PHPStan\Rules\FoundTypeResult($type, $directClassNames, [], $tip); } } */ public array $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); } } */ #[RegisteredRule(4)] final class TooWideArrowFunctionReturnTypehintRule implements Rule { private \PHPStan\Rules\TooWideTypehints\TooWideTypeCheck $check; public function __construct(\PHPStan\Rules\TooWideTypehints\TooWideTypeCheck $check) { $this->check = $check; } 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 []; } return $this->check->checkAnonymousFunction($scope->getType($expr), $functionReturnType); } } */ #[RegisteredRule(4)] final class TooWideClosureReturnTypehintRule implements Rule { private \PHPStan\Rules\TooWideTypehints\TooWideTypeCheck $check; public function __construct(\PHPStan\Rules\TooWideTypehints\TooWideTypeCheck $check) { $this->check = $check; } 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 []; } return $this->check->checkAnonymousFunction(TypeCombinator::union(...$returnTypes), $closureReturnType); } } */ #[RegisteredRule(4)] final class TooWideFunctionParameterOutTypeRule implements Rule { private \PHPStan\Rules\TooWideTypehints\TooWideParameterOutTypeCheck $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->getStartLine(), $node->getExecutionEnds(), $node->getReturnStatements(), $inFunction->getParameters(), sprintf('Function %s()', $inFunction->getName())); } } */ #[RegisteredRule(4)] final class TooWideFunctionReturnTypehintRule implements Rule { private \PHPStan\Rules\TooWideTypehints\TooWideTypeCheck $check; public function __construct(\PHPStan\Rules\TooWideTypehints\TooWideTypeCheck $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->checkFunctionReturnType($node, $function->getNativeReturnType(), $function->getPhpDocReturnType(), sprintf('Function %s()', $function->getName()), \false, $scope); } } */ #[RegisteredRule(4)] final class TooWideMethodParameterOutTypeRule implements Rule { private \PHPStan\Rules\TooWideTypehints\TooWideParameterOutTypeCheck $check; private bool $checkProtectedAndPublicMethods; public function __construct( \PHPStan\Rules\TooWideTypehints\TooWideParameterOutTypeCheck $check, #[AutowiredParameter('%checkTooWideParameterOutInProtectedAndPublicMethods%')] bool $checkProtectedAndPublicMethods ) { $this->check = $check; $this->checkProtectedAndPublicMethods = $checkProtectedAndPublicMethods; } public function getNodeType(): string { return MethodReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope): array { $inMethod = $node->getMethodReflection(); if (!$inMethod->isPrivate()) { if (!$inMethod->getDeclaringClass()->isFinal() && !$inMethod->isFinal()->yes()) { if (!$this->checkProtectedAndPublicMethods) { return []; } } } return $this->check->check($node->getStartLine(), $node->getExecutionEnds(), $node->getReturnStatements(), $inMethod->getParameters(), sprintf('Method %s::%s()', $inMethod->getDeclaringClass()->getDisplayName(), $inMethod->getName())); } } */ #[RegisteredRule(4)] final class TooWideMethodReturnTypehintRule implements Rule { private bool $checkProtectedAndPublicMethods; private \PHPStan\Rules\TooWideTypehints\TooWideTypeCheck $check; public function __construct( #[AutowiredParameter('%checkTooWideReturnTypesInProtectedAndPublicMethods%')] bool $checkProtectedAndPublicMethods, \PHPStan\Rules\TooWideTypehints\TooWideTypeCheck $check ) { $this->checkProtectedAndPublicMethods = $checkProtectedAndPublicMethods; $this->check = $check; } 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 (!$method->getDeclaringClass()->isFinal() && !$method->isFinal()->yes()) { if (!$this->checkProtectedAndPublicMethods) { return []; } if ($isFirstDeclaration) { return []; } } } return $this->check->checkFunctionReturnType($node, $method->getNativeReturnType(), $method->getPhpDocReturnType(), sprintf('Method %s::%s()', $method->getDeclaringClass()->getDisplayName(), $method->getName()), !$isFirstDeclaration && !$method->isPrivate(), $scope); } } tooWideTypeCheck = $tooWideTypeCheck; } /** * @param list $executionEnds * @param list $returnStatements * @param ExtendedParameterReflection[] $parameters * @return list */ public function check(int $startLine, 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($startLine, $finalScope, $functionDescription, $parameter) as $error) { $errors[] = $error; } } return $errors; } /** * @return list */ private function processSingleParameter(int $startLine, Scope $scope, string $functionDescription, ExtendedParameterReflection $parameter): array { $isParamOutType = \true; $outType = $parameter->getOutType(); if ($outType === null) { $isParamOutType = \false; $outType = $parameter->getType(); } $variableExpr = new Variable($parameter->getName()); $variableType = $scope->getType($variableExpr); return $this->tooWideTypeCheck->checkParameterOutType($outType, $variableType, sprintf('%s never assigns %%s to &$%s so it can be removed from the %s.', $functionDescription, $parameter->getName(), $isParamOutType ? '@param-out type' : 'by-ref type'), sprintf('%s never assigns %%s to &$%s so the %s can be changed to %%s.', $functionDescription, $parameter->getName(), $isParamOutType ? '@param-out type' : 'by-ref type'), sprintf('%s %%s of %s can be narrowed to %%s.', $isParamOutType ? 'PHPDoc tag @param-out type' : 'By-ref type', lcfirst($functionDescription)), $scope, $startLine, $isParamOutType ? 'paramOut' : 'parameterByRef', $isParamOutType ? null : 'You can narrow the parameter out type with @param-out PHPDoc tag.'); } } */ #[RegisteredRule(4)] final class TooWidePropertyTypeRule implements Rule { private ReadWritePropertiesExtensionProvider $extensionProvider; private \PHPStan\Rules\TooWideTypehints\TooWideTypeCheck $check; public function __construct(ReadWritePropertiesExtensionProvider $extensionProvider, \PHPStan\Rules\TooWideTypehints\TooWideTypeCheck $check) { $this->extensionProvider = $extensionProvider; $this->check = $check; } 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); 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; } } $propertyDescription = $this->describePropertyByName($propertyReflection, $propertyName); $propertyErrors = $this->check->checkProperty($property, $propertyReflection->getDeclaringClass(), $node->getPropertyAssigns(), $propertyReflection->getNativeType(), $propertyReflection->getPhpDocType(), $propertyDescription, $scope); foreach ($propertyErrors as $error) { $errors[] = $error; } } 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); } } propertyReflectionFinder = $propertyReflectionFinder; $this->reportTooWideBool = $reportTooWideBool; $this->reportNestedTooWideType = $reportNestedTooWideType; } /** * @param PropertyAssign[] $propertyAssigns * @return list */ public function checkProperty(ClassPropertyNode $node, ClassReflection $declaringClass, array $propertyAssigns, Type $nativePropertyType, Type $phpDocPropertyType, string $propertyDescription, Scope $scope): array { $errors = []; $assignedTypes = []; foreach ($propertyAssigns as $assign) { $assignNode = $assign->getAssign(); $assignPropertyReflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($assignNode->getPropertyFetch(), $assign->getScope()); if (count($assignPropertyReflections) === 0) { return []; } foreach ($assignPropertyReflections as $assignPropertyReflection) { if ($node->getName() !== $assignPropertyReflection->getName()) { continue; } if ($declaringClass->getName() !== $assignPropertyReflection->getDeclaringClass()->getName()) { continue; } $assignedTypes[] = $assignPropertyReflection->getScope()->getType($assignNode->getAssignedExpr()); } } if ($node->getDefault() !== null) { $assignedTypes[] = $scope->getType($node->getDefault()); } if ($node->getNativeType() === null && $node->getDefault() === null) { $assignedTypes[] = new NullType(); } if (count($assignedTypes) === 0) { return []; } $assignedType = TypeCombinator::union(...$assignedTypes); $unionMessagePattern = '%s (%s) is never assigned %%s so it can be removed from the property type.'; $boolMessagePattern = '%s (%s) is never assigned %%s so the property type can be changed to %%s.'; if (!$phpDocPropertyType instanceof MixedType || $phpDocPropertyType->isExplicitMixed()) { $phpDocPropertyType = TypeUtils::resolveLateResolvableTypes(TypehintHelper::decideType($nativePropertyType, $phpDocPropertyType)); $narrowedPhpDocType = $this->narrowType($phpDocPropertyType, $assignedType, $scope, \false, \false); if (!$narrowedPhpDocType->equals($phpDocPropertyType)) { $phpDocPropertyTypeDescription = $phpDocPropertyType->describe(VerbosityLevel::getRecommendedLevelByType($phpDocPropertyType)); return $this->createErrors($narrowedPhpDocType, $phpDocPropertyType, sprintf($unionMessagePattern, $propertyDescription, $phpDocPropertyTypeDescription), sprintf($boolMessagePattern, $propertyDescription, $phpDocPropertyTypeDescription), $node->getStartLine(), 'property', null); } if (!$this->reportNestedTooWideType) { return []; } $narrowedPhpDocType = SimultaneousTypeTraverser::map($phpDocPropertyType, $assignedType, function (Type $declaredType, Type $actualType, callable $traverse) use ($scope) { $narrowed = $this->narrowType($declaredType, $actualType, $scope, \false, \false); if (!$narrowed->equals($declaredType)) { return $narrowed; } return $traverse($declaredType, $actualType); }); if ($narrowedPhpDocType->equals($phpDocPropertyType)) { return []; } return [RuleErrorBuilder::message(sprintf('Type %s of %s can be narrowed to %s.', $phpDocPropertyType->describe(VerbosityLevel::getRecommendedLevelByType($phpDocPropertyType)), lcfirst($propertyDescription), $narrowedPhpDocType->describe(VerbosityLevel::getRecommendedLevelByType($narrowedPhpDocType))))->identifier('property.nestedUnusedType')->line($node->getStartLine())->acceptsReasonsTip($narrowedPhpDocType->accepts($phpDocPropertyType, \true)->reasons)->build()]; } $narrowedNativeType = $this->narrowType($nativePropertyType, $assignedType, $scope, \false, \true); if (!$narrowedNativeType->equals($nativePropertyType)) { $propertyTypeDescription = $nativePropertyType->describe(VerbosityLevel::getRecommendedLevelByType($nativePropertyType)); return $this->createErrors($narrowedNativeType, $nativePropertyType, sprintf($unionMessagePattern, $propertyDescription, $propertyTypeDescription), sprintf($boolMessagePattern, $propertyDescription, $propertyTypeDescription), $node->getStartLine(), 'property', null); } return $errors; } /** * @return list * @param \PHPStan\Node\MethodReturnStatementsNode|\PHPStan\Node\FunctionReturnStatementsNode $node */ public function checkFunctionReturnType($node, Type $nativeFunctionReturnType, Type $phpDocFunctionReturnType, string $functionDescription, bool $checkDescendantClass, Scope $scope): array { $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(); } if (!$node->hasNativeReturnTypehint()) { foreach ($node->getExecutionEnds() as $executionEnd) { if ($executionEnd->getStatementResult()->isAlwaysTerminating()) { continue; } $returnTypes[] = new NullType(); break; } } $returnType = TypeCombinator::union(...$returnTypes); if (count($returnStatements) === 1 && $returnStatements[0]->getReturnNode()->expr instanceof ConstFetch && in_array(strtolower($returnStatements[0]->getReturnNode()->expr->name->toString()), ['true', 'false'], \true) && ($nativeFunctionReturnType->isBoolean()->yes() || $phpDocFunctionReturnType->isBoolean()->yes())) { return []; } $unionMessagePattern = sprintf('%s never returns %%s so it can be removed from the return type.', $functionDescription); $boolMessagePattern = sprintf('%s never returns %%s so the return type can be changed to %%s.', $functionDescription); // Do not require to have @return null/true/false in descendant classes if ($checkDescendantClass && ($returnType->isNull()->yes() || $returnType->isTrue()->yes() || $returnType->isFalse()->yes())) { return []; } if (!$phpDocFunctionReturnType instanceof MixedType || $phpDocFunctionReturnType->isExplicitMixed()) { $phpDocFunctionReturnType = TypeUtils::resolveLateResolvableTypes(TypehintHelper::decideType($nativeFunctionReturnType, $phpDocFunctionReturnType)); $narrowedPhpDocType = $this->narrowType($phpDocFunctionReturnType, $returnType, $scope, \false, \false); if (!$narrowedPhpDocType->equals($phpDocFunctionReturnType)) { return $this->createErrors($narrowedPhpDocType, $phpDocFunctionReturnType, $unionMessagePattern, $boolMessagePattern, $node->getStartLine(), 'return', null); } if (!$this->reportNestedTooWideType) { return []; } $narrowedPhpDocType = SimultaneousTypeTraverser::map($phpDocFunctionReturnType, $returnType, function (Type $declaredType, Type $actualReturnType, callable $traverse) use ($scope, $checkDescendantClass) { $narrowed = $this->narrowType($declaredType, $actualReturnType, $scope, $checkDescendantClass, \false); if (!$narrowed->equals($declaredType)) { return $narrowed; } return $traverse($declaredType, $actualReturnType); }); if ($narrowedPhpDocType->equals($phpDocFunctionReturnType)) { return []; } return [RuleErrorBuilder::message(sprintf('Return type %s of %s can be narrowed to %s.', $phpDocFunctionReturnType->describe(VerbosityLevel::getRecommendedLevelByType($phpDocFunctionReturnType)), lcfirst($functionDescription), $narrowedPhpDocType->describe(VerbosityLevel::getRecommendedLevelByType($narrowedPhpDocType))))->identifier('return.nestedUnusedType')->line($node->getStartLine())->acceptsReasonsTip($narrowedPhpDocType->accepts($phpDocFunctionReturnType, \true)->reasons)->build()]; } $narrowedNativeType = $this->narrowType($nativeFunctionReturnType, $returnType, $scope, \false, \true); if (!$narrowedNativeType->equals($nativeFunctionReturnType)) { return $this->createErrors($narrowedNativeType, $nativeFunctionReturnType, $unionMessagePattern, $boolMessagePattern, $node->getStartLine(), 'return', null); } return []; } /** * @param 'paramOut'|'parameterByRef' $identifierPart * @return list */ public function checkParameterOutType(Type $parameterOutType, Type $actualVariableType, string $unionMessagePattern, string $boolMessagePattern, string $nestedTooWideTypePattern, Scope $scope, int $startLine, string $identifierPart, ?string $tip): array { $parameterOutType = TypeUtils::resolveLateResolvableTypes($parameterOutType); $narrowedType = $this->narrowType($parameterOutType, $actualVariableType, $scope, \false, \false); if ($narrowedType->equals($parameterOutType)) { if (!$this->reportNestedTooWideType) { return []; } $narrowedType = SimultaneousTypeTraverser::map($parameterOutType, $actualVariableType, function (Type $declaredType, Type $actualType, callable $traverse) use ($scope) { $narrowed = $this->narrowType($declaredType, $actualType, $scope, \false, \false); if (!$narrowed->equals($declaredType)) { return $narrowed; } return $traverse($declaredType, $actualType); }); if ($narrowedType->equals($parameterOutType)) { return []; } return [RuleErrorBuilder::message(sprintf($nestedTooWideTypePattern, $parameterOutType->describe(VerbosityLevel::getRecommendedLevelByType($parameterOutType)), $narrowedType->describe(VerbosityLevel::getRecommendedLevelByType($narrowedType))))->identifier(sprintf('%s.nestedUnusedType', $identifierPart))->line($startLine)->acceptsReasonsTip($narrowedType->accepts($parameterOutType, \true)->reasons)->build()]; } return $this->createErrors($narrowedType, $parameterOutType, $unionMessagePattern, $boolMessagePattern, $startLine, $identifierPart, $tip); } /** * @param 'return'|'property'|'paramOut'|'parameterByRef' $identifierPart * @return list */ private function createErrors(Type $narrowedType, Type $originalType, string $unionMessagePattern, string $boolMessagePattern, int $startLine, string $identifierPart, ?string $tip): array { if ($originalType->isBoolean()->yes()) { $neverReturns = $narrowedType->isTrue()->yes() ? new ConstantBooleanType(\false) : new ConstantBooleanType(\true); $errorBuilder = RuleErrorBuilder::message(sprintf($boolMessagePattern, $neverReturns->describe(VerbosityLevel::getRecommendedLevelByType($neverReturns)), $narrowedType->describe(VerbosityLevel::getRecommendedLevelByType($narrowedType))))->identifier(sprintf('%s.tooWideBool', $identifierPart))->line($startLine); if ($tip !== null) { $errorBuilder->tip($tip); } return [$errorBuilder->build()]; } if (!$originalType instanceof UnionType) { return []; } $messages = []; foreach ($originalType->getTypes() as $innerType) { if (!$narrowedType->isSuperTypeOf($innerType)->no()) { continue; } $errorBuilder = RuleErrorBuilder::message(sprintf($unionMessagePattern, $innerType->describe(VerbosityLevel::getRecommendedLevelByType($innerType))))->identifier(sprintf('%s.unusedType', $identifierPart))->line($startLine); if ($tip !== null) { $errorBuilder->tip($tip); } $messages[] = $errorBuilder->build(); } return $messages; } /** * @return list */ public function checkAnonymousFunction(Type $returnType, UnionType $functionReturnType): array { 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; } private function narrowType(Type $declaredType, Type $actualReturnType, Scope $scope, bool $checkDescendantClass, bool $native): Type { if ($declaredType instanceof UnionType) { if ($declaredType->isConstantScalarValue()->yes() && $actualReturnType->isConstantScalarValue()->yes()) { return $declaredType; } $usedTypes = []; foreach ($declaredType->getTypes() as $innerType) { if ($innerType->isSuperTypeOf($actualReturnType)->no()) { if (!$checkDescendantClass) { continue; } if ($innerType->isNull()->yes()) { $usedTypes[] = $innerType; continue; } if (!$actualReturnType->isTrue()->yes() && !$actualReturnType->isFalse()->yes() && !$actualReturnType->isNull()->yes()) { continue; } } $usedTypes[] = $innerType; } return TypeCombinator::union(...$usedTypes); } if (!$this->reportTooWideBool) { return $declaredType; } if ($native && !$scope->getPhpVersion()->supportsTrueAndFalseStandaloneType()->yes()) { return $declaredType; } if (!$declaredType->isBoolean()->yes()) { return $declaredType; } if ($declaredType->isTrue()->yes() || $declaredType->isFalse()->yes()) { return $declaredType; } $usedTypes = []; foreach ($declaredType->getFiniteTypes() as $innerType) { if ($innerType->isSuperTypeOf($actualReturnType)->no()) { if (!$checkDescendantClass) { continue; } if (!$actualReturnType->isTrue()->yes() && !$actualReturnType->isFalse()->yes() && !$actualReturnType->isNull()->yes()) { continue; } } $usedTypes[] = $innerType; } return TypeCombinator::union(...$usedTypes); } } */ #[RegisteredRule(0)] final class ConflictingTraitConstantsRule implements Rule { private InitializerExprTypeResolver $initializerExprTypeResolver; private ReflectionProvider $reflectionProvider; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver, ReflectionProvider $reflectionProvider) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->reflectionProvider = $reflectionProvider; } public function getNodeType(): string { return Node\Stmt\ClassConst::class; } public function processNode(Node $node, Scope $scope): array { if (!$scope->isInClass()) { return []; } $classReflection = $scope->getClassReflection(); $recursiveTraitConstants = []; foreach ($classReflection->getTraits(\true) as $trait) { foreach ($trait->getNativeReflection()->getReflectionConstants() as $constant) { $recursiveTraitConstants[] = $constant; } } $errors = []; foreach ($node->consts as $const) { foreach ($recursiveTraitConstants as $recursiveTraitConstant) { if ($recursiveTraitConstant->getName() !== $const->name->toString()) { continue; } foreach ($this->processSingleConstant($classReflection, $recursiveTraitConstant, $node) as $error) { $errors[] = $error; } } } $immediateTraitConstants = []; foreach ($classReflection->getTraits() as $trait) { foreach ($trait->getNativeReflection()->getReflectionConstants() as $constant) { $immediateTraitConstants[] = $constant; } } foreach ($node->consts as $const) { foreach ($immediateTraitConstants as $immediateTraitConstant) { if ($immediateTraitConstant->getName() !== $const->name->toString()) { continue; } $classConstantValueType = $this->initializerExprTypeResolver->getType($const->value, InitializerExprContext::fromClassReflection($classReflection)); $traitConstantValueType = $this->initializerExprTypeResolver->getType($immediateTraitConstant->getValueExpression(), InitializerExprContext::fromClassReflection($classReflection)); if ($classConstantValueType->equals($traitConstantValueType)) { continue; } $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(), $immediateTraitConstant->getName(), $classConstantValueType->describe(VerbosityLevel::value()), $immediateTraitConstant->getDeclaringClass()->getName(), $immediateTraitConstant->getName(), $traitConstantValueType->describe(VerbosityLevel::value())))->nonIgnorable()->identifier('classConstant.value')->build(); } } return $errors; } /** * @return list */ private function processSingleConstant(ClassReflection $classReflection, ReflectionClassConstant $traitConstant, Node\Stmt\ClassConst $classConst): 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, $this->reflectionProvider->getClass($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, $this->reflectionProvider->getClass($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(); } } return $errors; } } */ #[RegisteredRule(0)] final class ConstantsInTraitsRule implements Rule { private PhpVersion $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()]; } } */ #[RegisteredRule(4)] 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; } } */ #[RegisteredRule(0)] final class TraitAttributesRule implements Rule { private AttributesCheck $attributesCheck; private PhpVersion $phpVersion; public function __construct(AttributesCheck $attributesCheck, PhpVersion $phpVersion) { $this->attributesCheck = $attributesCheck; $this->phpVersion = $phpVersion; } public function getNodeType(): string { return InTraitNode::class; } public function processNode(Node $node, Scope $scope): array { if (!$this->phpVersion->supportsDeprecatedTraits()) { if (count($node->getTraitReflection()->getNativeReflection()->getAttributes('Deprecated')) > 0) { return [RuleErrorBuilder::message('Attribute class Deprecated can be used with traits only on PHP 8.5 and later.')->identifier('trait.deprecatedAttribute')->nonIgnorable()->build()]; } } $originalNode = $node->getOriginalNode(); $errors = $this->attributesCheck->check($scope, $originalNode->attrGroups, Attribute::TARGET_CLASS, 'class'); if (count($node->getTraitReflection()->getNativeReflection()->getAttributes('AllowDynamicProperties')) > 0) { $errors[] = RuleErrorBuilder::message('Attribute class AllowDynamicProperties cannot be used with trait.')->identifier('trait.allowDynamicProperties')->nonIgnorable()->build(); } return $errors; } } */ #[RegisteredCollector(4)] 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()]; } } > */ #[RegisteredCollector(4)] 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 fn(Node\Name $traitName) => $traitName->toString(), $node->traits)); } } */ #[RegisteredRule(0)] 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->getNativeTypeNode() instanceof Node\ComplexType) { return []; } return $this->processComplexType($classPropertyNode->getNativeTypeNode()); } /** * @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 []; } } reflectionProvider = $reflectionProvider; $this->reportExactLine = $reportExactLine; } /** * @param Variable[] $parameterVars * @param Node[] $statements * @param 'constructor.unusedParameter'|'closure.unusedUse' $identifier * @return list */ public function getUnusedParameters(Scope $scope, array $parameterVars, array $statements, string $unusedParameterMessage, string $identifier): array { $unusedParameters = []; foreach ($parameterVars as $variable) { if (!is_string($variable->name)) { throw new ShouldNotHappenException(); } $unusedParameters[$variable->name] = $variable; } foreach ($this->getUsedVariables($scope, $statements) as $variableName) { unset($unusedParameters[$variableName]); } $errors = []; foreach ($unusedParameters as $name => $variable) { $errorBuilder = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($unusedParameterMessage, $name))->identifier($identifier); if ($this->reportExactLine) { $errorBuilder->line($variable->getStartLine()); } $errors[] = $errorBuilder->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 && !$node->isFirstClassCallable()) { $functionName = $this->reflectionProvider->resolveFunctionName($node->name, $scope); if (in_array($functionName, ['func_get_args', 'get_defined_vars'], \true)) { return $scope->getDefinedVariables(); } } if ($node instanceof Variable && is_string($node->name) && $node->name !== 'this') { return [$node->name]; } if ($node instanceof Node\ClosureUse && is_string($node->var->name)) { return [$node->var->name]; } if ($node instanceof Node\Expr\FuncCall && !$node->isFirstClassCallable() && $node->name instanceof Node\Name && (string) $node->name === 'compact') { foreach ($node->getArgs() as $arg) { $argType = $scope->getType($arg->value); foreach ($argType->getConstantStrings() as $constantStringType) { $variableNames[] = $constantStringType->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; } } */ final class AssignToByRefExprFromForeachRule implements Rule { private ExprPrinter $printer; public function __construct(ExprPrinter $printer) { $this->printer = $printer; } public function getNodeType(): string { return NodeAbstract::class; } public function processNode(Node $node, Scope $scope): array { if ($node instanceof VariableAssignNode) { $expr = $node->getVariable(); } elseif ($node instanceof PropertyAssignNode) { $expr = $node->getPropertyFetch(); } else { return []; } if ($scope->hasExpressionType(new ForeachValueByRefExpr($expr))->no()) { return []; } return [RuleErrorBuilder::message(sprintf('Assign to %s overwrites the last element from array.', $this->printer->printExpr($expr)))->identifier('assign.byRefForeachExpr')->tip('Unset it right after foreach to avoid this problem.')->build()]; } } */ #[RegisteredRule(0)] final class CompactVariablesRule implements Rule { private bool $checkMaybeUndefinedVariables; public function __construct( #[AutowiredParameter] 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 list */ private function findConstantStrings(Type $type): array { $constantStrings = $type->getConstantStrings(); if (count($constantStrings) > 0) { return $constantStrings; } $result = []; foreach ($type->getConstantArrays() as $constantArrayType) { foreach ($constantArrayType->getValueTypes() as $valueType) { $constantStrings = $this->findConstantStrings($valueType); $result = array_merge($result, $constantStrings); } } return $result; } } */ #[RegisteredRule(0)] final class DefinedVariableRule implements Rule { private bool $cliArgumentsVariablesRegistered; private bool $checkMaybeUndefinedVariables; public function __construct( #[AutowiredParameter] bool $cliArgumentsVariablesRegistered, #[AutowiredParameter] bool $checkMaybeUndefinedVariables ) { $this->cliArgumentsVariablesRegistered = $cliArgumentsVariablesRegistered; $this->checkMaybeUndefinedVariables = $checkMaybeUndefinedVariables; } public function getNodeType(): string { return Variable::class; } public function processNode(Node $node, Scope $scope): array { $errors = []; if (is_string($node->name)) { $variableNameScopes = [$node->name => $scope]; } else { $nameType = $scope->getType($node->name); $variableNameScopes = []; foreach ($nameType->getConstantStrings() as $constantString) { $name = $constantString->getValue(); $variableNameScopes[$name] = $scope->filterByTruthyValue(new Identical($node->name, new String_($name))); } } foreach ($variableNameScopes as $name => $variableScope) { $errors = array_merge($errors, $this->processSingleVariable($variableScope, $node, (string) $name)); } return $errors; } /** * @return list */ private function processSingleVariable(Scope $scope, Variable $node, string $variableName): array { if ($this->cliArgumentsVariablesRegistered && in_array($variableName, ['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($variableName)->no()) { return [RuleErrorBuilder::message(sprintf('Undefined variable: $%s', $variableName))->identifier('variable.undefined')->build()]; } elseif ($this->checkMaybeUndefinedVariables && !$scope->hasVariableType($variableName)->yes()) { return [RuleErrorBuilder::message(sprintf('Variable $%s might not be defined.', $variableName))->identifier('variable.undefined')->build()]; } return []; } } */ #[RegisteredRule(1)] final class EmptyRule implements Rule { private IssetCheck $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]; } } */ #[RegisteredRule(0)] final class InvalidVariableAssignRule implements Rule { public function getNodeType(): string { return VariableAssignNode::class; } public function processNode(Node $node, Scope $scope): array { $variable = $node->getVariable(); if (!is_string($variable->name)) { return []; } if ($variable->name === 'this') { if ($scope->isInClass()) { $classReflection = $scope->getClassReflection(); if ($classReflection->implementsInterface(ArrayAccess::class)) { return []; } } return [RuleErrorBuilder::message('Cannot re-assign $this.')->identifier('assign.this')->nonIgnorable()->build()]; } return []; } } */ #[RegisteredRule(1)] final class IssetRule implements Rule { private IssetCheck $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; } } */ #[RegisteredRule(1)] final class NullCoalesceRule implements Rule { private IssetCheck $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]; } } */ #[RegisteredRule(3)] final class ParameterOutAssignedTypeRule implements Rule { private RuleLevelHelper $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 fn(Type $type): bool => $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()]; } } */ #[RegisteredRule(3)] final class ParameterOutExecutionEndTypeRule implements Rule { private RuleLevelHelper $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 []; } } $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 \PHPStan\Reflection\FunctionReflection|\PHPStan\Reflection\ExtendedMethodReflection $inFunction */ private function processSingleParameter(Scope $scope, $inFunction, ExtendedParameterReflection $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 fn(Type $type): bool => $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()]; } } */ #[RegisteredRule(0)] final class ThisInGlobalStatementRule implements Rule { public function getNodeType(): string { return Node\Stmt\Global_::class; } public function processNode(Node $node, Scope $scope): array { $errors = []; foreach ($node->vars as $var) { if (!$var instanceof Variable) { continue; } if (!is_string($var->name)) { continue; } if ($var->name !== 'this') { continue; } $errors[] = RuleErrorBuilder::message('Cannot use $this as global variable.')->identifier('global.this')->nonIgnorable()->build(); } return $errors; } } */ #[RegisteredRule(0)] final class ThisInStaticStatementRule implements Rule { public function getNodeType(): string { return Node\Stmt\Static_::class; } public function processNode(Node $node, Scope $scope): array { $errors = []; foreach ($node->vars as $var) { if (!is_string($var->var->name)) { continue; } if ($var->var->name !== 'this') { continue; } $errors[] = RuleErrorBuilder::message('Cannot use $this as static variable.')->identifier('static.this')->nonIgnorable()->build(); } return $errors; } } */ #[RegisteredRule(0)] final class UnsetRule implements Rule { private PropertyReflectionFinder $propertyReflectionFinder; private PhpVersion $phpVersion; public function __construct(PropertyReflectionFinder $propertyReflectionFinder, PhpVersion $phpVersion) { $this->propertyReflectionFinder = $propertyReflectionFinder; $this->phpVersion = $phpVersion; } 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) { if ($argument instanceof Node\Expr\PropertyFetch && $argument->name instanceof Node\Identifier) { $foundPropertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($argument, $scope); if ($foundPropertyReflection === null) { continue; } $propertyReflection = $foundPropertyReflection->getNativeReflection(); if ($propertyReflection === null) { continue; } if ($propertyReflection->isReadOnly() || $propertyReflection->isReadOnlyByPhpDoc()) { $errors[] = RuleErrorBuilder::message(sprintf('Cannot unset %s %s::$%s property.', $propertyReflection->isReadOnly() ? 'readonly' : '@readonly', $propertyReflection->getDeclaringClass()->getDisplayName(), $foundPropertyReflection->getName()))->line($argument->getStartLine())->identifier($propertyReflection->isReadOnly() ? 'unset.readOnlyProperty' : 'unset.readOnlyPropertyByPhpDoc')->build(); continue; } if ($propertyReflection->isHooked()) { $errors[] = RuleErrorBuilder::message(sprintf('Cannot unset hooked %s::$%s property.', $propertyReflection->getDeclaringClass()->getDisplayName(), $foundPropertyReflection->getName()))->line($argument->getStartLine())->identifier('unset.hookedProperty')->build(); continue; } elseif ($this->phpVersion->supportsPropertyHooks()) { if (!$propertyReflection->isPrivate() && !$propertyReflection->isFinal()->yes() && !$propertyReflection->getDeclaringClass()->isFinal()) { $errors[] = RuleErrorBuilder::message(sprintf('Cannot unset property %s::$%s because it might have hooks in a subclass.', $propertyReflection->getDeclaringClass()->getDisplayName(), $foundPropertyReflection->getName()))->line($argument->getStartLine())->identifier('unset.possiblyHookedProperty')->build(); continue; } } } $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; } } */ #[RegisteredRule(3)] final class VariableCloningRule implements Rule { private RuleLevelHelper $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 fn(Type $type): bool => $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()]; } } */ #[RegisteredRule(0)] 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 array $lastNodes = []; /** * @return int|null */ #[Override] public function enterNode(Node $node) { if ($node instanceof Node\Stmt\Declare_) { if ($node->stmts !== null && count($node->stmts) > 0) { $this->lastNodes[] = array_last($node->stmts); } return null; } if ($node instanceof Node\Stmt\Namespace_) { if (count($node->stmts) > 0) { $this->lastNodes[] = array_last($node->stmts); } return null; } return NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN; } /** * @return Node[] */ public function getLastNodes(): array { return $this->lastNodes; } }; $nodeTraverser->addVisitor($visitor); $nodeTraverser->traverse($nodes); $lastNodes = $visitor->getLastNodes(); $lastNodes[] = array_last($nodes); 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; } } * * @api */ final class CompositeRule implements Rule { private DirectRegistry $registry; /** * @template T of Node * @param array> $rules * * @api */ public function __construct(array $rules) { $this->registry = new DirectRegistry($rules); } public function getNodeType(): string { return Node::class; } /** * @param \PHPStan\Analyser\Scope&\PHPStan\Analyser\NodeCallbackInvoker $scope */ public function processNode(Node $node, \PHPStan\Analyser\Scope $scope): array { $errors = []; $nodeType = get_class($node); foreach ($this->registry->getRules($nodeType) as $rule) { foreach ($rule->processNode($node, $scope) as $error) { $errors[] = $error; } } return $errors; } } */ final class DelayedRule implements Rule { private Registry $registry; /** @var list */ private array $errors = []; /** * @param Rule $rule */ public function __construct(Rule $rule) { $this->registry = new DirectRegistry([$rule]); } public function getNodeType(): string { return Node::class; } /** * @return list */ public function getDelayedErrors(): array { return $this->errors; } /** * @param \PHPStan\Analyser\Scope&\PHPStan\Analyser\NodeCallbackInvoker $scope */ public function processNode(Node $node, \PHPStan\Analyser\Scope $scope): array { $nodeType = get_class($node); foreach ($this->registry->getRules($nodeType) as $rule) { foreach ($rule->processNode($node, $scope) as $error) { $this->errors[] = $error; } } return []; } } */ private array $outputStream = []; /** @var array */ private array $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()); 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, 7), \true) || !in_array($offsetFileErrors, range(0, 7), \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'), new Error('Error with @param or @phpstan-param and class@anonymous in the message.', self::DIRECTORY_PATH . '/bar.php', 5)], $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 fn(string $line): string => rtrim($line, " \r\n"), explode("\n", $output)); return implode("\n", $result); } } > */ abstract public static function dataTopics(): array; abstract public function getDataPath(): string; abstract public function getPhpStanExecutablePath(): string; abstract public 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, 10) 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); } } */ final class NonexistentAnalysedClassRule implements Rule { private ReflectionProvider $reflectionProvider; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } public function getNodeType(): string { return InClassNode::class; } public function processNode(Node $node, Scope $scope): array { $className = $node->getClassReflection()->getName(); if ($this->reflectionProvider->hasClass($className)) { return []; } return [RuleErrorBuilder::message(sprintf('%s %s not found in ReflectionProvider. Configure "autoload-dev" section in composer.json to include your tests directory.', $node->getClassReflection()->getClassTypeDescription(), $node->getClassReflection()->getName()))->identifier('phpstan.classNotFound')->nonIgnorable()->build()]; } } */ final class NonexistentAnalysedTraitRule implements Rule { private ReflectionProvider $reflectionProvider; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } public function getNodeType(): string { return Node\Stmt\Trait_::class; } public function processNode(Node $node, Scope $scope): array { if ($node->namespacedName === null) { throw new ShouldNotHappenException(); } $traitName = $node->namespacedName->toString(); if ($this->reflectionProvider->hasClass($traitName)) { return []; } return [RuleErrorBuilder::message(sprintf('Trait %s not found in ReflectionProvider. Configure "autoload-dev" section in composer.json to include your tests directory.', $traitName))->identifier('phpstan.traitNotFound')->nonIgnorable()->build()]; } } getService('defaultAnalysisParser'); return $parser; } /** @api */ public static function createReflectionProvider(): ReflectionProvider { return self::getContainer()->getByType(ReflectionProvider::class); } public static function getReflector(): Reflector { return self::getContainer()->getService('betterReflectionReflector'); } 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); $composerPhpVersionFactory = $container->getByType(ComposerPhpVersionFactory::class); $constantResolver = new ConstantResolver($reflectionProviderProvider, $dynamicConstantNames, null, $composerPhpVersionFactory, $container); $initializerExprTypeResolver = new InitializerExprTypeResolver($constantResolver, $reflectionProviderProvider, $container->getByType(PhpVersion::class), $container->getByType(OperatorTypeSpecifyingExtensionRegistryProvider::class), $container->getByType(UnaryOperatorTypeSpecifyingExtensionRegistryProvider::class), new OversizedArrayBuilder(), $container->getParameter('usePathConstantsAsConstantString')); return new ScopeFactory(new DirectInternalScopeFactoryFactory($container, $reflectionProvider, $initializerExprTypeResolver, $container->getByType(ExpressionTypeResolverExtensionRegistryProvider::class), $container->getByType(ExprPrinter::class), $typeSpecifier, new PropertyReflectionFinder(), self::getParser(), $container->getByType(PhpVersion::class), $container->getByType(AttributeReflectionFactory::class), $container->getParameter('phpVersion'), $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; } /** * 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() ?? 0); } 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 static array $containers = []; public static function getContainer(): Container { $additionalConfigFiles = [__DIR__ . '/TestCase.neon']; foreach (static::getAdditionalConfigFiles() as $configFile) { $additionalConfigFiles[] = $configFile; } $cacheKey = hash('sha256', implode("\n", $additionalConfigFiles)); if (!isset(self::$containers[$cacheKey])) { $tmpDir = sys_get_temp_dir() . '/phpstan-tests'; try { DirectoryCreator::ensureDirectoryExists($tmpDir, 0777); } catch (DirectoryCreatorException $e) { throw new RuntimeException($e->getMessage(), 0, $e); } $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 getFileHelper(): FileHelper { return self::getContainer()->getByType(FileHelper::class); } } testMethod()->className(); if (!is_a($testClassName, PhpStanTestCase::class, \true)) { return; } \PHPStan\Testing\PHPUnit\ContainerInitializer::initialize($testClassName); } } test(); if (!$test->isTestMethod()) { // skip PHPT tests return; } $testClassName = $test->className(); if (!is_a($testClassName, PhpStanTestCase::class, \true)) { return; } \PHPStan\Testing\PHPUnit\ContainerInitializer::initialize($testClassName); } } registerSubscriber(new \PHPStan\Testing\PHPUnit\InitContainerBeforeDataProviderSubscriber()); $facade->registerSubscriber(new \PHPStan\Testing\PHPUnit\InitContainerBeforeTestSubscriber()); } } > */ protected function getCollectors(): array { return []; } /** * @return ReadWritePropertiesExtension[] */ protected function getReadWritePropertiesExtensions(): array { return []; } protected function getTypeSpecifier(): TypeSpecifier { return self::getContainer()->getService('typeSpecifier'); } protected function createNodeScopeResolver(): NodeScopeResolver { $readWritePropertiesExtensions = $this->getReadWritePropertiesExtensions(); $reflectionProvider = $this->createReflectionProvider(); $typeSpecifier = $this->getTypeSpecifier(); $enableFnsr = getenv('PHPSTAN_FNSR'); $className = NodeScopeResolver::class; if (PHP_VERSION_ID >= 80100 && $enableFnsr !== '0') { $className = FiberNodeScopeResolver::class; } return new $className(self::getContainer(), $reflectionProvider, self::getContainer()->getByType(InitializerExprTypeResolver::class), self::getReflector(), self::getContainer()->getByType(ClassReflectionFactory::class), self::getContainer()->getByType(ParameterOutTypeExtensionProvider::class), $this->getParser(), self::getContainer()->getByType(FileTypeMapper::class), self::getContainer()->getByType(PhpDocInheritanceResolver::class), self::getContainer()->getByType(FileHelper::class), $typeSpecifier, $readWritePropertiesExtensions !== [] ? new DirectReadWritePropertiesExtensionProvider($readWritePropertiesExtensions) : self::getContainer()->getByType(ReadWritePropertiesExtensionProvider::class), self::getContainer()->getByType(ParameterClosureThisExtensionProvider::class), self::getContainer()->getByType(ParameterClosureTypeExtensionProvider::class), self::createScopeFactory($reflectionProvider, $typeSpecifier), self::getContainer()->getByType(DeepNodeCloner::class), $this->shouldPolluteScopeWithLoopInitialAssignments(), $this->shouldPolluteScopeWithAlwaysIterableForeach(), self::getContainer()->getParameter('polluteScopeWithBlock'), [], [], self::getContainer()->getParameter('exceptions')['implicitThrows'], $this->shouldTreatPhpDocTypesAsCertain(), self::getContainer()->getByType(ImplicitToStringCallHelper::class)); } private function getAnalyser(DirectRuleRegistry $ruleRegistry): Analyser { if ($this->analyser === null) { $collectorRegistry = new CollectorRegistry($this->getCollectors()); $nodeScopeResolver = $this->createNodeScopeResolver(); $fileAnalyser = new FileAnalyser(self::createScopeFactory($this->createReflectionProvider(), $this->getTypeSpecifier()), $nodeScopeResolver, $this->getParser(), self::getContainer()->getByType(DependencyResolver::class), new IgnoreErrorExtensionProvider(self::getContainer()), self::getContainer()->getByType(RuleErrorTransformer::class), new LocalIgnoresProcessor(), \false); $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, $delayedErrors] = $this->gatherAnalyserErrorsWithDelayedErrors($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; }; usort($expectedErrors, static function ($a, $b) { if ($a[1] !== $b[1]) { return $a[1] <=> $b[1]; } if ($a[0] !== $b[0]) { return strcmp($a[0], $b[0]); } if (!isset($a[2])) { if (!isset($b[2])) { return 0; } return 1; } elseif (!isset($b[2])) { return -1; } return strcmp($a[2], $b[2]); }); $expectedErrors = array_map(static fn(array $error): string => $strictlyTypedSprintf($error[1], $error[0], $error[2] ?? null), $expectedErrors); usort($actualErrors, static function ($a, $b) { if ($a->getLine() !== $b->getLine()) { return $a->getLine() <=> $b->getLine(); } if ($a->getMessage() !== $b->getMessage()) { return strcmp($a->getMessage(), $b->getMessage()); } if ($a->getTip() === null) { if ($b->getTip() === null) { return 0; } return 1; } elseif ($b->getTip() === null) { return -1; } return strcmp($a->getTip(), $b->getTip()); }); $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); $expectedErrorsString = implode("\n", $expectedErrors) . "\n"; $actualErrorsString = implode("\n", $actualErrors) . "\n"; if (count($delayedErrors) === 0) { $this->assertSame($expectedErrorsString, $actualErrorsString); return; } if ($expectedErrorsString === $actualErrorsString) { $this->assertSame($expectedErrorsString, $actualErrorsString); return; } $actualErrorsString .= sprintf("\n%s might be reported because of the following misconfiguration %s:\n\n", count($actualErrors) === 1 ? 'This error' : 'These errors', count($delayedErrors) === 1 ? 'issue' : 'issues'); foreach ($delayedErrors as $delayedError) { $actualErrorsString .= sprintf("* %s\n", $delayedError->getMessage()); } $this->assertSame($expectedErrorsString, $actualErrorsString); } public function fix(string $file, string $expectedFile): void { [$errors] = $this->gatherAnalyserErrorsWithDelayedErrors([$file]); $diffs = []; foreach ($errors as $error) { if ($error->getFixedErrorDiff() === null) { continue; } $diffs[] = $error->getFixedErrorDiff(); } $patcher = self::getContainer()->getByType(Patcher::class); $newFileContents = $patcher->applyDiffs($file, $diffs); // @phpstan-ignore missingType.checkedException, missingType.checkedException $fixedFileContents = FileReader::read($expectedFile); $this->assertSame($this->normalizeLineEndings($fixedFileContents), $this->normalizeLineEndings($newFileContents)); } private function normalizeLineEndings(string $string): string { return str_replace("\r\n", "\n", $string); } /** * @param string[] $files * @return list */ public function gatherAnalyserErrors(array $files): array { return $this->gatherAnalyserErrorsWithDelayedErrors($files)[0]; } /** * @param string[] $files * @return array{list, list} */ private function gatherAnalyserErrorsWithDelayedErrors(array $files): array { $reflectionProvider = $this->createReflectionProvider(); $classRule = new \PHPStan\Testing\DelayedRule(new \PHPStan\Testing\NonexistentAnalysedClassRule($reflectionProvider)); $traitRule = new \PHPStan\Testing\DelayedRule(new \PHPStan\Testing\NonexistentAnalysedTraitRule($reflectionProvider)); $ruleRegistry = new DirectRuleRegistry([$this->getRule(), $classRule, $traitRule]); $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 fn(InternalError $internalError) => $internalError->getMessage(), $analyserResult->getInternalErrors()))); } if ($this->shouldFailOnPhpErrors() && count($analyserResult->getAllPhpErrors()) > 0) { $this->fail(implode("\n", array_map(static fn(Error $error): string => sprintf('%s on %s:%d', $error->getMessage(), $error->getFile(), $error->getLine() ?? 0), $analyserResult->getAllPhpErrors()))); } $finalizer = new AnalyserResultFinalizer($ruleRegistry, new IgnoreErrorExtensionProvider(self::getContainer()), self::getContainer()->getByType(RuleErrorTransformer::class), self::createScopeFactory($reflectionProvider, self::getContainer()->getService('typeSpecifier')), new LocalIgnoresProcessor(), \true); return [$finalizer->finalize($analyserResult, \false, \true)->getAnalyserResult()->getUnorderedErrors(), array_merge($classRule->getDelayedErrors(), $traitRule->getDelayedErrors())]; } protected function shouldPolluteScopeWithLoopInitialAssignments(): bool { return \true; } protected function shouldPolluteScopeWithAlwaysIterableForeach(): bool { return \true; } protected function shouldFailOnPhpErrors(): bool { return \true; } public static function getAdditionalConfigFiles(): array { return [__DIR__ . '/../../conf/bleedingEdge.neon']; } } parameters: inferPrivatePropertyTypeFromConstructor: true services: - class: PHPStan\Testing\TestCaseSourceLocatorFactory arguments: phpParser: @phpParserDecorator php8Parser: @php8PhpParser fileExtensions: %fileExtensions% excludePaths: %excludePaths% 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 , analyseAndScan?: array}|null */ private ?array $excludePaths; /** @var array> */ private static array $composerSourceLocatorsCache = []; /** * @param string[] $fileExtensions * @param array{analyse?: array, analyseAndScan?: array}|null $excludePaths */ public function __construct(ComposerJsonAndInstalledJsonSourceLocatorMaker $composerJsonAndInstalledJsonSourceLocatorMaker, OptimizedSingleFileSourceLocatorRepository $optimizedSingleFileSourceLocatorRepository, Parser $phpParser, Parser $php8Parser, FileNodesFetcher $fileNodesFetcher, PhpStormStubsSourceStubber $phpstormStubsSourceStubber, ReflectionSourceStubber $reflectionSourceStubber, PhpVersion $phpVersion, array $fileExtensions, ?array $excludePaths) { $this->composerJsonAndInstalledJsonSourceLocatorMaker = $composerJsonAndInstalledJsonSourceLocatorMaker; $this->optimizedSingleFileSourceLocatorRepository = $optimizedSingleFileSourceLocatorRepository; $this->phpParser = $phpParser; $this->php8Parser = $php8Parser; $this->fileNodesFetcher = $fileNodesFetcher; $this->phpstormStubsSourceStubber = $phpstormStubsSourceStubber; $this->reflectionSourceStubber = $reflectionSourceStubber; $this->phpVersion = $phpVersion; $this->fileExtensions = $fileExtensions; $this->excludePaths = $excludePaths; } public function create(): SourceLocator { $classLoaders = ClassLoader::getRegisteredLoaders(); $classLoaderReflection = new ReflectionClass(ClassLoader::class); $cacheKey = hash('sha256', serialize([$this->phpVersion->getVersionId(), $this->fileExtensions, $this->excludePaths])); if ($classLoaderReflection->hasProperty('vendorDir') && !isset(self::$composerSourceLocatorsCache[$cacheKey])) { $composerLocators = [$this->optimizedSingleFileSourceLocatorRepository->getOrCreate(PHP_VERSION_ID < 80500 ? __DIR__ . '/../../stubs/runtime/Attribute84.php' : __DIR__ . '/../../stubs/runtime/Attribute85.php')]; $vendorDirProperty = $classLoaderReflection->getProperty('vendorDir'); if (PHP_VERSION_ID < 80100) { $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] = [new SkipPolyfillSourceLocator(new AggregateSourceLocator($composerLocators), $this->phpVersion)]; } $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'); $enableFnsr = getenv('PHPSTAN_FNSR'); $className = NodeScopeResolver::class; if (PHP_VERSION_ID >= 80100 && $enableFnsr !== '0') { $className = FiberNodeScopeResolver::class; } return new $className($container, $reflectionProvider, $container->getByType(InitializerExprTypeResolver::class), self::getReflector(), $container->getByType(ClassReflectionFactory::class), $container->getByType(ParameterOutTypeExtensionProvider::class), self::getParser(), $container->getByType(FileTypeMapper::class), $container->getByType(PhpDocInheritanceResolver::class), $container->getByType(FileHelper::class), $typeSpecifier, $container->getByType(ReadWritePropertiesExtensionProvider::class), $container->getByType(ParameterClosureThisExtensionProvider::class), $container->getByType(ParameterClosureTypeExtensionProvider::class), self::createScopeFactory($reflectionProvider, $typeSpecifier), self::getContainer()->getByType(DeepNodeCloner::class), $container->getParameter('polluteScopeWithLoopInitialAssignments'), $container->getParameter('polluteScopeWithAlwaysIterableForeach'), $container->getParameter('polluteScopeWithBlock'), static::getEarlyTerminatingMethodCalls(), static::getEarlyTerminatingFunctionCalls(), $container->getParameter('exceptions')['implicitThrows'], $container->getParameter('treatPhpDocTypesAsCertain'), $container->getByType(ImplicitToStringCallHelper::class)); } /** * @param string[] $dynamicConstantNames */ protected static function createScope(string $file, array $dynamicConstantNames = []): MutatingScope { $scopeFactory = self::createScopeFactory(self::createReflectionProvider(), self::getContainer()->getService('typeSpecifier'), $dynamicConstantNames); return $scopeFactory->create(ScopeContext::create($file)); } /** * @param callable(Node , Scope ): void $callback * @param string[] $dynamicConstantNames */ public static function processFile(string $file, callable $callback, array $dynamicConstantNames = []): void { $fileHelper = self::getContainer()->getByType(FileHelper::class); $resolver = static::createNodeScopeResolver(); $resolver->setAnalysedFiles(array_map(static fn(string $file): string => $fileHelper->normalizePath($file), array_merge([$file], static::getAdditionalAnalysedFiles()))); $resolver->processNodes(self::getParser()->parseFile($file), self::createScope($file, $dynamicConstantNames), $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]; } $failureMessage = sprintf('Expected type %s, got type %s in %s on line %d.', $expected, $actual, $file, $args[2]); $delayedErrors = $args[3] ?? []; if (count($delayedErrors) > 0) { $failureMessage .= sprintf("\n\nThis failure might be reported because of the following misconfiguration %s:\n\n", count($delayedErrors) === 1 ? 'issue' : 'issues'); foreach ($delayedErrors as $delayedError) { $failureMessage .= sprintf("* %s\n", $delayedError); } } $this->assertSame($expected, $actual, $failureMessage); } elseif ($assertType === 'superType') { $expected = $args[0]; $actual = $args[1]; $isCorrect = $args[2]; $failureMessage = sprintf('Expected subtype of %s, got type %s in %s on line %d.', $expected, $actual, $file, $args[3]); $delayedErrors = $args[4] ?? []; if (count($delayedErrors) > 0) { $failureMessage .= sprintf("\n\nThis failure might be reported because of the following misconfiguration %s:\n\n", count($delayedErrors) === 1 ? 'issue' : 'issues'); foreach ($delayedErrors as $delayedError) { $failureMessage .= sprintf("* %s\n", $delayedError); } } $this->assertTrue($isCorrect, $failureMessage); } elseif ($assertType === 'variableCertainty') { $expectedCertainty = $args[0]; $actualCertainty = $args[1]; $variableName = $args[2]; $failureMessage = sprintf('Expected %s, actual certainty of %s is %s in %s on line %d.', $expectedCertainty->describe(), $variableName, $actualCertainty->describe(), $file, $args[3]); $delayedErrors = $args[4] ?? []; if (count($delayedErrors) > 0) { $failureMessage .= sprintf("\n\nThis failure might be reported because of the following misconfiguration %s:\n\n", count($delayedErrors) === 1 ? 'issue' : 'issues'); foreach ($delayedErrors as $delayedError) { $failureMessage .= sprintf("* %s\n", $delayedError); } } $this->assertTrue($expectedCertainty->equals($actualCertainty), $failureMessage); } } /** * @return array}| * array{0: 'superType', 1: string, 2: string, 3: string, 4: bool, 5: int, 6?: non-empty-list}| * array{0: 'variableCertainty', 1: string, 2: TrinaryLogic, 3: TrinaryLogic, 4: string, 5: int, 6?: non-empty-list} * )> * * @api */ public static function gatherAssertTypes(string $file): array { $fileHelper = self::getContainer()->getByType(FileHelper::class); $relativePathHelper = new SystemAgnosticSimpleRelativePathHelper($fileHelper); $reflectionProvider = self::getContainer()->getByType(ReflectionProvider::class); $typeStringResolver = self::getContainer()->getByType(TypeStringResolver::class); $file = $fileHelper->normalizePath($file); $asserts = []; $delayedErrors = []; self::processFile($file, static function (Node $node, Scope $scope) use (&$asserts, &$delayedErrors, $file, $relativePathHelper, $reflectionProvider, $typeStringResolver): void { if ($node instanceof InClassNode) { if (!$reflectionProvider->hasClass($node->getClassReflection()->getName())) { $delayedErrors[] = sprintf('%s %s in %s not found in ReflectionProvider. Configure "autoload-dev" section in composer.json to include your tests directory.', $node->getClassReflection()->getClassTypeDescription(), $node->getClassReflection()->getName(), $file); } } elseif ($node instanceof Node\Stmt\Trait_) { if ($node->namespacedName === null) { throw new ShouldNotHappenException(); } if (!$reflectionProvider->hasClass($node->namespacedName->toString())) { $delayedErrors[] = sprintf('Trait %s not found in ReflectionProvider. Configure "autoload-dev" section in composer.json to include your tests directory.', $node->namespacedName->toString()); } } 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', 'assertsupertype', '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->getStartLine())); } $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->getStartLine())); } $actualType = $scope->getNativeType($node->getArgs()[1]->value); $assert = ['type', $file, $expectedType->getValue(), $actualType->describe(VerbosityLevel::precise()), $node->getStartLine()]; } elseif ($functionName === 'PHPStan\Testing\assertSuperType') { $expectedType = $scope->getType($node->getArgs()[0]->value); $expectedTypeStrings = $expectedType->getConstantStrings(); if (count($expectedTypeStrings) !== 1) { self::fail(sprintf('Expected super type must be a literal string, %s given in %s on line %d.', $expectedType->describe(VerbosityLevel::precise()), $relativePathHelper->getRelativePath($file), $node->getStartLine())); } $actualType = $scope->getType($node->getArgs()[1]->value); $isCorrect = $typeStringResolver->resolve($expectedTypeStrings[0]->getValue())->isSuperTypeOf($actualType)->yes(); $assert = ['superType', $file, $expectedTypeStrings[0]->getValue(), $actualType->describe(VerbosityLevel::precise()), $isCorrect, $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', 'assertSuperType' => 'PHPStan\Testing\assertSuperType', '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)); } if (count($delayedErrors) === 0) { return $asserts; } foreach ($asserts as $i => $assert) { $assert[] = $delayedErrors; $asserts[$i] = $assert; } 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(); try { if (self::isFileLintSkipped($path)) { continue; } } catch (LogicException $e) { self::fail($e->getMessage()); } $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 (str_starts_with($firstLine, '#!')) { $firstLine = fgets($f); if ($firstLine === \false) { return \false; } } @fclose($f); if (preg_match('~isString()->yes()) { * // Definitely a string * } * if ($type->isString()->maybe()) { * // Could be a string (e.g. mixed) * } * if ($type->isString()->no()) { * // Definitely not a string * } * * TrinaryLogic supports logical operations (and, or, negate) that propagate * uncertainty correctly. It is used as a flyweight — instances are cached and * compared by identity. * * @api * @see https://phpstan.org/developing-extensions/trinary-logic */ final class TrinaryLogic { private int $value; private const YES = 3; private const MAYBE = 1; private const NO = 0; /** @var self[] */ private static array $registry = []; private static self $YES; private static self $MAYBE; private static self $NO; private function __construct(int $value) { $this->value = $value; } public static function createYes(): self { return self::$YES ??= self::$registry[self::YES] ??= new self(self::YES); } public static function createNo(): self { return self::$NO ??= self::$registry[self::NO] ??= new self(self::NO); } public static function createMaybe(): self { return 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] ??= new self($yesNo); } private static function create(int $value): self { return self::$registry[$value] ??= new self($value); } /** * @phpstan-assert-if-true =false $this->no() * @phpstan-assert-if-true =false $this->maybe() */ public function yes(): bool { return $this->value === self::YES; } /** * @phpstan-assert-if-true =false $this->no() * @phpstan-assert-if-true =false $this->yes() */ public function maybe(): bool { return $this->value === self::MAYBE; } /** * @phpstan-assert-if-true =false $this->maybe() * @phpstan-assert-if-true =false $this->yes() */ 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 $operand = null, self ...$rest): self { $min = $this->value & ($operand !== null ? $operand->value : self::YES); foreach ($rest as $restOperand) { $min &= $restOperand->value; } return self::$registry[$min] ??= new self($min); } /** * @template T * @param T[] $objects * @param callable(T): self $callback */ public function lazyAnd(array $objects, callable $callback): self { if ($this->value === self::NO) { return $this; } $results = []; foreach ($objects as $object) { $result = $callback($object); if ($result->value === self::NO) { return $result; } $results[] = $result; } return $this->and(...$results); } public function or(?self $operand = null, self ...$rest): self { $max = $this->value | ($operand !== null ? $operand->value : self::NO); foreach ($rest as $restOperand) { $max |= $restOperand->value; } return self::$registry[$max] ??= new self($max); } /** * @template T * @param T[] $objects * @param callable(T): self $callback */ public function lazyOr(array $objects, callable $callback): self { if ($this->value === self::YES) { return $this; } $results = []; foreach ($objects as $object) { $result = $callback($object); if ($result->value === self::YES) { return $result; } $results[] = $result; } return $this->or(...$results); } /** * Returns the operands' value if they all agree, Maybe if any differ. */ 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; } /** * Returns Yes if any operand is Yes, otherwise the minimum. */ public static function maxMin(self ...$operands): self { if ($operands === []) { throw new \PHPStan\ShouldNotHappenException(); } $max = self::NO; $min = self::YES; foreach ($operands as $operand) { $max |= $operand->value; $min &= $operand->value; } $maxMin = $max === self::YES ? self::YES : $min; return self::$registry[$maxMin] ??= new self($maxMin); } /** * @template T * @param T[] $objects * @param callable(T): self $callback */ public static function lazyMaxMin(array $objects, callable $callback): self { $min = self::YES; foreach ($objects as $object) { $result = $callback($object); if ($result->value === self::YES) { return $result; } $min &= $result->value; } return self::$registry[$min] ??= new self($min); } public function negate(): self { // 0b11 >> 0 == 0b11 (3) // 0b11 >> 1 == 0b01 (1) // 0b11 >> 3 == 0b00 (0) return self::create(3 >> $this->value); } public function equals(self $other): bool { return $this === $other; } /** * Returns the stronger of the two values, or null if they are equal (Yes > Maybe > No). */ 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]; } } */ public array $reasons; private static self $YES; private static self $MAYBE; private static self $NO; /** * @api * @param list $reasons Human-readable explanations of why acceptance failed */ public function __construct(TrinaryLogic $result, array $reasons) { $this->result = $result; $this->reasons = $reasons; } /** * @phpstan-assert-if-true =false $this->no() * @phpstan-assert-if-true =false $this->maybe() */ public function yes(): bool { return $this->result->yes(); } /** * @phpstan-assert-if-true =false $this->no() * @phpstan-assert-if-true =false $this->yes() */ public function maybe(): bool { return $this->result->maybe(); } /** * @phpstan-assert-if-true =false $this->maybe() * @phpstan-assert-if-true =false $this->yes() */ public function no(): bool { return $this->result->no(); } public static function createYes(): self { return self::$YES ??= new self(TrinaryLogic::createYes(), []); } /** @param list $reasons */ public static function createNo(array $reasons = []): self { if ($reasons === []) { return self::$NO ??= new self(TrinaryLogic::createNo(), $reasons); } return new self(TrinaryLogic::createNo(), $reasons); } public static function createMaybe(): self { return self::$MAYBE ??= new self(TrinaryLogic::createMaybe(), []); } public static function createFromBoolean(bool $value): self { if ($value === \true) { return self::createYes(); } return self::createNo(); } 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); } /** @see TrinaryLogic::extremeIdentity() */ public static function extremeIdentity(self ...$operands): self { if ($operands === []) { throw new ShouldNotHappenException(); } $results = []; $reasons = []; foreach ($operands as $operand) { $results[] = $operand->result; foreach ($operand->reasons as $reason) { $reasons[] = $reason; } } return new self(TrinaryLogic::extremeIdentity(...$results), array_values(array_unique($reasons))); } /** @see TrinaryLogic::maxMin() */ public static function maxMin(self ...$operands): self { if ($operands === []) { throw new ShouldNotHappenException(); } $results = []; $reasons = []; foreach ($operands as $operand) { $results[] = $operand->result; foreach ($operand->reasons as $reason) { $reasons[] = $reason; } } return new self(TrinaryLogic::maxMin(...$results), array_values(array_unique($reasons))); } /** * @template T * @param T[] $objects * @param callable(T): self $callback */ public static function lazyMaxMin(array $objects, callable $callback): self { $reasons = []; $hasNo = \false; foreach ($objects as $object) { $isAcceptedBy = $callback($object); if ($isAcceptedBy->result->yes()) { return $isAcceptedBy; } elseif ($isAcceptedBy->result->no()) { $hasNo = \true; } foreach ($isAcceptedBy->reasons as $reason) { $reasons[] = $reason; } } return new self($hasNo ? TrinaryLogic::createNo() : TrinaryLogic::createMaybe(), array_values(array_unique($reasons))); } } isArray(); $isList = $type->isList(); $isListArray = $isArray->and($isList); if ($isListArray->yes()) { return AcceptsResult::createYes(); } if ($type instanceof CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($isListArray, []); } public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } if ($type instanceof CompoundType) { return $type->isSubTypeOf($this); } return new IsSuperTypeOfResult($type->isArray()->and($type->isList()), []); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOf($this); } return new IsSuperTypeOfResult($otherType->isArray()->and($otherType->isList())->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), []); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return $this->isSubTypeOf($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)->result->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 { return $this; } public function unsetOffset(Type $offsetType): Type { if ($this->hasOffsetValueType($offsetType)->no()) { return $this; } return new ErrorType(); } public function getKeysArrayFiltered(Type $filterValueType, TrinaryLogic $strict): Type { return $this->getKeysArray(); } 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, ?TrinaryLogic $strict = null): 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 spliceArray(Type $offsetType, Type $lengthType, Type $replacementType): Type { return $this; } public function makeListMaybe(): Type { // This accessory is the list assertion itself; weakening the // list-ness to "maybe" means the accessory no longer applies. // Returning `MixedType` lets the enclosing `IntersectionType` drop // it via `TypeCombinator::intersect` while preserving the rest. return new MixedType(); } public function mapValueType(callable $cb): Type { // Mapping values doesn't disturb list-ness. return $this; } public function mapKeyType(callable $cb): Type { return $this; } public function makeAllArrayKeysOptional(): Type { // Marking keys optional in an arbitrary list keeps it a list. return $this; } public function changeKeyCaseArray(?int $case): Type { // List keys are integers; case-folding leaves them alone. return $this; } public function filterArrayRemovingFalsey(): Type { // Filtering creates gaps in the integer-key sequence — list-ness lost. 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 isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString(): 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 toBitwiseNotType(): Type { return new ErrorType(); } public function toAbsoluteNumber(): Type { return new ErrorType(); } public function toInteger(): Type { return new UnionType([new ConstantIntegerType(0), new ConstantIntegerType(1)]); } public function toFloat(): Type { return new UnionType([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 toCoercedArgumentType(bool $strictTypes): Type { return $this; } 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 function getDefaultBaseType(): Type { return new ArrayType(new MixedType(), new MixedType()); } public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode('list'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } isLiteralString(); if ($isLiteralString->yes()) { return AcceptsResult::createYes(); } if ($type instanceof CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($isLiteralString, []); } public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOf($this); } if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } return new IsSuperTypeOfResult($type->isLiteralString(), []); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOf($this); } return new IsSuperTypeOfResult($otherType->isLiteralString()->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), []); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return $this->isSubTypeOf($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 toBitwiseNotType(): Type { return new StringType(); } 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 toCoercedArgumentType(bool $strictTypes): Type { if (!$strictTypes) { return TypeCombinator::union($this->toInteger(), $this->toFloat(), $this, $this->toBoolean()); } 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 isClassString(): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isUppercaseString(): 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 function exponentiate(Type $exponent): Type { return new BenevolentUnionType([new FloatType(), new IntegerType()]); } public function getFiniteTypes(): array { return []; } public function getDefaultBaseType(): Type { return new StringType(); } public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode('literal-string'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } isLowercaseString(); if ($isLowercaseString->yes()) { return AcceptsResult::createYes(); } if ($type instanceof CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($isLowercaseString, []); } public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOf($this); } if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } return new IsSuperTypeOfResult($type->isLowercaseString(), []); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOf($this); } return new IsSuperTypeOfResult($otherType->isLowercaseString()->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), []); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return $this->isSubTypeOf($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 toBitwiseNotType(): Type { return new StringType(); } 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 toCoercedArgumentType(bool $strictTypes): Type { if (!$strictTypes) { return TypeCombinator::union($this->toInteger(), $this->toFloat(), $this, $this->toBoolean()); } 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 isClassString(): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isUppercaseString(): 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 { if ($type->isString()->yes() && $type->isLowercaseString()->no() && ($type->isNumericString()->no() || $this->isNumericString()->no())) { return new ConstantBooleanType(\false); } 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 function exponentiate(Type $exponent): Type { return new BenevolentUnionType([new FloatType(), new IntegerType()]); } public function getFiniteTypes(): array { return []; } public function getDefaultBaseType(): Type { return new StringType(); } public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode('lowercase-string'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } isNonEmptyString(); if ($isNonEmptyString->yes()) { return AcceptsResult::createYes(); } if ($type instanceof CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($isNonEmptyString, []); } public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOf($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): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOf($this); } return new IsSuperTypeOfResult($otherType->isNonEmptyString()->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), []); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return $this->isSubTypeOf($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 toBitwiseNotType(): Type { return new IntersectionType([new StringType(), new self()]); } 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 toCoercedArgumentType(bool $strictTypes): Type { if (!$strictTypes) { return TypeCombinator::union($this->toInteger(), $this->toFloat(), $this, $this->toBoolean()); } 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 isClassString(): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isUppercaseString(): 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 { if ($type->isNull()->yes()) { return new ConstantBooleanType(\false); } if ($type->isString()->yes() && $type->isNonEmptyString()->no()) { return new ConstantBooleanType(\false); } 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 function tryRemove(Type $typeToRemove): ?Type { if ($typeToRemove instanceof ConstantStringType && $typeToRemove->getValue() === '0') { return 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 getDefaultBaseType(): Type { return new StringType(); } public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode('non-empty-string'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } isNonFalsyString(); if ($isNonFalsyString->yes()) { return AcceptsResult::createYes(); } if ($type instanceof CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($isNonFalsyString, []); } public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOf($this); } if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } return new IsSuperTypeOfResult($type->isNonFalsyString(), []); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOf($this); } if ($otherType instanceof \PHPStan\Type\Accessory\AccessoryNonEmptyStringType) { return IsSuperTypeOfResult::createYes(); } return new IsSuperTypeOfResult($otherType->isNonFalsyString()->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), []); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return $this->isSubTypeOf($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 toBitwiseNotType(): Type { return new IntersectionType([new StringType(), new \PHPStan\Type\Accessory\AccessoryNonEmptyStringType()]); } public function toAbsoluteNumber(): Type { return new ErrorType(); } public function toInteger(): Type { // Do not remove `0` since `(int) '00'` is still `0`. 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 toCoercedArgumentType(bool $strictTypes): Type { if (!$strictTypes) { return TypeCombinator::union($this->toInteger(), $this->toFloat(), $this, $this->toBoolean()); } 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 isClassString(): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isUppercaseString(): 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 { $dominated = TypeCombinator::union(new NullType(), new ConstantBooleanType(\false), new ConstantStringType(''), new ConstantArrayType([], [])); if ($dominated->isSuperTypeOf($type)->yes()) { return new ConstantBooleanType(\false); } 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 function exponentiate(Type $exponent): Type { return new BenevolentUnionType([new FloatType(), new IntegerType()]); } public function getFiniteTypes(): array { return []; } public function getDefaultBaseType(): Type { return new StringType(); } public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode('non-falsy-string'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } isNumericString(); if ($isNumericString->yes()) { return AcceptsResult::createYes(); } if ($type instanceof CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($isNumericString, []); } public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOf($this); } if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } return new IsSuperTypeOfResult($type->isNumericString(), []); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOf($this); } return new IsSuperTypeOfResult($otherType->isNumericString()->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), []); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return $this->isSubTypeOf($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 toBitwiseNotType(): Type { return new IntersectionType([new StringType(), new \PHPStan\Type\Accessory\AccessoryNonEmptyStringType()]); } 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 toCoercedArgumentType(bool $strictTypes): Type { if (!$strictTypes) { return TypeCombinator::union($this->toInteger(), $this->toFloat(), $this, $this->toBoolean()); } 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::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 isClassString(): 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 { if ($type->isNull()->yes()) { return new ConstantBooleanType(\false); } if ($type->isString()->yes() && $type->isNumericString()->no()) { return new ConstantBooleanType(\false); } 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 function tryRemove(Type $typeToRemove): ?Type { if ($typeToRemove instanceof ConstantStringType && $typeToRemove->getValue() === '0') { return new IntersectionType([new StringType(), $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 getDefaultBaseType(): Type { return new StringType(); } public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode('numeric-string'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } ` is represented as: * * IntersectionType([ArrayType(int, int), NonEmptyArrayType, AccessoryArrayListType]) * * Each AccessoryType implementation has a corresponding query method on the `Type` interface * that returns `TrinaryLogic`. This lets any code query the refinement without knowing * how it is represented internally: * * | AccessoryType class | Corresponding Type method | * |----------------------------------|---------------------------------| * | AccessoryNonEmptyStringType | `isNonEmptyString()` | * | AccessoryNonFalsyStringType | `isNonFalsyString()` | * | AccessoryLiteralStringType | `isLiteralString()` | * | AccessoryNumericStringType | `isNumericString()` | * | AccessoryLowercaseStringType | `isLowercaseString()` | * | AccessoryUppercaseStringType | `isUppercaseString()` | * | AccessoryArrayListType | `isList()` | * | NonEmptyArrayType | `isIterableAtLeastOnce()` | * | OversizedArrayType | `isOversizedArray()` | * | HasMethodType | `hasMethod(string)` | * | HasPropertyType | `hasProperty(string)` | * | HasOffsetType | `hasOffsetValueType(Type)` | * | HasOffsetValueType | `getOffsetValueType(Type)` | * * All implementations also implement `CompoundType`, so they participate in the * double-dispatch protocol for type comparison — simple types delegate to * `$type->isAcceptedBy()`/`$type->isSubTypeOf()` when they encounter an AccessoryType. * * The `instanceof AccessoryType` check is used in a few specific places: * - `IntersectionType::describe()` — skips AccessoryTypes when building base type names * (they are rendered as type-level qualifiers like `non-empty-` instead) * - `IntersectionType::describeItself()` — separates base types from accessory types * when composing the human-readable type description * - `UnionTypeHelper::sortTypes()` — sorts AccessoryTypes after base types * - `TypeCombinator` — handles AccessoryType intersection/union normalization * - `MissingTypehintCheck` — skips AccessoryTypes in typehint analysis */ interface AccessoryType extends Type { /** * Returns the base type this accessory refines. * * Used when an accessory would otherwise end up in an `IntersectionType` * without an explicit base type — the returned type provides that base. * For example `AccessoryNonEmptyStringType` returns `string`, array accessories * return `array`, and offset accessories return `array|ArrayAccess`. */ public function getDefaultBaseType(): Type; } isUppercaseString(); if ($isUppercaseString->yes()) { return AcceptsResult::createYes(); } if ($type instanceof CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($isUppercaseString, []); } public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOf($this); } if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } return new IsSuperTypeOfResult($type->isUppercaseString(), []); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOf($this); } return new IsSuperTypeOfResult($otherType->isUppercaseString()->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), []); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return $this->isSubTypeOf($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 toBitwiseNotType(): Type { return new StringType(); } 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 toCoercedArgumentType(bool $strictTypes): Type { if (!$strictTypes) { return TypeCombinator::union($this->toInteger(), $this->toFloat(), $this, $this->toBoolean()); } 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 isClassString(): 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 { if ($type->isString()->yes() && $type->isUppercaseString()->no() && ($type->isNumericString()->no() || $this->isNumericString()->no())) { return new ConstantBooleanType(\false); } 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 function exponentiate(Type $exponent): Type { return new BenevolentUnionType([new FloatType(), new IntegerType()]); } public function getFiniteTypes(): array { return []; } public function getDefaultBaseType(): Type { return new StringType(); } public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode('uppercase-string'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } methodName = $methodName; } public function getReferencedClasses(): array { return []; } public function getObjectClassNames(): array { return []; } public function getObjectClassReflections(): array { return []; } public function getClassStringType(): Type { return new GenericClassStringType($this); } private function getCanonicalMethodName(): string { return strtolower($this->methodName); } public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return AcceptsResult::createFromBoolean($this->equals($type)); } public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOf($this); } return new IsSuperTypeOfResult($type->hasMethod($this->methodName), []); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOf($this); } if ($this->isCallable()->yes() && $otherType->isCallable()->yes() && !(new ObjectType(Closure::class))->isSuperTypeOf($otherType)->yes()) { return IsSuperTypeOfResult::createYes(); } if ($otherType instanceof self) { $limit = TrinaryLogic::createYes(); } else { $limit = TrinaryLogic::createMaybe(); } return new IsSuperTypeOfResult($limit->and($otherType->hasMethod($this->methodName)), []); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return $this->isSubTypeOf($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 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 fn(Type $type): Type => $type); } public function isCallable(): TrinaryLogic { if ($this->getCanonicalMethodName() === '__invoke') { return TrinaryLogic::createYes(); } 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 getClassStringObjectType(): Type { return $this; } public function getObjectTypeOrClassStringObjectType(): Type { return $this; } public function isVoid(): TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); } public function toNumber(): Type { return new ErrorType(); } public function toBitwiseNotType(): Type { return new ErrorType(); } public function toAbsoluteNumber(): Type { return new ErrorType(); } public function toString(): Type { if ($this->getCanonicalMethodName() === '__tostring') { return new StringType(); } return new ErrorType(); } public function toInteger(): Type { return new ErrorType(); } public function toFloat(): Type { return new ErrorType(); } public function toArray(): Type { return new MixedType(); } public function toArrayKey(): Type { return new ErrorType(); } public function toCoercedArgumentType(bool $strictTypes): Type { if (!$strictTypes) { return TypeCombinator::union($this, $this->toString()); } return $this; } public function getEnumCases(): array { return []; } public function getEnumCaseObject(): ?EnumCaseObjectType { return null; } 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 function getDefaultBaseType(): Type { return new ObjectWithoutClassType(); } public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode(''); // no PHPDoc representation } public function hasTemplateOrLateResolvableType(): bool { return \false; } } offsetType = $offsetType; } /** * @return \PHPStan\Type\Constant\ConstantStringType|\PHPStan\Type\Constant\ConstantIntegerType */ public function getOffsetType() { return $this->offsetType; } public function getReferencedClasses(): array { return []; } public function getObjectClassNames(): array { return []; } public function getObjectClassReflections(): array { return []; } public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($type->isOffsetAccessible()->and($type->hasOffsetValueType($this->offsetType)), []); } public function isSuperTypeOf(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): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOf($this); } return new IsSuperTypeOfResult($otherType->isOffsetAccessible()->and($otherType->hasOffsetValueType($this->offsetType))->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), []); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return $this->isSubTypeOf($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 spliceArray(Type $offsetType, Type $lengthType, Type $replacementType): Type { if ((new ConstantIntegerType(0))->isSuperTypeOf($lengthType)->yes()) { return $this; } return new MixedType(); } public function makeListMaybe(): Type { // Having an offset doesn't conflict with list-being-maybe. return $this; } public function mapValueType(callable $cb): Type { // `HasOffsetType` only records that an offset exists, not its // value; the assertion still holds after a value transformation. return $this; } public function mapKeyType(callable $cb): Type { // Match the prior `TypeTraverser`-based pattern that left // accessories untouched while rewriting the array key type. return $this; } public function makeAllArrayKeysOptional(): Type { // "Has offset X" is no longer guaranteed when X is now optional. return new MixedType(); } public function changeKeyCaseArray(?int $case): Type { // A string offset is itself case-folded; an int offset is unchanged. if (!$this->offsetType instanceof ConstantStringType) { return $this; } $value = $this->offsetType->getValue(); if ($case === CASE_LOWER) { return new self(new ConstantStringType(strtolower($value))); } if ($case === CASE_UPPER) { return new self(new ConstantStringType(strtoupper($value))); } // Unknown case → could be either fold; the accessory weakens to // "no specific offset known". return new MixedType(); } public function filterArrayRemovingFalsey(): Type { // We don't track the value at this offset, so we can't guarantee // it survives a falsey filter. Drop the assertion. 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 getClassStringObjectType(): Type { return new ObjectWithoutClassType(); } public function getObjectTypeOrClassStringObjectType(): Type { return new ObjectWithoutClassType(); } public function isVoid(): TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); } public function getKeysArrayFiltered(Type $filterValueType, TrinaryLogic $strict): Type { return $this->getKeysArray(); } 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 toBitwiseNotType(): 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 toCoercedArgumentType(bool $strictTypes): Type { return $this; } public function getEnumCases(): array { return []; } public function getEnumCaseObject(): ?EnumCaseObjectType { return null; } 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 function getDefaultBaseType(): Type { return new UnionType([new ArrayType(new MixedType(), new MixedType()), new ObjectType(ArrayAccess::class)]); } public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode(''); // no PHPDoc representation } public function hasTemplateOrLateResolvableType(): bool { return $this->offsetType->hasTemplateOrLateResolvableType(); } } offsetType = $offsetType; $this->valueType = $valueType; } /** * @return \PHPStan\Type\Constant\ConstantStringType|\PHPStan\Type\Constant\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 accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($type->isOffsetAccessible()->and($type->hasOffsetValueType($this->offsetType))->and($this->valueType->accepts($type->getOffsetValueType($this->offsetType), $strictTypes)->result), []); } public function isSuperTypeOf(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->isSuperTypeOf($type->getOffsetValueType($this->offsetType))); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOf($this); } $result = new IsSuperTypeOfResult($otherType->isOffsetAccessible()->and($otherType->hasOffsetValueType($this->offsetType))->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), []); return $result->and($otherType->getOffsetValueType($this->offsetType)->isSuperTypeOf($this->valueType)); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return $this->isSubTypeOf($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 { $arrayKeyType = $offsetType->toArrayKey(); if ($arrayKeyType->isConstantScalarValue()->yes() && $arrayKeyType->equals($this->offsetType)) { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } public function getOffsetValueType(Type $offsetType): Type { $arrayKeyType = $offsetType->toArrayKey(); if ($arrayKeyType->isConstantScalarValue()->yes() && $arrayKeyType->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 { if (!$offsetType->equals($this->offsetType)) { return $this; } 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 getKeysArrayFiltered(Type $filterValueType, TrinaryLogic $strict): Type { return $this->getKeysArray(); } 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, ?TrinaryLogic $strict = null): Type { $strict ??= TrinaryLogic::createMaybe(); if ($needleType instanceof ConstantScalarType && $this->valueType instanceof ConstantScalarType && ($needleType->getValue() === $this->valueType->getValue() || $strict->no() && $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 spliceArray(Type $offsetType, Type $lengthType, Type $replacementType): Type { if ((new ConstantIntegerType(0))->isSuperTypeOf($lengthType)->yes()) { return $this; } return new MixedType(); } public function makeListMaybe(): Type { // Knowing a specific offset/value is independent of list-ness. return $this; } public function mapValueType(callable $cb): Type { // The assertion is "offset X has value V"; after the transform // the value at X is `cb(V)`. return new self($this->offsetType, $cb($this->valueType)); } public function mapKeyType(callable $cb): Type { // The offset itself is unaffected; passes through. return $this; } public function makeAllArrayKeysOptional(): Type { return new MixedType(); } public function changeKeyCaseArray(?int $case): Type { if (!$this->offsetType instanceof ConstantStringType) { return $this; } $value = $this->offsetType->getValue(); if ($case === CASE_LOWER) { return new self(new ConstantStringType(strtolower($value)), $this->valueType); } if ($case === CASE_UPPER) { return new self(new ConstantStringType(strtoupper($value)), $this->valueType); } // Unknown case → drop the specific-offset assertion. return new MixedType(); } public function filterArrayRemovingFalsey(): Type { $falseyTypes = StaticTypeFactory::falsey(); $isFalsey = $falseyTypes->isSuperTypeOf($this->valueType); if ($isFalsey->yes()) { // Definitely filtered out — the offset assertion no longer holds. return new MixedType(); } if ($isFalsey->no()) { // Definitely survives. return $this; } // Maybe filtered: drop the specific-value assertion. 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 getClassStringObjectType(): Type { return new ObjectWithoutClassType(); } public function getObjectTypeOrClassStringObjectType(): Type { return new ObjectWithoutClassType(); } public function isVoid(): TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); } public function toNumber(): Type { return new ErrorType(); } public function toBitwiseNotType(): 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 toCoercedArgumentType(bool $strictTypes): Type { return $this; } public function getEnumCases(): array { return []; } public function getEnumCaseObject(): ?EnumCaseObjectType { return null; } 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 function getDefaultBaseType(): Type { return new UnionType([new ArrayType(new MixedType(), new MixedType()), new ObjectType(ArrayAccess::class)]); } public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode(''); // no PHPDoc representation } public function hasTemplateOrLateResolvableType(): bool { return $this->offsetType->hasTemplateOrLateResolvableType() || $this->valueType->hasTemplateOrLateResolvableType(); } } propertyName = $propertyName; } public function getReferencedClasses(): array { return []; } public function getObjectClassNames(): array { return []; } public function getObjectClassReflections(): array { return []; } public function getClassStringType(): Type { return new GenericClassStringType($this); } public function getPropertyName(): string { return $this->propertyName; } public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return AcceptsResult::createFromBoolean($this->equals($type)); } public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOf($this); } return new IsSuperTypeOfResult($type->hasInstanceProperty($this->propertyName)->or($type->hasStaticProperty($this->propertyName)), []); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOf($this); } if ($otherType instanceof self) { $limit = TrinaryLogic::createYes(); } else { $limit = TrinaryLogic::createMaybe(); } return new IsSuperTypeOfResult($limit->and($otherType->hasInstanceProperty($this->propertyName)->or($otherType->hasStaticProperty($this->propertyName))), []); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return $this->isSubTypeOf($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 hasProperty(string $propertyName): TrinaryLogic { if ($this->propertyName === $propertyName) { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } public function hasInstanceProperty(string $propertyName): TrinaryLogic { if ($this->propertyName === $propertyName) { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } public function hasStaticProperty(string $propertyName): TrinaryLogic { if ($this->propertyName === $propertyName) { return TrinaryLogic::createYes(); } 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 getClassStringObjectType(): Type { return $this; } public function getObjectTypeOrClassStringObjectType(): Type { return $this; } public function isVoid(): TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); } public function toNumber(): Type { return new ErrorType(); } public function toBitwiseNotType(): 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 MixedType(); } public function toArrayKey(): Type { return new ErrorType(); } public function toCoercedArgumentType(bool $strictTypes): Type { if (!$strictTypes) { return TypeCombinator::union($this, $this->toString()); } return $this; } public function getEnumCases(): array { return []; } public function getEnumCaseObject(): ?EnumCaseObjectType { return null; } 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 function getDefaultBaseType(): Type { return new ObjectWithoutClassType(); } public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode(''); // no PHPDoc representation } public function hasTemplateOrLateResolvableType(): bool { return \false; } } isArray(); $isIterableAtLeastOnce = $type->isIterableAtLeastOnce(); $isNonEmptyArray = $isArray->and($isIterableAtLeastOnce); if ($isNonEmptyArray->yes()) { return AcceptsResult::createYes(); } if ($type instanceof CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($isNonEmptyArray, []); } public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } if ($type instanceof CompoundType) { return $type->isSubTypeOf($this); } return new IsSuperTypeOfResult($type->isArray()->and($type->isIterableAtLeastOnce()), []); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOf($this); } return new IsSuperTypeOfResult($otherType->isArray()->and($otherType->isIterableAtLeastOnce())->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), []); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return $this->isSubTypeOf($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 getKeysArrayFiltered(Type $filterValueType, TrinaryLogic $strict): 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, ?TrinaryLogic $strict = null): 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()) { return $this; } return new MixedType(); } public function spliceArray(Type $offsetType, Type $lengthType, Type $replacementType): Type { if ((new ConstantIntegerType(0))->isSuperTypeOf($lengthType)->yes() || $replacementType->toArray()->isIterableAtLeastOnce()->yes()) { return $this; } return new MixedType(); } public function makeListMaybe(): Type { // Non-emptiness is independent of list-ness; weaken-list keeps it. return $this; } public function mapValueType(callable $cb): Type { // Mapping doesn't change the entry count; non-emptiness is preserved. return $this; } public function mapKeyType(callable $cb): Type { return $this; } public function makeAllArrayKeysOptional(): Type { // Without `ConstantArrayType` keys to mark optional, this is a no-op. // Non-emptiness is unrelated to per-key optionality and is preserved. return $this; } public function changeKeyCaseArray(?int $case): Type { // Case-folding keys doesn't change the entry count. return $this; } public function filterArrayRemovingFalsey(): Type { // Filtering may leave the array empty — drop the assertion. 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 isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString(): 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 { if ($type->isArray()->yes() && $type->isIterableAtLeastOnce()->no()) { return new ConstantBooleanType(\false); } return new BooleanType(); } public function toNumber(): Type { return new ErrorType(); } public function toBitwiseNotType(): 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 toCoercedArgumentType(bool $strictTypes): Type { return $this; } 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 function getDefaultBaseType(): Type { return new ArrayType(new MixedType(), new MixedType()); } public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode('non-empty-array'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } isAcceptedBy($this, $strictTypes); } return new AcceptsResult($type->isArray()->and($type->isIterableAtLeastOnce()), []); } public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } if ($type instanceof CompoundType) { return $type->isSubTypeOf($this); } return new IsSuperTypeOfResult($type->isArray()->and($type->isOversizedArray()), []); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOf($this); } return new IsSuperTypeOfResult($otherType->isArray()->and($otherType->isOversizedArray())->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), []); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return $this->isSubTypeOf($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 getKeysArrayFiltered(Type $filterValueType, TrinaryLogic $strict): Type { return $this->getKeysArray(); } 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, ?TrinaryLogic $strict = null): 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 spliceArray(Type $offsetType, Type $lengthType, Type $replacementType): Type { return $this; } public function makeListMaybe(): Type { return $this; } public function mapValueType(callable $cb): Type { return $this; } public function mapKeyType(callable $cb): Type { return $this; } public function makeAllArrayKeysOptional(): Type { return $this; } public function changeKeyCaseArray(?int $case): Type { return $this; } public function filterArrayRemovingFalsey(): 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 isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString(): 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 toBitwiseNotType(): Type { return new ErrorType(); } public function toAbsoluteNumber(): Type { return new ErrorType(); } public function toBoolean(): BooleanType { return new BooleanType(); } 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 toCoercedArgumentType(bool $strictTypes): Type { return $this; } 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 function getDefaultBaseType(): Type { return new ArrayType(new MixedType(), new MixedType()); } public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode(''); // no PHPDoc representation } public function hasTemplateOrLateResolvableType(): bool { return \false; } } 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; } /** * Build a same-kind array with new key/item types. Subclasses * (e.g. {@see TemplateArrayType}) override this to preserve their * extra metadata across array-mutating operations such as offset * writes and unsets. */ protected function withTypes(\PHPStan\Type\Type $keyType, \PHPStan\Type\Type $itemType): self { return new self($keyType, $itemType); } public function getReferencedClasses(): array { return array_merge($this->keyType->getReferencedClasses(), $this->getItemType()->getReferencedClasses()); } public function getConstantArrays(): array { return []; } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes): \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedBy($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->accepts($keyType, $strictTypes); $acceptsValue = $itemType->accepts($valueType, $strictTypes); $result = $result->and($acceptsKey)->and($acceptsValue); } return $result; } if ($type instanceof \PHPStan\Type\ArrayType) { return $this->getItemType()->accepts($type->getItemType(), $strictTypes)->and($this->keyType->accepts($type->keyType, $strictTypes)); } return \PHPStan\Type\AcceptsResult::createNo(); } public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self || $type instanceof ConstantArrayType) { return $this->getItemType()->isSuperTypeOf($type->getItemType())->and($this->getIterableKeyType()->isSuperTypeOf($type->getIterableKeyType())); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOf($this); } return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } public function equals(\PHPStan\Type\Type $type): bool { return $type instanceof self && $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' && !$this->keyType->isExplicitMixed(); $isMixedItemType = $this->itemType instanceof \PHPStan\Type\MixedType && $this->itemType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed' && !$this->itemType->isExplicitMixed(); $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)); }); } public function generalizeValues(): self { return new self($this->keyType, $this->itemType->generalize(\PHPStan\Type\GeneralizePrecision::lessSpecific())); } public function getKeysArrayFiltered(\PHPStan\Type\Type $filterValueType, TrinaryLogic $strict): \PHPStan\Type\Type { return $this->getKeysArray(); } public function getKeysArray(): \PHPStan\Type\Type { return \PHPStan\Type\TypeCombinator::intersect(new self(new \PHPStan\Type\IntegerType(), $this->getIterableKeyType()), new AccessoryArrayListType()); } public function getValuesArray(): \PHPStan\Type\Type { return \PHPStan\Type\TypeCombinator::intersect(new self(new \PHPStan\Type\IntegerType(), $this->itemType), new AccessoryArrayListType()); } 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 isConstantArray(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isList(): TrinaryLogic { if ($this->isList === null) { if (\PHPStan\Type\IntegerRangeType::fromInterval(0, null)->isSuperTypeOf($this->getKeyType())->no()) { return $this->isList = TrinaryLogic::createNo(); } if ($this->getKeyType()->isSuperTypeOf(new ConstantIntegerType(0))->no()) { return $this->isList = TrinaryLogic::createNo(); } return $this->isList = TrinaryLogic::createMaybe(); } return $this->isList; } public function isConstantValue(): TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion): \PHPStan\Type\BooleanType { if ($type->isInteger()->yes()) { return new ConstantBooleanType(\false); } return new \PHPStan\Type\BooleanType(); } public function hasOffsetValueType(\PHPStan\Type\Type $offsetType): TrinaryLogic { $offsetArrayKeyType = $offsetType->toArrayKey(); if ($offsetArrayKeyType instanceof \PHPStan\Type\ErrorType) { $allowedArrayKeys = AllowedArrayKeysTypes::getType(); $offsetArrayKeyType = \PHPStan\Type\TypeCombinator::intersect($allowedArrayKeys, $offsetType)->toArrayKey(); if ($offsetArrayKeyType instanceof \PHPStan\Type\NeverType) { return TrinaryLogic::createNo(); } } $offsetType = $offsetArrayKeyType; 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 new \PHPStan\Type\IntersectionType([$this->withTypes(\PHPStan\Type\TypeCombinator::union($this->keyType, $offsetType), \PHPStan\Type\TypeCombinator::union($this->itemType, $valueType)), new HasOffsetValueType($offsetType, $valueType), new NonEmptyArrayType()]); } return new \PHPStan\Type\IntersectionType([$this->withTypes(\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 { if ($this->itemType->isConstantArray()->yes() && $valueType->isConstantArray()->yes()) { $newItemTypes = []; foreach ($valueType->getConstantArrays() as $constArray) { $newItemType = $this->itemType; $optionalKeyTypes = []; foreach ($constArray->getKeyTypes() as $i => $keyType) { $newItemType = $newItemType->setExistingOffsetValueType($keyType, $constArray->getOffsetValueType($keyType)); if (!$constArray->isOptionalKey($i)) { continue; } $optionalKeyTypes[] = $keyType; } $newItemTypes[] = $newItemType; if ($optionalKeyTypes === []) { continue; } foreach ($optionalKeyTypes as $keyType) { $newItemType = $newItemType->unsetOffset($keyType); } $newItemTypes[] = $newItemType; } $newItemType = \PHPStan\Type\TypeCombinator::union(...$newItemTypes); if ($newItemType !== $this->itemType) { return new self($this->keyType, $newItemType); } } 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 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, ?TrinaryLogic $strict = null): \PHPStan\Type\Type { $strict ??= TrinaryLogic::createMaybe(); if ($strict->yes() && $this->getIterableValueType()->isSuperTypeOf($needleType)->no()) { return new ConstantBooleanType(\false); } 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 new \PHPStan\Type\IntersectionType([$this->withTypes(\PHPStan\Type\IntegerRangeType::createAllGreaterThanOrEqualTo(0), $this->itemType), new AccessoryArrayListType()]); } public function sliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys): \PHPStan\Type\Type { if ((new ConstantIntegerType(0))->isSuperTypeOf($lengthType)->yes()) { return new ConstantArrayType([], []); } if ($preserveKeys->no() && $this->keyType->isInteger()->yes()) { return new \PHPStan\Type\IntersectionType([new self(\PHPStan\Type\IntegerRangeType::createAllGreaterThanOrEqualTo(0), $this->itemType), new AccessoryArrayListType()]); } return $this; } public function spliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, \PHPStan\Type\Type $replacementType): \PHPStan\Type\Type { $replacementArrayType = $replacementType->toArray(); $replacementArrayTypeIsIterableAtLeastOnce = $replacementArrayType->isIterableAtLeastOnce(); if ((new ConstantIntegerType(0))->isSuperTypeOf($offsetType)->yes() && $lengthType->isNull()->yes() && $replacementArrayTypeIsIterableAtLeastOnce->no()) { return new ConstantArrayType([], []); } $existingArrayKeyType = $this->getIterableKeyType(); $keyType = \PHPStan\Type\TypeTraverser::map($existingArrayKeyType, static function (\PHPStan\Type\Type $type, callable $traverse): \PHPStan\Type\Type { if ($type instanceof \PHPStan\Type\UnionType) { return $traverse($type); } if ($type->isInteger()->yes()) { return \PHPStan\Type\IntegerRangeType::createAllGreaterThanOrEqualTo(0); } return $type; }); $arrayType = new self(\PHPStan\Type\TypeCombinator::union($keyType, $replacementArrayType->getKeysArray()->getIterableKeyType()), \PHPStan\Type\TypeCombinator::union($this->getIterableValueType(), $replacementArrayType->getIterableValueType())); $accessories = []; if ($replacementArrayTypeIsIterableAtLeastOnce->yes()) { $accessories[] = new NonEmptyArrayType(); } if ($existingArrayKeyType->isInteger()->yes()) { $accessories[] = new AccessoryArrayListType(); } if (count($accessories) > 0) { $accessories[] = $arrayType; return new \PHPStan\Type\IntersectionType($accessories); } return $arrayType; } public function makeListMaybe(): \PHPStan\Type\Type { // `ArrayType` doesn't carry list-ness on its own — that's an // `AccessoryArrayListType` in an enclosing `IntersectionType`. return $this; } public function mapValueType(callable $cb): \PHPStan\Type\Type { return new \PHPStan\Type\ArrayType($this->keyType, $cb($this->getItemType())); } public function mapKeyType(callable $cb): \PHPStan\Type\Type { return new \PHPStan\Type\ArrayType($cb($this->keyType), $this->getItemType()); } public function makeAllArrayKeysOptional(): \PHPStan\Type\Type { // `ArrayType` already models arbitrary key subsets. return $this; } public function changeKeyCaseArray(?int $case): \PHPStan\Type\Type { $newKeyType = \PHPStan\Type\TypeTraverser::map($this->keyType, static function (\PHPStan\Type\Type $type, callable $traverse) use ($case): \PHPStan\Type\Type { if ($type instanceof \PHPStan\Type\UnionType) { return $traverse($type); } $constantStrings = $type->getConstantStrings(); if (count($constantStrings) > 0) { return \PHPStan\Type\TypeCombinator::union(...array_map(static fn(ConstantStringType $type): \PHPStan\Type\Type => self::foldConstantStringKeyCase($type, $case), $constantStrings)); } if ($type->isString()->yes()) { $types = [new \PHPStan\Type\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(); } if (count($types) === 1) { return $types[0]; } return new \PHPStan\Type\IntersectionType($types); } return $type; }); return new \PHPStan\Type\ArrayType($newKeyType, $this->getItemType()); } public function filterArrayRemovingFalsey(): \PHPStan\Type\Type { $falseyTypes = \PHPStan\Type\StaticTypeFactory::falsey(); $valueType = \PHPStan\Type\TypeCombinator::remove($this->getItemType(), $falseyTypes); if ($valueType instanceof \PHPStan\Type\NeverType) { return new ConstantArrayType([], []); } return new \PHPStan\Type\ArrayType($this->keyType, $valueType); } private static function foldConstantStringKeyCase(ConstantStringType $type, ?int $case): \PHPStan\Type\Type { if ($case === CASE_LOWER) { return new ConstantStringType(strtolower($type->getValue())); } if ($case === CASE_UPPER) { return new ConstantStringType(strtoupper($type->getValue())); } return \PHPStan\Type\TypeCombinator::union(new ConstantStringType(strtolower($type->getValue())), new ConstantStringType(strtoupper($type->getValue()))); } 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 toInteger(): \PHPStan\Type\Type { return new \PHPStan\Type\UnionType([new ConstantIntegerType(0), new ConstantIntegerType(1)]); } public function toFloat(): \PHPStan\Type\Type { return new \PHPStan\Type\UnionType([new ConstantFloatType(0.0), new ConstantFloatType(1.0)]); } 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 $this->withTypes($keyType, $itemType); } return $this; } public function toPhpDocNode(): TypeNode { $isMixedKeyType = $this->keyType instanceof \PHPStan\Type\MixedType && $this->keyType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed' && !$this->keyType->isExplicitMixed(); $isMixedItemType = $this->itemType instanceof \PHPStan\Type\MixedType && $this->itemType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed' && !$this->itemType->isExplicitMixed(); 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 $this->withTypes($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->isSuperTypeOf(new ConstantArrayType([], []))->yes()) { return \PHPStan\Type\TypeCombinator::intersect($this, new NonEmptyArrayType()); } if ($typeToRemove instanceof NonEmptyArrayType) { return new ConstantArrayType([], []); } return null; } public function getFiniteTypes(): array { return []; } public function hasTemplateOrLateResolvableType(): bool { return $this->keyType->hasTemplateOrLateResolvableType() || $this->itemType->hasTemplateOrLateResolvableType(); } } $types */ public function __construct(array $types, bool $normalized = \false) { parent::__construct($types, $normalized); } public function filterTypes(callable $filterCb): \PHPStan\Type\Type { $result = parent::filterTypes($filterCb); if (!$result instanceof self && $result instanceof \PHPStan\Type\UnionType) { return \PHPStan\Type\TypeUtils::toBenevolentUnion($result); } return $result; } public function describe(\PHPStan\Type\VerbosityLevel $level): string { return '(' . parent::describe($level) . ')'; } protected function unionTypes(callable $getType): \PHPStan\Type\Type { $resultTypes = []; foreach ($this->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): \PHPStan\Type\AcceptsResult { $result = \PHPStan\Type\AcceptsResult::createNo(); foreach ($this->getTypes() as $innerType) { $result = $result->or($acceptingType->accepts($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 { $newType = parent::traverseSimultaneously($right, $cb); if ($newType === $this) { return $this; } return \PHPStan\Type\TypeUtils::toBenevolentUnion($newType); } } 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(); } } toInteger(); } public function toBitwiseNotType(): \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toAbsoluteNumber(): \PHPStan\Type\Type { return $this->toNumber()->toAbsoluteNumber(); } public function toString(): \PHPStan\Type\Type { return new \PHPStan\Type\UnionType([new ConstantStringType(''), new ConstantStringType('1')]); } public function toInteger(): \PHPStan\Type\Type { return new \PHPStan\Type\UnionType([new ConstantIntegerType(0), new ConstantIntegerType(1)]); } public function toFloat(): \PHPStan\Type\Type { return new \PHPStan\Type\UnionType([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 toCoercedArgumentType(bool $strictTypes): \PHPStan\Type\Type { if (!$strictTypes) { return \PHPStan\Type\TypeCombinator::union($this->toInteger(), $this->toFloat(), $this->toString(), $this); } return $this; } 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'); } public function toTrinaryLogic(): TrinaryLogic { if ($this->isTrue()->yes()) { return TrinaryLogic::createYes(); } if ($this->isFalse()->yes()) { return TrinaryLogic::createNo(); } return TrinaryLogic::createMaybe(); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } */ private array $templateTags; use MaybeArrayTypeTrait; use MaybeIterableTypeTrait; use MaybeObjectTypeTrait; use MaybeOffsetAccessibleTypeTrait; use TruthyBooleanTypeTrait; use UndecidedComparisonCompoundTypeTrait; use NonRemoveableTypeTrait; use NonGeneralizableTypeTrait; /** @var list */ private array $parameters; private \PHPStan\Type\Type $returnType; private bool $isCommonCallable; private TemplateTypeMap $templateTypeMap; private TemplateTypeMap $resolvedTemplateTypeMap; private TrinaryLogic $isPure; /** * @api * @param list|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; } 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): \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\CompoundType && !$type instanceof self) { return $type->isAcceptedBy($this, $strictTypes); } return $this->isSuperTypeOfInternal($type, \true, $strictTypes)->toAcceptsResult(); } public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof \PHPStan\Type\CompoundType && !$type instanceof self) { return $type->isSubTypeOf($this); } return $this->isSuperTypeOfInternal($type, \false); } private function isSuperTypeOfInternal(\PHPStan\Type\Type $type, bool $treatMixedAsAny, bool $strictTypes = \true): \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 fn($parameter) => $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, $strictTypes); 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): \PHPStan\Type\IsSuperTypeOfResult { if ($otherType instanceof \PHPStan\Type\IntersectionType || $otherType instanceof \PHPStan\Type\UnionType) { return $otherType->isSuperTypeOf($this); } return new \PHPStan\Type\IsSuperTypeOfResult($otherType->isCallable()->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), []); } public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes): \PHPStan\Type\AcceptsResult { return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(\PHPStan\Type\Type $type): bool { if (!$type instanceof self) { return \false; } if ($this->isCommonCallable) { if (!$type->isCommonCallable) { return \false; } } elseif ($type->isCommonCallable) { return \false; } if ($this->variadic !== $type->variadic) { return \false; } if ($this->isPure !== $type->isPure) { return \false; } if (!$this->returnType->equals($type->returnType)) { return \false; } if (count($this->parameters) !== count($type->parameters)) { return \false; } foreach ($this->parameters as $i => $parameter) { $otherParameter = $type->parameters[$i]; if ($parameter->isOptional() !== $otherParameter->isOptional()) { return \false; } if (!$parameter->passedByReference()->equals($otherParameter->passedByReference())) { return \false; } if ($parameter->isVariadic() !== $otherParameter->isVariadic()) { return \false; } if (!$parameter->getType()->equals($otherParameter->getType())) { return \false; } if ($parameter->getDefaultValue() !== null) { if ($otherParameter->getDefaultValue() === null) { return \false; } return $parameter->getDefaultValue()->equals($otherParameter->getDefaultValue()); } elseif ($otherParameter->getDefaultValue() !== null) { return \false; } } foreach ([[$this->templateTypeMap, $type->templateTypeMap], [$this->resolvedTemplateTypeMap, $type->resolvedTemplateTypeMap]] as [$templateTypeMap, $otherTemplateTypeMap]) { if ($templateTypeMap->count() !== $otherTemplateTypeMap->count()) { return \false; } foreach ($templateTypeMap->getTypes() as $typeName => $templateType) { $otherTemplateType = $otherTemplateTypeMap->getType($typeName); if ($otherTemplateType === null) { return \false; } if (!$templateType->equals($otherTemplateType)) { return \false; } } } foreach ($this->templateTags as $tagName => $tag) { if (!array_key_exists($tagName, $type->templateTags)) { return \false; } $otherTag = $type->templateTags[$tagName]; if ($tag->getName() !== $otherTag->getName()) { return \false; } if (!$tag->getBound()->equals($otherTag->getBound())) { return \false; } if (!$tag->getVariance()->equals($otherTag->getVariance())) { return \false; } if ($tag->getDefault() !== null) { if ($otherTag->getDefault() === null) { return \false; } return $tag->getDefault()->equals($otherTag->getDefault()); } elseif ($otherTag->getDefault() !== null) { return \false; } } return \true; } public function describe(\PHPStan\Type\VerbosityLevel $level): string { return $level->handle(static fn(): string => 'callable', function (): string { $printer = new Printer(); $selfWithoutParameterNames = new self(array_map(static fn(ParameterReflection $p): ParameterReflection => 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(): TrinaryLogic { return TrinaryLogic::createYes(); } public function mustUseReturnValue(): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getAsserts(): Assertions { return Assertions::createEmpty(); } public function toNumber(): \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toBitwiseNotType(): \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 toCoercedArgumentType(bool $strictTypes): \PHPStan\Type\Type { return \PHPStan\Type\TypeCombinator::union($this, new \PHPStan\Type\IntersectionType([new \PHPStan\Type\StringType(), new AccessoryNonEmptyStringType()]), new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(\true), new \PHPStan\Type\MixedType(\true)), new \PHPStan\Type\ObjectType(Closure::class)); } public function getTemplateTypeMap(): TemplateTypeMap { return $this->templateTypeMap; } public function getResolvedTemplateTypeMap(): TemplateTypeMap { return $this->resolvedTemplateTypeMap; } public function getCallSiteVarianceMap(): TemplateTypeVarianceMap { return TemplateTypeVarianceMap::createEmpty(); } /** * @return list */ 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 fn($parameter) => $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 isClassString(): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isUppercaseString(): 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 getEnumCaseObject(): ?EnumCaseObjectType { return null; } 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); } public function hasTemplateOrLateResolvableType(): bool { foreach ($this->parameters as $parameter) { if ($parameter->getType()->hasTemplateOrLateResolvableType()) { return \true; } if (!$parameter instanceof ExtendedParameterReflection) { continue; } if ($parameter->getOutType() !== null && $parameter->getOutType()->hasTemplateOrLateResolvableType()) { return \true; } if ($parameter->getClosureThisType() !== null && $parameter->getClosureThisType()->hasTemplateOrLateResolvableType()) { return \true; } } return $this->getReturnType()->hasTemplateOrLateResolvableType(); } } 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()->accepts($ourParameterType, $strictTypes); $isSuperType = new \PHPStan\Type\IsSuperTypeOfResult($isSuperType->result, $isSuperType->reasons); } else { $isSuperType = $theirParameter->getType()->isSuperTypeOf($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()->accepts($theirReturnType, \true); $isReturnTypeSuperType = new \PHPStan\Type\IsSuperTypeOfResult($isReturnTypeSuperType->result, $isReturnTypeSuperType->reasons); } else { $isReturnTypeSuperType = $ours->getReturnType()->isSuperTypeOf($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); } } type = $type; $this->constantName = $constantName; } 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->constantName === $type->constantName && $this->type->equals($type->type); } public function describe(\PHPStan\Type\VerbosityLevel $level): string { return $this->resolve()->describe($level); } public function isResolvable(): bool { return !\PHPStan\Type\TypeUtils::containsTemplateType($this->type); } protected function getResult(): \PHPStan\Type\Type { if ($this->type->hasConstant($this->constantName)->yes()) { return $this->type->getConstant($this->constantName)->getValueType(); } return new \PHPStan\Type\ErrorType(); } /** * @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, $this->constantName); } 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, $this->constantName); } public function toPhpDocNode(): TypeNode { return new ConstTypeNode(new ConstFetchNode('static', $this->constantName)); } } type = $type; $this->uncertainty = $uncertainty; } } isAcceptedBy($this, $strictTypes); } return new \PHPStan\Type\AcceptsResult($type->isClassString(), []); } public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOf($this); } return new \PHPStan\Type\IsSuperTypeOfResult($type->isClassString(), []); } 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 isClassString(): 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'); } } */ private array $templateTags; /** * @var SimpleThrowPoint[] */ private array $throwPoints; /** * @var InvalidateExprNode[] */ private array $invalidateExpressions; /** * @var string[] */ private array $usedVariables; use NonArrayTypeTrait; use NonIterableTypeTrait; use UndecidedComparisonTypeTrait; use NonOffsetAccessibleTypeTrait; use NonRemoveableTypeTrait; use NonGeneralizableTypeTrait; /** @var list */ private array $parameters; private \PHPStan\Type\Type $returnType; private bool $isCommonCallable; private \PHPStan\Type\ObjectType $objectType; private TemplateTypeMap $templateTypeMap; private TemplateTypeMap $resolvedTemplateTypeMap; private TemplateTypeVarianceMap $callSiteVarianceMap; /** @var SimpleImpurePoint[] */ private array $impurePoints; private TrinaryLogic $acceptsNamedArguments; private TrinaryLogic $mustUseReturnValue; private Assertions $assertions; /** * @api * @param list|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 = [], ?TrinaryLogic $acceptsNamedArguments = null, ?TrinaryLogic $mustUseReturnValue = null, ?Assertions $assertions = null) { $this->variadic = $variadic; $this->templateTags = $templateTags; $this->throwPoints = $throwPoints; $this->invalidateExpressions = $invalidateExpressions; $this->usedVariables = $usedVariables; if ($acceptsNamedArguments === null) { $acceptsNamedArguments = TrinaryLogic::createYes(); } $this->acceptsNamedArguments = $acceptsNamedArguments; if ($mustUseReturnValue === null) { $mustUseReturnValue = TrinaryLogic::createMaybe(); } $this->mustUseReturnValue = $mustUseReturnValue; $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)]; $this->assertions = $assertions ?? Assertions::createEmpty(); } public function getAsserts(): Assertions { return $this->assertions; } /** * @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); } 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): \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } if (!$type instanceof \PHPStan\Type\ClosureType) { return $this->objectType->accepts($type, $strictTypes); } return $this->isSuperTypeOfInternal($type, \true, $strictTypes)->toAcceptsResult(); } public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOf($this); } return $this->isSuperTypeOfInternal($type, \false); } private function isSuperTypeOfInternal(\PHPStan\Type\Type $type, bool $treatMixedAsAny, bool $strictTypes = \true): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { $parameterTypes = array_map(static fn($parameter) => $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, $strictTypes); } if ($type->getObjectClassNames() === [Closure::class]) { return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } return $this->objectType->isSuperTypeOf($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()) && $this->isPure()->equals($type->isPure()); } public function describe(\PHPStan\Type\VerbosityLevel $level): string { return $level->handle(static fn(): string => 'Closure', function (): string { if ($this->isCommonCallable) { return $this->isPure()->yes() ? 'pure-Closure' : 'Closure'; } $printer = new Printer(); $selfWithoutParameterNames = new self(array_map(static fn(ParameterReflection $p): ParameterReflection => 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, $this->acceptsNamedArguments, $this->mustUseReturnValue); return $printer->print($selfWithoutParameterNames->toPhpDocNode()); }); } public function isOffsetAccessLegal(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isObject(): TrinaryLogic { return $this->objectType->isObject(); } public function getClassStringType(): \PHPStan\Type\Type { return $this->objectType->getClassStringType(); } 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): ExtendedPropertyReflection { return $this->objectType->getProperty($propertyName, $scope); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { return $this->objectType->getUnresolvedPropertyPrototype($propertyName, $scope); } public function hasInstanceProperty(string $propertyName): TrinaryLogic { return $this->objectType->hasInstanceProperty($propertyName); } public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->objectType->getInstanceProperty($propertyName, $scope); } public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { return $this->objectType->getUnresolvedInstancePropertyPrototype($propertyName, $scope); } public function hasStaticProperty(string $propertyName): TrinaryLogic { return $this->objectType->hasStaticProperty($propertyName); } public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->objectType->getStaticProperty($propertyName, $scope); } public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { return $this->objectType->getUnresolvedStaticPropertyPrototype($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): ClassConstantReflection { 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 getEnumCaseObject(): ?EnumCaseObjectType { return null; } 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(): TrinaryLogic { return $this->acceptsNamedArguments; } public function mustUseReturnValue(): TrinaryLogic { return $this->mustUseReturnValue; } 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 toBitwiseNotType(): \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toGetClassResultType(): \PHPStan\Type\Type { return $this->getClassStringType(); } public function toClassConstantType(ReflectionProvider $reflectionProvider): \PHPStan\Type\Type { return $this->objectType->toClassConstantType($reflectionProvider); } public function toObjectTypeForInstanceofCheck(): \PHPStan\Type\ClassNameToObjectTypeResult { return new \PHPStan\Type\ClassNameToObjectTypeResult($this, \true); } public function toObjectTypeForIsACheck(\PHPStan\Type\Type $objectOrClassType, bool $allowString, bool $allowSameClass): \PHPStan\Type\ClassNameToObjectTypeResult { if ($allowString) { return new \PHPStan\Type\ClassNameToObjectTypeResult(new \PHPStan\Type\UnionType([new \PHPStan\Type\ObjectWithoutClassType(), new \PHPStan\Type\ClassStringType()]), \false); } return new \PHPStan\Type\ClassNameToObjectTypeResult(new \PHPStan\Type\ObjectWithoutClassType(), \false); } 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 toCoercedArgumentType(bool $strictTypes): \PHPStan\Type\Type { return \PHPStan\Type\TypeCombinator::union($this, new \PHPStan\Type\CallableType()); } public function getTemplateTypeMap(): TemplateTypeMap { return $this->templateTypeMap; } public function getResolvedTemplateTypeMap(): TemplateTypeMap { return $this->resolvedTemplateTypeMap; } public function getCallSiteVarianceMap(): TemplateTypeVarianceMap { return $this->callSiteVarianceMap; } /** * @return list */ 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 fn($parameter) => $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, $this->mustUseReturnValue, $this->assertions); } 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, $this->mustUseReturnValue, $this->assertions); } 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 isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString(): 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); } public function hasTemplateOrLateResolvableType(): bool { foreach ($this->parameters as $parameter) { if ($parameter->getType()->hasTemplateOrLateResolvableType()) { return \true; } if (!$parameter instanceof ExtendedParameterReflection) { continue; } if ($parameter->getOutType() !== null && $parameter->getOutType()->hasTemplateOrLateResolvableType()) { return \true; } if ($parameter->getClosureThisType() !== null && $parameter->getClosureThisType()->hasTemplateOrLateResolvableType()) { return \true; } } return $this->getReturnType()->hasTemplateOrLateResolvableType(); } } initializerExprTypeResolver = $initializerExprTypeResolver; $this->reflectionSourceStubber = $reflectionSourceStubber; $this->reflector = $reflector; $this->reflectionProviderProvider = $reflectionProviderProvider; $this->parser = $parser; } /** * @param Closure(mixed): mixed $closure */ public function fromClosureObject(Closure $closure): \PHPStan\Type\ClosureType { $closureReflectionFunction = new ReflectionFunction($closure); $stubData = $this->reflectionSourceStubber->generateFunctionStubFromReflection($closureReflectionFunction); 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(fn(BetterReflectionParameter $parameter) => new class($parameter, $this->initializerExprTypeResolver) implements ParameterReflection { private BetterReflectionParameter $reflection; private InitializerExprTypeResolver $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()); $selfClass = null; if (method_exists($closureReflectionFunction, 'getClosureCalledClass') && $closureReflectionFunction->getClosureCalledClass() !== null) { $potentialSelfClassName = $closureReflectionFunction->getClosureCalledClass()->getName(); $reflectionProvider = $this->reflectionProviderProvider->getReflectionProvider(); if ($reflectionProvider->hasClass($potentialSelfClassName)) { $selfClass = $reflectionProvider->getClass($potentialSelfClassName); } } elseif ($closureReflectionFunction->getClosureScopeClass() !== null) { $potentialSelfClassName = $closureReflectionFunction->getClosureScopeClass()->getName(); $reflectionProvider = $this->reflectionProviderProvider->getReflectionProvider(); if ($reflectionProvider->hasClass($potentialSelfClassName)) { $selfClass = $reflectionProvider->getClass($potentialSelfClassName); } } return new \PHPStan\Type\ClosureType($parameters, \PHPStan\Type\TypehintHelper::decideTypeFromReflection(ReflectionType::fromTypeOrNull($betterReflectionFunction->getReturnType()), \null, $selfClass), $betterReflectionFunction->isVariadic()); } } isAcceptedBy($this, …)` or `$type->isSubTypeOf($this)`. * 4. The compound type then decomposes itself (e.g., iterates union members) * and calls back to the simple type for each component. * * This avoids the simple type having to understand union/intersection/mixed/never * semantics. For example, `StringType::accepts()` doesn't need to know how to * check a `UnionType` — it just delegates to `UnionType::isAcceptedBy()`, * which iterates its members and asks `StringType::accepts()` for each one. * * Unlike `instanceof SomeSpecificType` checks (which are discouraged in CLAUDE.md), * `instanceof CompoundType` is the correct and intended pattern throughout the * type system. It is part of the double-dispatch protocol, not a type query. * * Implementations include: * - `UnionType` — `isSubTypeOf()` requires ALL members to be subtypes, `isAcceptedBy()` requires ALL to be accepted * - `IntersectionType` — `isSubTypeOf()` requires at least ONE member to be a subtype (via `maxMin`) * - `MixedType`, `NeverType` — terminal cases (mixed accepts everything, never is subtype of everything) * - All `AccessoryType` implementations — refinement types that live inside intersections * - `IntegerRangeType`, `CallableType`, `IterableType` — types with internal structure * - `ConditionalType`, `KeyOfType`, `ValueOfType`, etc. — late-resolvable types * * @api * @api-do-not-implement */ interface CompoundType extends \PHPStan\Type\Type { /** * Answers "is this compound type accepted by $acceptingType?" from the compound type's perspective. * * Called by simple types when they encounter a CompoundType argument in their `accepts()` method. * The compound type decomposes itself and calls `$acceptingType->accepts()` for each component. * * For example, `UnionType(string|int)::isAcceptedBy(StringType)` asks StringType to accept * `string` and `int` separately, then combines results with `extremeIdentity` (all must pass). */ public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes): \PHPStan\Type\AcceptsResult; /** * Answers "is this compound type a subtype of $otherType?" from the compound type's perspective. * * Called by simple types when they encounter a CompoundType argument in their `isSuperTypeOf()` method. * The compound type decomposes itself and calls `$otherType->isSuperTypeOf()` for each component. * * For example, `UnionType(string|int)::isSubTypeOf(MixedType)` asks MixedType whether it is * a supertype of `string` and `int` separately, then combines with `extremeIdentity` (all must pass). */ public function isSubTypeOf(\PHPStan\Type\Type $otherType): \PHPStan\Type\IsSuperTypeOfResult; /** * Compares this compound type against $otherType using greater-than semantics. * * Used for comparison operators (`>`). Each compound type decomposes the comparison * across its members (e.g., IntegerRangeType checks whether all values in the range * are greater than the other type). */ public function isGreaterThan(\PHPStan\Type\Type $otherType, PhpVersion $phpVersion): TrinaryLogic; /** * Compares this compound type against $otherType using greater-than-or-equal semantics. * * Used for comparison operators (`>=`). Same decomposition strategy as `isGreaterThan()`. */ public function isGreaterThanOrEqual(\PHPStan\Type\Type $otherType, PhpVersion $phpVersion): TrinaryLogic; } 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): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return $this->if->isSuperTypeOf($type->if)->and($this->else->isSuperTypeOf($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 { if (!\PHPStan\Type\TypeUtils::containsTemplateType($this->subject) && !\PHPStan\Type\TypeUtils::containsTemplateType($this->target)) { return \true; } $isSuperType = $this->target->isSuperTypeOf($this->subject); return $isSuperType->yes() || $isSuperType->no(); } 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); } private function getNormalizedIf(): \PHPStan\Type\Type { return $this->normalizedIf ??= \PHPStan\Type\TypeTraverser::map($this->if, fn(\PHPStan\Type\Type $type, callable $traverse) => $type === $this->subject ? !$this->negated ? $this->getSubjectWithTargetIntersectedType() : $this->getSubjectWithTargetRemovedType() : $traverse($type)); } private function getNormalizedElse(): \PHPStan\Type\Type { return $this->normalizedElse ??= \PHPStan\Type\TypeTraverser::map($this->else, fn(\PHPStan\Type\Type $type, callable $traverse) => $type === $this->subject ? !$this->negated ? $this->getSubjectWithTargetRemovedType() : $this->getSubjectWithTargetIntersectedType() : $traverse($type)); } private function getSubjectWithTargetIntersectedType(): \PHPStan\Type\Type { return $this->subjectWithTargetIntersectedType ??= \PHPStan\Type\TypeCombinator::intersect($this->subject, $this->target); } private function getSubjectWithTargetRemovedType(): \PHPStan\Type\Type { return $this->subjectWithTargetRemovedType ??= \PHPStan\Type\TypeCombinator::remove($this->subject, $this->target); } } 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): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return $this->if->isSuperTypeOf($type->if)->and($this->else->isSuperTypeOf($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); } } */ private array $keyTypes; /** * @var array */ private array $valueTypes; /** * @var list */ private array $nextAutoIndexes; /** * @var int[] */ private array $optionalKeys; use ArrayTypeTrait { chunkArray as traitChunkArray; } use NonObjectTypeTrait; use UndecidedComparisonTypeTrait; private const DESCRIBE_LIMIT = 8; private const CHUNK_FINITE_TYPES_LIMIT = 5; private TrinaryLogic $isList; /** @var self[]|null */ private ?array $allArrays = null; private ?Type $iterableKeyType = null; private ?Type $iterableValueType = null; /** @var array|null */ private ?array $keyIndexMap = null; /** * @api * @param list $keyTypes * @param array $valueTypes * @param list $nextAutoIndexes * @param int[] $optionalKeys */ public function __construct(array $keyTypes, array $valueTypes, array $nextAutoIndexes = [0], array $optionalKeys = [], ?TrinaryLogic $isList = null) { $this->keyTypes = $keyTypes; $this->valueTypes = $valueTypes; $this->nextAutoIndexes = $nextAutoIndexes; $this->optionalKeys = $optionalKeys; assert(count($keyTypes) === count($valueTypes)); $keyTypesCount = count($this->keyTypes); if ($keyTypesCount === 0) { $isList = TrinaryLogic::createYes(); } if ($isList === null) { $isList = TrinaryLogic::createNo(); } $this->isList = $isList; } /** * @param list $keyTypes * @param array $valueTypes * @param list $nextAutoIndexes * @param int[] $optionalKeys */ protected function recreate(array $keyTypes, array $valueTypes, array $nextAutoIndexes = [0], array $optionalKeys = [], ?TrinaryLogic $isList = null): self { return new self($keyTypes, $valueTypes, $nextAutoIndexes, $optionalKeys, $isList); } public function getConstantArrays(): array { return [$this]; } public function getReferencedClasses(): array { $referencedClasses = []; foreach ($this->getKeyTypes() as $keyType) { foreach ($keyType->getReferencedClasses() as $referencedClass) { $referencedClasses[] = $referencedClass; } } foreach ($this->getValueTypes() as $valueType) { foreach ($valueType->getReferencedClasses() as $referencedClass) { $referencedClasses[] = $referencedClass; } } return $referencedClasses; } public function getIterableKeyType(): Type { if ($this->iterableKeyType !== null) { return $this->iterableKeyType; } $keyTypesCount = count($this->keyTypes); if ($keyTypesCount === 0) { $keyType = new NeverType(\true); } elseif ($keyTypesCount === 1) { $keyType = $this->keyTypes[0]; } else { $keyType = new UnionType($this->keyTypes); } return $this->iterableKeyType = $keyType; } public function getIterableValueType(): Type { if ($this->iterableValueType !== null) { return $this->iterableValueType; } return $this->iterableValueType = count($this->valueTypes) > 0 ? TypeCombinator::union(...$this->valueTypes) : new NeverType(\true); } public function getKeyType(): Type { return $this->getIterableKeyType(); } public function getItemType(): Type { return $this->getIterableValueType(); } public function isConstantValue(): TrinaryLogic { return TrinaryLogic::createYes(); } /** * @return list */ public function getNextAutoIndexes(): array { return $this->nextAutoIndexes; } /** * @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 = [[], array_slice($this->optionalKeys, 0, 1, \true), array_slice($this->optionalKeys, -1, 1, \true), $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(); $builder->disableArrayDegradation(); foreach ($keys as $i) { $builder->setOffsetValueType($this->keyTypes[$i], $this->valueTypes[$i]); } $array = $builder->getArray(); if (!$array instanceof self) { 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 list */ public function getKeyTypes(): array { return $this->keyTypes; } /** * @return array */ public function getValueTypes(): array { return $this->valueTypes; } public function isOptionalKey(int $i): bool { return in_array($i, $this->optionalKeys, \true); } public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType && !$type instanceof IntersectionType) { return $type->isAcceptedBy($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->accepts($otherValueType, $strictTypes)->decorateReasons(static fn(string $reason) => 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): 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]->isSuperTypeOf($type->getOffsetValueType($keyType)); if ($isValueSuperType->no()) { return $isValueSuperType->decorateReasons(static fn(string $reason) => 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()->isSuperTypeOf($type->getKeyType()); if ($isKeySuperType->no()) { return $isKeySuperType; } return $result->and($isKeySuperType, $this->getItemType()->isSuperTypeOf($type->getItemType())); } if ($type instanceof CompoundType) { return $type->isSubTypeOf($this); } return IsSuperTypeOfResult::createNo(); } public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { if ($type->isInteger()->yes()) { return new \PHPStan\Type\Constant\ConstantBooleanType(\false); } if ($this->isIterableAtLeastOnce()->no()) { if ($type->isIterableAtLeastOnce()->yes()) { return new \PHPStan\Type\Constant\ConstantBooleanType(\false); } $constantScalarValues = $type->getConstantScalarValues(); if (count($constantScalarValues) > 0) { $results = []; foreach ($constantScalarValues as $constantScalarValue) { // @phpstan-ignore equal.invalid, equal.notAllowed $results[] = TrinaryLogic::createFromBoolean($constantScalarValue == []); // phpcs:ignore } return TrinaryLogic::extremeIdentity(...$results)->toBooleanType(); } } 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 { $result = RecursionGuard::run($this, function (): TrinaryLogic { $hasNonExistentMethod = \false; $typeAndMethods = $this->doFindTypeAndMethodNames($hasNonExistentMethod); if ($typeAndMethods === []) { return TrinaryLogic::createNo(); } $results = array_map(static fn(\PHPStan\Type\Constant\ConstantArrayTypeAndMethod $typeAndMethod): TrinaryLogic => $typeAndMethod->getCertainty(), $typeAndMethods); $result = TrinaryLogic::createYes()->and(...$results); if ($hasNonExistentMethod) { $result = $result->and(TrinaryLogic::createMaybe()); } return $result; }); if ($result instanceof ErrorType) { return TrinaryLogic::createNo(); } return $result; } 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 ConstantArrayTypeAndMethod[] */ public function findTypeAndMethodNames(): array { return $this->doFindTypeAndMethodNames(); } /** @return ConstantArrayTypeAndMethod[] */ private function doFindTypeAndMethodNames(bool &$hasNonExistentMethod = \false): 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 []; } $callableArray = [$classOrObject, $method]; [$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 $methodName) { $has = $type->hasMethod($methodName->getValue()); if ($has->no()) { $hasNonExistentMethod = \true; continue; } if ($has->yes() && !$phpVersion->supportsCallableInstanceMethods()) { $isString = $classOrObject->isString(); if ($isString->yes()) { $methodReflection = $type->getMethod($methodName->getValue(), new OutOfClassScope()); if (!$methodReflection->isStatic()) { continue; } } elseif ($isString->maybe()) { $has = $has->and(TrinaryLogic::createMaybe()); } } if ($this->isOptionalKey(0) || $this->isOptionalKey(1)) { $has = $has->and(TrinaryLogic::createMaybe()); } $typeAndMethods[] = \PHPStan\Type\Constant\ConstantArrayTypeAndMethod::createConcrete($type, $methodName->getValue(), $has); } return $typeAndMethods; } public function hasOffsetValueType(Type $offsetType): TrinaryLogic { $offsetArrayKeyType = $offsetType->toArrayKey(); if ($offsetArrayKeyType instanceof ErrorType) { $allowedArrayKeys = AllowedArrayKeysTypes::getType(); $offsetArrayKeyType = TypeCombinator::intersect($allowedArrayKeys, $offsetType)->toArrayKey(); if ($offsetArrayKeyType instanceof NeverType) { return TrinaryLogic::createNo(); } } 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 { if ($offsetType === null && count($this->nextAutoIndexes) === 0) { return new ErrorType(); } $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createFromConstantArray($this); $builder->setOffsetValueType($offsetType, $valueType); return $builder->getArray(); } public function setExistingOffsetValueType(Type $offsetType, Type $valueType): Type { $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createFromConstantArray($this); $builder->setOffsetValueType($offsetType, $valueType); return $builder->getArray(); } /** * Removes or marks as optional the key(s) matching the given offset type from this constant array. * * By default, the method assumes an actual `unset()` call was made, which actively modifies the * array and weakens its list certainty to "maybe". However, in some contexts, such as the else * branch of an array_key_exists() check, the key is statically known to be absent without any * modification, so list certainty should be preserved as-is. */ public function unsetOffset(Type $offsetType, bool $preserveListCertainty = \false): 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++; } $newIsList = self::isListAfterUnset($newKeyTypes, $newOptionalKeys, $this->isList, in_array($i, $this->optionalKeys, \true)); if (!$preserveListCertainty) { $newIsList = $newIsList->and(TrinaryLogic::createMaybe()); } elseif ($this->isList->yes() && $newIsList->no()) { return new NeverType(); } return $this->recreate($newKeyTypes, $newValueTypes, $this->nextAutoIndexes, $newOptionalKeys, $newIsList); } return $this; } $constantScalars = $offsetType->getConstantScalarTypes(); if (count($constantScalars) > 0) { $optionalKeys = $this->optionalKeys; $arrayHasChanged = \false; 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; } $arrayHasChanged = \true; if (in_array($i, $optionalKeys, \true)) { continue 2; } $optionalKeys[] = $i; } } if (!$arrayHasChanged) { return $this; } $newIsList = self::isListAfterUnset($this->keyTypes, $optionalKeys, $this->isList, count($optionalKeys) === count($this->optionalKeys)); if (!$preserveListCertainty) { $newIsList = $newIsList->and(TrinaryLogic::createMaybe()); } elseif ($this->isList->yes() && $newIsList->no()) { return new NeverType(); } return $this->recreate($this->keyTypes, $this->valueTypes, $this->nextAutoIndexes, $optionalKeys, $newIsList); } $optionalKeys = $this->optionalKeys; $arrayHasChanged = \false; foreach ($this->keyTypes as $i => $keyType) { if (!$offsetType->isSuperTypeOf($keyType)->yes()) { continue; } $arrayHasChanged = \true; $optionalKeys[] = $i; } $optionalKeys = array_values(array_unique($optionalKeys)); if (!$arrayHasChanged) { return $this; } $newIsList = self::isListAfterUnset($this->keyTypes, $optionalKeys, $this->isList, count($optionalKeys) === count($this->optionalKeys)); if (!$preserveListCertainty) { $newIsList = $newIsList->and(TrinaryLogic::createMaybe()); } elseif ($this->isList->yes() && $newIsList->no()) { return new NeverType(); } return $this->recreate($this->keyTypes, $this->valueTypes, $this->nextAutoIndexes, $optionalKeys, $newIsList); } /** * When we're unsetting something not on the array, it will be untouched, * So the nextAutoIndexes won't change, and the array might still be a list even with PHPStan definition. * * @param list $newKeyTypes * @param int[] $newOptionalKeys */ private static function isListAfterUnset(array $newKeyTypes, array $newOptionalKeys, TrinaryLogic $arrayIsList, bool $unsetOptionalKey): TrinaryLogic { if (!$unsetOptionalKey || $arrayIsList->no()) { return TrinaryLogic::createNo(); } $isListOnlyIfKeysAreOptional = \false; foreach ($newKeyTypes as $k2 => $newKeyType2) { if (!$newKeyType2 instanceof \PHPStan\Type\Constant\ConstantIntegerType || $newKeyType2->getValue() !== $k2) { // We found a non-optional key that implies that the array is never a list. if (!in_array($k2, $newOptionalKeys, \true)) { return TrinaryLogic::createNo(); } // The array can still be a list if all the following keys are also optional. $isListOnlyIfKeysAreOptional = \true; continue; } if ($isListOnlyIfKeysAreOptional && !in_array($k2, $newOptionalKeys, \true)) { return TrinaryLogic::createNo(); } } return $arrayIsList; } 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 $this->traitChunkArray($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 $this->traitChunkArray($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, ?TrinaryLogic $strict = null): Type { $strict ??= TrinaryLogic::createMaybe(); $matches = []; $hasIdenticalValue = \false; foreach ($this->valueTypes as $index => $valueType) { if ($strict->yes()) { $isNeedleSuperType = $valueType->isSuperTypeOf($needleType); if ($isNeedleSuperType->no()) { continue; } } if ($needleType instanceof ConstantScalarType && $valueType instanceof ConstantScalarType) { // @phpstan-ignore equal.notAllowed $isLooseEqual = $needleType->getValue() == $valueType->getValue(); // phpcs:ignore if (!$isLooseEqual) { continue; } if (($strict->no() || $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 { return $this->getValuesArray()->degradeToGeneralArray(); } 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() : null; if ($lengthType instanceof \PHPStan\Type\Constant\ConstantIntegerType) { $length = $lengthType->getValue(); } elseif ($lengthType->isNull()->yes()) { $length = $keyTypesCount; } else { $length = null; } if ($offset === null || $length === null) { return $this->degradeToGeneralArray()->sliceArray($offsetType, $lengthType, $preserveKeys); } if ($keyTypesCount + $offset <= 0) { // A negative offset cannot reach left outside the array twice $offset = 0; } if ($keyTypesCount + $length <= 0) { // A negative length cannot reach left outside the array twice $length = 0; } if ($length === 0 || $offset < 0 && $length < 0 && $offset - $length >= 0) { // 0 / 0, 3 / 0 or e.g. -3 / -3 or -3 / -4 and so on never extract anything return $this->recreate([], []); } if ($length < 0) { // Negative lengths prevent access to the most right n elements return $this->removeLastElements($length * -1)->sliceArray($offsetType, new NullType(), $preserveKeys); } if ($offset < 0) { /* * Transforms the problem with the negative offset in one with a positive offset using array reversion. * The reason is below 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; } $offsetType = $preserveKeys->yes() || $this->keyTypes[$i]->isInteger()->no() ? $this->keyTypes[$i] : null; $builder->setOffsetValueType($offsetType, $this->valueTypes[$i], $isOptional); } return $builder->getArray(); } public function spliceArray(Type $offsetType, Type $lengthType, Type $replacementType): Type { $keyTypesCount = count($this->keyTypes); if ($keyTypesCount === 0) { return $this; } $offset = $offsetType instanceof \PHPStan\Type\Constant\ConstantIntegerType ? $offsetType->getValue() : null; if ($lengthType instanceof \PHPStan\Type\Constant\ConstantIntegerType) { $length = $lengthType->getValue(); } elseif ($lengthType->isNull()->yes()) { $length = $keyTypesCount; } else { $length = null; } if ($offset === null || $length === null) { return $this->degradeToGeneralArray()->spliceArray($offsetType, $lengthType, $replacementType); } $allKeysInteger = $this->getIterableKeyType()->isInteger()->yes(); if ($keyTypesCount + $offset <= 0) { // A negative offset cannot reach left outside the array twice $offset = 0; } if ($keyTypesCount + $length <= 0) { // A negative length cannot reach left outside the array twice $length = 0; } $offsetWasNegative = \false; if ($offset < 0) { $offsetWasNegative = \true; $offset = $keyTypesCount + $offset; } if ($length < 0) { $length = $keyTypesCount - $offset + $length; } $extractType = $this->sliceArray($offsetType, $lengthType, TrinaryLogic::createYes()); $types = []; foreach ($replacementType->toArray()->getArrays() as $replacementArrayType) { $removeKeysCount = 0; $optionalKeysBeforeReplacement = 0; $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createEmpty(); for ($i = 0;; $i++) { $isOptional = $this->isOptionalKey($i); if (!$offsetWasNegative && $i < $offset && $isOptional) { $optionalKeysBeforeReplacement++; } if ($i === $offset + $optionalKeysBeforeReplacement) { // When the offset is reached we have to a) put the replacement array in and b) remove $length elements $removeKeysCount = $length; if ($replacementArrayType instanceof self) { $valuesArray = $replacementArrayType->getValuesArray(); for ($j = 0, $jMax = count($valuesArray->keyTypes); $j < $jMax; $j++) { $builder->setOffsetValueType(null, $valuesArray->valueTypes[$j], $valuesArray->isOptionalKey($j)); } } else { $builder->degradeToGeneralArray(); $builder->setOffsetValueType($replacementArrayType->getValuesArray()->getIterableKeyType(), $replacementArrayType->getIterableValueType(), \true); } } if (!isset($this->keyTypes[$i])) { break; } if ($removeKeysCount > 0) { $extractTypeHasOffsetValueType = $extractType->hasOffsetValueType($this->keyTypes[$i]); if (!$isOptional && $extractTypeHasOffsetValueType->yes() || $isOptional && $extractTypeHasOffsetValueType->maybe()) { $removeKeysCount--; continue; } } if (!$isOptional && $extractType->hasOffsetValueType($this->keyTypes[$i])->maybe()) { $isOptional = \true; } $builder->setOffsetValueType($this->keyTypes[$i]->isInteger()->no() ? $this->keyTypes[$i] : null, $this->valueTypes[$i], $isOptional); } $builtType = $builder->getArray(); if ($allKeysInteger && !$builtType->isList()->yes()) { $builtType = TypeCombinator::intersect($builtType, new AccessoryArrayListType()); } $types[] = $builtType; } return TypeCombinator::union(...$types); } 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; } /** @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; $nextAutoindexes = $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); $nextAutoindexes = $removedKeyType instanceof \PHPStan\Type\Constant\ConstantIntegerType ? [$removedKeyType->getValue()] : $this->nextAutoIndexes; continue; } if ($isOptional || $optionalKeysRemoved <= 0) { continue; } $optionalKeys[] = $i; $optionalKeysRemoved--; } return $this->recreate($keyTypes, $valueTypes, $nextAutoindexes, array_values($optionalKeys), $this->isList); } /** @param positive-int $length */ private function removeFirstElements(int $length, bool $reindex = \true): Type { $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); } return $builder->getArray(); } 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 fn(Type $type) => $type->generalize($precision)); } $arrayType = new ArrayType($this->getIterableKeyType()->generalize($precision), $this->getIterableValueType()->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 = TypeCombinator::intersect($arrayType, new AccessoryArrayListType()); } if (count($accessoryTypes) > 0) { return TypeCombinator::intersect($arrayType, ...$accessoryTypes); } return $arrayType; } public function generalizeValues(): self { $valueTypes = []; foreach ($this->valueTypes as $valueType) { $valueTypes[] = $valueType->generalize(GeneralizePrecision::lessSpecific()); } return $this->recreate($this->keyTypes, $valueTypes, $this->nextAutoIndexes, $this->optionalKeys, $this->isList); } private function degradeToGeneralArray(): Type { $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createFromConstantArray($this); $builder->degradeToGeneralArray(); return $builder->getArray(); } public function getKeysArrayFiltered(Type $filterValueType, TrinaryLogic $strict): Type { $keysArray = $this->getKeysOrValuesArray($this->keyTypes); return new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $keysArray->getIterableValueType()), new AccessoryArrayListType()]); } public function getKeysArray(): self { return $this->getKeysOrValuesArray($this->keyTypes); } public function getValuesArray(): self { return $this->getKeysOrValuesArray($this->valueTypes); } /** * @param array $types */ private function getKeysOrValuesArray(array $types): self { $count = count($types); $autoIndexes = range($count - count($this->optionalKeys), $count); if ($this->isList->yes()) { // Optimized version for lists: Assume that if a later key exists, then earlier keys also exist. $keyTypes = array_map(static fn(int $i): \PHPStan\Type\Constant\ConstantIntegerType => new \PHPStan\Type\Constant\ConstantIntegerType($i), array_keys($types)); return $this->recreate($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 $this->recreate($keyTypes, $valueTypes, $autoIndexes, $optionalKeys, TrinaryLogic::createYes()); } public function describe(VerbosityLevel $level): string { $arrayName = $this->shouldBeDescribedAsAList() ? 'list' : 'array'; $describeValue = function (bool $truncate) use ($level, $arrayName): 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); } elseif (!self::isValidIdentifier($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('%s{%s%s}', $arrayName, implode(', ', $exportValuesOnly ? $values : $items), $append); }; return $level->handle(fn(): string => $this->isIterableAtLeastOnce()->no() ? $arrayName : sprintf('%s<%s, %s>', $arrayName, $this->getIterableKeyType()->describe($level), $this->getIterableValueType()->describe($level)), static fn(): string => $describeValue(\true), static fn(): string => $describeValue(\false)); } private function shouldBeDescribedAsAList(): bool { if (!$this->isList->yes()) { return \false; } if (count($this->optionalKeys) === 0) { return \false; } if (count($this->optionalKeys) > 1) { return \true; } return $this->optionalKeys[0] !== count($this->keyTypes) - 1; } 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; } if ($receivedType->isArray()->yes()) { $keyTypeMap = $this->getIterableKeyType()->inferTemplateTypes($receivedType->getIterableKeyType()); $itemTypeMap = $this->getIterableValueType()->inferTemplateTypes($receivedType->getIterableValueType()); return $keyTypeMap->union($itemTypeMap); } return TemplateTypeMap::createEmpty(); } 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 tryRemove(Type $typeToRemove): ?Type { if ($typeToRemove->isConstantArray()->yes() && $typeToRemove->isIterableAtLeastOnce()->no()) { return TypeCombinator::intersect($this, new NonEmptyArrayType()); } if ($typeToRemove instanceof NonEmptyArrayType) { return new \PHPStan\Type\Constant\ConstantArrayType([], []); } if ($typeToRemove instanceof HasOffsetType) { return $this->unsetOffset($typeToRemove->getOffsetType(), \true); } if ($typeToRemove instanceof HasOffsetValueType) { return $this->unsetOffset($typeToRemove->getOffsetType(), \true); } return null; } 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 $this->recreate($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 $this->recreate($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; $keyIndexMap = $this->getKeyIndexMap(); $otherKeyValues = []; foreach ($otherArray->keyTypes as $j => $keyType) { $keyValue = $keyType->getValue(); $i = $keyIndexMap[$keyValue] ?? null; if ($i === null) { return \false; } $otherKeyValues[$keyValue] = \true; $valueType = $this->valueTypes[$i]; $otherValueType = $otherArray->valueTypes[$j]; if (!$otherValueType->isSuperTypeOf($valueType)->no()) { continue; } if ($failOnDifferentValueType) { return \false; } $failOnDifferentValueType = \true; } $requiredKeyCount = 0; foreach ($this->keyTypes as $i => $keyType) { if (isset($otherKeyValues[$keyType->getValue()])) { continue; } 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 $this->recreate($this->keyTypes, $valueTypes, $nextAutoIndexes, $optionalKeys, $this->isList->and($otherArray->isList)); } /** * @return array */ private function getKeyIndexMap(): array { if ($this->keyIndexMap !== null) { return $this->keyIndexMap; } $map = []; foreach ($this->keyTypes as $i => $keyType) { $map[$keyType->getValue()] = $i; } return $this->keyIndexMap = $map; } /** * @param ConstantIntegerType|ConstantStringType $otherKeyType */ private function getKeyIndex($otherKeyType): ?int { return $this->getKeyIndexMap()[$otherKeyType->getValue()] ?? null; } public function makeOffsetRequired(Type $offsetType): self { $offsetType = $offsetType->toArrayKey(); $optionalKeys = $this->optionalKeys; $isList = $this->isList->yes(); foreach ($this->keyTypes as $i => $keyType) { if (!$keyType->equals($offsetType)) { continue; } $keyValue = $keyType->getValue(); foreach ($optionalKeys as $j => $key) { if ($i !== $key && (!$isList || !is_int($keyValue) || !is_int($this->keyTypes[$key]->getValue()) || $this->keyTypes[$key]->getValue() >= $keyValue)) { continue; } unset($optionalKeys[$j]); } if (count($this->optionalKeys) !== count($optionalKeys)) { return $this->recreate($this->keyTypes, $this->valueTypes, $this->nextAutoIndexes, array_values($optionalKeys), $this->isList); } break; } return $this; } public function makeList(): Type { if ($this->isList->yes()) { return $this; } if ($this->isList->no()) { return new NeverType(); } return $this->recreate($this->keyTypes, $this->valueTypes, $this->nextAutoIndexes, $this->optionalKeys, TrinaryLogic::createYes()); } public function makeListMaybe(): Type { if (!$this->isList->yes()) { return $this; } return $this->recreate($this->keyTypes, $this->valueTypes, $this->nextAutoIndexes, $this->optionalKeys, TrinaryLogic::createMaybe()); } public function mapValueType(callable $cb): Type { $newValueTypes = []; foreach ($this->valueTypes as $valueType) { $newValueTypes[] = $cb($valueType); } return $this->recreate($this->keyTypes, $newValueTypes, $this->nextAutoIndexes, $this->optionalKeys, $this->isList); } public function mapKeyType(callable $cb): Type { // Constant array shapes already encode precise per-slot keys; a // blanket key-type rewrite (the prior `TypeTraverser`-based pattern // in `NodeScopeResolver`) would coerce constants into a broader // type and lose precision. Pass through unchanged. return $this; } public function makeAllArrayKeysOptional(): Type { $keyCount = count($this->keyTypes); if ($keyCount === 0) { return $this; } return $this->recreate($this->keyTypes, $this->valueTypes, $this->nextAutoIndexes, range(0, $keyCount - 1), $this->isList); } public function changeKeyCaseArray(?int $case): Type { $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createEmpty(); foreach ($this->keyTypes as $i => $keyType) { if ($keyType instanceof \PHPStan\Type\Constant\ConstantStringType) { $newKeyType = self::foldConstantStringKeyCase($keyType, $case); } else { $newKeyType = $keyType; } $builder->setOffsetValueType($newKeyType, $this->valueTypes[$i], $this->isOptionalKey($i)); } $result = $builder->getArray(); if ($this->isList()->yes()) { $result = TypeCombinator::intersect($result, new AccessoryArrayListType()); } return $result; } public function filterArrayRemovingFalsey(): Type { $falseyTypes = StaticTypeFactory::falsey(); $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createEmpty(); foreach ($this->keyTypes as $i => $keyType) { $value = $this->valueTypes[$i]; $isFalsey = $falseyTypes->isSuperTypeOf($value); if ($isFalsey->yes()) { continue; } if ($isFalsey->maybe()) { $builder->setOffsetValueType($keyType, TypeCombinator::remove($value, $falseyTypes), \true); continue; } $builder->setOffsetValueType($keyType, $value, $this->isOptionalKey($i)); } return $builder->getArray(); } private static function foldConstantStringKeyCase(\PHPStan\Type\Constant\ConstantStringType $type, ?int $case): Type { if ($case === CASE_LOWER) { return new \PHPStan\Type\Constant\ConstantStringType(strtolower($type->getValue())); } if ($case === CASE_UPPER) { return new \PHPStan\Type\Constant\ConstantStringType(strtoupper($type->getValue())); } return TypeCombinator::union(new \PHPStan\Type\Constant\ConstantStringType(strtolower($type->getValue())), new \PHPStan\Type\Constant\ConstantStringType(strtoupper($type->getValue()))); } 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 ArrayShapeNode::createSealed($exportValuesOnly ? $values : $items, $this->shouldBeDescribedAsAList() ? ArrayShapeNode::KIND_LIST : ArrayShapeNode::KIND_ARRAY); } 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 { $limit = InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT; // Build finite array types incrementally, processing one key at a time. // For optional keys, fork each partial result into with/without variants. // This avoids generating 2^N ConstantArrayType objects via getAllArrays(). /** @var list $partials */ $partials = [\PHPStan\Type\Constant\ConstantArrayTypeBuilder::createEmpty()]; foreach ($this->keyTypes as $i => $keyType) { $finiteValueTypes = $this->valueTypes[$i]->getFiniteTypes(); if ($finiteValueTypes === []) { return []; } $isOptional = $this->isOptionalKey($i); $newPartials = []; foreach ($partials as $partial) { if ($isOptional) { $newPartials[] = clone $partial; } foreach ($finiteValueTypes as $finiteValueType) { $newPartial = clone $partial; $newPartial->setOffsetValueType($keyType, $finiteValueType); $newPartials[] = $newPartial; } } $partials = $newPartials; if (count($partials) > $limit) { return []; } } $finiteTypes = []; foreach ($partials as $partial) { $finiteTypes[] = $partial->getArray(); } return $finiteTypes; } public function hasTemplateOrLateResolvableType(): bool { foreach ($this->valueTypes as $valueType) { if (!$valueType->hasTemplateOrLateResolvableType()) { continue; } return \true; } foreach ($this->keyTypes as $keyType) { if (!$keyType instanceof TemplateType) { continue; } return \true; } return \false; } } 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 array $keyTypes; /** * @var array */ private array $valueTypes; /** * @var list */ private array $nextAutoIndexes; /** * @var array */ private array $optionalKeys; private TrinaryLogic $isList; public const ARRAY_COUNT_LIMIT = 256; private const CLOSURES_COUNT_LIMIT = 32; private bool $degradeToGeneralArray = \false; private bool $disableArrayDegradation = \false; private ?bool $degradeClosures = null; private bool $oversized = \false; private TrinaryLogic $isNonEmpty; /** * @param list $keyTypes * @param array $valueTypes * @param 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; $this->isNonEmpty = TrinaryLogic::createNo(); } 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()); $builder->isNonEmpty = $startArrayType->isIterableAtLeastOnce(); 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 ($offsetType === null && count($this->nextAutoIndexes) === 0) { return; } if (!$optional) { $this->isNonEmpty = TrinaryLogic::createYes(); } if (!$this->degradeToGeneralArray) { if ($valueType instanceof ClosureType && $this->degradeClosures !== \false && !$this->disableArrayDegradation) { $numClosures = 1; foreach ($this->valueTypes as $innerType) { if (!$innerType instanceof ClosureType) { continue; } $numClosures++; } if ($numClosures >= self::CLOSURES_COUNT_LIMIT) { $this->degradeClosures = \true; $this->degradeToGeneralArray = \true; $this->oversized = \true; } } 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 fn(int $index): bool => $index !== $i)); } /** @var int|float $newAutoIndex */ $newAutoIndex = $keyType->getValue() + 1; if (!is_float($newAutoIndex)) { $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)) { $newAutoIndexes[] = $newAutoIndex; } $this->nextAutoIndexes = array_values(array_unique($newAutoIndexes)); if ($optional || $hasOptional) { $this->optionalKeys[] = count($this->keyTypes) - 1; } if (!$this->disableArrayDegradation && 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 fn(int $index): bool => $index !== $i)); if ($keyType instanceof \PHPStan\Type\Constant\ConstantIntegerType) { $this->nextAutoIndexes = array_values(array_filter($this->nextAutoIndexes, static fn(int $index) => $index > $keyType->getValue())); } } return; } $this->keyTypes[] = $offsetType; $this->valueTypes[] = $valueType; if ($offsetType instanceof \PHPStan\Type\Constant\ConstantIntegerType) { if (count($this->nextAutoIndexes) > 0) { $min = min($this->nextAutoIndexes); $max = max($this->nextAutoIndexes); $offsetValue = $offsetType->getValue(); if ($offsetValue >= 0) { if ($offsetValue > $min) { if ($offsetValue <= $max) { $this->isList = $this->isList->and(TrinaryLogic::createMaybe()); } else { $this->isList = TrinaryLogic::createNo(); } } } else { $this->isList = TrinaryLogic::createNo(); } if ($offsetValue >= $max) { /** @var int|float $newAutoIndex */ $newAutoIndex = $offsetValue + 1; if (is_float($newAutoIndex)) { if (!$optional) { $this->nextAutoIndexes = []; } } elseif (!$optional) { $this->nextAutoIndexes = [$newAutoIndex]; } else { $this->nextAutoIndexes[] = $newAutoIndex; } } } else { $this->isList = TrinaryLogic::createNo(); } } else { $this->isList = TrinaryLogic::createNo(); } if ($optional) { $this->optionalKeys[] = count($this->keyTypes) - 1; } if (!$this->disableArrayDegradation && count($this->keyTypes) > self::ARRAY_COUNT_LIMIT) { $this->degradeToGeneralArray = \true; $this->oversized = \true; } return; } $scalarTypes = $offsetType->toArrayKey()->getConstantScalarTypes(); if (count($scalarTypes) === 0) { $integerRanges = TypeUtils::getIntegerRanges($offsetType); if (count($integerRanges) > 0) { foreach ($integerRanges as $integerRange) { $finiteTypes = $integerRange->getFiniteTypes(); if (count($finiteTypes) === 0) { break; } foreach ($finiteTypes as $finiteType) { $scalarTypes[] = $finiteType; } } } } if (count($scalarTypes) > 0 && count($scalarTypes) < self::ARRAY_COUNT_LIMIT) { $match = \true; $hasMatch = \false; $valueTypes = $this->valueTypes; foreach ($scalarTypes as $scalarType) { $offsetMatch = \false; /** @var ConstantIntegerType|ConstantStringType $keyType */ foreach ($this->keyTypes as $i => $keyType) { if ($keyType->getValue() !== $scalarType->getValue()) { continue; } if (!$optional && in_array($i, $this->optionalKeys, \true)) { $valueTypes[$i] = $valueType; } else { $valueTypes[$i] = TypeCombinator::union($valueTypes[$i], $valueType); } $offsetMatch = \true; } if ($offsetMatch) { $hasMatch = \true; continue; } $match = \false; } if ($match) { $this->valueTypes = $valueTypes; return; } if (!$hasMatch) { foreach ($scalarTypes as $scalarType) { $this->keyTypes[] = $scalarType; $this->valueTypes[] = $valueType; $this->optionalKeys[] = count($this->keyTypes) - 1; if (!$scalarType instanceof \PHPStan\Type\Constant\ConstantIntegerType) { continue; } if (count($this->nextAutoIndexes) === 0) { continue; } $max = max($this->nextAutoIndexes); $offsetValue = $scalarType->getValue(); if ($offsetValue < $max) { continue; } /** @var int|float $newAutoIndex */ $newAutoIndex = $offsetValue + 1; if (is_float($newAutoIndex)) { continue; } $this->nextAutoIndexes[] = $newAutoIndex; } $this->isList = TrinaryLogic::createNo(); if (!$this->disableArrayDegradation && count($this->keyTypes) > self::ARRAY_COUNT_LIMIT) { $this->degradeToGeneralArray = \true; $this->oversized = \true; } return; } } $this->isList = TrinaryLogic::createNo(); } if ($offsetType === null) { $offsetType = TypeCombinator::union(...array_map(static fn(int $index) => 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 { if ($this->disableArrayDegradation) { throw new ShouldNotHappenException(); } $this->degradeToGeneralArray = \true; $this->oversized = $this->oversized || $oversized; } public function disableClosureDegradation(): void { $this->degradeClosures = \false; } public function disableArrayDegradation(): void { $this->degradeToGeneralArray = \false; $this->oversized = \false; $this->disableArrayDegradation = \true; } public function getArray(): Type { $keyTypesCount = count($this->keyTypes); if ($keyTypesCount === 0) { return new \PHPStan\Type\Constant\ConstantArrayType([], []); } if (!$this->degradeToGeneralArray) { /** @var list $keyTypes */ $keyTypes = $this->keyTypes; $array = new \PHPStan\Type\Constant\ConstantArrayType($keyTypes, $this->valueTypes, $this->nextAutoIndexes, $this->optionalKeys, $this->isList); if ($this->isNonEmpty->yes() && !$array->isIterableAtLeastOnce()->yes()) { return TypeCombinator::intersect($array, new NonEmptyArrayType()); } return $array; } if ($this->degradeClosures === \true) { $itemTypes = []; $itemTypes[] = new CallableType(); foreach ($this->valueTypes as $valueType) { if ($valueType instanceof ClosureType) { continue; } $itemTypes[] = $valueType; } } else { $itemTypes = $this->valueTypes; } $array = new ArrayType(TypeCombinator::union(...$this->keyTypes), TypeCombinator::union(...$itemTypes)); $types = []; if ($this->isNonEmpty->yes() || count($this->optionalKeys) < $keyTypesCount) { $types[] = new NonEmptyArrayType(); } if ($this->oversized) { $types[] = new OversizedArrayType(); } if ($this->isList->yes()) { $types[] = new AccessoryArrayListType(); } if (count($types) === 0) { return $array; } return new IntersectionType([$array, ...$types]); } public function isList(): bool { return $this->isList->yes(); } } 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(PhpVersion $phpVersion): Type { if ($this->value) { return StaticTypeFactory::falsey(); } return new NeverType(); } public function getSmallerOrEqualType(PhpVersion $phpVersion): Type { if ($this->value) { return new MixedType(); } return StaticTypeFactory::falsey(); } public function getGreaterType(PhpVersion $phpVersion): Type { if ($this->value) { return new NeverType(); } return StaticTypeFactory::truthy(); } public function getGreaterOrEqualType(PhpVersion $phpVersion): 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 toBitwiseNotType(): Type { return new ErrorType(); } 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 toCoercedArgumentType(bool $strictTypes): Type { if (!$strictTypes) { return TypeCombinator::union($this->toInteger(), $this->toFloat(), $this->toString(), $this); } return $this; } 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'); } public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { if ($type->isObject()->yes()) { return $this; } return $this->scalarLooseCompare($type, $phpVersion); } } 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 { if (is_nan($value)) { return 'NAN'; } $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 fn(): string => 'float', fn(): string => $this->castFloatToString($this->value)); } public function toString(): Type { if ($this->value === 0.0) { return new UnionType([new \PHPStan\Type\Constant\ConstantStringType('0'), new \PHPStan\Type\Constant\ConstantStringType('-0')]); } return new \PHPStan\Type\Constant\ConstantStringType((string) $this->value); } public function toInteger(): Type { return new \PHPStan\Type\Constant\ConstantIntegerType((int) $this->value); } public function toBitwiseNotType(): 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 getFiniteTypes(): array { if (is_nan($this->value)) { return []; } return [$this]; } public function generalize(GeneralizePrecision $precision): Type { return new FloatType(); } /** * @return ConstTypeNode */ public function toPhpDocNode(): TypeNode { return new ConstTypeNode(new ConstExprFloatNode($this->castFloatToString($this->value))); } } value = $value; parent::__construct(); } public function getValue(): int { return $this->value; } public function isSuperTypeOf(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->isSubTypeOf($this); } return IsSuperTypeOfResult::createNo(); } public function describe(VerbosityLevel $level): string { return $level->handle(static fn(): string => 'int', fn(): string => sprintf('%s', $this->value)); } public function toFloat(): Type { return new \PHPStan\Type\Constant\ConstantFloatType($this->value); } public function toBitwiseNotType(): Type { return new self(~$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 toCoercedArgumentType(bool $strictTypes): Type { if (!$strictTypes) { return TypeCombinator::union($this, $this->toFloat(), $this->toString(), $this->toBoolean()); } return TypeCombinator::union($this, $this->toFloat()); } public function generalize(GeneralizePrecision $precision): Type { return new IntegerType(); } /** * @return ConstTypeNode */ public function toPhpDocNode(): TypeNode { return new ConstTypeNode(new ConstExprIntegerNode((string) $this->value)); } } value); } } value = $value; $this->isClassString = $isClassString; parent::__construct(); } public function getValue(): string { return $this->value; } public function getConstantStrings(): array { return [$this]; } public function isClassString(): TrinaryLogic { if ($this->isClassString) { return TrinaryLogic::createYes(); } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); return TrinaryLogic::createFromBoolean($reflectionProvider->hasClass($this->value)); } public function getClassStringObjectType(): Type { if ($this->isClassString()->yes()) { return new ObjectType($this->value); } return new ErrorType(); } public function getObjectTypeOrClassStringObjectType(): Type { return $this->getClassStringObjectType(); } public function describe(VerbosityLevel $level): string { return $level->handle(static fn(): string => '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); }, fn(): string => 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): 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()->isSuperTypeOf($objectType); } else { $isSuperType = $genericType->isSuperTypeOf($objectType); } // Explicitly handle the uncertainty for Yes & Maybe. if ($isSuperType->yes()) { return IsSuperTypeOfResult::createMaybe(); } return IsSuperTypeOfResult::createNo(); } if ($type instanceof ClassStringType) { return $this->isClassString()->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->isSubTypeOf($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(); } $classRef = $reflectionProvider->getClass($matches[1]); if ($classRef->hasMethod($matches[2])) { $phpVersion = PhpVersionStaticAccessor::getInstance(); if (!$phpVersion->supportsCallableInstanceMethods()) { $method = $classRef->getMethod($matches[2], new OutOfClassScope()); if (!$method->isStatic()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createYes(); } if (!$classRef->isFinalByKeyword()) { 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->isFinalByKeyword()) { 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 toBitwiseNotType(): Type { return new \PHPStan\Type\Constant\ConstantStringType(~$this->value); } public function toObjectTypeForInstanceofCheck(): ClassNameToObjectTypeResult { return new ClassNameToObjectTypeResult(new ObjectType($this->value), \false); } public function toObjectTypeForIsACheck(Type $objectOrClassType, bool $allowString, bool $allowSameClass): ClassNameToObjectTypeResult { $objectOrClassTypeClassNames = $objectOrClassType->getObjectClassNames(); if ($allowString) { foreach ($objectOrClassType->getConstantStrings() as $constantString) { $objectOrClassTypeClassNames[] = $constantString->getValue(); } $objectOrClassTypeClassNames = array_values(array_unique($objectOrClassTypeClassNames)); } $uncertainty = \false; if (!$allowSameClass) { if ($objectOrClassTypeClassNames === [$this->value]) { $isSameClass = \true; foreach ($objectOrClassType->getObjectClassReflections() as $classReflection) { if (!$classReflection->isFinal()) { $isSameClass = \false; break; } } if ($isSameClass) { return new ClassNameToObjectTypeResult(new NeverType(), \false); } } if (in_array($this->value, $objectOrClassTypeClassNames, \true) || $allowString && $objectOrClassTypeClassNames === [] && $objectOrClassType->isSuperTypeOf($this)->yes()) { $uncertainty = \true; } } if ($allowString) { return new ClassNameToObjectTypeResult(new UnionType([new ObjectType($this->value), new GenericClassStringType(new ObjectType($this->value))]), $uncertainty); } return new ClassNameToObjectTypeResult(new ObjectType($this->value), $uncertainty); } 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]); if ($offsetValue === $this->value) { return $this; } 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)->result; } 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(PhpVersion $phpVersion): 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(PhpVersion $phpVersion): 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(PhpVersion $phpVersion): 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(PhpVersion $phpVersion): 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->isClassString(); } public function hasConstant(string $constantName): TrinaryLogic { return $this->getObjectType()->hasConstant($constantName); } public function getConstant(string $constantName): ClassConstantReflection { return $this->getObjectType()->getConstant($constantName); } private function getObjectType(): ObjectType { return $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 ConstExprStringNode($this->value, ConstExprStringNode::SINGLE_QUOTED)); } } items; for ($i = 0; $i < count($items); $i++) { $item = $items[$i]; 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 ArrayItem(new TypeExpr($innerValueType), $keyExpr)]); } } else { array_splice($items, $i, 1, [new ArrayItem(new TypeExpr($valueType->getIterableValueType()), new TypeExpr($valueType->getIterableKeyType()))]); } } foreach ($items as $item) { 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); $accessories = []; if ($isList) { $accessories[] = new AccessoryArrayListType(); } return TypeCombinator::intersect($arrayType, new NonEmptyArrayType(), new OversizedArrayType(), ...$accessories); } } 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(); } } typeAliasResolver = $typeAliasResolver; } public function getTypeAliasResolver(): \PHPStan\Type\TypeAliasResolver { return $this->typeAliasResolver; } } > */ private array $dynamicReturnTypeExtensionsByFunction = []; /** * @param DynamicMethodReturnTypeExtension[] $dynamicMethodReturnTypeExtensions * @param DynamicStaticMethodReturnTypeExtension[] $dynamicStaticMethodReturnTypeExtensions * @param DynamicFunctionReturnTypeExtension[] $dynamicFunctionReturnTypeExtensions */ public function __construct(ReflectionProvider $reflectionProvider, array $dynamicMethodReturnTypeExtensions, array $dynamicStaticMethodReturnTypeExtensions, array $dynamicFunctionReturnTypeExtensions) { $this->reflectionProvider = $reflectionProvider; $this->dynamicMethodReturnTypeExtensions = $dynamicMethodReturnTypeExtensions; $this->dynamicStaticMethodReturnTypeExtensions = $dynamicStaticMethodReturnTypeExtensions; $this->dynamicFunctionReturnTypeExtensions = $dynamicFunctionReturnTypeExtensions; } /** * @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(FunctionReflection $functionReflection): array { $functionName = $functionReflection->getName(); if (isset($this->dynamicReturnTypeExtensionsByFunction[$functionName])) { return $this->dynamicReturnTypeExtensionsByFunction[$functionName]; } $supportedFunctions = []; foreach ($this->dynamicFunctionReturnTypeExtensions as $dynamicFunctionReturnTypeExtension) { if (!$dynamicFunctionReturnTypeExtension->isFunctionSupported($functionReflection)) { continue; } $supportedFunctions[] = $dynamicFunctionReturnTypeExtension; } return $this->dynamicReturnTypeExtensionsByFunction[$functionName] = $supportedFunctions; } } 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): AcceptsResult { return $this->isSuperTypeOf($type)->toAcceptsResult(); } public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self) { return IsSuperTypeOfResult::createFromBoolean($this->enumCaseName === $type->enumCaseName && $this->getClassName() === $type->getClassName()); } if ($type instanceof CompoundType) { return $type->isSubTypeOf($this); } if ($type instanceof SubtractableType && $type->getSubtractedType() !== null) { $isSuperType = $type->getSubtractedType()->isSuperTypeOf($this); if ($isSuperType->yes()) { return IsSuperTypeOfResult::createNo(); } } $parent = new parent($this->getClassName(), $this->getSubtractedType(), $this->getClassReflection()); return $parent->isSuperTypeOf($type)->and(IsSuperTypeOfResult::createMaybe()); } public function subtract(Type $type): Type { return $this->changeSubtractedType($type); } public function getTypeWithoutSubtractedType(): Type { return $this; } public function changeSubtractedType(?Type $subtractedType): Type { if ($subtractedType === null || !$this->equals($subtractedType)) { return $this; } return new NeverType(); } 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 { return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope); } public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return parent::getUnresolvedInstancePropertyPrototype($propertyName, $scope); } if ($propertyName === 'name') { return new EnumUnresolvedPropertyPrototypeReflection(new EnumPropertyReflection($propertyName, $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($propertyName, $classReflection, $valueType)); } } return parent::getUnresolvedInstancePropertyPrototype($propertyName, $scope); } public function hasStaticProperty(string $propertyName): TrinaryLogic { return TrinaryLogic::createNo(); } public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { throw new ShouldNotHappenException(); } public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { throw new ShouldNotHappenException(); } 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, PhpVersion $phpVersion): TrinaryLogic { return TrinaryLogic::createNo(); } public function isSmallerThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return TrinaryLogic::createNo(); } public function getEnumCases(): array { return [$this]; } public function getEnumCaseObject(): ?\PHPStan\Type\Enum\EnumCaseObjectType { return $this; } public function getClassStringType(): Type { return new GenericClassStringType(new ObjectType($this->getClassName())); } public function toClassConstantType(ReflectionProvider $reflectionProvider): Type { // Enum cases always read their `::class` as the bare enum class // name. Skip the parent's finality collapse: even though enum // classes are reported as `final` by reflection, `Foo::Bar::class` // in user code should resolve to `class-string&literal-string`, // not the literal `'Foo'`, to keep the case-binding visible at // downstream sites. return new IntersectionType([$this->getClassStringType(), new AccessoryLiteralStringType()]); } public function toPhpDocNode(): TypeNode { return new ConstTypeNode(new ConstFetchNode($this->getClassName(), $this->getEnumCaseName())); } } handle(fn(): string => parent::describe($level), fn(): string => parent::describe($level), static fn(): string => '*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; } } 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); } } */ private array $extensions; /** * @param array $extensions */ public function __construct(array $extensions) { $this->extensions = $extensions; } /** * @return array */ public function getExtensions(): array { return $this->extensions; } } }> */ private array $memoryCache = []; private int $memoryCacheCount = 0; /** @var array */ private array $inProcess = []; /** @var array */ private array $inProcessNameScopes = []; /** @var array */ private array $resolvedPhpDocBlockCache = []; private int $resolvedPhpDocBlockCacheCount = 0; public function __construct( ReflectionProviderProvider $reflectionProviderProvider, #[AutowiredParameter('@defaultAnalysisParser')] Parser $phpParser, PhpDocStringResolver $phpDocStringResolver, PhpDocNodeResolver $phpDocNodeResolver, AnonymousClassNameHelper $anonymousClassNameHelper, FileHelper $fileHelper, Cache $cache, #[AutowiredParameter('%cache.resolvedPhpDocBlockCacheCountMax%')] int $resolvedPhpDocBlockCacheCountMax, #[AutowiredParameter('%cache.nameScopeMapMemoryCacheCountMax%')] int $nameScopeMapMemoryCacheCountMax ) { $this->reflectionProviderProvider = $reflectionProviderProvider; $this->phpParser = $phpParser; $this->phpDocStringResolver = $phpDocStringResolver; $this->phpDocNodeResolver = $phpDocNodeResolver; $this->anonymousClassNameHelper = $anonymousClassNameHelper; $this->fileHelper = $fileHelper; $this->cache = $cache; $this->resolvedPhpDocBlockCacheCountMax = $resolvedPhpDocBlockCacheCountMax; $this->nameScopeMapMemoryCacheCountMax = $nameScopeMapMemoryCacheCountMax; } /** @api */ public function getResolvedPhpDoc(?string $fileName, ?string $className, ?string $traitName, ?string $functionName, ?string $docComment): ResolvedPhpDocBlock { if ($className === null && $traitName !== null) { throw new ShouldNotHappenException(); } if (in_array($docComment, [null, ''], \true)) { return ResolvedPhpDocBlock::createEmpty(); } if ($fileName !== null) { $fileName = $this->fileHelper->normalizePath($fileName); } $nameScopeKey = $this->getNameScopeKey($fileName, $className, $traitName, $functionName); $phpDocKey = $this->getPhpDocKey($nameScopeKey, $docComment); if (isset($this->resolvedPhpDocBlockCache[$phpDocKey])) { return $this->resolvedPhpDocBlockCache[$phpDocKey]; } if ($this->resolvedPhpDocBlockCacheCount >= $this->resolvedPhpDocBlockCacheCountMax) { $this->resolvedPhpDocBlockCache = array_slice($this->resolvedPhpDocBlockCache, 1, \null, \true); $this->resolvedPhpDocBlockCacheCount--; } $this->resolvedPhpDocBlockCacheCount++; if ($fileName === null) { return $this->resolvedPhpDocBlockCache[$phpDocKey] = $this->createResolvedPhpDocBlock($this->phpDocStringResolver->resolve($docComment), new NameScope(null, []), $docComment, null); } try { $nameScope = $this->getNameScope($fileName, $className, $traitName, $functionName); } catch (NameScopeAlreadyBeingCreatedException $e) { return $this->resolvedPhpDocBlockCache[$phpDocKey] = ResolvedPhpDocBlock::createEmpty(); } return $this->resolvedPhpDocBlockCache[$phpDocKey] = $this->createResolvedPhpDocBlock($this->phpDocStringResolver->resolve($docComment), $nameScope, $docComment, $fileName); } private function createResolvedPhpDocBlock(PhpDocNode $phpDocNode, NameScope $nameScope, string $phpDocString, ?string $fileName): ResolvedPhpDocBlock { $docBlockTemplateTypes = []; $templateTypeMap = $nameScope->getTemplateTypeMap(); $templateTags = []; $phpDocNodeTemplateTagsByName = []; foreach ($phpDocNode->getTags() as $tagNode) { $valueNode = $tagNode->value; if (!$valueNode instanceof TemplateTagValueNode) { continue; } $phpDocNodeTemplateTagsByName[$valueNode->name] = \true; } foreach ($nameScope->getTemplateTags() as $templateTagName => $templateTag) { if (!array_key_exists($templateTagName, $phpDocNodeTemplateTagsByName)) { continue; } $templateTags[$templateTagName] = $templateTag; $templateType = $templateTypeMap->getType($templateTagName); if ($templateType === null) { continue; } $docBlockTemplateTypes[$templateTagName] = $templateType; } return ResolvedPhpDocBlock::create($phpDocNode, $phpDocString, $fileName, $nameScope, new TemplateTypeMap($docBlockTemplateTypes), $templateTags, $this->phpDocNodeResolver, $this->reflectionProviderProvider->getReflectionProvider()); } /** * @throws NameScopeAlreadyBeingCreatedException */ public function getNameScope(string $fileName, ?string $className, ?string $traitName, ?string $functionName): NameScope { $nameScopeKey = $this->getNameScopeKey($fileName, $className, $traitName, $functionName); if (isset($this->inProcess[$nameScopeKey])) { if (isset($this->inProcessNameScopes[$nameScopeKey])) { return $this->inProcessNameScopes[$nameScopeKey]; } throw new NameScopeAlreadyBeingCreatedException(); } [$nameScopeMap] = $this->getNameScopeMap($fileName); if (!isset($nameScopeMap[$nameScopeKey])) { throw new NameScopeAlreadyBeingCreatedException(); } $intermediaryNameScope = $nameScopeMap[$nameScopeKey]; $this->inProcess[$nameScopeKey] = \true; try { $parents = [$intermediaryNameScope]; $i = $intermediaryNameScope; while ($i->getParent() !== null) { $parents[] = $i->getParent(); $i = $i->getParent(); } $phpDocTemplateTypes = []; $templateTags = []; $reflectionProvider = $this->reflectionProviderProvider->getReflectionProvider(); foreach (array_reverse($parents) as $parent) { $nameScope = new NameScope($parent->getNamespace(), $parent->getUses(), $parent->getClassName(), $parent->getFunctionName(), new TemplateTypeMap($phpDocTemplateTypes), $templateTags, $parent->getTypeAliasesMap(), $parent->shouldBypassTypeAliases(), $parent->getConstUses(), $parent->getClassNameForTypeAlias()); if ($parent->getTraitData() !== null) { [$traitFileName, $traitClassName, $traitName, $lookForTraitName, $traitDocComment] = $parent->getTraitData(); if (!$reflectionProvider->hasClass($traitName)) { continue; } $traitReflection = $reflectionProvider->getClass($traitName); $useTags = $this->getResolvedPhpDoc($traitFileName, $traitClassName, $lookForTraitName, null, $traitDocComment)->getUsesTags(); $useType = null; foreach ($useTags as $useTag) { $useTagType = $useTag->getType(); if (!$useTagType instanceof GenericObjectType) { continue; } if ($useTagType->getClassName() !== $traitReflection->getName()) { continue; } $useType = $useTagType; break; } $traitTemplateTypeMap = $traitReflection->getTemplateTypeMap(); $namesToUnset = []; if ($useType === null) { foreach ($traitTemplateTypeMap->resolveToBounds()->getTypes() as $name => $templateType) { $phpDocTemplateTypes[$name] = $templateType; $namesToUnset[] = $name; } } else { $transformedTraitTypeMap = $traitReflection->typeMapFromList($useType->getTypes()); $nameScopeTemplateTypeMap = $traitTemplateTypeMap->map(static fn(string $name, \PHPStan\Type\Type $type): \PHPStan\Type\Type => TemplateTypeHelper::resolveTemplateTypes($type, $transformedTraitTypeMap, TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createStatic())); foreach ($nameScopeTemplateTypeMap->getTypes() as $name => $templateType) { $phpDocTemplateTypes[$name] = $templateType; $namesToUnset[] = $name; } } $parent = $parent->unsetTemplatePhpDocNodes($namesToUnset); } $templateTypeScope = $nameScope->getTemplateTypeScope(); if ($templateTypeScope === null) { continue; } $this->inProcessNameScopes[$nameScopeKey] = $nameScope; $templateTags = $this->phpDocNodeResolver->resolveTemplateTags($parent->getTemplatePhpDocNodes(), $nameScope); $templateTypeMap = new TemplateTypeMap(array_map(static fn(TemplateTag $tag): \PHPStan\Type\Type => TemplateTypeFactory::fromTemplateTag($templateTypeScope, $tag), $templateTags)); $nameScope = $nameScope->withTemplateTypeMap($templateTypeMap, $templateTags); $templateTags = $this->phpDocNodeResolver->resolveTemplateTags($parent->getTemplatePhpDocNodes(), $nameScope); $templateTypeMap = new TemplateTypeMap(array_map(static fn(TemplateTag $tag): \PHPStan\Type\Type => TemplateTypeFactory::fromTemplateTag($templateTypeScope, $tag), $templateTags)); $nameScope = $nameScope->withTemplateTypeMap($templateTypeMap, $templateTags); $templateTags = $this->phpDocNodeResolver->resolveTemplateTags($parent->getTemplatePhpDocNodes(), $nameScope); $templateTypeMap = new TemplateTypeMap(array_map(static fn(TemplateTag $tag): \PHPStan\Type\Type => TemplateTypeFactory::fromTemplateTag($templateTypeScope, $tag), $templateTags)); foreach (array_keys($templateTags) as $name) { $templateType = $templateTypeMap->getType($name); if ($templateType === null) { continue; } $phpDocTemplateTypes[$name] = $templateType; } } return new NameScope($intermediaryNameScope->getNamespace(), $intermediaryNameScope->getUses(), $intermediaryNameScope->getClassName(), $intermediaryNameScope->getFunctionName(), new TemplateTypeMap($phpDocTemplateTypes), $templateTags, $intermediaryNameScope->getTypeAliasesMap(), $intermediaryNameScope->shouldBypassTypeAliases(), $intermediaryNameScope->getConstUses(), $intermediaryNameScope->getClassNameForTypeAlias()); } finally { unset($this->inProcess[$nameScopeKey]); unset($this->inProcessNameScopes[$nameScopeKey]); } } /** * @return array{array} */ private function getNameScopeMap(string $fileName): array { if (!isset($this->memoryCache[$fileName])) { $cacheKey = sprintf('ftm-%s', $fileName); $variableCacheKey = sprintf('v5-%s', ComposerHelper::getPhpDocParserVersion()); $cached = $this->loadCachedPhpDocNodeMap($cacheKey, $variableCacheKey); if ($cached === null) { [$nameScopeMap, $files] = $this->createPhpDocNodeMap($fileName, null, null, [], $fileName); $filesWithHashes = []; foreach ($files as $file) { $newHash = hash_file('sha256', $file); $filesWithHashes[$file] = $newHash; } $this->cache->save($cacheKey, $variableCacheKey, [$nameScopeMap, $filesWithHashes]); } else { [$nameScopeMap, $files] = $cached; } if ($this->memoryCacheCount >= $this->nameScopeMapMemoryCacheCountMax) { $this->memoryCache = array_slice($this->memoryCache, 1, \null, \true); $this->memoryCacheCount--; } $this->memoryCache[$fileName] = [$nameScopeMap, $files]; $this->memoryCacheCount++; } return $this->memoryCache[$fileName]; } /** * @param non-empty-string $cacheKey * @return array{array, list}|null */ private function loadCachedPhpDocNodeMap(string $cacheKey, string $variableCacheKey): ?array { $cached = $this->cache->load($cacheKey, $variableCacheKey); if ($cached !== null) { /** * @var array $filesWithHashes */ [$nameScopeMap, $filesWithHashes] = $cached; $useCache = \true; foreach ($filesWithHashes as $file => $hash) { $newHash = @hash_file('sha256', $file); if ($newHash === \false) { $useCache = \false; break; } if ($newHash === $hash) { continue; } $useCache = \false; break; } if ($useCache) { return [$nameScopeMap, array_keys($filesWithHashes)]; } } return null; } /** * @param array $traitMethodAliases * @param array $activeTraitResolutions * @return array{array, list} */ private function createPhpDocNodeMap(string $fileName, ?string $lookForTrait, ?string $traitUseClass, array $traitMethodAliases, string $originalClassFileName, array $activeTraitResolutions = []): array { /** @var array $nameScopeMap */ $nameScopeMap = []; /** @var array $typeMapStack */ $typeMapStack = []; /** @var array> $typeAliasStack */ $typeAliasStack = []; /** @var string[] $classStack */ $classStack = []; if ($lookForTrait !== null && $traitUseClass !== null) { $classStack[] = $traitUseClass; $typeAliasStack[] = []; } $namespace = null; $traitFound = \false; $files = [$fileName]; /** @var array $functionStack */ $functionStack = []; $uses = []; $constUses = []; $this->processNodes($this->phpParser->parseFile($fileName), function (Node $node) use ($fileName, $lookForTrait, &$traitFound, $traitMethodAliases, $originalClassFileName, $activeTraitResolutions, &$nameScopeMap, &$typeMapStack, &$typeAliasStack, &$classStack, &$namespace, &$functionStack, &$uses, &$constUses, &$files): ?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), '\\'); } elseif ($node instanceof Node\PropertyHook) { $propertyName = $node->getAttribute('propertyName'); if ($propertyName !== null) { $functionStack[] = sprintf('$%s::%s', $propertyName, $node->name->toString()); } } $className = array_last($classStack) ?? null; $functionName = array_last($functionStack) ?? null; $nameScopeKey = $this->getNameScopeKey($originalClassFileName, $className, $lookForTrait, $functionName); $phpDocNode = null; $docComment = null; if ($node instanceof Node\Stmt || $node instanceof Node\PropertyHook && $node->getAttribute('propertyName') !== null) { $docComment = GetLastDocComment::forNode($node); if ($docComment !== null) { $phpDocNode = $this->phpDocStringResolver->resolve($docComment); } } if ($node instanceof Node\Stmt\ClassLike || $node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_ || $node instanceof Node\PropertyHook) { if ($phpDocNode !== null) { if ($node instanceof Node\Stmt\ClassLike) { $typeAliasStack[] = $this->getTypeAliasesMap($phpDocNode); } $parentNameScope = array_last($typeMapStack) ?? null; $typeMapStack[] = new IntermediaryNameScope($namespace, $uses, $className, $functionName, $this->chooseTemplateTagValueNodesByPriority($phpDocNode->getTags()), $parentNameScope, array_last($typeAliasStack) ?? [], \false, $constUses, $lookForTrait); } elseif ($node instanceof Node\Stmt\ClassLike) { $typeAliasStack[] = []; } else { $parentNameScope = array_last($typeMapStack) ?? null; $typeMapStack[] = new IntermediaryNameScope($namespace, $uses, $className, $functionName, [], $parentNameScope, array_last($typeAliasStack) ?? [], \false, $constUses, $lookForTrait); } } if (($node instanceof Node\PropertyHook || $node instanceof Node\Stmt && !$node instanceof Node\Stmt\Namespace_ && !$node instanceof Node\Stmt\Declare_ && !$node instanceof Node\Stmt\Use_ && !$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)) { $parentNameScope = array_last($typeMapStack) ?? null; $typeAliasesMap = array_last($typeAliasStack) ?? []; $nameScopeMap[$nameScopeKey] = new IntermediaryNameScope($namespace, $uses, $className, $functionName, $parentNameScope !== null ? $parentNameScope->getTemplatePhpDocNodes() : [], $parentNameScope !== null ? $parentNameScope->getParent() : null, $typeAliasesMap, \false, $constUses, $lookForTrait); } if ($node instanceof Node\Stmt\ClassLike || $node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_ || $node instanceof Node\PropertyHook) { if ($phpDocNode !== null || !$node instanceof Node\Stmt\ClassLike) { 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; } 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 = array_last($classStack) ?? null; if ($className === null) { throw new ShouldNotHappenException(); } $traitResolutionKey = $this->getTraitResolutionKey($traitReflection->getFileName(), $traitName, $className, $originalClassFileName); if (isset($activeTraitResolutions[$traitResolutionKey])) { continue; } $nestedActiveTraitResolutions = $activeTraitResolutions; $nestedActiveTraitResolutions[$traitResolutionKey] = \true; [$traitNameScopeMap, $traitFiles] = $this->createPhpDocNodeMap($traitReflection->getFileName(), $traitName, $className, $traitMethodAliases[$traitName] ?? [], $originalClassFileName, $nestedActiveTraitResolutions); $nameScopeMap = array_merge($nameScopeMap, array_map(static fn($originalNameScope) => $originalNameScope->getTraitData() === null ? $originalNameScope->withTraitData($originalClassFileName, $className, $traitName, $lookForTrait, $docComment) : $originalNameScope, $traitNameScopeMap)); $files = array_merge($files, $traitFiles); } } 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); } elseif ($node instanceof Node\PropertyHook) { $propertyName = $node->getAttribute('propertyName'); if ($propertyName !== null) { 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, $files]; } /** * @param PhpDocTagNode[] $tags * @return array */ private function chooseTemplateTagValueNodesByPriority(array $tags): array { $resolved = []; $resolvedPrefix = []; $prefixPriority = ['' => 0, 'phan' => 1, 'psalm' => 2, 'phpstan' => 3]; foreach ($tags as $phpDocTagNode) { $valueNode = $phpDocTagNode->value; if (!$valueNode instanceof TemplateTagValueNode) { continue; } $tagName = $phpDocTagNode->name; 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; } } $resolved[$valueNode->name] = [$phpDocTagNode->name, $valueNode]; $resolvedPrefix[$valueNode->name] = $prefix; } return $resolved; } /** * @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)); } private function getPhpDocKey(string $nameScopeKey, string $docComment): string { $doc = new Doc($docComment); return md5(sprintf('%s-%s', $nameScopeKey, $doc->getReformattedText())); } private function getTraitResolutionKey(string $fileName, string $traitName, string $className, string $originalClassFileName): string { return md5(sprintf('%s-%s-%s-%s', $fileName, $traitName, $className, $originalClassFileName)); } } isInteger()->yes()) { return \PHPStan\Type\AcceptsResult::createYes(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return \PHPStan\Type\AcceptsResult::createNo(); } public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOf($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 toBitwiseNotType(): \PHPStan\Type\Type { return new \PHPStan\Type\IntegerType(); } 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 toCoercedArgumentType(bool $strictTypes): \PHPStan\Type\Type { if (!$strictTypes) { return \PHPStan\Type\TypeCombinator::union($this->toInteger(), $this, $this->toString(), $this->toBoolean()); } return $this; } 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 isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString(): 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 []; } public function hasTemplateOrLateResolvableType(): bool { return \false; } } ) * - **moreSpecific**: Preserves more detail — e.g. non-empty-string stays * non-empty-string instead of widening to string * - **templateArgument**: Used when generalizing template type arguments, * preserving template-specific structure * * Used as a parameter to Type::generalize(): * * $type->generalize(GeneralizePrecision::lessSpecific()) */ final class GeneralizePrecision { private int $value; private const LESS_SPECIFIC = 1; private const MORE_SPECIFIC = 2; private const TEMPLATE_ARGUMENT = 3; /** @var self[] */ private static array $registry; private function __construct(int $value) { $this->value = $value; } private static function create(int $value): self { 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 isMoreSpecific(): bool { return $this->value === self::MORE_SPECIFIC; } public function isTemplateArgument(): bool { return $this->value === self::TEMPLATE_ARGUMENT; } } type = $type; parent::__construct(); } public function getReferencedClasses(): array { return $this->type->getReferencedClasses(); } public function getGenericType(): Type { return $this->type; } public function toObjectTypeForInstanceofCheck(): ClassNameToObjectTypeResult { // `class-string` narrows to `X` for the comparison target, but // the actual runtime class can be any subclass of `X` — keep // uncertainty so the caller falls back to `BooleanType` instead // of a definite yes when `$x instanceof Y` and `Y === X`. return new ClassNameToObjectTypeResult($this->getGenericType(), \true); } public function toObjectTypeForIsACheck(Type $objectOrClassType, bool $allowString, bool $allowSameClass): ClassNameToObjectTypeResult { if ($allowString) { return new ClassNameToObjectTypeResult(TypeCombinator::union($this->getGenericType(), $this), \false); } return new ClassNameToObjectTypeResult($this->getGenericType(), \false); } 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 accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } if ($type instanceof ConstantStringType) { if (!$type->isClassString()->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->accepts($objectType, $strictTypes); } public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOf($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()->isSuperTypeOf($objectType); } else { $isSuperType = $genericType->isSuperTypeOf($objectType); } if (!$type->isClassString()->yes()) { $isSuperType = $isSuperType->and(IsSuperTypeOfResult::createMaybe()); } return $isSuperType; } elseif ($type instanceof self) { return $this->type->isSuperTypeOf($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->isClassString()->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; } 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->isClassString()->yes()) { $generic = $this->getGenericType(); $genericObjectClassNames = $generic->getObjectClassNames(); $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); if (count($genericObjectClassNames) === 1) { if ($reflectionProvider->hasClass($genericObjectClassNames[0])) { $classReflection = $reflectionProvider->getClass($genericObjectClassNames[0]); if ($classReflection->isFinal() && $genericObjectClassNames[0] === $typeToRemove->getValue()) { return new NeverType(); } if ($classReflection->getAllowedSubTypes() !== null) { $objectTypeToRemove = new ObjectType($typeToRemove->getValue()); $remainingType = TypeCombinator::remove($generic, $objectTypeToRemove); if ($remainingType instanceof NeverType) { return new NeverType(); } if (!$remainingType->equals($generic)) { return new self($remainingType); } } } } elseif (count($genericObjectClassNames) > 1) { $objectTypeToRemove = new ObjectType($typeToRemove->getValue()); if ($reflectionProvider->hasClass($typeToRemove->getValue())) { $classReflection = $reflectionProvider->getClass($typeToRemove->getValue()); if ($classReflection->isFinal()) { $remainingType = TypeCombinator::remove($generic, $objectTypeToRemove); if ($remainingType instanceof NeverType) { return new NeverType(); } return new self($remainingType); } } } } return parent::tryRemove($typeToRemove); } public function hasTemplateOrLateResolvableType(): bool { return $this->type->hasTemplateOrLateResolvableType(); } } */ private array $types; private ?ClassReflection $classReflection; /** * @var array */ private array $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 fn(Type $type, ?\PHPStan\Type\Generic\TemplateTypeVariance $variance = null): string => \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; } public function getReferencedClasses(): array { $classes = parent::getReferencedClasses(); foreach ($this->types as $type) { $referencedClasses = RecursionGuard::runOnObjectIdentity($type, static fn() => $type->getReferencedClasses()); if ($referencedClasses instanceof ErrorType) { continue; } foreach ($referencedClasses 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): AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return $this->isSuperTypeOfInternal($type, \true)->toAcceptsResult(); } public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOf($this); } return $this->isSuperTypeOfInternal($type, \false); } private function isSuperTypeOfInternal(Type $type, bool $acceptsContext): IsSuperTypeOfResult { $nakedSuperTypeOf = parent::isSuperTypeOf($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()) { $results[] = $thisVariance->isValidVariance($templateType, $this->types[$i], $ancestor->types[$i]); } else { $results[] = $templateType->isValidVariance($this->types[$i], $ancestor->types[$i]); } $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): ExtendedPropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $prototype = parent::getUnresolvedPropertyPrototype($propertyName, $scope); return $prototype->doNotResolveTemplateTypeMapToBounds(); } public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $prototype = parent::getUnresolvedInstancePropertyPrototype($propertyName, $scope); return $prototype->doNotResolveTemplateTypeMapToBounds(); } public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedStaticPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $prototype = parent::getUnresolvedStaticPropertyPrototype($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); } /** * @param TemplateTypeVariance[] $variances */ public function changeVariances(array $variances): self { return $this->recreate($this->getClassName(), $this->getTypes(), $this->getSubtractedType(), $variances); } public function changeSubtractedType(?Type $subtractedType): Type { $result = parent::changeSubtractedType($subtractedType); // Parent handles sealed type exhaustiveness (returning NeverType when all // allowed subtypes are subtracted, or a single remaining subtype). if (!$result instanceof ObjectType || $result->getClassName() !== $this->getClassName()) { return $result; } 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 fn(Type $type) => $type->toPhpDocNode(), $this->types), array_map(static fn(\PHPStan\Type\Generic\TemplateTypeVariance $variance) => $variance->toPhpDocNodeVariance(), $this->variances)); } public function hasTemplateOrLateResolvableType(): bool { foreach ($this->types as $type) { if (!$type->hasTemplateOrLateResolvableType()) { continue; } return \true; } if ($this->getSubtractedType() === null) { return \false; } return $this->getSubtractedType()->hasTemplateOrLateResolvableType(); } } */ private array $types; private ?Type $subtractedType; /** * @var array */ private array $variances; private ?ObjectType $staticObjectType = null; /** * @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); } /** * @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 (array_keys($templateTags) as $typeName) { 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 isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOf($this); } if ($type instanceof self) { return $this->getStaticObjectType()->isSuperTypeOf($type->getStaticObjectType()); } return parent::isSuperTypeOf($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 fn(Type $type) => $type->toPhpDocNode(), $this->types), array_map(static fn(\PHPStan\Type\Generic\TemplateTypeVariance $variance) => $variance->toPhpDocNodeVariance(), $this->variances)); } public function hasTemplateOrLateResolvableType(): bool { foreach ($this->types as $type) { if (!$type->hasTemplateOrLateResolvableType()) { continue; } return \true; } if ($this->subtractedType === null) { return \false; } return $this->subtractedType->hasTemplateOrLateResolvableType(); } } */ 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 withTypes(Type $keyType, Type $itemType): ArrayType { return new self($this->scope, $this->strategy, $this->variance, $this->name, new ArrayType($keyType, $itemType), $this->default); } } */ 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 list $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; } } */ 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; } } */ 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 recreate(array $keyTypes, array $valueTypes, array $nextAutoIndexes = [0], array $optionalKeys = [], ?TrinaryLogic $isList = null): ConstantArrayType { return new self($this->scope, $this->strategy, $this->variance, $this->name, new ConstantArrayType($keyTypes, $valueTypes, $nextAutoIndexes, $optionalKeys, $isList), $this->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, 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; } } */ 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; } } */ 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; } } */ 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); } } */ 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; } } */ 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; } } */ 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; } } */ 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()); } } */ 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): IsSuperTypeOfResult { return $this->isSuperTypeOf($type); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { $isSuperType = $this->isSuperTypeOf($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); } public function getClassStringType(): Type { return new \PHPStan\Type\Generic\GenericClassStringType($this); } } */ 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, NullType $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, 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; } } */ 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; } } */ 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; } public function getClassStringType(): Type { return new \PHPStan\Type\Generic\GenericClassStringType($this); } } */ 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): IsSuperTypeOfResult { return $this->isSuperTypeOf($type); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return $this->isSubTypeOf($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, StringType $bound, ?Type $default) { parent::__construct(); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } } isAcceptedBy($left, $strictTypes); } else { $accepts = $left->getBound()->accepts($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; } } getName(), $tag->getBound(), $tag->getVariance(), \null, $tag->getDefault()); } } hasTemplateOrLateResolvableType()) { return $type; } $references = $type->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; } } */ private array $types; /** * @var array */ private array $lowerBoundTypes; private static ?\PHPStan\Type\Generic\TemplateTypeMap $empty = null; private ?\PHPStan\Type\Generic\TemplateTypeMap $resolvedToBounds = null; /** * @api * @param array $types Concrete types for each template parameter (upper bounds) * @param array $lowerBoundTypes Types inferred from contravariant positions */ 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); } /** * Replaces unresolved TemplateType values with their declared bounds (or defaults). */ public function resolveToBounds(): self { if ($this->resolvedToBounds !== null) { return $this->resolvedToBounds; } return $this->resolvedToBounds = $this->map(static fn(string $name, Type $type): Type => TypeTraverser::map($type, static fn(Type $type, callable $traverse): Type => $type instanceof \PHPStan\Type\Generic\TemplateType ? $traverse($type->getDefault() ?? $type->getBound()) : $traverse($type))); } } isAcceptedBy($left, $strictTypes); } return $left->getBound()->accepts($right, $strictTypes); } public function isArgument(): bool { return \false; } } ` or `Comparable`), * this class pairs the TemplateType with its positional variance — whether T appears * in a covariant position (return type), contravariant position (parameter type), * invariant position, or bivariant position. * * Used by Type::getReferencedTemplateTypes() to report all template types within * a type along with their variance context. This information is used for: * - Template type inference (knowing the variance affects how types are inferred) * - Variance validation (checking that @template-covariant types only appear in * covariant positions) */ final class TemplateTypeReference { private \PHPStan\Type\Generic\TemplateType $type; private \PHPStan\Type\Generic\TemplateTypeVariance $positionVariance; public function __construct(\PHPStan\Type\Generic\TemplateType $type, \PHPStan\Type\Generic\TemplateTypeVariance $positionVariance) { $this->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; } } 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); } } 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 = ''; if ($this->default !== null) { $recursionGuard = RecursionGuard::runOnObjectIdentity($this->default, fn() => $this->default->describe($level)); if (!$recursionGuard instanceof ErrorType) { $defaultDescription .= sprintf(' = %s', $recursionGuard); } } return sprintf('%s%s%s', $this->name, $boundDescription, $defaultDescription); }; return $level->handle($basicDescription, $basicDescription, fn(): string => 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): IsSuperTypeOfResult { return $this->variance->isValidVariance($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): 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->accepts($this, $strictTypes); } if (!$acceptingType instanceof \PHPStan\Type\Generic\TemplateType) { return $acceptingType->accepts($this->getBound(), $strictTypes); } if ($this->getScope()->equals($acceptingType->getScope()) && $this->getName() === $acceptingType->getName()) { return $acceptingType->getBound()->accepts($this->getBound(), $strictTypes); } return $acceptingType->getBound()->accepts($this->getBound(), $strictTypes)->and(new AcceptsResult(TrinaryLogic::createMaybe(), [])); } public function accepts(Type $type, bool $strictTypes): AcceptsResult { return $this->strategy->accepts($this, $type, $strictTypes); } public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof \PHPStan\Type\Generic\TemplateType || $type instanceof IntersectionType) { return $type->isSubTypeOf($this); } if ($type instanceof NeverType) { return IsSuperTypeOfResult::createYes(); } return $this->getBound()->isSuperTypeOf($type)->and(IsSuperTypeOfResult::createMaybe()); } public function isSubTypeOf(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->isSuperTypeOf($this); } if (!$type instanceof \PHPStan\Type\Generic\TemplateType) { return $type->isSuperTypeOf($this->getBound()); } if ($this->getScope()->equals($type->getScope()) && $this->getName() === $type->getName()) { return $type->getBound()->isSuperTypeOf($this->getBound()); } return $type->getBound()->isSuperTypeOf($this->getBound())->and(IsSuperTypeOfResult::createMaybe()); } public function toArrayKey(): Type { return $this; } public function toCoercedArgumentType(bool $strictTypes): Type { return $this; } public function toClassConstantType(ReflectionProvider $reflectionProvider): Type { // `T::class` keeps the template variable visible — express the // result as `class-string&literal-string` rather than the bound // class, regardless of whether `T` has an object bound or not. // Only when the bound is a known final class does the result // collapse to the literal class name (the bound is the only // possible substitution in that case). if ($this->isNull()->yes()) { return new NullType(); } $classNames = $this->getObjectClassNames(); if (count($classNames) === 1 && $reflectionProvider->hasClass($classNames[0])) { $reflection = $reflectionProvider->getClass($classNames[0]); if ($reflection->isFinalByKeyword()) { return new ConstantStringType($reflection->getName(), \true); } } return new IntersectionType([new \PHPStan\Type\Generic\GenericClassStringType($this), new AccessoryLiteralStringType()]); } 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())); $boundMatches = $resolvedBound->isSuperTypeOf($receivedType); if ($boundMatches->yes()) { return (new \PHPStan\Type\Generic\TemplateTypeMap([$this->name => $receivedType]))->union($map); } if ($boundMatches->maybe() && $receivedType instanceof UnionType) { $matchingTypes = []; foreach ($receivedType->getTypes() as $innerType) { if (!$resolvedBound->isSuperTypeOf($innerType)->yes()) { continue; } $matchingTypes[] = $innerType; } if (count($matchingTypes) > 0) { $filteredType = TypeCombinator::union(...$matchingTypes); return (new \PHPStan\Type\Generic\TemplateTypeMap([$this->name => $filteredType]))->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; } 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 { if ($typeToRemove instanceof \PHPStan\Type\Generic\TemplateType) { return null; } $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); } public function hasTemplateOrLateResolvableType(): bool { return \true; } } `: * * - **Invariant** (default): `Box` is NOT a subtype of `Box`, even though * Cat extends Animal. The type argument must match exactly. Declared with `@template T`. * - **Covariant**: `Box` IS a subtype of `Box`. Safe when T only appears * in "output" positions (return types). Declared with `@template-covariant T`. * - **Contravariant**: `Box` IS a subtype of `Box`. Safe when T only * appears in "input" positions (parameter types). Declared with `@template-contravariant T`. * - **Bivariant**: The type argument is ignored for subtyping purposes. Rarely used. * - **Static**: Special variance for `static` return type in template context. * * Variance composition follows standard rules — e.g. covariant composed with * contravariant yields contravariant. This is used when template types appear * inside nested generic types. * * @api */ final class TemplateTypeVariance { private int $value; private const INVARIANT = 1; private const COVARIANT = 2; private const CONTRAVARIANT = 3; private const STATIC = 4; private const BIVARIANT = 5; /** @var self[] */ private static array $registry; private function __construct(int $value) { $this->value = $value; } private static function create(int $value): self { self::$registry[$value] ??= new self($value); return self::$registry[$value]; } /** Type argument must match exactly. This is the default for @template T. */ public static function createInvariant(): self { return self::create(self::INVARIANT); } /** Subtyping flows with the type argument: Cat <: Animal ⟹ Box <: Box. */ public static function createCovariant(): self { return self::create(self::COVARIANT); } /** Subtyping flows against the type argument: Cat <: Animal ⟹ Box <: Box. */ public static function createContravariant(): self { return self::create(self::CONTRAVARIANT); } /** Special variance for static return type in template context. */ public static function createStatic(): self { return self::create(self::STATIC); } /** Type argument is ignored for subtyping — all types are compatible. */ 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 ($this->invariant()) { return self::createInvariant(); } if ($this->bivariant()) { return self::createBivariant(); } return $other; } public function isValidVariance(\PHPStan\Type\Generic\TemplateType $templateType, Type $a, Type $b): IsSuperTypeOfResult { if ($b instanceof NeverType) { return IsSuperTypeOfResult::createYes(); } if ($a instanceof MixedType && !$a instanceof \PHPStan\Type\Generic\TemplateType) { return IsSuperTypeOfResult::createYes(); } if ($a instanceof BenevolentUnionType) { if (!$a->isSuperTypeOf($b)->no()) { return IsSuperTypeOfResult::createYes(); } } if ($b instanceof BenevolentUnionType) { if (!$b->isSuperTypeOf($a)->no()) { return IsSuperTypeOfResult::createYes(); } } if ($b instanceof MixedType && !$b instanceof \PHPStan\Type\Generic\TemplateType) { return IsSuperTypeOfResult::createYes(); } if ($this->invariant()) { $result = $a->equals($b); $reasons = []; if (!$result) { if ($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 IsSuperTypeOfResult(TrinaryLogic::createFromBoolean($result), $reasons); } if ($this->covariant()) { return $a->isSuperTypeOf($b); } if ($this->contravariant()) { return $b->isSuperTypeOf($a); } if ($this->bivariant()) { return IsSuperTypeOfResult::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(); } } */ private array $variances; private static ?\PHPStan\Type\Generic\TemplateTypeVarianceMap $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, 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; } } describe($level); if ($variance === null || $variance->invariant()) { return $describedType; } if ($variance->bivariant()) { return '*'; } return sprintf('%s %s', $variance->describe(), $describedType); } } 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 ConstExprStringNode($this->templateTypeName, ConstExprStringNode::SINGLE_QUOTED))]); } } 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): \PHPStan\Type\AcceptsResult { if ($type instanceof parent) { return $this->isSuperTypeOf($type)->toAcceptsResult(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return \PHPStan\Type\AcceptsResult::createNo(); } public function isSuperTypeOf(\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->isSubTypeOf($this); } return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } public function isSubTypeOf(\PHPStan\Type\Type $otherType): \PHPStan\Type\IsSuperTypeOfResult { if ($otherType instanceof parent) { return $otherType->isSuperTypeOf($this); } if ($otherType instanceof \PHPStan\Type\UnionType) { return $this->isSubTypeOfUnionWithReason($otherType); } if ($otherType instanceof \PHPStan\Type\IntersectionType) { return $otherType->isSuperTypeOf($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(), fn(\PHPStan\Type\Type $type): bool => $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(fn(\PHPStan\Type\Type $innerType) => $this->isSubTypeOf($innerType), $otherType->getTypes())); } public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes): \PHPStan\Type\AcceptsResult { return $this->isSubTypeOf($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, PhpVersion $phpVersion): TrinaryLogic { if ($this->min === null) { $minIsSmaller = TrinaryLogic::createYes(); } else { $minIsSmaller = (new ConstantIntegerType($this->min))->isSmallerThan($otherType, $phpVersion); } if ($this->max === null) { $maxIsSmaller = TrinaryLogic::createNo(); } else { $maxIsSmaller = (new ConstantIntegerType($this->max))->isSmallerThan($otherType, $phpVersion); } // 0 can have different results in contrast to the interval edges, see https://3v4l.org/iGoti $zeroInt = new ConstantIntegerType(0); if (!$zeroInt->isSuperTypeOf($this)->no()) { return TrinaryLogic::extremeIdentity($zeroInt->isSmallerThan($otherType, $phpVersion), $minIsSmaller, $maxIsSmaller); } return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller); } public function isSmallerThanOrEqual(\PHPStan\Type\Type $otherType, PhpVersion $phpVersion): TrinaryLogic { if ($this->min === null) { $minIsSmaller = TrinaryLogic::createYes(); } else { $minIsSmaller = (new ConstantIntegerType($this->min))->isSmallerThanOrEqual($otherType, $phpVersion); } if ($this->max === null) { $maxIsSmaller = TrinaryLogic::createNo(); } else { $maxIsSmaller = (new ConstantIntegerType($this->max))->isSmallerThanOrEqual($otherType, $phpVersion); } // 0 can have different results in contrast to the interval edges, see https://3v4l.org/iGoti $zeroInt = new ConstantIntegerType(0); if (!$zeroInt->isSuperTypeOf($this)->no()) { return TrinaryLogic::extremeIdentity($zeroInt->isSmallerThanOrEqual($otherType, $phpVersion), $minIsSmaller, $maxIsSmaller); } return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller); } public function isGreaterThan(\PHPStan\Type\Type $otherType, PhpVersion $phpVersion): TrinaryLogic { if ($this->min === null) { $minIsSmaller = TrinaryLogic::createNo(); } else { $minIsSmaller = $otherType->isSmallerThan(new ConstantIntegerType($this->min), $phpVersion); } if ($this->max === null) { $maxIsSmaller = TrinaryLogic::createYes(); } else { $maxIsSmaller = $otherType->isSmallerThan(new ConstantIntegerType($this->max), $phpVersion); } // 0 can have different results in contrast to the interval edges, see https://3v4l.org/iGoti $zeroInt = new ConstantIntegerType(0); if (!$zeroInt->isSuperTypeOf($this)->no()) { return TrinaryLogic::extremeIdentity($otherType->isSmallerThan($zeroInt, $phpVersion), $minIsSmaller, $maxIsSmaller); } return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller); } public function isGreaterThanOrEqual(\PHPStan\Type\Type $otherType, PhpVersion $phpVersion): TrinaryLogic { if ($this->min === null) { $minIsSmaller = TrinaryLogic::createNo(); } else { $minIsSmaller = $otherType->isSmallerThanOrEqual(new ConstantIntegerType($this->min), $phpVersion); } if ($this->max === null) { $maxIsSmaller = TrinaryLogic::createYes(); } else { $maxIsSmaller = $otherType->isSmallerThanOrEqual(new ConstantIntegerType($this->max), $phpVersion); } // 0 can have different results in contrast to the interval edges, see https://3v4l.org/iGoti $zeroInt = new ConstantIntegerType(0); if (!$zeroInt->isSuperTypeOf($this)->no()) { return TrinaryLogic::extremeIdentity($otherType->isSmallerThanOrEqual($zeroInt, $phpVersion), $minIsSmaller, $maxIsSmaller); } return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller); } public function getSmallerType(PhpVersion $phpVersion): \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(PhpVersion $phpVersion): \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(PhpVersion $phpVersion): \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(PhpVersion $phpVersion): \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 { $zeroInt = new ConstantIntegerType(0); if ($zeroInt->isSuperTypeOf($this)->no()) { if ($type->isTrue()->yes()) { return new ConstantBooleanType(\true); } if ($type->isFalse()->yes()) { return new ConstantBooleanType(\false); } } if ($this->isSmallerThan($type, $phpVersion)->yes() || $this->isGreaterThan($type, $phpVersion)->yes()) { return new ConstantBooleanType(\false); } return parent::looseCompare($type, $phpVersion); } } toFloat(), $this->toString(), $this->toBoolean()); } return \PHPStan\Type\TypeCombinator::union($this, $this->toFloat()); } public function isOffsetAccessLegal(): TrinaryLogic { return TrinaryLogic::createYes(); } 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::createYes(); } public function isScalar(): TrinaryLogic { return TrinaryLogic::createYes(); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion): \PHPStan\Type\BooleanType { if ($type->isArray()->yes()) { return new ConstantBooleanType(\false); } if ($phpVersion->nonNumericStringAndIntegerIsFalseOnLooseComparison() && $type->isString()->yes() && $type->isNumericString()->no()) { return new ConstantBooleanType(\false); } return new \PHPStan\Type\BooleanType(); } public function tryRemove(\PHPStan\Type\Type $typeToRemove): ?\PHPStan\Type\Type { if ($typeToRemove instanceof \PHPStan\Type\IntegerRangeType || $typeToRemove instanceof ConstantIntegerType) { if ($typeToRemove instanceof \PHPStan\Type\IntegerRangeType) { $removeValueMin = $typeToRemove->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'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } */ private array $types; use NonRemoveableTypeTrait; use NonGeneralizableTypeTrait; private bool $sortedTypes = \false; private ?TrinaryLogic $isBoolean = null; private ?TrinaryLogic $isFloat = null; private ?TrinaryLogic $isInteger = null; private ?TrinaryLogic $isString = null; private ?TrinaryLogic $isArray = null; private ?TrinaryLogic $isList = null; private ?TrinaryLogic $isConstantArray = null; private ?TrinaryLogic $isOversizedArray = null; private ?TrinaryLogic $isOffsetAccessible = null; private ?TrinaryLogic $isIterableAtLeastOnce = null; private ?TrinaryLogic $isConstantScalarValue = null; private ?TrinaryLogic $isCallable = null; /** @var array */ private array $cachedGetOffsetValueType = []; /** @var array */ private array $cachedHasOffsetValueType = []; /** * @api * @param list $types */ public function __construct(array $types) { $this->types = $types; if (count($types) < 2) { throw new ShouldNotHappenException(sprintf('Cannot create %s with: %s', self::class, implode(', ', array_map(static fn(\PHPStan\Type\Type $type): string => $type->describe(\PHPStan\Type\VerbosityLevel::value()), $types)))); } } /** * @return list */ public function getTypes(): array { return $this->types; } /** * @return list */ 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 { if ($this->isCallable()->yes() && $this->isArray()->yes()) { $builder = ConstantArrayTypeBuilder::createEmpty(); $zero = new ConstantIntegerType(0); $builder->setOffsetValueType($zero, $this->getOffsetValueType($zero)); $one = new ConstantIntegerType(1); $builder->setOffsetValueType($one, $this->getOffsetValueType($one)); $constantArray = $builder->getArray(); if (!$constantArray instanceof ConstantArrayType) { throw new ShouldNotHappenException(); } return [$builder->getArray()]; } $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 $otherType, bool $strictTypes): \PHPStan\Type\AcceptsResult { $result = \PHPStan\Type\AcceptsResult::createYes(); foreach ($this->types as $type) { $result = $result->and($type->accepts($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): \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 fn(\PHPStan\Type\Type $innerType) => $innerType->isSuperTypeOf($otherType), $this->types)); } public function isSubTypeOf(\PHPStan\Type\Type $otherType): \PHPStan\Type\IsSuperTypeOfResult { if (($otherType instanceof self || $otherType instanceof \PHPStan\Type\UnionType) && !$otherType instanceof TemplateType) { return $otherType->isSuperTypeOf($this); } $result = \PHPStan\Type\IsSuperTypeOfResult::lazyMaxMin($this->types, static fn(\PHPStan\Type\Type $innerType) => $otherType->isSuperTypeOf($innerType)); if (!$result->no() && $this->isOversizedArray()->yes() && !$otherType->isIterableAtLeastOnce()->no()) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } return $result; } public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes): \PHPStan\Type\AcceptsResult { $result = \PHPStan\Type\AcceptsResult::lazyMaxMin($this->types, static fn(\PHPStan\Type\Type $innerType) => $acceptingType->accepts($innerType, $strictTypes)); // lazyMaxMin can short-circuit to Yes when array (inside e.g. array&callable // or array&hasOffsetValue) is accepted by a specific array type like array, // because MixedType::isAcceptedBy() always returns Yes. The isSuperTypeOf check // considers the intersection holistically and catches these false positives. if ($result->yes()) { $isSuperType = $acceptingType->isSuperTypeOf($this); if ($isSuperType->no()) { return $isSuperType->toAcceptsResult(); } } 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(fn(): string => $this->describeType($level), fn(): string => $this->describeItself($level, \true), fn(): string => $this->describeItself($level, \false)); } private function describeType(\PHPStan\Type\VerbosityLevel $level): string { $typeNames = []; $isList = $this->isList()->yes(); $valueType = null; foreach ($this->getSortedTypes() as $type) { if ($isList) { if ($type instanceof \PHPStan\Type\ArrayType || $type instanceof ConstantArrayType) { $valueType = $type->getIterableValueType(); continue; } if ($type instanceof NonEmptyArrayType) { continue; } } if ($type instanceof AccessoryType) { continue; } $typeNames[] = $type->generalize(\PHPStan\Type\GeneralizePrecision::lessSpecific())->describe($level); } if ($isList) { $isMixedValueType = $valueType instanceof \PHPStan\Type\MixedType && $valueType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed' && !$valueType->isExplicitMixed(); $innerType = ''; if ($valueType !== null && !$isMixedValueType) { $innerType = sprintf('<%s>', $valueType->describe($level)); } $typeNames[] = 'list' . $innerType; } usort($typeNames, static function ($a, $b) { $cmp = strcasecmp($a, $b); if ($cmp !== 0) { return $cmp; } return $a <=> $b; }); return implode('&', $typeNames); } private function describeItself(\PHPStan\Type\VerbosityLevel $level, bool $skipAccessoryTypes): string { $baseTypes = []; $typesToDescribe = []; $skipTypeNames = []; $nonEmptyStr = \false; $nonFalsyStr = \false; $isList = $this->isList()->yes(); $isArray = $this->isArray()->yes(); $isNonEmptyArray = $this->isIterableAtLeastOnce()->yes(); // When a TemplateArrayType carries the array refinement, we describe // it via its own describe() (e.g. "T of array") rather than collapsing // it into a generic `array<...>` prefix. In that case the // `NonEmptyArrayType` and `AccessoryArrayListType` markers must // describe themselves explicitly — they cannot be absorbed into a // non-existent `non-empty-array` prefix. $hasTemplateArray = \false; if ($isArray || $isList) { foreach ($this->types as $type) { if ($type instanceof TemplateArrayType) { $hasTemplateArray = \true; break; } } } $describedTypes = []; 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() && !$level->isCache()) { 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 ($isList || $isArray) { if ($type instanceof TemplateArrayType) { // Preserve the template's own describe (e.g. "T of array") // instead of collapsing it to a generic array shape — the // other intersection members already carry the array // refinement. $describedTypes[$i] = $type->describe($level); continue; } if ($type instanceof \PHPStan\Type\ArrayType) { $keyType = $type->getKeyType(); $valueType = $type->getItemType(); if ($isList) { $isMixedValueType = $valueType instanceof \PHPStan\Type\MixedType && $valueType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed' && !$valueType->isExplicitMixed(); $valueTypeDescription = ''; if (!$isMixedValueType) { $valueTypeDescription = sprintf('<%s>', $valueType->describe($level)); } $describedTypes[$i] = ($isNonEmptyArray ? 'non-empty-list' : 'list') . $valueTypeDescription; } else { $isMixedKeyType = $keyType instanceof \PHPStan\Type\MixedType && $keyType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed' && !$keyType->isExplicitMixed(); $isMixedValueType = $valueType instanceof \PHPStan\Type\MixedType && $valueType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed' && !$valueType->isExplicitMixed(); $typeDescription = ''; if (!$isMixedKeyType) { $typeDescription = sprintf('<%s, %s>', $keyType->describe($level), $valueType->describe($level)); } elseif (!$isMixedValueType) { $typeDescription = sprintf('<%s>', $valueType->describe($level)); } $describedTypes[$i] = ($isNonEmptyArray ? 'non-empty-array' : 'array') . $typeDescription; } continue; } elseif ($type instanceof ConstantArrayType) { $description = $type->describe($level); $kind = str_starts_with($description, 'list') ? 'list' : 'array'; $descriptionWithoutKind = substr($description, strlen($kind)); $begin = $isList ? 'list' : 'array'; if ($isNonEmptyArray && !$type->isIterableAtLeastOnce()->yes()) { $begin = 'non-empty-' . $begin; } $describedTypes[$i] = $begin . $descriptionWithoutKind; continue; } if ($type instanceof NonEmptyArrayType || $type instanceof AccessoryArrayListType) { if ($hasTemplateArray) { $describedTypes[$i] = $type->describe($level); } 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; } 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 (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 fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getTemplateType($ancestorClassName, $templateTypeName)); } public function isObject(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isObject()); } public function getClassStringType(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getClassStringType()); } public function isEnum(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isEnum()); } public function canAccessProperties(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->canAccessProperties()); } public function hasProperty(string $propertyName): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->hasProperty($propertyName)); } public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { 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 MissingPropertyFromReflectionException($this->describe(\PHPStan\Type\VerbosityLevel::typeOnly()), $propertyName); } if ($propertiesCount === 1) { return $propertyPrototypes[0]; } return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes); } public function hasInstanceProperty(string $propertyName): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->hasInstanceProperty($propertyName)); } public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $propertyPrototypes = []; foreach ($this->types as $type) { if (!$type->hasInstanceProperty($propertyName)->yes()) { continue; } $propertyPrototypes[] = $type->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->withFechedOnType($this); } $propertiesCount = count($propertyPrototypes); if ($propertiesCount === 0) { throw new MissingPropertyFromReflectionException($this->describe(\PHPStan\Type\VerbosityLevel::typeOnly()), $propertyName); } if ($propertiesCount === 1) { return $propertyPrototypes[0]; } return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes); } public function hasStaticProperty(string $propertyName): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->hasStaticProperty($propertyName)); } public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedStaticPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $propertyPrototypes = []; foreach ($this->types as $type) { if (!$type->hasStaticProperty($propertyName)->yes()) { continue; } $propertyPrototypes[] = $type->getUnresolvedStaticPropertyPrototype($propertyName, $scope)->withFechedOnType($this); } $propertiesCount = count($propertyPrototypes); if ($propertiesCount === 0) { throw new MissingPropertyFromReflectionException($this->describe(\PHPStan\Type\VerbosityLevel::typeOnly()), $propertyName); } if ($propertiesCount === 1) { return $propertyPrototypes[0]; } return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes); } public function canCallMethods(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->canCallMethods()); } public function hasMethod(string $methodName): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $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 MissingMethodFromReflectionException($this->describe(\PHPStan\Type\VerbosityLevel::typeOnly()), $methodName); } if ($methodsCount === 1) { return $methodPrototypes[0]; } return new IntersectionTypeUnresolvedMethodPrototypeReflection($methodName, $methodPrototypes); } public function canAccessConstants(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->canAccessConstants()); } public function hasConstant(string $constantName): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->hasConstant($constantName)); } public function getConstant(string $constantName): ClassConstantReflection { foreach ($this->types as $type) { if ($type->hasConstant($constantName)->yes()) { return $type->getConstant($constantName); } } throw new MissingConstantFromReflectionException($this->describe(\PHPStan\Type\VerbosityLevel::typeOnly()), $constantName); } public function isIterable(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isIterable()); } public function isIterableAtLeastOnce(): TrinaryLogic { if ($this->isCallable()->yes() && $this->isArray()->yes()) { return TrinaryLogic::createYes(); } return $this->isIterableAtLeastOnce ??= $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isIterableAtLeastOnce(), static fn(\PHPStan\Type\Type $type): bool => !$type->isIterable()->no()); } public function getArraySize(): \PHPStan\Type\Type { if ($this->isCallable()->yes() && $this->isArray()->yes()) { return new ConstantIntegerType(2); } $arraySize = $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getArraySize()); $knownOffsets = []; foreach ($this->types as $type) { if (!$type instanceof HasOffsetValueType && !$type instanceof HasOffsetType) { continue; } $knownOffsets[$type->getOffsetType()->getValue()] = \true; } if ($this->isList()->yes() && $this->isIterableAtLeastOnce()->yes()) { $knownOffsets[0] = \true; } if ($knownOffsets !== []) { return \PHPStan\Type\TypeCombinator::intersect($arraySize, \PHPStan\Type\IntegerRangeType::fromInterval(count($knownOffsets), null)); } return $arraySize; } public function getIterableKeyType(): \PHPStan\Type\Type { if ($this->isCallable()->yes() && $this->isArray()->yes()) { return new \PHPStan\Type\UnionType([new ConstantIntegerType(0), new ConstantIntegerType(1)]); } return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getIterableKeyType()); } public function getFirstIterableKeyType(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getIterableKeyType()); } public function getLastIterableKeyType(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getIterableKeyType()); } public function getIterableValueType(): \PHPStan\Type\Type { $result = $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getIterableValueType()); if ($this->isCallable()->yes() && $this->isArray()->yes()) { return \PHPStan\Type\TypeCombinator::intersect($result, new \PHPStan\Type\UnionType([new \PHPStan\Type\ObjectWithoutClassType(), new \PHPStan\Type\IntersectionType([new \PHPStan\Type\StringType(), new AccessoryNonFalsyStringType()])])); } return $result; } public function getFirstIterableValueType(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getIterableValueType()); } public function getLastIterableValueType(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getIterableValueType()); } public function isArray(): TrinaryLogic { return $this->isArray ??= $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isArray()); } public function isConstantArray(): TrinaryLogic { if ($this->isCallable()->yes() && $this->isArray()->yes()) { return TrinaryLogic::createYes(); } return $this->isConstantArray ??= $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isConstantArray()); } public function isOversizedArray(): TrinaryLogic { return $this->isOversizedArray ??= $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isOversizedArray()); } public function isList(): TrinaryLogic { if ($this->isCallable()->yes() && $this->isArray()->yes()) { return TrinaryLogic::createYes(); } return $this->isList ??= $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isList()); } public function isString(): TrinaryLogic { return $this->isString ??= $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isString()); } public function isNumericString(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isNumericString()); } public function isNonEmptyString(): TrinaryLogic { if ($this->isCallable()->yes() && $this->isString()->yes()) { return TrinaryLogic::createYes(); } return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isNonEmptyString()); } public function isNonFalsyString(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isNonFalsyString()); } public function isLiteralString(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isLiteralString()); } public function isLowercaseString(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isLowercaseString()); } public function isUppercaseString(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isUppercaseString()); } public function isClassString(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isClassString()); } public function getClassStringObjectType(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getClassStringObjectType()); } public function getObjectTypeOrClassStringObjectType(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getObjectTypeOrClassStringObjectType()); } public function isVoid(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isScalar()); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion): \PHPStan\Type\BooleanType { return $this->intersectResults(static fn(\PHPStan\Type\Type $innerType): TrinaryLogic => $innerType->looseCompare($type, $phpVersion)->toTrinaryLogic())->toBooleanType(); } public function isOffsetAccessible(): TrinaryLogic { return $this->isOffsetAccessible ??= $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isOffsetAccessible()); } public function isOffsetAccessLegal(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isOffsetAccessLegal()); } public function hasOffsetValueType(\PHPStan\Type\Type $offsetType): TrinaryLogic { $cacheKey = $offsetType->describe(\PHPStan\Type\VerbosityLevel::cache()); if (isset($this->cachedHasOffsetValueType[$cacheKey])) { return $this->cachedHasOffsetValueType[$cacheKey]; } return $this->cachedHasOffsetValueType[$cacheKey] = $this->doHasOffsetValueType($offsetType); } private function doHasOffsetValueType(\PHPStan\Type\Type $offsetType): TrinaryLogic { if ($this->isCallable()->yes() && $this->isArray()->yes()) { $arrayKeyOffsetType = $offsetType->toArrayKey(); $callableArrayOffsetType = new \PHPStan\Type\UnionType([new ConstantIntegerType(0), new ConstantIntegerType(1)]); return $callableArrayOffsetType->isSuperTypeOf($arrayKeyOffsetType)->result; } if ($this->isList()->yes()) { $arrayKeyOffsetType = $offsetType->toArrayKey(); $negative = \PHPStan\Type\IntegerRangeType::fromInterval(null, -1); if ($negative->isSuperTypeOf($arrayKeyOffsetType)->yes()) { return TrinaryLogic::createNo(); } $size = $this->getArraySize(); if ($size instanceof \PHPStan\Type\IntegerRangeType && $size->getMin() !== null) { $knownOffsets = \PHPStan\Type\IntegerRangeType::fromInterval(0, $size->getMin() - 1); } elseif ($size instanceof ConstantIntegerType) { $knownOffsets = \PHPStan\Type\IntegerRangeType::fromInterval(0, $size->getValue() - 1); } elseif ($this->isIterableAtLeastOnce()->yes()) { $knownOffsets = new ConstantIntegerType(0); } else { $knownOffsets = null; } if ($knownOffsets !== null && $knownOffsets->isSuperTypeOf($arrayKeyOffsetType)->yes()) { return TrinaryLogic::createYes(); } foreach ($this->types as $type) { if (!$type instanceof HasOffsetValueType && !$type instanceof HasOffsetType) { continue; } foreach ($type->getOffsetType()->getConstantScalarValues() as $constantScalarValue) { if (!is_int($constantScalarValue)) { continue; } if (\PHPStan\Type\IntegerRangeType::fromInterval(0, $constantScalarValue)->isSuperTypeOf($arrayKeyOffsetType)->yes()) { return TrinaryLogic::createYes(); } } } } return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->hasOffsetValueType($offsetType)); } public function getOffsetValueType(\PHPStan\Type\Type $offsetType): \PHPStan\Type\Type { $cacheKey = $offsetType->describe(\PHPStan\Type\VerbosityLevel::cache()); if (isset($this->cachedGetOffsetValueType[$cacheKey])) { return $this->cachedGetOffsetValueType[$cacheKey]; } return $this->cachedGetOffsetValueType[$cacheKey] = $this->doGetOffsetValueType($offsetType); } private function doGetOffsetValueType(\PHPStan\Type\Type $offsetType): \PHPStan\Type\Type { $result = $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getOffsetValueType($offsetType)); if ($this->isOversizedArray()->yes()) { return \PHPStan\Type\TypeUtils::toBenevolentUnion($result); } if ($this->isCallable()->yes() && $this->isArray()->yes()) { $arrayKeyOffsetType = $offsetType->toArrayKey(); if ((new ConstantIntegerType(0))->isSuperTypeOf($arrayKeyOffsetType)->yes()) { $narrowedType = new \PHPStan\Type\UnionType([new \PHPStan\Type\ClassStringType(), new \PHPStan\Type\ObjectWithoutClassType()]); } elseif ((new ConstantIntegerType(1))->isSuperTypeOf($arrayKeyOffsetType)->yes()) { $narrowedType = new \PHPStan\Type\IntersectionType([new \PHPStan\Type\StringType(), new AccessoryNonFalsyStringType()]); } else { $narrowedType = new \PHPStan\Type\UnionType([new \PHPStan\Type\IntersectionType([new \PHPStan\Type\StringType(), new AccessoryNonFalsyStringType()]), new \PHPStan\Type\ObjectWithoutClassType()]); } $result = \PHPStan\Type\TypeCombinator::intersect($result, $narrowedType); } 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 new \PHPStan\Type\IntersectionType([new \PHPStan\Type\ArrayType(\PHPStan\Type\TypeCombinator::union($type->getKeyType(), $offsetType), \PHPStan\Type\TypeCombinator::union($type->getItemType(), $valueType)), new NonEmptyArrayType()]); }); } $result = $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->setOffsetValueType($offsetType, $valueType, $unionValues)); if ($offsetType !== null && $this->isList()->yes() && !$result->isList()->yes()) { if ($this->isIterableAtLeastOnce()->yes() && (new ConstantIntegerType(1))->isSuperTypeOf($offsetType)->yes()) { $result = \PHPStan\Type\TypeCombinator::intersect($result, new AccessoryArrayListType()); } else { foreach ($this->types as $type) { if (!$type instanceof HasOffsetValueType && !$type instanceof HasOffsetType) { continue; } foreach ($type->getOffsetType()->getConstantScalarValues() as $constantScalarValue) { if (!is_int($constantScalarValue)) { continue; } if (\PHPStan\Type\IntegerRangeType::fromInterval(0, $constantScalarValue + 1)->isSuperTypeOf($offsetType)->yes()) { $result = \PHPStan\Type\TypeCombinator::intersect($result, new AccessoryArrayListType()); break 2; } } } } } if ($this->isList()->yes() && $offsetType !== null && $offsetType->toArrayKey()->isInteger()->yes() && $this->getIterableValueType()->isArray()->yes()) { $result = \PHPStan\Type\TypeCombinator::intersect($result, new AccessoryArrayListType()); } return $result; } public function setExistingOffsetValueType(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->setExistingOffsetValueType($offsetType, $valueType)); } public function unsetOffset(\PHPStan\Type\Type $offsetType): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->unsetOffset($offsetType)); } public function getKeysArrayFiltered(\PHPStan\Type\Type $filterValueType, TrinaryLogic $strict): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getKeysArrayFiltered($filterValueType, $strict)); } public function getKeysArray(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getKeysArray()); } public function getValuesArray(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getValuesArray()); } public function chunkArray(\PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->chunkArray($lengthType, $preserveKeys)); } public function fillKeysArray(\PHPStan\Type\Type $valueType): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->fillKeysArray($valueType)); } public function flipArray(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->flipArray()); } public function intersectKeyArray(\PHPStan\Type\Type $otherArraysType): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->intersectKeyArray($otherArraysType)); } public function popArray(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->popArray()); } public function reverseArray(TrinaryLogic $preserveKeys): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->reverseArray($preserveKeys)); } public function searchArray(\PHPStan\Type\Type $needleType, ?TrinaryLogic $strict = null): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->searchArray($needleType, $strict)); } public function shiftArray(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->shiftArray()); } public function shuffleArray(): \PHPStan\Type\Type { $isList = $this->isList()->yes(); return $this->intersectTypes(static function (\PHPStan\Type\Type $type) use ($isList): \PHPStan\Type\Type { if ($isList && $type instanceof TemplateType) { return $type; } return $type->shuffleArray(); }); } public function sliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys): \PHPStan\Type\Type { $result = $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->sliceArray($offsetType, $lengthType, $preserveKeys)); if ($this->isList()->yes() && $this->isIterableAtLeastOnce()->yes() && (new ConstantIntegerType(0))->isSuperTypeOf($offsetType)->yes() && \PHPStan\Type\IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($lengthType)->yes()) { $result = \PHPStan\Type\TypeCombinator::intersect($result, new NonEmptyArrayType()); } return $result; } public function spliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, \PHPStan\Type\Type $replacementType): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->spliceArray($offsetType, $lengthType, $replacementType)); } public function makeListMaybe(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->makeListMaybe()); } public function mapValueType(callable $cb): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->mapValueType($cb)); } public function mapKeyType(callable $cb): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->mapKeyType($cb)); } public function makeAllArrayKeysOptional(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->makeAllArrayKeysOptional()); } public function changeKeyCaseArray(?int $case): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->changeKeyCaseArray($case)); } public function filterArrayRemovingFalsey(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->filterArrayRemovingFalsey()); } 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 getEnumCaseObject(): ?EnumCaseObjectType { $singleCase = null; foreach ($this->types as $type) { $caseObject = $type->getEnumCaseObject(); if ($caseObject === null) { continue; } if ($singleCase !== null) { return null; } $singleCase = $caseObject; } return $singleCase; } public function isCallable(): TrinaryLogic { return $this->isCallable ??= $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isCallable()); } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope): array { $yesAcceptors = []; foreach ($this->types as $type) { if (!$type->isCallable()->yes()) { continue; } $yesAcceptors[] = $type->getCallableParametersAcceptors($scope); } if (count($yesAcceptors) === 0) { if ($this->isCallable()->no()) { throw new ShouldNotHappenException(); } return [new TrivialParametersAcceptor()]; } $result = []; $combinations = CombinationsHelper::combinations($yesAcceptors); foreach ($combinations as $combination) { $combined = ParametersAcceptorSelector::combineAcceptors($combination); if (!$combined instanceof CallableParametersAcceptor) { throw new ShouldNotHappenException(); } $result[] = $combined; } return $result; } public function isCloneable(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isCloneable()); } public function isSmallerThan(\PHPStan\Type\Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isSmallerThan($otherType, $phpVersion)); } public function isSmallerThanOrEqual(\PHPStan\Type\Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isSmallerThanOrEqual($otherType, $phpVersion)); } public function isNull(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isNull()); } public function isConstantValue(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isConstantValue()); } public function isConstantScalarValue(): TrinaryLogic { return $this->isConstantScalarValue ??= $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $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 fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isTrue()); } public function isFalse(): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isFalse()); } public function isBoolean(): TrinaryLogic { return $this->isBoolean ??= $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isBoolean()); } public function isFloat(): TrinaryLogic { return $this->isFloat ??= $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isFloat()); } public function isInteger(): TrinaryLogic { return $this->isInteger ??= $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isInteger()); } public function isGreaterThan(\PHPStan\Type\Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $otherType->isSmallerThan($type, $phpVersion)); } public function isGreaterThanOrEqual(\PHPStan\Type\Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return $this->intersectResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $otherType->isSmallerThanOrEqual($type, $phpVersion)); } public function getSmallerType(PhpVersion $phpVersion): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getSmallerType($phpVersion)); } public function getSmallerOrEqualType(PhpVersion $phpVersion): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getSmallerOrEqualType($phpVersion)); } public function getGreaterType(PhpVersion $phpVersion): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getGreaterType($phpVersion)); } public function getGreaterOrEqualType(PhpVersion $phpVersion): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getGreaterOrEqualType($phpVersion)); } public function toBoolean(): \PHPStan\Type\BooleanType { $type = $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\BooleanType => $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 fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toNumber()); return $type; } public function toBitwiseNotType(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toBitwiseNotType()); } public function toGetClassResultType(): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toGetClassResultType()); } public function toClassConstantType(ReflectionProvider $reflectionProvider): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toClassConstantType($reflectionProvider)); } public function toObjectTypeForInstanceofCheck(): \PHPStan\Type\ClassNameToObjectTypeResult { $types = []; $uncertainty = \false; foreach ($this->getTypes() as $innerType) { $result = $innerType->toObjectTypeForInstanceofCheck(); $types[] = $result->type; if (!$result->uncertainty) { continue; } $uncertainty = \true; } return new \PHPStan\Type\ClassNameToObjectTypeResult(\PHPStan\Type\TypeCombinator::intersect(...$types), $uncertainty); } public function toObjectTypeForIsACheck(\PHPStan\Type\Type $objectOrClassType, bool $allowString, bool $allowSameClass): \PHPStan\Type\ClassNameToObjectTypeResult { $types = []; $uncertainty = \false; foreach ($this->getTypes() as $innerType) { $result = $innerType->toObjectTypeForIsACheck($objectOrClassType, $allowString, $allowSameClass); $types[] = $result->type; if (!$result->uncertainty) { continue; } $uncertainty = \true; } return new \PHPStan\Type\ClassNameToObjectTypeResult(\PHPStan\Type\TypeCombinator::intersect(...$types), $uncertainty); } public function toAbsoluteNumber(): \PHPStan\Type\Type { $type = $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toAbsoluteNumber()); return $type; } public function toString(): \PHPStan\Type\Type { $type = $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toString()); return $type; } public function toInteger(): \PHPStan\Type\Type { $type = $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toInteger()); return $type; } public function toFloat(): \PHPStan\Type\Type { $type = $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toFloat()); return $type; } public function toArray(): \PHPStan\Type\Type { $type = $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $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 fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toArrayKey()); } public function toCoercedArgumentType(bool $strictTypes): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toCoercedArgumentType($strictTypes)); } 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) { $result = $types[0]; for ($i = 1, $count = count($types); $i < $count; $i++) { $result = \PHPStan\Type\TypeCombinator::intersect($result, $types[$i]); } return $result; } return $this; } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb): \PHPStan\Type\Type { if ($this->isArray()->yes() && $right->isArray()->yes()) { $changed = \false; $newTypes = []; foreach ($this->types as $innerType) { $newKeyType = $cb($innerType->getIterableKeyType(), $right->getIterableKeyType()); $newValueType = $cb($innerType->getIterableValueType(), $right->getIterableValueType()); if ($newKeyType === $innerType->getIterableKeyType() && $newValueType === $innerType->getIterableValueType()) { $newTypes[] = $innerType; continue; } $changed = \true; $newTypes[] = \PHPStan\Type\TypeTraverser::map($innerType, static function (\PHPStan\Type\Type $type, callable $traverse) use ($innerType, $newKeyType, $newValueType): \PHPStan\Type\Type { if ($type === $innerType->getIterableKeyType()) { return $newKeyType; } if ($type === $innerType->getIterableValueType()) { return $newValueType; } return $traverse($type); }); } if (!$changed) { return $this; } $result = $newTypes[0]; for ($i = 1, $count = count($newTypes); $i < $count; $i++) { $result = \PHPStan\Type\TypeCombinator::intersect($result, $newTypes[$i]); } return $result; } return $this; } public function tryRemove(\PHPStan\Type\Type $typeToRemove): ?\PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => \PHPStan\Type\TypeCombinator::remove($type, $typeToRemove)); } public function exponentiate(\PHPStan\Type\Type $exponent): \PHPStan\Type\Type { return $this->intersectTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->exponentiate($exponent)); } public function getFiniteTypes(): array { $compare = []; foreach ($this->types as $type) { $oneType = []; foreach ($type->getFiniteTypes() as $finiteType) { if ($finiteType instanceof EnumCaseObjectType) { $oneType[$finiteType->getClassName() . '::' . $finiteType->getEnumCaseName()] = $finiteType; continue; } $oneType[$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 callable(Type $type): TrinaryLogic $getResult * @param (callable(Type $type): bool)|null $filter */ private function intersectResults(callable $getResult, ?callable $filter = null): TrinaryLogic { $types = $this->types; if ($filter !== null) { $types = array_filter($types, $filter); } if (count($types) === 0) { return TrinaryLogic::createNo(); } return TrinaryLogic::lazyMaxMin($types, $getResult); } /** * @param callable(Type $type): Type $getType */ private function intersectTypes(callable $getType): \PHPStan\Type\Type { $operands = array_map($getType, $this->types); $result = $operands[0]; for ($i = 1, $count = count($operands); $i < $count; $i++) { $result = \PHPStan\Type\TypeCombinator::intersect($result, $operands[$i]); } return $result; } public function toPhpDocNode(): TypeNode { $baseTypes = []; $typesToDescribe = []; $skipTypeNames = []; $nonEmptyStr = \false; $nonFalsyStr = \false; $isList = $this->isList()->yes(); $isArray = $this->isArray()->yes(); $isNonEmptyArray = $this->isIterableAtLeastOnce()->yes(); $describedTypes = []; 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 ($isList || $isArray) { if ($type instanceof \PHPStan\Type\ArrayType) { $keyType = $type->getKeyType(); $valueType = $type->getItemType(); if ($isList) { $isMixedValueType = $valueType instanceof \PHPStan\Type\MixedType && $valueType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed' && !$valueType->isExplicitMixed(); $identifierTypeNode = new IdentifierTypeNode($isNonEmptyArray ? 'non-empty-list' : 'list'); if (!$isMixedValueType) { $describedTypes[$i] = new GenericTypeNode($identifierTypeNode, [$valueType->toPhpDocNode()]); } else { $describedTypes[$i] = $identifierTypeNode; } } else { $isMixedKeyType = $keyType instanceof \PHPStan\Type\MixedType && $keyType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed' && !$keyType->isExplicitMixed(); $isMixedValueType = $valueType instanceof \PHPStan\Type\MixedType && $valueType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed' && !$valueType->isExplicitMixed(); $identifierTypeNode = new IdentifierTypeNode($isNonEmptyArray ? 'non-empty-array' : 'array'); if (!$isMixedKeyType) { $describedTypes[$i] = new GenericTypeNode($identifierTypeNode, [$keyType->toPhpDocNode(), $valueType->toPhpDocNode()]); } elseif (!$isMixedValueType) { $describedTypes[$i] = new GenericTypeNode($identifierTypeNode, [$valueType->toPhpDocNode()]); } else { $describedTypes[$i] = $identifierTypeNode; } } continue; } elseif ($type instanceof ConstantArrayType) { $constantArrayTypeNode = $type->toPhpDocNode(); if ($constantArrayTypeNode instanceof ArrayShapeNode) { $newKind = $constantArrayTypeNode->kind; if ($isList) { if ($isNonEmptyArray && !$type->isIterableAtLeastOnce()->yes()) { $newKind = ArrayShapeNode::KIND_NON_EMPTY_LIST; } else { $newKind = ArrayShapeNode::KIND_LIST; } } elseif ($isNonEmptyArray && !$type->isIterableAtLeastOnce()->yes()) { $newKind = ArrayShapeNode::KIND_NON_EMPTY_ARRAY; } if ($newKind !== $constantArrayTypeNode->kind) { if ($constantArrayTypeNode->sealed) { $constantArrayTypeNode = ArrayShapeNode::createSealed($constantArrayTypeNode->items, $newKind); } else { $constantArrayTypeNode = ArrayShapeNode::createUnsealed($constantArrayTypeNode->items, $constantArrayTypeNode->unsealedType, $newKind); } } $describedTypes[$i] = $constantArrayTypeNode; continue; } } if ($type instanceof NonEmptyArrayType || $type instanceof AccessoryArrayListType) { continue; } } if (!$type instanceof AccessoryType) { $baseTypes[$i] = $type; continue; } $accessoryPhpDocNode = $type->toPhpDocNode(); if ($accessoryPhpDocNode instanceof IdentifierTypeNode && $accessoryPhpDocNode->name === '') { continue; } $typesToDescribe[$i] = $type; } 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]; } if (count($describedTypes) === 0) { throw new ShouldNotHappenException(sprintf('Intersection consists of %s but there should be at least one base type.', implode('&', array_map(static fn(\PHPStan\Type\Type $type) => $type->describe(\PHPStan\Type\VerbosityLevel::precise()), $this->types)))); } return new IntersectionTypeNode($describedTypes); } public function hasTemplateOrLateResolvableType(): bool { foreach ($this->types as $type) { if (!$type->hasTemplateOrLateResolvableType()) { continue; } return \true; } return \false; } } isSuperTypeOf(new ConstantStringType('hello'))` → Yes * - `(new IntegerType())->isSuperTypeOf(new StringType())` → No * - `(new StringType())->isSuperTypeOf(new MixedType())` → Maybe * * This is distinct from `accepts()` which also considers rule levels and PHPDoc context. * Use `isSuperTypeOf()` for type-theoretic comparisons and `accepts()` for assignability checks. * * Can be converted to AcceptsResult via toAcceptsResult(). * * @api */ final class IsSuperTypeOfResult { /** * @readonly */ public TrinaryLogic $result; /** * @readonly * @var list */ public array $reasons; private static self $YES; private static self $MAYBE; private static self $NO; /** * @api * @param list $reasons Human-readable explanations of the type relationship */ public function __construct(TrinaryLogic $result, array $reasons) { $this->result = $result; $this->reasons = $reasons; } /** * @phpstan-assert-if-true =false $this->no() * @phpstan-assert-if-true =false $this->maybe() */ public function yes(): bool { return $this->result->yes(); } /** * @phpstan-assert-if-true =false $this->no() * @phpstan-assert-if-true =false $this->yes() */ public function maybe(): bool { return $this->result->maybe(); } /** * @phpstan-assert-if-true =false $this->maybe() * @phpstan-assert-if-true =false $this->yes() */ public function no(): bool { return $this->result->no(); } public static function createYes(): self { return self::$YES ??= new self(TrinaryLogic::createYes(), []); } /** @param list $reasons */ public static function createNo(array $reasons = []): self { if ($reasons === []) { return self::$NO ??= new self(TrinaryLogic::createNo(), $reasons); } return new self(TrinaryLogic::createNo(), $reasons); } public static function createMaybe(): self { return self::$MAYBE ??= new self(TrinaryLogic::createMaybe(), []); } public static function createFromBoolean(bool $value): self { if ($value === \true) { return self::createYes(); } return self::createNo(); } 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); } /** @see TrinaryLogic::extremeIdentity() */ public static function extremeIdentity(self ...$operands): self { if ($operands === []) { throw new ShouldNotHappenException(); } $results = []; $reasons = []; foreach ($operands as $operand) { $results[] = $operand->result; foreach ($operand->reasons as $reason) { $reasons[] = $reason; } } return new self(TrinaryLogic::extremeIdentity(...$results), array_values(array_unique($reasons))); } /** @see TrinaryLogic::maxMin() */ public static function maxMin(self ...$operands): self { if ($operands === []) { throw new ShouldNotHappenException(); } $results = []; $reasons = []; foreach ($operands as $operand) { $results[] = $operand->result; foreach ($operand->reasons as $reason) { $reasons[] = $reason; } } return new self(TrinaryLogic::maxMin(...$results), array_values(array_unique($reasons))); } /** * @template T * @param T[] $objects * @param callable(T): self $callback */ public static function lazyMaxMin(array $objects, callable $callback): self { $reasons = []; $hasNo = \false; foreach ($objects as $object) { $isSuperTypeOf = $callback($object); if ($isSuperTypeOf->result->yes()) { return $isSuperTypeOf; } elseif ($isSuperTypeOf->result->no()) { $hasNo = \true; } foreach ($isSuperTypeOf->reasons as $reason) { $reasons[] = $reason; } } return new self($hasNo ? TrinaryLogic::createNo() : TrinaryLogic::createMaybe(), array_values(array_unique($reasons))); } public function negate(): self { return new self($this->result->negate(), $this->reasons); } public function describe(): string { return $this->result->describe(); } } keyType = $keyType; $this->itemType = $itemType; } public function getKeyType(): \PHPStan\Type\Type { return $this->keyType; } public function getItemType(): \PHPStan\Type\Type { return $this->itemType; } 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): \PHPStan\Type\AcceptsResult { if ($type->isConstantArray()->yes() && $type->isIterableAtLeastOnce()->no()) { return \PHPStan\Type\AcceptsResult::createYes(); } if ($type->isIterable()->yes()) { return $this->getIterableValueType()->accepts($type->getIterableValueType(), $strictTypes)->and($this->getIterableKeyType()->accepts($type->getIterableKeyType(), $strictTypes)); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return \PHPStan\Type\AcceptsResult::createNo(); } public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOf($this); } return (new \PHPStan\Type\IsSuperTypeOfResult($type->isIterable(), []))->and($this->getIterableValueType()->isSuperTypeOf($type->getIterableValueType()))->and($this->getIterableKeyType()->isSuperTypeOf($type->getIterableKeyType())); } public function isSuperTypeOfMixed(\PHPStan\Type\Type $type): \PHPStan\Type\IsSuperTypeOfResult { return (new \PHPStan\Type\IsSuperTypeOfResult($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): \PHPStan\Type\IsSuperTypeOfResult { 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 \PHPStan\Type\IsSuperTypeOfResult::createYes(); } return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } public function isSubTypeOf(\PHPStan\Type\Type $otherType): \PHPStan\Type\IsSuperTypeOfResult { if ($otherType instanceof \PHPStan\Type\IntersectionType || $otherType instanceof \PHPStan\Type\UnionType) { return $otherType->isSuperTypeOf($this->toArrayOrTraversable()); } 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()->isSuperTypeOf($this->itemType), $otherType->getIterableKeyType()->isSuperTypeOf($this->keyType)); } public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes): \PHPStan\Type\AcceptsResult { return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(\PHPStan\Type\Type $type): bool { if (get_class($type) !== static::class) { 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 toBitwiseNotType(): \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 toArrayOrTraversable(): \PHPStan\Type\Type { return new \PHPStan\Type\UnionType([new \PHPStan\Type\ArrayType($this->keyType, $this->itemType), new GenericObjectType(Traversable::class, [$this->keyType, $this->itemType])]); } public function toArrayKey(): \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toCoercedArgumentType(bool $strictTypes): \PHPStan\Type\Type { return \PHPStan\Type\TypeCombinator::union($this, new \PHPStan\Type\ArrayType(\PHPStan\Type\TypeCombinator::intersect($this->keyType->toArrayKey(), new \PHPStan\Type\UnionType([new \PHPStan\Type\IntegerType(), new \PHPStan\Type\StringType()])), $this->itemType), new GenericObjectType(Traversable::class, [$this->keyType, $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 { 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 isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString(): 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 getEnumCaseObject(): ?EnumCaseObjectType { return null; } 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()]); } public function hasTemplateOrLateResolvableType(): bool { return $this->keyType->hasTemplateOrLateResolvableType() || $this->itemType->hasTemplateOrLateResolvableType(); } } isAcceptedBy($this, $strictTypes); } return \PHPStan\Type\AcceptsResult::createNo(); } public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOf($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 isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString(): 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(); } } 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()]); } } container = $container; } public function getTypeAliasResolver(): \PHPStan\Type\TypeAliasResolver { return $this->container->getByType(\PHPStan\Type\TypeAliasResolver::class); } } 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 } } isExplicitMixed = $isExplicitMixed; if ($subtractedType instanceof \PHPStan\Type\NeverType) { $subtractedType = null; } $this->subtractedType = $subtractedType; } 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): \PHPStan\Type\AcceptsResult { return \PHPStan\Type\AcceptsResult::createYes(); } public function isSuperTypeOfMixed(\PHPStan\Type\MixedType $type): \PHPStan\Type\IsSuperTypeOfResult { if ($this->subtractedType === null) { if ($this->isExplicitMixed) { if ($type->isExplicitMixed) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($type->subtractedType === null) { return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } $isSuperType = $type->subtractedType->isSuperTypeOf($this->subtractedType); if ($isSuperType->yes()) { if ($this->isExplicitMixed) { if ($type->isExplicitMixed) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } public function isSuperTypeOf(\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->isSuperTypeOf($this->subtractedType); if ($isSuperType->yes()) { return $isSuperType; } return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } $result = $this->subtractedType->isSuperTypeOf($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 getKeysArrayFiltered(\PHPStan\Type\Type $filterValueType, TrinaryLogic $strict): \PHPStan\Type\Type { return $this->getKeysArray(); } public function getKeysArray(): \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return new \PHPStan\Type\IntersectionType([new \PHPStan\Type\ArrayType(\PHPStan\Type\IntegerRangeType::createAllGreaterThanOrEqualTo(0), new \PHPStan\Type\UnionType([new \PHPStan\Type\IntegerType(), new \PHPStan\Type\StringType()])), new AccessoryArrayListType()]); } public function getValuesArray(): \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return new \PHPStan\Type\IntersectionType([new \PHPStan\Type\ArrayType(\PHPStan\Type\IntegerRangeType::createAllGreaterThanOrEqualTo(0), new \PHPStan\Type\MixedType($this->isExplicitMixed)), new AccessoryArrayListType()]); } public function chunkArray(\PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys): \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return new \PHPStan\Type\IntersectionType([new \PHPStan\Type\ArrayType(\PHPStan\Type\IntegerRangeType::createAllGreaterThanOrEqualTo(0), new \PHPStan\Type\MixedType($this->isExplicitMixed)), new AccessoryArrayListType()]); } 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, ?TrinaryLogic $strict = null): \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return new \PHPStan\Type\UnionType([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 new \PHPStan\Type\IntersectionType([new \PHPStan\Type\ArrayType(\PHPStan\Type\IntegerRangeType::createAllGreaterThanOrEqualTo(0), new \PHPStan\Type\MixedType($this->isExplicitMixed)), new AccessoryArrayListType()]); } 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 spliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, \PHPStan\Type\Type $replacementType): \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 makeListMaybe(): \PHPStan\Type\Type { // `mixed` doesn't track list-ness; nothing to weaken. return $this; } public function mapValueType(callable $cb): \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType($this->isExplicitMixed), $cb(new \PHPStan\Type\MixedType($this->isExplicitMixed))); } public function mapKeyType(callable $cb): \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return new \PHPStan\Type\ArrayType($cb(new \PHPStan\Type\MixedType($this->isExplicitMixed)), new \PHPStan\Type\MixedType($this->isExplicitMixed)); } public function makeAllArrayKeysOptional(): \PHPStan\Type\Type { // `mixed` is already arbitrary; nothing to weaken. return $this; } public function changeKeyCaseArray(?int $case): \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 filterArrayRemovingFalsey(): \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 getEnumCaseObject(): ?EnumCaseObjectType { return null; } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope): array { return [new TrivialParametersAcceptor()]; } public function equals(\PHPStan\Type\Type $type): bool { if (get_class($type) !== static::class) { 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): \PHPStan\Type\IsSuperTypeOfResult { if ($otherType instanceof self && !$otherType instanceof TemplateMixedType) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($this->subtractedType !== null) { $isSuperType = $this->subtractedType->isSuperTypeOf($otherType); if ($isSuperType->yes()) { return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } } return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes): \PHPStan\Type\AcceptsResult { $isSuperType = $this->isSuperTypeOf($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 getClassStringType(): \PHPStan\Type\Type { return new \PHPStan\Type\ClassStringType(); } 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): ExtendedPropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $property = new DummyPropertyReflection($propertyName); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type); } public function hasInstanceProperty(string $propertyName): TrinaryLogic { return TrinaryLogic::createYes(); } public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $property = new DummyPropertyReflection($propertyName); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type); } public function hasStaticProperty(string $propertyName): TrinaryLogic { return TrinaryLogic::createYes(); } public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedStaticPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $property = new DummyPropertyReflection($propertyName); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $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 fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type); } public function canAccessConstants(): TrinaryLogic { return TrinaryLogic::createYes(); } public function hasConstant(string $constantName): TrinaryLogic { return TrinaryLogic::createYes(); } public function getConstant(string $constantName): ClassConstantReflection { return new DummyClassConstantReflection($constantName); } public function isCloneable(): TrinaryLogic { return TrinaryLogic::createYes(); } public function describe(\PHPStan\Type\VerbosityLevel $level): string { return $level->handle(static fn(): string => 'mixed', static fn(): string => 'mixed', fn(): string => 'mixed' . $this->describeSubtractedType($this->subtractedType, $level), function () use ($level): string { $description = 'mixed' . $this->describeSubtractedType($this->subtractedType, $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 toBitwiseNotType(): \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toGetClassResultType(): \PHPStan\Type\Type { $isObject = $this->isObject(); if ($isObject->no()) { return new ConstantBooleanType(\false); } $classString = $this->getClassStringType(); if ($isObject->yes()) { return $classString; } return new \PHPStan\Type\UnionType([$classString, new ConstantBooleanType(\false)]); } public function toClassConstantType(ReflectionProvider $reflectionProvider): \PHPStan\Type\Type { // `mixed::class` is undefined — the original `TypeTraverser` cb fell // through to `ErrorType` for any leaf that wasn't a definite object. return new \PHPStan\Type\ErrorType(); } public function toObjectTypeForInstanceofCheck(): \PHPStan\Type\ClassNameToObjectTypeResult { return new \PHPStan\Type\ClassNameToObjectTypeResult(new \PHPStan\Type\MixedType(), \false); } public function toObjectTypeForIsACheck(\PHPStan\Type\Type $objectOrClassType, bool $allowString, bool $allowSameClass): \PHPStan\Type\ClassNameToObjectTypeResult { if ($allowString) { return new \PHPStan\Type\ClassNameToObjectTypeResult(new \PHPStan\Type\UnionType([new \PHPStan\Type\ObjectWithoutClassType(), new \PHPStan\Type\ClassStringType()]), \false); } return new \PHPStan\Type\ClassNameToObjectTypeResult(new \PHPStan\Type\ObjectWithoutClassType(), \false); } 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 toCoercedArgumentType(bool $strictTypes): \PHPStan\Type\Type { return $this; } 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 = new \PHPStan\Type\IntersectionType([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 = new \PHPStan\Type\IntersectionType([new \PHPStan\Type\ArrayType(\PHPStan\Type\IntegerRangeType::createAllGreaterThanOrEqualTo(0), 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 = new \PHPStan\Type\IntersectionType([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 = new \PHPStan\Type\IntersectionType([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 = new \PHPStan\Type\IntersectionType([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 = new \PHPStan\Type\IntersectionType([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 = new \PHPStan\Type\IntersectionType([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 = new \PHPStan\Type\IntersectionType([new \PHPStan\Type\StringType(), new AccessoryUppercaseStringType()]); if ($this->subtractedType->isSuperTypeOf($uppercaseString)->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isClassString(): 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->isClassString()->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'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } isExplicit = $isExplicit; } public function isExplicit(): bool { return $this->isExplicit; } 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): \PHPStan\Type\AcceptsResult { return \PHPStan\Type\AcceptsResult::createYes(); } public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($type instanceof TemplateType) { return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } public function equals(\PHPStan\Type\Type $type): bool { return $type instanceof self; } public function isSubTypeOf(\PHPStan\Type\Type $otherType): \PHPStan\Type\IsSuperTypeOfResult { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes): \PHPStan\Type\AcceptsResult { return $this->isSubTypeOf($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 getClassStringType(): \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } 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): ExtendedPropertyReflection { throw new ShouldNotHappenException(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { throw new ShouldNotHappenException(); } public function hasInstanceProperty(string $propertyName): TrinaryLogic { return TrinaryLogic::createNo(); } public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { throw new ShouldNotHappenException(); } public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { throw new ShouldNotHappenException(); } public function hasStaticProperty(string $propertyName): TrinaryLogic { return TrinaryLogic::createNo(); } public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { throw new ShouldNotHappenException(); } public function getUnresolvedStaticPropertyPrototype(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): ClassConstantReflection { 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 getKeysArrayFiltered(\PHPStan\Type\Type $filterValueType, TrinaryLogic $strict): \PHPStan\Type\Type { return $this->getKeysArray(); } 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, ?TrinaryLogic $strict = null): \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 spliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, \PHPStan\Type\Type $replacementType): \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function makeListMaybe(): \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function mapValueType(callable $cb): \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function mapKeyType(callable $cb): \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function makeAllArrayKeysOptional(): \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function changeKeyCaseArray(?int $case): \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function filterArrayRemovingFalsey(): \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 toBitwiseNotType(): \PHPStan\Type\Type { return $this; } public function toGetClassResultType(): \PHPStan\Type\Type { return $this; } public function toClassConstantType(ReflectionProvider $reflectionProvider): \PHPStan\Type\Type { return $this; } public function toObjectTypeForInstanceofCheck(): \PHPStan\Type\ClassNameToObjectTypeResult { return new \PHPStan\Type\ClassNameToObjectTypeResult($this, \false); } public function toObjectTypeForIsACheck(\PHPStan\Type\Type $objectOrClassType, bool $allowString, bool $allowSameClass): \PHPStan\Type\ClassNameToObjectTypeResult { return new \PHPStan\Type\ClassNameToObjectTypeResult($this, \false); } 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 toCoercedArgumentType(bool $strictTypes): \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 isClassString(): 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 getEnumCaseObject(): ?EnumCaseObjectType { return null; } 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'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } 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()]); } } getClassStringType(); } public function toClassConstantType(ReflectionProvider $reflectionProvider): \PHPStan\Type\Type { return new \PHPStan\Type\IntersectionType([$this->getClassStringType(), new AccessoryLiteralStringType()]); } public function toObjectTypeForInstanceofCheck(): \PHPStan\Type\ClassNameToObjectTypeResult { return new \PHPStan\Type\ClassNameToObjectTypeResult($this, \true); } public function toObjectTypeForIsACheck(\PHPStan\Type\Type $objectOrClassType, bool $allowString, bool $allowSameClass): \PHPStan\Type\ClassNameToObjectTypeResult { if ($allowString) { return new \PHPStan\Type\ClassNameToObjectTypeResult(new \PHPStan\Type\UnionType([new \PHPStan\Type\ObjectWithoutClassType(), new \PHPStan\Type\ClassStringType()]), \false); } return new \PHPStan\Type\ClassNameToObjectTypeResult(new \PHPStan\Type\ObjectWithoutClassType(), \false); } 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 toCoercedArgumentType(bool $strictTypes): \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function isOffsetAccessLegal(): 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 getEnumCaseObject(): ?EnumCaseObjectType { 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 { return new IdentifierTypeNode('parent'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } isAcceptedBy($this, $strictTypes); } return \PHPStan\Type\AcceptsResult::createNo(); } public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOf($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, PhpVersion $phpVersion): TrinaryLogic { if ($otherType instanceof \PHPStan\Type\ConstantScalarType) { return TrinaryLogic::createFromBoolean(null < $otherType->getValue()); } if ($otherType instanceof \PHPStan\Type\CompoundType) { return $otherType->isGreaterThan($this, $phpVersion); } if ($otherType->isObject()->yes()) { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } public function isSmallerThanOrEqual(\PHPStan\Type\Type $otherType, PhpVersion $phpVersion): TrinaryLogic { if ($otherType instanceof \PHPStan\Type\ConstantScalarType) { return TrinaryLogic::createFromBoolean(null <= $otherType->getValue()); } if ($otherType instanceof \PHPStan\Type\CompoundType) { return $otherType->isGreaterThanOrEqual($this, $phpVersion); } if ($otherType->isObject()->yes()) { return TrinaryLogic::createYes(); } 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 toBitwiseNotType(): \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toClassConstantType(ReflectionProvider $reflectionProvider): \PHPStan\Type\Type { // Null `::class` reads as `null` (mirrors how `null::class` flows // through the `::class` resolution pipeline alongside object types). return $this; } 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 toCoercedArgumentType(bool $strictTypes): \PHPStan\Type\Type { return $this; } 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 isClassString(): 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(PhpVersion $phpVersion): \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function getSmallerOrEqualType(PhpVersion $phpVersion): \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(PhpVersion $phpVersion): \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(PhpVersion $phpVersion): \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'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } name = $name; $this->type = $type; } public function getName(): string { return $this->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 getDocComment(): ?string { return null; } public function hasPhpDocType(): bool { return \true; } public function getPhpDocType(): \PHPStan\Type\Type { return $this->type; } public function hasNativeType(): bool { return \false; } public function getNativeType(): \PHPStan\Type\Type { return new \PHPStan\Type\MixedType(); } 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(); } public function isAbstract(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinalByKeyword(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinal(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isVirtual(): TrinaryLogic { return TrinaryLogic::createNo(); } public function hasHook(string $hookType): bool { return \false; } public function getHook(string $hookType): ExtendedMethodReflection { throw new ShouldNotHappenException(); } public function isProtectedSet(): bool { return \false; } public function isPrivateSet(): bool { return \false; } public function getAttributes(): array { return []; } public function isDummy(): TrinaryLogic { return TrinaryLogic::createNo(); } } */ private array $properties; /** * @var list */ private array $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 getClassStringType(): \PHPStan\Type\Type { return new GenericClassStringType($this); } public function hasProperty(string $propertyName): TrinaryLogic { return $this->hasInstanceProperty($propertyName); } public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getInstanceProperty($propertyName, $scope); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope); } public function hasInstanceProperty(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 getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { if (!array_key_exists($propertyName, $this->properties)) { throw new ShouldNotHappenException(); } $property = new \PHPStan\Type\ObjectShapePropertyReflection($propertyName, $this->properties[$propertyName]); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type); } public function hasStaticProperty(string $propertyName): TrinaryLogic { return TrinaryLogic::createNo(); } public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { throw new ShouldNotHappenException(); } public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { throw new ShouldNotHappenException(); } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes): \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); foreach ($type->getObjectClassReflections() as $classReflection) { if (!UniversalObjectCratesClassReflectionExtension::isUniversalObjectCrate($reflectionProvider, $classReflection)) { continue; } return \PHPStan\Type\AcceptsResult::createMaybe(); } $result = \PHPStan\Type\AcceptsResult::createYes(); $scope = new OutOfClassScope(); foreach ($this->properties as $propertyName => $propertyType) { $typeHasProperty = $type->hasInstanceProperty((string) $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->yes() && $type->hasStaticProperty((string) $propertyName)->yes()) { $result = $result->and(new \PHPStan\Type\AcceptsResult(TrinaryLogic::createNo(), [sprintf('Property %s::$%s is static.', $type->getStaticProperty((string) $propertyName, $scope)->getDeclaringClass()->getDisplayName(), $propertyName)])); continue; } if ($hasProperty->no()) { if (in_array($propertyName, $this->optionalProperties, \true)) { continue; } $result = $result->and($hasProperty); continue; } if ($hasProperty->maybe()) { if (!in_array($propertyName, $this->optionalProperties, \true)) { $result = $result->and($hasProperty); continue; } $hasProperty = \PHPStan\Type\AcceptsResult::createYes(); } $result = $result->and($hasProperty); try { $otherProperty = $type->getInstanceProperty((string) $propertyName, $scope); } catch (MissingPropertyFromReflectionException $e) { continue; } 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->accepts($otherPropertyType, $strictTypes)->decorateReasons(static fn(string $reason) => 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): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOf($this); } if ($type instanceof \PHPStan\Type\ObjectWithoutClassType) { return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); foreach ($type->getObjectClassReflections() as $classReflection) { if (!UniversalObjectCratesClassReflectionExtension::isUniversalObjectCrate($reflectionProvider, $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->hasInstanceProperty((string) $propertyName), []); if ($hasProperty->no()) { if (in_array($propertyName, $this->optionalProperties, \true)) { continue; } $result = $result->and($hasProperty); continue; } if ($hasProperty->maybe()) { if (!in_array($propertyName, $this->optionalProperties, \true)) { $result = $result->and($hasProperty); continue; } $hasProperty = \PHPStan\Type\IsSuperTypeOfResult::createYes(); } $result = $result->and($hasProperty); try { $otherProperty = $type->getInstanceProperty((string) $propertyName, $scope); } catch (MissingPropertyFromReflectionException $e) { continue; } 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->isSuperTypeOf($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 fn($propertyName) => $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 fn($currentPropertyName) => $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->hasInstanceProperty((string) $name)->no()) { continue; } try { $receivedProperty = $receivedType->getInstanceProperty((string) $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 getEnumCases(): array { return []; } public function getEnumCaseObject(): ?EnumCaseObjectType { return null; } 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->hasInstanceProperty((string) $name)->yes()) { return $this; } $transformed = $cb($propertyType, $right->getInstanceProperty((string) $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((string) $name)) { $keyNode = new IdentifierTypeNode((string) $name); } else { $keyPhpDocNode = (new ConstantStringType((string) $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); } public function hasTemplateOrLateResolvableType(): bool { foreach ($this->properties as $property) { if (!$property->hasTemplateOrLateResolvableType()) { continue; } return \true; } return \false; } } > */ private static array $superTypes = []; private ?self $cachedParent = null; /** @var self[]|null */ private ?array $cachedInterfaces = null; /** @var array>> */ private static array $methods = []; /** @var array>> */ private static array $properties = []; /** @var array>> */ private static array $instanceProperties = []; /** @var array>> */ private static array $staticProperties = []; /** @var array> */ private static array $ancestors = []; /** @var array */ private array $currentAncestors = []; private ?string $cachedDescription = null; /** @var array> */ private static array $enumCases = []; /** @var array */ private array $methodCache = []; /** @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::$instanceProperties = []; self::$staticProperties = []; self::$ancestors = []; self::$enumCases = []; } 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 fn(): bool => $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): ExtendedPropertyReflection { 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($properties); } } } if (!$nakedClassReflection->hasNativeProperty($propertyName)) { $nakedClassReflection = $this->getClassReflection(); } if ($nakedClassReflection === null) { throw new ClassNotFoundException($this->className); } $property = \PHPStan\Type\RecursionGuard::run($this, static fn() => $nakedClassReflection->getProperty($propertyName, $scope)); if ($property instanceof \PHPStan\Type\ErrorType) { $property = new DummyPropertyReflection($propertyName); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $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); } public function hasInstanceProperty(string $propertyName): TrinaryLogic { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return TrinaryLogic::createMaybe(); } $classHasProperty = \PHPStan\Type\RecursionGuard::run($this, static fn(): bool => $classReflection->hasInstanceProperty($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 getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { if (!$scope->isInClass()) { $canAccessProperty = 'no'; } else { $canAccessProperty = $scope->getClassReflection()->getName(); } $description = $this->describeCache(); if (isset(self::$instanceProperties[$description][$propertyName][$canAccessProperty])) { return self::$instanceProperties[$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->getUnresolvedInstancePropertyPrototype($propertyName, $scope); } if (count($properties) > 0) { if (count($properties) === 1) { return $properties[0]; } return new UnionTypeUnresolvedPropertyPrototypeReflection($properties); } } } if (!$nakedClassReflection->hasNativeProperty($propertyName)) { $nakedClassReflection = $this->getClassReflection(); } if ($nakedClassReflection === null) { throw new ClassNotFoundException($this->className); } $property = \PHPStan\Type\RecursionGuard::run($this, static fn() => $nakedClassReflection->getInstanceProperty($propertyName, $scope)); if ($property instanceof \PHPStan\Type\ErrorType) { $property = new DummyPropertyReflection($propertyName); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type); } $ancestor = $this->getAncestorWithClassName($property->getDeclaringClass()->getName()); $resolvedClassReflection = null; if ($ancestor !== null && $ancestor->hasInstanceProperty($propertyName)->yes()) { $resolvedClassReflection = $ancestor->getClassReflection(); if ($ancestor !== $this) { $property = $ancestor->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->getNakedProperty(); } } if ($resolvedClassReflection === null) { $resolvedClassReflection = $property->getDeclaringClass(); } return self::$instanceProperties[$description][$propertyName][$canAccessProperty] = new CalledOnTypeUnresolvedPropertyPrototypeReflection($property, $resolvedClassReflection, \true, $this); } public function hasStaticProperty(string $propertyName): TrinaryLogic { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return TrinaryLogic::createMaybe(); } $classHasProperty = \PHPStan\Type\RecursionGuard::run($this, static fn(): bool => $classReflection->hasStaticProperty($propertyName)); if ($classHasProperty === \true || $classHasProperty instanceof \PHPStan\Type\ErrorType) { return TrinaryLogic::createYes(); } if (!$classReflection->isFinal()) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createNo(); } public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedStaticPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { if (!$scope->isInClass()) { $canAccessProperty = 'no'; } else { $canAccessProperty = $scope->getClassReflection()->getName(); } $description = $this->describeCache(); if (isset(self::$staticProperties[$description][$propertyName][$canAccessProperty])) { return self::$staticProperties[$description][$propertyName][$canAccessProperty]; } $nakedClassReflection = $this->getNakedClassReflection(); if ($nakedClassReflection === null) { throw new ClassNotFoundException($this->className); } if (!$nakedClassReflection->hasNativeProperty($propertyName)) { $nakedClassReflection = $this->getClassReflection(); } if ($nakedClassReflection === null) { throw new ClassNotFoundException($this->className); } $property = \PHPStan\Type\RecursionGuard::run($this, static fn() => $nakedClassReflection->getStaticProperty($propertyName)); if ($property instanceof \PHPStan\Type\ErrorType) { $property = new DummyPropertyReflection($propertyName); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type); } $ancestor = $this->getAncestorWithClassName($property->getDeclaringClass()->getName()); $resolvedClassReflection = null; if ($ancestor !== null && $ancestor->hasStaticProperty($propertyName)->yes()) { $resolvedClassReflection = $ancestor->getClassReflection(); if ($ancestor !== $this) { $property = $ancestor->getUnresolvedStaticPropertyPrototype($propertyName, $scope)->getNakedProperty(); } } if ($resolvedClassReflection === null) { $resolvedClassReflection = $property->getDeclaringClass(); } return self::$staticProperties[$description][$propertyName][$canAccessProperty] = new CalledOnTypeUnresolvedPropertyPrototypeReflection($property, $resolvedClassReflection, \true, $this); } public function getReferencedClasses(): array { if ($this->className === '') { return []; } 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): \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\StaticType) { return $this->checkSubclassAcceptability($type->getClassName()); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedBy($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): \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->isSubTypeOf($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 fn(\PHPStan\Type\IsSuperTypeOfResult $result) => $result; if ($this->subtractedType !== null) { $isSuperType = $this->subtractedType->isSuperTypeOf($type); if ($isSuperType->yes()) { return self::$superTypes[$thisDescription][$description] = \PHPStan\Type\IsSuperTypeOfResult::createNo(); } if ($isSuperType->maybe()) { $transformResult = static fn(\PHPStan\Type\IsSuperTypeOfResult $result) => $result->and(\PHPStan\Type\IsSuperTypeOfResult::createMaybe()); } } if ($type instanceof \PHPStan\Type\SubtractableType && $type->getSubtractedType() !== null) { $isSuperType = $type->getSubtractedType()->isSuperTypeOf($this); if ($isSuperType->yes()) { return self::$superTypes[$thisDescription][$description] = \PHPStan\Type\IsSuperTypeOfResult::createNo(); } } $thisClassName = $this->className; if (count($thatClassNames) > 1) { throw new ShouldNotHappenException(); } $thisClassReflection = $this->getClassReflection(); $thatClassReflections = $type->getObjectClassReflections(); if (count($thatClassReflections) === 1) { $thatClassReflection = $thatClassReflections[0]; } else { $thatClassReflection = null; } if ($thisClassReflection === null || $thatClassReflection === null) { if ($thatClassNames[0] === $thisClassName) { return self::$superTypes[$thisDescription][$description] = $transformResult(\PHPStan\Type\IsSuperTypeOfResult::createYes()); } return self::$superTypes[$thisDescription][$description] = \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } if ($thatClassNames[0] === $thisClassName) { if ($thisClassReflection->getNativeReflection()->isFinal()) { return self::$superTypes[$thisDescription][$description] = $transformResult(\PHPStan\Type\IsSuperTypeOfResult::createYes()); } if ($thisClassReflection->hasFinalByKeywordOverride()) { if (!$thatClassReflection->hasFinalByKeywordOverride()) { return self::$superTypes[$thisDescription][$description] = $transformResult(\PHPStan\Type\IsSuperTypeOfResult::createMaybe()); } } return self::$superTypes[$thisDescription][$description] = $transformResult(\PHPStan\Type\IsSuperTypeOfResult::createYes()); } if ($thisClassReflection->isTrait() || $thatClassReflection->isTrait()) { return self::$superTypes[$thisDescription][$description] = \PHPStan\Type\IsSuperTypeOfResult::createNo(); } if ($thisClassReflection->getName() === $thatClassReflection->getName()) { return self::$superTypes[$thisDescription][$description] = $transformResult(\PHPStan\Type\IsSuperTypeOfResult::createYes()); } if ($thatClassReflection->isSubclassOfClass($thisClassReflection)) { return self::$superTypes[$thisDescription][$description] = $transformResult(\PHPStan\Type\IsSuperTypeOfResult::createYes()); } if ($thisClassReflection->isSubclassOfClass($thatClassReflection)) { return self::$superTypes[$thisDescription][$description] = \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } if ($thisClassReflection->isInterface() && !$thatClassReflection->isFinalByKeyword()) { return self::$superTypes[$thisDescription][$description] = \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } if ($thatClassReflection->isInterface() && !$thisClassReflection->isFinalByKeyword()) { 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 (get_class($type) !== static::class) { 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->isSubclassOfClass($thisReflection)); } 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 = fn(): string => $this->className . $this->describeSubtractedType($this->subtractedType, $level); 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) . '>'; } $description .= $this->describeSubtractedType($this->subtractedType, \PHPStan\Type\VerbosityLevel::cache()); $reflection = $this->classReflection; if ($reflection !== null) { $description .= '-'; $description .= (string) $reflection->getNativeReflection()->getStartLine(); $description .= '-'; if ($reflection->hasFinalByKeywordOverride()) { $description .= 'f=' . ($reflection->isFinalByKeyword() ? 't' : 'f'); } } return $this->cachedDescription = $description; } public function toNumber(): \PHPStan\Type\Type { if ($this->isInstanceOf('SimpleXMLElement')->yes() || $this->isInstanceOf('GMP')->yes()) { return new \PHPStan\Type\UnionType([new \PHPStan\Type\FloatType(), new \PHPStan\Type\IntegerType()]); } return new \PHPStan\Type\ErrorType(); } public function toBitwiseNotType(): \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toGetClassResultType(): \PHPStan\Type\Type { return $this->getClassStringType(); } public function toClassConstantType(ReflectionProvider $reflectionProvider): \PHPStan\Type\Type { if ($reflectionProvider->hasClass($this->className)) { $reflection = $reflectionProvider->getClass($this->className); if ($reflection->isFinalByKeyword()) { return new ConstantStringType($reflection->getName(), \true); } } return new \PHPStan\Type\IntersectionType([$this->getClassStringType(), new AccessoryLiteralStringType()]); } public function toObjectTypeForInstanceofCheck(): \PHPStan\Type\ClassNameToObjectTypeResult { return new \PHPStan\Type\ClassNameToObjectTypeResult($this, \true); } public function toObjectTypeForIsACheck(\PHPStan\Type\Type $objectOrClassType, bool $allowString, bool $allowSameClass): \PHPStan\Type\ClassNameToObjectTypeResult { if ($allowString) { return new \PHPStan\Type\ClassNameToObjectTypeResult(new \PHPStan\Type\UnionType([new \PHPStan\Type\ObjectWithoutClassType(), new \PHPStan\Type\ClassStringType()]), \false); } return new \PHPStan\Type\ClassNameToObjectTypeResult(new \PHPStan\Type\ObjectWithoutClassType(), \false); } public function toAbsoluteNumber(): \PHPStan\Type\Type { return $this->toNumber()->toAbsoluteNumber(); } public function toInteger(): \PHPStan\Type\Type { if ($this->isInstanceOf('SimpleXMLElement')->yes() || $this->isInstanceOf('GMP')->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() || $this->isInstanceOf('GMP')->yes()) { return new \PHPStan\Type\FloatType(); } return new \PHPStan\Type\ErrorType(); } public function toString(): \PHPStan\Type\Type { if ($this->isInstanceOf('BcMath\Number')->yes() || $this->isInstanceOf('GMP')->yes()) { return new \PHPStan\Type\IntersectionType([new \PHPStan\Type\StringType(), new AccessoryNumericStringType(), new AccessoryNonEmptyStringType()]); } $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, $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) { if (count($arrayKeys) === 0 || count($arrayKeys) > 16) { return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType()); } $types = [new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType())]; foreach ($arrayKeys as $i => $arrayKey) { $types[] = new HasOffsetValueType($arrayKey, $arrayValues[$i]); } return new \PHPStan\Type\IntersectionType($types); } return new ConstantArrayType($arrayKeys, $arrayValues); } public function toArrayKey(): \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toCoercedArgumentType(bool $strictTypes): \PHPStan\Type\Type { if (!$strictTypes) { $classReflection = $this->getClassReflection(); if ($classReflection === null || !$classReflection->hasNativeMethod('__toString')) { return $this; } return \PHPStan\Type\TypeCombinator::union($this, $this->toString()); } return $this; } public function toBoolean(): \PHPStan\Type\BooleanType { if ($this->isInstanceOf('SimpleXMLElement')->yes() || $this->isInstanceOf('BcMath\Number')->yes() || $this->isInstanceOf('GMP')->yes()) { return new \PHPStan\Type\BooleanType(); } return new ConstantBooleanType(\true); } public function isObject(): TrinaryLogic { return TrinaryLogic::createYes(); } public function getClassStringType(): \PHPStan\Type\Type { return new GenericClassStringType($this); } public function isEnum(): TrinaryLogic { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return TrinaryLogic::createMaybe(); } if ($classReflection->isEnum() || $classReflection->is('UnitEnum')) { return TrinaryLogic::createYes(); } if ($classReflection->isInterface() && !$classReflection->is(Stringable::class) && !$classReflection->is(Throwable::class) && !$classReflection->is(DateTimeInterface::class)) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createNo(); } 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 { $key = $methodName; if ($scope->isInClass()) { $key = sprintf('%s-%s', $key, $scope->getClassReflection()->getCacheKey()); } return $this->methodCache[$key] ??= $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 { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return TrinaryLogic::createMaybe(); } if ($classReflection->hasConstant($constantName)) { return TrinaryLogic::createYes(); } if ($classReflection->isFinal()) { return TrinaryLogic::createNo(); } return TrinaryLogic::createMaybe(); } public function getConstant(string $constantName): ClassConstantReflection { $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(); } if ($this->hasMethod('count')->yes() === \false) { return \PHPStan\Type\IntegerRangeType::fromInterval(0, null); } return \PHPStan\Type\RecursionGuard::run($this, fn(): \PHPStan\Type\Type => $this->getMethod('count', new OutOfClassScope())->getOnlyVariant()->getReturnType()); } public function getIterableKeyType(): \PHPStan\Type\Type { $isTraversable = \false; if ($this->isInstanceOf(IteratorAggregate::class)->yes()) { $keyType = \PHPStan\Type\RecursionGuard::run($this, fn(): \PHPStan\Type\Type => $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, fn(): \PHPStan\Type\Type => $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, fn(): \PHPStan\Type\Type => $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, fn(): \PHPStan\Type\Type => $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 isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString(): 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->is($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->isInstanceOf(ArrayAccess::class)->yes()) { return \PHPStan\Type\RecursionGuard::run($this, fn(): \PHPStan\Type\Type => $this->getMethod('offsetGet', new OutOfClassScope())->getOnlyVariant()->getReturnType()); } if (!$this->isExtraOffsetAccessibleClass()->no()) { return new \PHPStan\Type\MixedType(); } 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 getEnumCaseObject(): ?EnumCaseObjectType { $cases = $this->getEnumCases(); if (count($cases) === 1) { return $cases[0]; } return null; } public function isCallable(): TrinaryLogic { $parametersAcceptors = \PHPStan\Type\RecursionGuard::run($this, fn() => $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 list|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->isFinalByKeyword()) { return [new TrivialParametersAcceptor()]; } return null; } public function isCloneable(): TrinaryLogic { return TrinaryLogic::createYes(); } public function isInstanceOf(string $className): TrinaryLogic { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return TrinaryLogic::createMaybe(); } if ($classReflection->is($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) { $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); if (!$reflectionProvider->hasClass($this->className)) { return null; } $this->classReflection = $reflectionProvider->getClass($this->className); } if ($this->classReflection->isGeneric()) { return $this->classReflection->withTypes(array_values($this->classReflection->getTemplateTypeMap()->map(static fn(): \PHPStan\Type\Type => new \PHPStan\Type\ErrorType())->getTypes())); } return $this->classReflection; } public function getAncestorWithClassName(string $className): ?self { 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 = $parentReflection->getObjectType(); } /** @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 fn(ClassReflection $interfaceReflection): self => $interfaceReflection->getObjectType(), $thisReflection->getInterfaces()); } public function tryRemove(\PHPStan\Type\Type $typeToRemove): ?\PHPStan\Type\Type { if ($typeToRemove instanceof \PHPStan\Type\ObjectType) { foreach (\PHPStan\Type\UnionType::EQUAL_UNION_CLASSES as $baseClass => $classes) { if ($this->getClassName() !== $baseClass) { continue; } foreach ($classes as $index => $class) { if ($typeToRemove->getClassName() === $class) { unset($classes[$index]); return \PHPStan\Type\TypeCombinator::union(...array_map(static fn(string $objectClass): \PHPStan\Type\Type => new \PHPStan\Type\ObjectType($objectClass), $classes)); } } } } 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()); } public function hasTemplateOrLateResolvableType(): bool { if ($this->subtractedType === null) { return \false; } return $this->subtractedType->hasTemplateOrLateResolvableType(); } } subtractedType = $subtractedType; } public function getReferencedClasses(): array { return []; } public function getObjectClassNames(): array { return []; } public function getObjectClassReflections(): array { return []; } public function getClassStringType(): \PHPStan\Type\Type { return new \PHPStan\Type\ClassStringType(); } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes): \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return \PHPStan\Type\AcceptsResult::createFromBoolean($type instanceof self || $type instanceof \PHPStan\Type\ObjectShapeType || $type->getObjectClassNames() !== []); } public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOf($this); } if ($type instanceof self) { if ($this->subtractedType === null) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($type->subtractedType !== null) { $isSuperType = $type->subtractedType->isSuperTypeOf($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->isSuperTypeOf($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 fn(): string => 'object', static fn(): string => 'object', fn(): string => 'object' . $this->describeSubtractedType($this->subtractedType, $level)); } public function getEnumCases(): array { return []; } public function getEnumCaseObject(): ?EnumCaseObjectType { return null; } 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'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } 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()); } } extensions = $extensions; } /** * @return OperatorTypeSpecifyingExtension[] */ private function getOperatorTypeSpecifyingExtensions(string $operator, \PHPStan\Type\Type $leftType, \PHPStan\Type\Type $rightType): array { return array_values(array_filter($this->extensions, static fn(\PHPStan\Type\OperatorTypeSpecifyingExtension $extension): bool => $extension->isOperatorSupported($operator, $leftType, $rightType))); } public function callOperatorTypeSpecifyingExtensions(Expr\BinaryOp $expr, \PHPStan\Type\Type $leftType, \PHPStan\Type\Type $rightType): ?\PHPStan\Type\Type { $operatorSigil = $expr->getOperatorSigil(); $operatorTypeSpecifyingExtensions = $this->getOperatorTypeSpecifyingExtensions($operatorSigil, $leftType, $rightType); /** @var list $extensionTypes */ $extensionTypes = []; foreach ($operatorTypeSpecifyingExtensions as $extension) { $extensionTypes[] = $extension->specifyType($operatorSigil, $leftType, $rightType); } if (count($extensionTypes) > 0) { return \PHPStan\Type\TypeCombinator::union(...$extensionTypes); } return null; } } getName() === 'createIdentifier'; } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type { $args = $methodCall->getArgs(); if (!isset($args[0])) { return null; } $secondPartType = $scope->getType($args[0]->value); $secondPartValues = $secondPartType->getConstantStrings(); if (count($secondPartValues) === 0) { return null; } $reflection = new ReflectionClass(ClassNameUsageLocation::class); $identifiers = []; $locationValueType = $scope->getType(new PropertyFetch($methodCall->var, 'value')); foreach ($reflection->getConstants() as $constant) { if (!$locationValueType->isSuperTypeOf($scope->getTypeFromValue($constant))->yes()) { continue; } $location = ClassNameUsageLocation::from($constant); foreach ($secondPartValues as $secondPart) { $identifiers[] = $location->createIdentifier($secondPart->getValue()); } } sort($identifiers); $types = []; foreach ($identifiers as $identifier) { $types[] = $scope->getTypeFromValue($identifier); } return TypeCombinator::union(...$types); } } 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(); } } 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; } } 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 { if (!array_key_exists($functionReflection->getName(), self::FUNCTION_NAMES)) { throw new ShouldNotHappenException(); } $argumentPosition = self::FUNCTION_NAMES[$functionReflection->getName()]; $args = $functionCall->getArgs(); if (!isset($args[$argumentPosition])) { return null; } $argument = $args[$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 = new IntersectionType([$array, new NonEmptyArrayType()]); } return $array; } } getName() === 'array_change_key_case'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (!isset($args[0])) { return null; } $arrayType = $scope->getType($args[0]->value); if (!isset($args[1])) { $case = CASE_LOWER; } else { $caseType = $scope->getType($args[1]->value); $scalarValues = $caseType->getConstantScalarValues(); if (count($scalarValues) === 1) { $case = (int) $scalarValues[0]; } else { $case = null; } } return $arrayType->changeKeyCaseArray($case); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'array_chunk'; } 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(); } $lengthType = $scope->getType($args[1]->value); $negativeOrZero = IntegerRangeType::fromInterval(null, 0); if ($negativeOrZero->isSuperTypeOf($lengthType)->yes()) { return $this->phpVersion->throwsValueErrorForInternalFunctions() ? new NeverType() : new NullType(); } $preserveKeysType = isset($args[2]) ? $scope->getType($args[2]->value) : new ConstantBooleanType(\false); return $arrayType->chunkArray($lengthType, $preserveKeysType->isTrue()); } } arrayColumnHelper = $arrayColumnHelper; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'array_column'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); $numArgs = count($args); if ($numArgs < 2) { return null; } $arrayType = $scope->getType($args[0]->value); $columnType = $scope->getType($args[1]->value); $indexType = $numArgs >= 3 ? $scope->getType($args[2]->value) : new NullType(); $constantArrayTypes = $arrayType->getConstantArrays(); if (count($constantArrayTypes) === 1) { $type = $this->arrayColumnHelper->handleConstantArray($constantArrayTypes[0], $columnType, $indexType, $scope); if ($type !== null) { return $type; } } return $this->arrayColumnHelper->handleAnyArray($arrayType, $columnType, $indexType, $scope); } } phpVersion = $phpVersion; } /** * @return array{Type, TrinaryLogic} */ public function getReturnValueType(Type $arrayType, Type $columnType, Scope $scope): array { $iterableAtLeastOnce = $arrayType->isIterableAtLeastOnce(); if ($iterableAtLeastOnce->no()) { return [new NeverType(), $iterableAtLeastOnce]; } $iterableValueType = $arrayType->getIterableValueType(); [$returnValueType, $certainty] = $this->getOffsetOrProperty($iterableValueType, $columnType, $scope); if (!$certainty->yes()) { $iterableAtLeastOnce = TrinaryLogic::createMaybe(); } return [$returnValueType, $iterableAtLeastOnce]; } public function getReturnIndexType(Type $arrayType, Type $indexType, Scope $scope): Type { if (!$indexType->isNull()->yes()) { $iterableValueType = $arrayType->getIterableValueType(); [$type, $certainty] = $this->getOffsetOrProperty($iterableValueType, $indexType, $scope); if ($type instanceof NeverType) { return new IntegerType(); } if ($certainty->yes()) { return $type; } return TypeCombinator::union($type, new IntegerType()); } return new IntegerType(); } public function handleAnyArray(Type $arrayType, Type $columnType, Type $indexType, Scope $scope): Type { [$returnValueType, $iterableAtLeastOnce] = $this->getReturnValueType($arrayType, $columnType, $scope); if ($returnValueType instanceof NeverType) { return new ConstantArrayType([], []); } $returnKeyType = $this->getReturnIndexType($arrayType, $indexType, $scope); $returnType = new ArrayType($this->castToArrayKeyType($returnKeyType), $returnValueType); if ($iterableAtLeastOnce->yes()) { $returnType = TypeCombinator::intersect($returnType, new NonEmptyArrayType()); } if ($indexType->isNull()->yes()) { $returnType = TypeCombinator::intersect($returnType, new AccessoryArrayListType()); } return $returnType; } public function handleConstantArray(ConstantArrayType $arrayType, Type $columnType, Type $indexType, Scope $scope): ?Type { $builder = ConstantArrayTypeBuilder::createEmpty(); foreach ($arrayType->getValueTypes() as $i => $iterableValueType) { [$valueType, $certainty] = $this->getOffsetOrProperty($iterableValueType, $columnType, $scope); if (!$certainty->yes()) { return null; } if ($valueType instanceof NeverType) { continue; } if (!$indexType->isNull()->yes()) { [$type, $certainty] = $this->getOffsetOrProperty($iterableValueType, $indexType, $scope); if ($type instanceof NeverType) { $keyType = null; } elseif ($certainty->yes()) { $keyType = $type; } else { $keyType = TypeCombinator::union($type, new IntegerType()); } } else { $keyType = null; } if ($keyType !== null) { $keyType = $this->castToArrayKeyType($keyType); } $builder->setOffsetValueType($keyType, $valueType, $arrayType->isOptionalKey($i)); } return $builder->getArray(); } /** * @return array{Type, TrinaryLogic} */ private function getOffsetOrProperty(Type $type, Type $offsetOrProperty, Scope $scope): array { $offsetIsNull = $offsetOrProperty->isNull(); if ($offsetIsNull->yes()) { return [$type, TrinaryLogic::createYes()]; } $returnTypes = []; if ($offsetIsNull->maybe()) { $returnTypes[] = $type; } if (!$type->canAccessProperties()->no()) { $propertyTypes = $offsetOrProperty->getConstantStrings(); if ($propertyTypes === []) { return [new MixedType(), TrinaryLogic::createMaybe()]; } foreach ($propertyTypes as $propertyType) { $propertyName = $propertyType->getValue(); $hasProperty = $type->hasInstanceProperty($propertyName); if ($hasProperty->maybe()) { return [new MixedType(), TrinaryLogic::createMaybe()]; } if (!$hasProperty->yes()) { continue; } $property = $type->getInstanceProperty($propertyName, $scope); if (!$scope->canReadProperty($property)) { foreach ($type->getObjectClassReflections() as $classReflection) { if ($classReflection->hasMethod('__isset') && $classReflection->hasMethod('__get')) { return [new MixedType(), TrinaryLogic::createMaybe()]; } if (!$classReflection->isFinalByKeyword()) { if ($property->isPrivate()) { return [new MixedType(), TrinaryLogic::createMaybe()]; } return [$property->getReadableType(), TrinaryLogic::createMaybe()]; } } continue; } $returnTypes[] = $property->getReadableType(); } } $certainty = TrinaryLogic::createYes(); if ($type->isOffsetAccessible()->yes()) { $hasOffset = $type->hasOffsetValueType($offsetOrProperty); if ($hasOffset->maybe()) { $certainty = TrinaryLogic::createMaybe(); } if (!$hasOffset->no()) { $returnTypes[] = $type->getOffsetValueType($offsetOrProperty); } } if ($returnTypes === []) { return [new NeverType(), TrinaryLogic::createYes()]; } return [TypeCombinator::union(...$returnTypes), $certainty]; } 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()); } } arrayCombineHelper = $arrayCombineHelper; $this->phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'array_combine'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) < 2) { return null; } $firstArg = $args[0]->value; $secondArg = $args[1]->value; [$returnType, $hasValueError] = $this->arrayCombineHelper->getReturnAndThrowType($firstArg, $secondArg, $scope); if ($hasValueError->no()) { return $returnType; } if ($hasValueError->yes()) { if ($this->phpVersion->throwsValueErrorForInternalFunctions()) { return new NeverType(); } return new ConstantBooleanType(\false); } if ($this->phpVersion->throwsValueErrorForInternalFunctions()) { return $returnType; } return new UnionType([$returnType, new ConstantBooleanType(\false)]); } } arrayCombineHelper = $arrayCombineHelper; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'array_combine'; } public function getThrowTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $funcCall, Scope $scope): ?Type { if (count($funcCall->getArgs()) < 2) { return $functionReflection->getThrowType(); } $firstArg = $funcCall->getArgs()[0]->value; $secondArg = $funcCall->getArgs()[1]->value; $hasValueError = $this->arrayCombineHelper->getReturnAndThrowType($firstArg, $secondArg, $scope)[1]; if (!$hasValueError->no()) { return $functionReflection->getThrowType(); } return null; } } getType($firstArg); $valuesParamType = $scope->getType($secondArg); $constantKeysArrays = $keysParamType->getConstantArrays(); $constantValuesArrays = $valuesParamType->getConstantArrays(); if ($constantKeysArrays !== [] && $constantValuesArrays !== [] && count($constantKeysArrays) === count($constantValuesArrays)) { $results = []; foreach ($constantKeysArrays as $k => $constantKeysArray) { $constantValueArrays = $constantValuesArrays[$k]; $keyTypes = $constantKeysArray->getValueTypes(); $valueTypes = $constantValueArrays->getValueTypes(); if (count($keyTypes) !== count($valueTypes)) { return [new NeverType(), TrinaryLogic::createYes()]; } $keyTypes = $this->sanitizeConstantArrayKeyTypes($keyTypes); if ($keyTypes === null) { continue; } $builder = ConstantArrayTypeBuilder::createEmpty(); foreach ($keyTypes as $i => $keyType) { if (!array_key_exists($i, $valueTypes)) { $results = []; break 2; } $valueType = $valueTypes[$i]; $builder->setOffsetValueType($keyType, $valueType); } $results[] = $builder->getArray(); } if ($results !== []) { return [TypeCombinator::union(...$results), TrinaryLogic::createNo()]; } } if ($keysParamType->isArray()->yes()) { $itemType = $keysParamType->getIterableValueType(); if ($itemType->isInteger()->no()) { if ($itemType->toString() instanceof ErrorType) { return [new NeverType(), TrinaryLogic::createNo()]; } $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 ($firstArg instanceof Variable && $secondArg instanceof Variable && $firstArg->name === $secondArg->name) { return [$arrayType, TrinaryLogic::createNo()]; } return [$arrayType, TrinaryLogic::createMaybe()]; } /** * @param array $types * * @return list|null */ private function sanitizeConstantArrayKeyTypes(array $types): ?array { $sanitizedTypes = []; foreach ($types as $type) { if (!$type->isInteger()->yes() && !$type->toString() instanceof ErrorType) { $type = $type->toString(); } $scalars = $type->getConstantScalarTypes(); if (count($scalars) === 0) { return null; } foreach ($scalars as $scalar) { $value = $scalar->getValue(); if (!is_int($value) && !is_string($value)) { return null; } $sanitizedTypes[] = $scalar; } } return $sanitizedTypes; } } getName() === 'array_count_values'; } 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); $arrayTypes = $inputType->getArrays(); $isInputNonEmpty = $inputType->isIterableAtLeastOnce()->yes(); $outputTypes = []; $allowedValues = new UnionType([new IntegerType(), new StringType()]); foreach ($arrayTypes as $arrayType) { $itemType = TypeCombinator::intersect($arrayType->getItemType(), $allowedValues); if ($itemType instanceof NeverType) { continue; } $resultArrayType = new ArrayType($itemType->toArrayKey(), IntegerRangeType::fromInterval(1, null)); if ($isInputNonEmpty) { $outputTypes[] = new IntersectionType([$resultArrayType, new NonEmptyArrayType()]); } else { $outputTypes[] = $resultArrayType; } } if (count($outputTypes) === 0) { return new ConstantArrayType([], []); } return TypeCombinator::union(...$outputTypes); } } getName() === 'current'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (!isset($args[0])) { return null; } $argType = $scope->getType($args[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)); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'array_fill'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) < 3) { return null; } $numberType = $scope->getType($args[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($args[0]->value); $valueType = $scope->getType($args[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 = TypeCombinator::intersect($resultType, new AccessoryArrayListType()); } 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; } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'array_fill_keys'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) < 2) { return null; } $keysType = $scope->getType($args[0]->value); if ($keysType->isArray()->no()) { return $this->phpVersion->arrayFunctionsReturnNullWithNonArray() ? new NullType() : new NeverType(); } return $keysType->fillKeysArray($scope->getType($args[1]->value)); } } arrayFilterFunctionReturnTypeHelper = $arrayFilterFunctionReturnTypeHelper; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'array_filter'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): Type { $args = $functionCall->getArgs(); $arrayArg = $args[0]->value ?? null; $callbackArg = $args[1]->value ?? null; $flagArg = $args[2]->value ?? null; return $this->arrayFilterFunctionReturnTypeHelper->getType($scope, $arrayArg, $callbackArg, $flagArg); } } reflectionProvider = $reflectionProvider; $this->phpVersion = $phpVersion; } 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) { if ($this->phpVersion->throwsValueErrorForInternalFunctions()) { return new ArrayType(new MixedType(), new 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 { return $type->filterArrayRemovingFalsey(); } /** * @param \PhpParser\Node\Expr\Error|\PhpParser\Node\Expr\Variable|null $itemVar * @param \PhpParser\Node\Expr\Error|\PhpParser\Node\Expr\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 \PhpParser\Node\Expr\Error|\PhpParser\Node\Expr\Variable|null $itemVar * @param \PhpParser\Node\Expr\Error|\PhpParser\Node\Expr\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(), TrinaryLogic::createYes()); } $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(), TrinaryLogic::createYes()); } $booleanResult = $scope->getType($expr)->toBoolean(); if ($booleanResult->isFalse()->yes()) { return [new NeverType(), new NeverType(), \false]; } $truthyScope = $scope->filterByTruthyValue($expr); $optional = !$booleanResult->isTrue()->yes(); if ($optional) { $falseyScope = $scope->filterByFalseyValue($expr); $falseyItemType = $itemVarName !== null ? $falseyScope->getVariableType($itemVarName) : $itemType; $falseyKeyType = $keyVarName !== null ? $falseyScope->getVariableType($keyVarName) : $keyType; if ($falseyItemType instanceof NeverType || $falseyKeyType instanceof NeverType) { $optional = \false; } } return [$keyVarName !== null ? $truthyScope->getVariableType($keyVarName) : $keyType, $itemVarName !== null ? $truthyScope->getVariableType($itemVarName) : $itemType, $optional]; } 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; } } arrayFilterFunctionReturnTypeHelper = $arrayFilterFunctionReturnTypeHelper; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'array_find'; } 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 (count($arrayType->getArrays()) < 1) { return null; } $arrayArg = $args[0]->value; $callbackArg = $args[1]->value; $resultTypes = $this->arrayFilterFunctionReturnTypeHelper->getType($scope, $arrayArg, $callbackArg, null); $resultType = TypeCombinator::union(...array_map(static fn($type) => $type->getIterableValueType(), $resultTypes->getArrays())); return $resultTypes->isIterableAtLeastOnce()->yes() ? $resultType : TypeCombinator::addNull($resultType); } } getName() === 'array_find_key'; } 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 (count($arrayType->getArrays()) < 1) { return null; } return TypeCombinator::union($arrayType->getIterableKeyType(), new NullType()); } } getName(), ['array_key_first', 'array_key_last', 'array_first', 'array_last'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) < 1) { return null; } $argType = $scope->getType($args[0]->value); $iterableAtLeastOnce = $argType->isIterableAtLeastOnce(); if ($iterableAtLeastOnce->no()) { return new NullType(); } switch ($functionReflection->getName()) { case 'array_key_first': case 'array_key_last': $resultType = $argType->getIterableKeyType(); break; case 'array_first': case 'array_last': $resultType = $argType->getIterableValueType(); break; default: throw new ShouldNotHappenException(); } if ($iterableAtLeastOnce->yes()) { return $resultType; } return TypeCombinator::union($resultType, new NullType()); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'array_flip'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) !== 1) { return null; } $arrayType = $scope->getType($args[0]->value); if ($arrayType->isArray()->no()) { return $this->phpVersion->arrayFunctionsReturnNullWithNonArray() ? new NullType() : new NeverType(); } $flipped = $arrayType->flipArray(); if ($arrayType->isIterableAtLeastOnce()->yes()) { return TypeCombinator::intersect($flipped, new NonEmptyArrayType()); } return $flipped; } } 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); } } getName() === 'key'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (!isset($args[0])) { return null; } $argType = $scope->getType($args[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 setTypeSpecifier(TypeSpecifier $typeSpecifier): void { $this->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 { $args = $node->getArgs(); if (count($args) < 2) { return new SpecifiedTypes(); } $key = $args[0]->value; $array = $args[1]->value; $keyType = $scope->getType($key)->toArrayKey(); $arrayType = $scope->getType($array); if (!$keyType instanceof ConstantIntegerType && !$keyType instanceof ConstantStringType) { if ($context->true()) { $specifiedTypes = new SpecifiedTypes(); $nonEmptyType = $arrayType->isArray()->yes() ? new NonEmptyArrayType() : TypeCombinator::intersect(new ArrayType(new MixedType(), new MixedType()), new NonEmptyArrayType()); $specifiedTypes = $specifiedTypes->unionWith($this->typeSpecifier->create($array, $nonEmptyType, $context, $scope)); if ($arrayType->isIterableAtLeastOnce()->no()) { return $specifiedTypes; } $arrayKeyType = $arrayType->getIterableKeyType(); if ($keyType->isString()->yes()) { $arrayKeyType = $arrayKeyType->toString(); } elseif ($keyType->isString()->maybe()) { $arrayKeyType = TypeCombinator::union($arrayKeyType, $arrayKeyType->toString()); } $specifiedTypes = $specifiedTypes->unionWith($this->typeSpecifier->create($key, $arrayKeyType, $context, $scope)); $arrayDimFetch = new ArrayDimFetch($array, $key); return $specifiedTypes->unionWith($this->typeSpecifier->create($arrayDimFetch, $arrayType->getIterableValueType(), $context, $scope))->setRootExpr(new Identical($arrayDimFetch, new ConstFetch(new Name('__PHPSTAN_FAUX_CONSTANT')))); } return new SpecifiedTypes(); } if ($context->true()) { $type = new IntersectionType([new ArrayType(new MixedType(), new MixedType()), new HasOffsetType($keyType)]); } elseif ($this->phpVersion->throwsValueErrorForInternalFunctions()) { $specifiedTypes = $this->typeSpecifier->create($array, new HasOffsetType($keyType), $context, $scope); $type = new ArrayType(new MixedType(), new MixedType()); $type = $type->unsetOffset($keyType); return $specifiedTypes->unionWith($this->typeSpecifier->create($array, $type, $context->negate(), $scope)); } else { $type = new HasOffsetType($keyType); } return $this->typeSpecifier->create($array, $type, $context, $scope); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return strtolower($functionReflection->getName()) === 'array_keys'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) < 1) { return null; } $arrayType = $scope->getType($args[0]->value); if ($arrayType->isArray()->no()) { return $this->phpVersion->arrayFunctionsReturnNullWithNonArray() ? new NullType() : new NeverType(); } if (count($args) >= 2) { $filterType = $scope->getType($args[1]->value); $strict = TrinaryLogic::createNo(); if (count($args) >= 3) { $strict = $scope->getType($args[2]->value)->isTrue(); } return $arrayType->getKeysArrayFiltered($filterType, $strict); } return $arrayType->getKeysArray(); } } getName() === 'array_map'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); $numArgs = count($args); if ($numArgs < 2) { return null; } $singleArrayArgument = !isset($args[2]); $callback = $args[0]->value; $callableType = $scope->getType($callback); $callableIsNull = $callableType->isNull()->yes(); if ($callableType->isCallable()->yes()) { $valueType = $scope->getType(new FuncCall($callback, array_map(static fn(Node\Arg $arg) => new Node\Arg(new TypeExpr($scope->getType($arg->value)->getIterableValueType())), array_slice($args, 1)))); } elseif ($callableIsNull) { $arrayBuilder = ConstantArrayTypeBuilder::createEmpty(); $argTypes = []; $areAllSameSize = \true; $expectedSize = null; foreach (array_slice($args, 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 ??= $size; if ($expectedSize === $size) { continue; } $areAllSameSize = \false; continue 2; } } if (!$areAllSameSize) { $firstArr = $args[1]->value; $identities = []; foreach (array_slice($args, 2) as $arg) { $identities[] = new Node\Expr\BinaryOp\Identical($firstArr, $arg->value); } $and = array_reduce($identities, static fn(Node\Expr $a, Node\Expr $b) => 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($args[1]->value); if ($singleArrayArgument) { if ($callableIsNull) { return $arrayType; } $constantArrays = $arrayType->getConstantArrays(); if (count($constantArrays) > 0) { $totalCount = TypeCombinator::countConstantArrayValueTypes($constantArrays) * TypeCombinator::countConstantArrayValueTypes([$valueType]); if ($totalCount < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT) { $mappedArrayType = $arrayType->mapValueType(static fn(Type $type): Type => $scope->getType(new FuncCall($callback, [new Node\Arg(new TypeExpr($type))]))); } else { $mappedArrayType = TypeCombinator::intersect(new ArrayType($arrayType->getIterableKeyType(), $valueType), ...$this->getAccessoryTypes($arrayType, $valueType)); } } elseif ($arrayType->isArray()->yes()) { $mappedArrayType = TypeCombinator::intersect(new ArrayType($arrayType->getIterableKeyType(), $valueType), ...$this->getAccessoryTypes($arrayType, $valueType)); } else { $mappedArrayType = new ArrayType(new MixedType(), $valueType); } } else { $mappedArrayType = new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $valueType), new AccessoryArrayListType(), ...$this->getAccessoryTypes($arrayType, $valueType)]); } if ($arrayType->isIterableAtLeastOnce()->yes()) { $mappedArrayType = TypeCombinator::intersect($mappedArrayType, new NonEmptyArrayType()); } return $mappedArrayType; } /** * @return list */ private function getAccessoryTypes(Type $arrayType, Type $valueType): array { $accessoryTypes = []; foreach (TypeUtils::getAccessoryTypes($arrayType) as $accessoryType) { if (!$accessoryType instanceof HasOffsetValueType) { $accessoryTypes[] = $accessoryType; continue; } $accessoryTypes[] = new HasOffsetValueType($accessoryType->getOffsetType(), $valueType); } return $accessoryTypes; } } 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) { $startIndex = count($argTypes); if ($argType->isConstantArray()->yes()) { foreach ($argType->getConstantArrays() as $constantArray) { foreach ($constantArray->getValueTypes() as $valueType) { $argTypes[] = $valueType; } } } else { $argTypes[] = $argType->getIterableValueType(); } if (!$argType->isIterableAtLeastOnce()->yes()) { for ($i = $startIndex; $i < count($argTypes); $i++) { $optionalArgTypes[] = $i; } } } else { $argTypes[] = $argType; } } $allConstant = TrinaryLogic::createYes()->lazyAnd($argTypes, static fn(Type $argType) => $argType->isConstantArray()); if ($allConstant->yes()) { $newArrayBuilder = ConstantArrayTypeBuilder::createEmpty(); foreach ($argTypes as $argIndex => $argType) { $isOptionalArg = in_array($argIndex, $optionalArgTypes, \true); /** @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), $isOptionalArg || !$argType->hasOffsetValueType($keyType)->yes()); } } return $newArrayBuilder->getArray(); } $offsetTypes = []; foreach ($argTypes as $argIndex => $argType) { if (in_array($argIndex, $optionalArgTypes, \true)) { continue; } $constArrays = $argType->getConstantArrays(); if ($constArrays !== []) { foreach ($constArrays as $constantArray) { foreach ($constantArray->getKeyTypes() as $keyType) { $hasOffsetValue = TrinaryLogic::createFromBoolean($argType->hasOffsetValueType($keyType)->yes()); $offsetTypes[$keyType->getValue()] = [$hasOffsetValue, $argType->getOffsetValueType($keyType)]; } } } else { foreach ($offsetTypes as $key => [$hasOffsetValue, $offsetValueType]) { // more precise values-types will be calculated elsewhere. // just remember the offset key. $offsetTypes[$key] = [$hasOffsetValue->and(TrinaryLogic::createMaybe()), new MixedType()]; } } foreach (TypeUtils::getAccessoryTypes($argType) as $accessoryType) { if (!$accessoryType instanceof HasOffsetType && !$accessoryType instanceof HasOffsetValueType) { continue; } $offsetType = $accessoryType->getOffsetType(); $offsetTypes[$offsetType->getValue()] = [TrinaryLogic::createYes(), $argType->getOffsetValueType($offsetType)]; } } $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 = TypeCombinator::intersect($arrayType, new AccessoryArrayListType()); } if ($offsetTypes !== []) { $knownOffsetValues = []; foreach ($offsetTypes as $key => [$hasOffsetValue, $offsetType]) { if (is_int($key)) { // int keys will be appended and renumbered. // at this point we can't reason about them, because unknown arrays are in the mix. continue; } $keyType = new ConstantStringType($key); if ($hasOffsetValue->yes()) { // the last string-keyed offset will overwrite previous values $hasOffsetType = new HasOffsetValueType($keyType, $offsetType); } elseif ($hasOffsetValue->maybe()) { $hasOffsetType = new HasOffsetType($keyType); } else { continue; } $knownOffsetValues[] = $hasOffsetType; } if ($knownOffsetValues !== []) { $arrayType = TypeCombinator::intersect($arrayType, ...$knownOffsetValues); } } return $arrayType; } } getName(), ['next', 'prev'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (!isset($args[0])) { return null; } $argType = $scope->getType($args[0]->value); $iterableAtLeastOnce = $argType->isIterableAtLeastOnce(); if ($iterableAtLeastOnce->no()) { return new ConstantBooleanType(\false); } $valueType = $argType->getIterableValueType(); return TypeCombinator::union($valueType, new ConstantBooleanType(\false)); } } getName() === 'array_pad'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (!isset($args[2])) { return null; } $arrayType = $scope->getType($args[0]->value); $itemType = $scope->getType($args[2]->value); $returnType = new ArrayType(TypeCombinator::union($arrayType->getIterableKeyType(), new IntegerType()), TypeCombinator::union($arrayType->getIterableValueType(), $itemType)); $lengthType = $scope->getType($args[1]->value); if ($arrayType->isIterableAtLeastOnce()->yes() || $lengthType->isSuperTypeOf(new ConstantIntegerType(0))->no()) { $returnType = TypeCombinator::intersect($returnType, new NonEmptyArrayType()); } if ($arrayType->isList()->yes()) { $returnType = TypeCombinator::intersect($returnType, new AccessoryArrayListType()); } return $returnType; } } 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->getIterableValueType() : $argType->getIterableValueType(); if ($iterableAtLeastOnce->yes()) { return $itemType; } return TypeCombinator::union($itemType, new ConstantBooleanType(\false)); } } getName() === 'array_pop'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (!isset($args[0])) { return null; } $argType = $scope->getType($args[0]->value); $iterableAtLeastOnce = $argType->isIterableAtLeastOnce(); if ($iterableAtLeastOnce->no()) { return new NullType(); } $itemType = $argType->getIterableValueType(); if ($iterableAtLeastOnce->yes()) { return $itemType; } return TypeCombinator::union($itemType, new NullType()); } } getName() === 'array_rand'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); $argsCount = count($args); if ($argsCount < 1) { return null; } $firstArgType = $scope->getType($args[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($args[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() === 'array_reduce'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (!isset($args[1])) { return null; } $callbackType = $scope->getType($args[1]->value); if ($callbackType->isCallable()->no()) { return null; } $callbackReturnType = ParametersAcceptorSelector::selectFromArgs($scope, $args, $callbackType->getCallableParametersAcceptors($scope))->getReturnType(); if (isset($args[2])) { $initialType = $scope->getType($args[2]->value); } else { $initialType = new NullType(); } $arraysType = $scope->getType($args[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); } } 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) { $startIndex = count($argTypes); if ($argType->isConstantArray()->yes()) { foreach ($argType->getConstantArrays() as $constantArray) { foreach ($constantArray->getValueTypes() as $valueType) { $argTypes[] = $valueType; } } } else { $argTypes[] = $argType->getIterableValueType(); } if (!$argType->isIterableAtLeastOnce()->yes()) { for ($i = $startIndex; $i < count($argTypes); $i++) { $optionalArgTypes[] = $i; } } } else { $argTypes[] = $argType; } } $allConstant = TrinaryLogic::createYes()->lazyAnd($argTypes, static fn(Type $argType) => $argType->isConstantArray()); if ($allConstant->yes()) { $newArrayBuilder = ConstantArrayTypeBuilder::createEmpty(); foreach ($argTypes as $argIndex => $argType) { $isOptionalArg = in_array($argIndex, $optionalArgTypes, \true); /** @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), $isOptionalArg || !$argType->hasOffsetValueType($keyType)->yes()); } } return $newArrayBuilder->getArray(); } $offsetTypes = []; foreach ($argTypes as $argIndex => $argType) { if (in_array($argIndex, $optionalArgTypes, \true)) { continue; } $constArrays = $argType->getConstantArrays(); if ($constArrays !== []) { foreach ($constArrays as $constantArray) { foreach ($constantArray->getKeyTypes() as $keyType) { $hasOffsetValue = TrinaryLogic::createFromBoolean($argType->hasOffsetValueType($keyType)->yes()); $offsetTypes[$keyType->getValue()] = [$hasOffsetValue, $argType->getOffsetValueType($keyType)]; } } } else { foreach ($offsetTypes as $key => [$hasOffsetValue, $offsetValueType]) { // more precise values-types will be calculated elsewhere. // just remember the offset key. $offsetTypes[$key] = [$hasOffsetValue->and(TrinaryLogic::createMaybe()), new MixedType()]; } } foreach (TypeUtils::getAccessoryTypes($argType) as $accessoryType) { if (!$accessoryType instanceof HasOffsetType && !$accessoryType instanceof HasOffsetValueType) { continue; } $offsetType = $accessoryType->getOffsetType(); $offsetTypes[$offsetType->getValue()] = [TrinaryLogic::createYes(), $argType->getOffsetValueType($offsetType)]; } } $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()); } if ($offsetTypes !== []) { $knownOffsetValues = []; foreach ($offsetTypes as $key => [$hasOffsetValue, $offsetType]) { $keyType = is_string($key) ? new ConstantStringType($key) : new ConstantIntegerType($key); if ($hasOffsetValue->yes()) { // the last known offset will overwrite previous values $hasOffsetType = new HasOffsetValueType($keyType, $offsetType); } elseif ($hasOffsetValue->maybe()) { $hasOffsetType = new HasOffsetType($keyType); } else { continue; } $knownOffsetValues[] = $hasOffsetType; } if ($knownOffsetValues !== []) { $arrayType = TypeCombinator::intersect($arrayType, ...$knownOffsetValues); } } return $arrayType; } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'array_reverse'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (!isset($args[0])) { return null; } $type = $scope->getType($args[0]->value); if ($type->isArray()->no()) { return $this->phpVersion->arrayFunctionsReturnNullWithNonArray() ? new NullType() : new NeverType(); } $preserveKeysType = isset($args[1]) ? $scope->getType($args[1]->value) : new ConstantBooleanType(\false); return $type->reverseArray($preserveKeysType->isTrue()); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'array_search'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); $argsCount = count($args); if ($argsCount < 2) { return null; } $haystackArgType = $scope->getType($args[1]->value); if ($haystackArgType->isArray()->no()) { return $this->phpVersion->arrayFunctionsReturnNullWithNonArray() ? new NullType() : new NeverType(); } if ($argsCount < 3) { $strictArgType = new ConstantBooleanType(\false); } else { $strictArgType = $scope->getType($args[2]->value); } $needleArgType = $scope->getType($args[0]->value); return $haystackArgType->searchArray($needleArgType, $strictArgType->isTrue()); } } 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(); } $arrayType = $scope->getType($arrayArg); $nonEmptyType = $arrayType->isArray()->yes() ? new NonEmptyArrayType() : TypeCombinator::intersect(new ArrayType(new MixedType(), new MixedType()), new NonEmptyArrayType()); return $this->typeSpecifier->create($arrayArg, $nonEmptyType, $context, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void { $this->typeSpecifier = $typeSpecifier; } } getName() === 'array_shift'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (!isset($args[0])) { return null; } $argType = $scope->getType($args[0]->value); $iterableAtLeastOnce = $argType->isIterableAtLeastOnce(); if ($iterableAtLeastOnce->no()) { return new NullType(); } $itemType = $argType->getIterableValueType(); if ($iterableAtLeastOnce->yes()) { return $itemType; } return TypeCombinator::union($itemType, new NullType()); } } 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()); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'array_splice'; } 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(); return $arrayType->sliceArray($offsetType, $lengthType, TrinaryLogic::createNo()); } } getName() === 'array_sum'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (!isset($args[0])) { return null; } $argType = $scope->getType($args[0]->value); $resultTypes = []; if (count($argType->getConstantArrays()) > 0) { foreach ($argType->getConstantArrays() as $constantArray) { $node = new Int_(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(); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return strtolower($functionReflection->getName()) === 'array_values'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) !== 1) { return null; } $arrayType = $scope->getType($args[0]->value); if ($arrayType->isArray()->no()) { return $this->phpVersion->arrayFunctionsReturnNullWithNonArray() ? new NullType() : new NeverType(); } return $arrayType->getValuesArray(); } } 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; } } getName() === 'assert'; } public function getThrowTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $funcCall, Scope $scope): ?Type { $args = $funcCall->getArgs(); if (count($args) < 2) { return $functionReflection->getThrowType(); } $customThrow = $scope->getType($args[1]->value); if ((new ObjectType(Throwable::class))->isSuperTypeOf($customThrow)->yes()) { return $customThrow; } return $functionReflection->getThrowType(); } } 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() === 'base64_decode'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): Type { $args = $functionCall->getArgs(); if (!isset($args[1])) { return new StringType(); } $argType = $scope->getType($args[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(); } } phpVersion = $phpVersion; } public function isOperatorSupported(string $operatorSigil, Type $leftSide, Type $rightSide): bool { if (!$this->phpVersion->supportsBcMathNumberOperatorOverloading() || $leftSide instanceof NeverType || $rightSide instanceof NeverType) { return \false; } $bcMathNumberType = new ObjectType('BcMath\Number'); return in_array($operatorSigil, ['-', '+', '*', '/', '**', '%', '<', '<=', '>', '>=', '==', '!=', '<=>'], \true) && ($bcMathNumberType->isSuperTypeOf($leftSide)->yes() || $bcMathNumberType->isSuperTypeOf($rightSide)->yes()); } public function specifyType(string $operatorSigil, Type $leftSide, Type $rightSide): Type { $bcMathNumberType = new ObjectType('BcMath\Number'); $otherSide = $bcMathNumberType->isSuperTypeOf($leftSide)->yes() ? $rightSide : $leftSide; if ($otherSide->isFloat()->yes()) { return new ErrorType(); } if (in_array($operatorSigil, ['<', '<=', '>', '>=', '==', '!='], \true)) { return new BooleanType(); } if ($operatorSigil === '<=>') { return IntegerRangeType::fromInterval(-1, 1); } if ($otherSide->isInteger()->yes() || $otherSide->isNumericString()->yes() || $bcMathNumberType->isSuperTypeOf($otherSide)->yes()) { return $bcMathNumberType; } return new ErrorType(); } } 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 = new IntersectionType([new StringType(), new AccessoryNumericStringType()]); $args = $functionCall->getArgs(); if (isset($args[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($args[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($args[2]) === \false) { if ($secondArgument instanceof ConstantScalarType || $secondArgumentIsNumeric) { return $stringAndNumericStringType; } return $defaultReturnType; } $thirdArgument = $scope->getType($args[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 = new IntersectionType([new StringType(), new AccessoryNumericStringType()]); if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { $defaultReturnType = $stringAndNumericStringType; } else { $defaultReturnType = new UnionType([$stringAndNumericStringType, new NullType()]); } $args = $functionCall->getArgs(); if (isset($args[0]) === \false) { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } return $defaultReturnType; } $firstArgument = $scope->getType($args[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($args[1]) === \false) { if ($firstArgumentIsPositive) { return $stringAndNumericStringType; } return $defaultReturnType; } $secondArgument = $scope->getType($args[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 { $args = $functionCall->getArgs(); if ($this->phpVersion->throwsTypeErrorForInternalFunctions() && isset($args[0]) === \false) { return new NeverType(); } $stringAndNumericStringType = new IntersectionType([new StringType(), new AccessoryNumericStringType()]); if (isset($args[1]) === \false) { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } return new UnionType([$stringAndNumericStringType, new ConstantBooleanType(\false)]); } $exponent = $scope->getType($args[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($args[2])) { $modulus = $scope->getType($args[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(), ['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 { $args = $node->getArgs(); $argType = $scope->getType($args[0]->value); if ($argType instanceof ConstantStringType) { $funcCall = new FuncCall(new FullyQualified('class_exists'), [new Arg(new String_(ltrim($argType->getValue(), '\\')))]); return $this->typeSpecifier->create(new AlwaysRememberedExpr($funcCall, new BooleanType(), new BooleanType()), new ConstantBooleanType(\true), $context, $scope); } $narrowedType = new ClassStringType(); if ($functionReflection->getName() === 'enum_exists') { $narrowedType = new GenericClassStringType(new ObjectType('UnitEnum')); } return $this->typeSpecifier->create($args[0]->value, $narrowedType, $context, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void { $this->typeSpecifier = $typeSpecifier; } } 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->isClassString()->no()) { return new ConstantBooleanType(\false); } return null; } } 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() === '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() === '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 ExtendedParametersAcceptor ? $variant->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), [], $variant->getThrowPoints(), $variant->getImpurePoints(), $variant->getInvalidateExpressions(), $variant->getUsedVariables(), $variant->acceptsNamedArguments(), $variant->mustUseReturnValue()); } return TypeCombinator::union(...$closureTypes); } } getName() === 'getCurrent'; } public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope): Type { if (!$scope->isInAnonymousFunction()) { return new NeverType(); } return $scope->getAnonymousFunctionReflection(); } } 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; } } 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; } } = 2) { $fqcn = ltrim($classConstParts[0], '\\'); if ($fqcn === '' || $classConstParts[1] === '') { 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)); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'count_chars'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) < 1) { return null; } $modeType = count($args) === 2 ? $scope->getType($args[1]->value) : new ConstantIntegerType(0); if (IntegerRangeType::fromInterval(0, 2)->isSuperTypeOf($modeType)->yes()) { $arrayType = new ArrayType(new IntegerType(), new IntegerType()); return $this->phpVersion->throwsValueErrorForInternalFunctions() ? $arrayType : TypeUtils::toBenevolentUnion(new UnionType([$arrayType, new ConstantBooleanType(\false)])); } $stringType = new StringType(); return $this->phpVersion->throwsValueErrorForInternalFunctions() ? $stringType : TypeUtils::toBenevolentUnion(new UnionType([$stringType, new ConstantBooleanType(\false)])); } } getName(), ['sizeof', 'count'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) < 1) { return null; } $arrayType = $scope->getType($args[0]->value); if (!$this->isNormalCount($functionCall, $arrayType, $scope)->yes()) { if ($arrayType->isIterableAtLeastOnce()->yes()) { return IntegerRangeType::fromInterval(1, null); } return null; } return $scope->getType($args[0]->value)->getArraySize(); } private function isNormalCount(FuncCall $countFuncCall, Type $countedType, Scope $scope): TrinaryLogic { if (count($countFuncCall->getArgs()) === 1) { $isNormalCount = TrinaryLogic::createYes(); } else { $mode = $scope->getType($countFuncCall->getArgs()[1]->value); $isNormalCount = (new ConstantIntegerType(COUNT_NORMAL))->isSuperTypeOf($mode)->result->or($countedType->getIterableValueType()->isArray()->negate()); } return $isNormalCount; } } 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, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void { $this->typeSpecifier = $typeSpecifier; } } 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, $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, $scope)); } return $specifiedTypes; } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void { $this->typeSpecifier = $typeSpecifier; } } 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 = new UnionType([$stringType, $falseType]); $integerFalseType = new UnionType([$integerType, $falseType]); $stringListType = new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $stringType), new AccessoryArrayListType()]); $nestedArrayInListType = new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new ArrayType($stringType, $stringType)), new AccessoryArrayListType()]); $mixedType = new MixedType(); $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' => $stringFalseType, 'CURLINFO_PRIMARY_IP' => $stringType, 'CURLINFO_PRIMARY_PORT' => $integerType, 'CURLINFO_LOCAL_IP' => $stringType, 'CURLINFO_LOCAL_PORT' => $integerType, 'CURLINFO_SIZE_UPLOAD' => $floatType, 'CURLINFO_SIZE_DOWNLOAD' => $floatType, 'CURLINFO_SPEED_DOWNLOAD' => $floatType, 'CURLINFO_SPEED_UPLOAD' => $floatType, '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' => $mixedType, 'CURLINFO_RESPONSE_CODE' => $integerType, 'CURLINFO_HTTP_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' => $stringListType, 'CURLINFO_COOKIELIST' => $stringListType, 'CURLINFO_FTP_ENTRY_PATH' => $stringFalseType, 'CURLINFO_APPCONNECT_TIME' => $floatType, 'CURLINFO_CERTINFO' => $nestedArrayInListType, 'CURLINFO_CONDITION_UNMET' => $integerType, 'CURLINFO_RTSP_CLIENT_CSEQ' => $integerType, 'CURLINFO_RTSP_CSEQ_RECV' => $integerType, 'CURLINFO_RTSP_SERVER_CSEQ' => $integerType, 'CURLINFO_RTSP_SESSION_ID' => $stringFalseType, 'CURLINFO_HTTP_VERSION' => $integerType, 'CURLINFO_PROTOCOL' => $integerType, '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, 'CURLINFO_EFFECTIVE_METHOD' => $stringType, 'CURLINFO_PROXY_ERROR' => $integerType, 'CURLINFO_REFERER' => $stringFalseType, 'CURLINFO_RETRY_AFTER' => $integerType, 'CURLINFO_CAINFO' => $stringFalseType, 'CURLINFO_CAPATH' => $stringFalseType, 'CURLINFO_POSTTRANSFER_TIME_T' => $integerFalseType, 'CURLINFO_QUEUE_TIME_T' => $integerFalseType, 'CURLINFO_USED_PROXY' => $integerFalseType, 'CURLINFO_HTTPAUTH_USED' => $integerFalseType, 'CURLINFO_PROXYAUTH_USED' => $integerFalseType, 'CURLINFO_CONN_ID' => $integerFalseType]; 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 = new UnionType([$stringType, new NullType()]); $nestedArrayInListType = new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new ArrayType($stringType, $stringType)), new AccessoryArrayListType()]); $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' => $nestedArrayInListType, 'primary_port' => $integerType, 'local_ip' => $stringType, 'local_port' => $integerType, 'http_version' => $integerType, 'protocol' => $integerType, 'ssl_verifyresult' => $integerType, 'scheme' => $stringType, 'appconnect_time_us' => $integerType, 'queue_time_us' => $integerType, 'connect_time_us' => $integerType, 'namelookup_time_us' => $integerType, 'pretransfer_time_us' => $integerType, 'redirect_time_us' => $integerType, 'starttransfer_time_us' => $integerType, 'posttransfer_time_us' => $integerType, 'total_time_us' => $integerType, 'request_header' => $stringType, 'effective_method' => $stringType, 'capath' => $stringType, 'cainfo' => $stringType, 'used_proxy' => $integerType, 'httpauth_used' => $integerType, 'proxyauth_used' => $integerType, 'conn_id' => $integerType]; foreach ($componentTypesPairedStrings as $componentName => $componentValueType) { $builder->setOffsetValueType(new ConstantStringType($componentName), $componentValueType); } $returnTypes[] = $builder->getArray(); return TypeUtils::toBenevolentUnion(TypeCombinator::union(...$returnTypes)); } } 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); } } 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); } } 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); } } getConstantStrings() as $formatString) { $types[] = $this->buildReturnTypeFromFormat($formatString->getValue(), $useMicrosec); } if (count($types) === 0) { $type = $formatType->isNonEmptyString()->yes() ? new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]) : new StringType(); } else { $type = TypeCombinator::union(...$types); } if ($type->isNumericString()->no() && $formatType->isNonEmptyString()->yes()) { $type = TypeCombinator::union($type, new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()])); } return $type; } private 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 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'); } } phpVersion = $phpVersion; } public function isStaticMethodSupported(MethodReflection $methodReflection): bool { return $methodReflection->getName() === 'createFromDateString' && $methodReflection->getDeclaringClass()->getName() === DateInterval::class; } public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $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 { @DateInterval::createFromDateString($constantString->getValue()); } catch (Throwable $e) { return $methodReflection->getThrowType(); } $valueType = TypeCombinator::remove($valueType, $constantString); } if (!$valueType instanceof NeverType) { return $methodReflection->getThrowType(); } return null; } } phpVersion = $phpVersion; } public function getClass(): string { return DateInterval::class; } public function isStaticMethodSupported(MethodReflection $methodReflection): bool { return $methodReflection->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(); $hasFalse = \false; $hasDateInterval = \false; foreach ($strings as $string) { try { $result = @DateInterval::createFromDateString($string->getValue()); } catch (Throwable $e) { $result = \false; } if ($result === \false) { $hasFalse = \true; } else { $hasDateInterval = \true; } } if ($hasFalse) { if (!$hasDateInterval) { if ($this->phpVersion->hasDateTimeExceptions()) { return new NeverType(); } return new ConstantBooleanType(\false); } return null; } if ($hasDateInterval) { return new ObjectType(DateInterval::class); } return null; } } helper = $helper; } public function getClass(): string { return DateInterval::class; } public function isMethodSupported(MethodReflection $methodReflection): bool { return $methodReflection->getName() === 'format'; } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type { $arguments = $methodCall->getArgs(); if (!isset($arguments[0])) { return null; } return $this->helper->getType($scope->getType($arguments[0]->value), $scope->getType($methodCall->var), $scope); } } helper = $helper; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'date_interval_format'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) < 2) { return null; } return $this->helper->getType($scope->getType($args[1]->value), $scope->getType($args[0]->value), $scope); } } getConstantStrings(); if (count($constantStrings) === 0) { if ($formatType->isNonEmptyString()->yes()) { return new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]); } return null; } $daysIsInt = $intervalType->hasInstanceProperty('days')->yes() && $intervalType->getInstanceProperty('days', $scope)->getReadableType()->isInteger()->yes(); $dateInterval = $daysIsInt ? (new DateTime('2000-01-01'))->diff(new DateTime('2000-01-01')) : new DateInterval('P0D'); $possibleReturnTypes = []; foreach ($constantStrings as $string) { $formatString = $string->getValue(); $value = $dateInterval->format($formatString); $accessories = []; if (is_numeric($value)) { $accessories[] = new AccessoryNumericStringType(); } if ($value !== '0' && $value !== '' && ($formatString !== '%a' || $daysIsInt)) { $accessories[] = new AccessoryNonFalsyStringType(); } elseif ($value !== '') { $accessories[] = new AccessoryNonEmptyStringType(); } if (strtolower($value) === $value) { $accessories[] = new AccessoryLowercaseStringType(); } if (strtoupper($value) === $value) { $accessories[] = new AccessoryUppercaseStringType(); } if (count($accessories) === 0) { return null; } $possibleReturnTypes[] = new IntersectionType([new StringType(), ...$accessories]); } return TypeCombinator::union(...$possibleReturnTypes); } } getName() === '__construct'; } public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope): ?Type { if (!$methodCall->class instanceof Name) { return null; } $className = $scope->resolveName($methodCall->class); if (strtolower($className) !== 'dateperiod') { return null; } $args = $methodCall->getArgs(); if (!isset($args[0])) { return null; } $firstArgType = $scope->getType($args[0]->value); if ($firstArgType->isString()->yes()) { $firstArgType = new ObjectType(DateTime::class); } $thirdArgType = null; if (isset($args[2])) { $thirdArgType = $scope->getType($args[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 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'); } } 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(), ['date_create_from_format', 'date_create_immutable_from_format'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) < 2) { return null; } $formats = $scope->getType($args[0]->value)->getConstantStrings(); $datetimes = $scope->getType($args[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); } } 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'); } } */ private string $dateTimeClass; /** @param class-string $dateTimeClass */ public function __construct(PhpVersion $phpVersion, string $dateTimeClass) { $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 { $args = $methodCall->getArgs(); if (count($args) < 1) { return null; } $valueType = $scope->getType($args[0]->value); $constantStrings = $valueType->getConstantStrings(); $hasFalse = \false; $hasDateTime = \false; foreach ($constantStrings as $constantString) { try { $result = @(new DateTime())->modify($constantString->getValue()); } catch (Throwable $e) { $result = \false; } if ($result === \false) { $hasFalse = \true; } else { $hasDateTime = \true; } $valueType = TypeCombinator::remove($valueType, $constantString); } if (!$valueType instanceof NeverType) { return null; } if ($hasFalse) { if (!$hasDateTime) { if ($this->phpVersion->hasDateTimeExceptions()) { return new NeverType(); } return new ConstantBooleanType(\false); } return null; } if ($hasDateTime) { $callerType = $scope->getType($methodCall->var); $dateTimeInterfaceType = new ObjectType(DateTimeInterface::class); if ($dateTimeInterfaceType->isSuperTypeOf($callerType)->yes()) { return $callerType; } return TypeTraverser::map($callerType, static function (Type $type, callable $traverse) use ($dateTimeInterfaceType): Type { if ($type instanceof UnionType) { return $traverse($type); } if ($dateTimeInterfaceType->isSuperTypeOf($type)->yes()) { return $type; } return new NeverType(); }); } return null; } } 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'); } } 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 $functionReflection->getName() === 'define' && $context->null() && count($node->getArgs()) >= 2; } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes { $args = $node->getArgs(); $constantName = $scope->getType($args[0]->value); if (!$constantName instanceof ConstantStringType || $constantName->getValue() === '') { return new SpecifiedTypes([], []); } $valueType = $scope->getType($args[1]->value); $finalType = $scope->getConstantExplicitTypeFromConfig($constantName->getValue(), $valueType); return $this->typeSpecifier->create(new Node\Expr\ConstFetch(new Node\Name\FullyQualified($constantName->getValue())), $finalType, TypeSpecifierContext::createTruthy(), $scope)->setAlwaysOverwriteTypes(); } } 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, $scope); } } 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() === 'createElement'; } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type { $args = $methodCall->getArgs(); if (!isset($args[0])) { return null; } $argType = $scope->getType($args[0]->value); $doc = new DOMDocument(); foreach ($argType->getConstantStrings() as $constantString) { try { $doc->createElement($constantString->getValue()); } catch (DOMException $e) { return null; } $argType = TypeCombinator::remove($argType, $constantString); } if (!$argType instanceof NeverType) { return null; } $variant = ParametersAcceptorSelector::selectFromArgs($scope, $args, $methodReflection->getVariants()); return TypeCombinator::remove($variant->getReturnType(), new ConstantBooleanType(\false)); } } getDeclaringClass()->getName() === DOMDocument::class && $methodReflection->getName() === 'createElement'; } public function getThrowTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type { $args = $methodCall->getArgs(); if (!isset($args[0])) { return new ObjectType(DOMException::class); } $argType = $scope->getType($args[0]->value); $doc = new DOMDocument(); foreach ($argType->getConstantStrings() as $constantString) { try { $doc->createElement($constantString->getValue()); } catch (DOMException $e) { return new ObjectType(DOMException::class); } $argType = TypeCombinator::remove($argType, $constantString); } if (!$argType instanceof NeverType) { return new ObjectType(DOMException::class); } return null; } } getDeclaringClass()->getName() === 'Ds\Map' && in_array($methodReflection->getName(), ['get', 'remove'], \true); } public function getThrowTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type { if (count($methodCall->args) < 2) { return $methodReflection->getThrowType(); } return new VoidType(); } } 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; } } 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 = new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $returnValueType), new AccessoryArrayListType()]); 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 = new UnionType([$returnType, new ConstantBooleanType(\false)]); } if ($delimiterType instanceof MixedType) { $returnType = TypeUtils::toBenevolentUnion($returnType); } return $returnType; } } |null */ private ?array $filterTypeMap = null; /** @var array>|null */ private ?array $filterTypeOptions = null; private ?Type $supportedFilterInputTypes = null; public function __construct(ReflectionProvider $reflectionProvider, PhpVersion $phpVersion) { $this->reflectionProvider = $reflectionProvider; $this->phpVersion = $phpVersion; $this->flagsString = new ConstantStringType('flags'); } private function getOffsetValueType(Type $inputType, Type $offsetType, ?Type $filterType, ?Type $flagsType): Type { $hasNullOnFailure = $this->hasFlag('FILTER_NULL_ON_FAILURE', $flagsType); if ($hasNullOnFailure->yes()) { $inexistentOffsetType = new ConstantBooleanType(\false); } elseif ($hasNullOnFailure->no()) { $inexistentOffsetType = new NullType(); } else { $inexistentOffsetType = new UnionType([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 ??= 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'); if ($filterValue === null) { return $mixedType; } } 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) : []; if (isset($options['default'])) { $defaultType = $options['default']; } else { $hasNullOnFailure = $this->hasFlag('FILTER_NULL_ON_FAILURE', $flagsType); if ($hasNullOnFailure->yes()) { $defaultType = new NullType(); } elseif ($hasNullOnFailure->no()) { $defaultType = new ConstantBooleanType(\false); } else { $defaultType = new UnionType([new ConstantBooleanType(\false), new NullType()]); } } $hasRequireArrayFlag = $this->hasFlag('FILTER_REQUIRE_ARRAY', $flagsType); if ($hasRequireArrayFlag->maybe()) { // Too complicated return $mixedType; } $inputIsArray = $inputType->isArray(); $hasRequireArrayFlag = $this->hasFlag('FILTER_REQUIRE_ARRAY', $flagsType); $hasThrowOnFailureFlag = $this->phpVersion->hasFilterThrowOnFailureConstant() ? $this->hasFlag('FILTER_THROW_ON_FAILURE', $flagsType) : TrinaryLogic::createNo(); if ($inputIsArray->no() && $hasRequireArrayFlag->yes()) { if ($hasThrowOnFailureFlag->yes()) { return new ErrorType(); } return $defaultType; } $hasForceArrayFlag = $this->hasFlag('FILTER_FORCE_ARRAY', $flagsType); if ($hasRequireArrayFlag->no() && $hasForceArrayFlag->maybe()) { // Too complicated return $mixedType; } if ($inputIsArray->yes() && ($hasRequireArrayFlag->yes() || $hasForceArrayFlag->yes())) { $inputArrayKeyType = $inputType->getIterableKeyType(); $inputType = $inputType->getIterableValueType(); } if ($inputType->isScalar()->no() && $inputType->isNull()->no()) { $exactType = $defaultType; } else { $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)->no()) { $accessory = new AccessoryNonEmptyStringType(); if ($inputType->isNonFalsyString()->yes()) { $accessory = new AccessoryNonFalsyStringType(); } $type = TypeCombinator::intersect($type, $accessory); } if ($exactType === null || $hasOptions->maybe() || !$inputType->equals($type) && $inputType->isSuperTypeOf($type)->yes()) { if (!$defaultType->isSuperTypeOf($type)->yes()) { $type = TypeCombinator::union($type, $defaultType); } } if ($hasThrowOnFailureFlag->yes()) { $type = TypeCombinator::remove($type, $defaultType); } if ($hasRequireArrayFlag->yes()) { $type = new ArrayType($inputArrayKeyType ?? $mixedType, $type); if (!$hasThrowOnFailureFlag->yes() && !$inputIsArray->yes()) { $type = TypeCombinator::union($type, $defaultType); } } if ($hasRequireArrayFlag->no() && $hasForceArrayFlag->yes()) { 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 = new IntersectionType([$stringType, new AccessoryNonFalsyStringType()]); $map = ['FILTER_UNSAFE_RAW' => $stringType, 'FILTER_SANITIZE_EMAIL' => $stringType, 'FILTER_SANITIZE_ENCODED' => $stringType, 'FILTER_SANITIZE_NUMBER_FLOAT' => $stringType, 'FILTER_SANITIZE_NUMBER_INT' => $stringType, 'FILTER_SANITIZE_SPECIAL_CHARS' => $stringType, 'FILTER_SANITIZE_STRING' => $stringType, 'FILTER_SANITIZE_URL' => $stringType, 'FILTER_VALIDATE_BOOLEAN' => $booleanType, 'FILTER_VALIDATE_DOMAIN' => $stringType, 'FILTER_VALIDATE_EMAIL' => $nonFalsyStringType, 'FILTER_VALIDATE_FLOAT' => $floatType, 'FILTER_VALIDATE_INT' => $intType, 'FILTER_VALIDATE_IP' => $nonFalsyStringType, 'FILTER_VALIDATE_MAC' => $nonFalsyStringType, 'FILTER_VALIDATE_REGEXP' => $stringType, 'FILTER_VALIDATE_URL' => $nonFalsyStringType]; $this->filterTypeMap = []; foreach ($map as $filter => $type) { $constant = $this->getConstant($filter); if ($constant === null) { continue; } $this->filterTypeMap[$constant] = $type; } if ($this->reflectionProvider->hasConstant(new Node\Name('FILTER_SANITIZE_MAGIC_QUOTES'), null)) { $sanitizeMagicQuote = $this->getConstant('FILTER_SANITIZE_MAGIC_QUOTES'); if ($sanitizeMagicQuote !== null) { $this->filterTypeMap[$sanitizeMagicQuote] = $stringType; } } if ($this->reflectionProvider->hasConstant(new Node\Name('FILTER_SANITIZE_ADD_SLASHES'), null)) { $sanitizeAddSlashes = $this->getConstant('FILTER_SANITIZE_ADD_SLASHES'); if ($sanitizeAddSlashes !== null) { $this->filterTypeMap[$sanitizeAddSlashes] = $stringType; } } return $this->filterTypeMap; } /** * @return array> */ private function getFilterTypeOptions(): array { if ($this->filterTypeOptions !== null) { return $this->filterTypeOptions; } $map = ['FILTER_VALIDATE_INT' => ['min_range', 'max_range']]; $this->filterTypeOptions = []; foreach ($map as $filter => $type) { $constant = $this->getConstant($filter); if ($constant === null) { continue; } $this->filterTypeOptions[$constant] = $type; } 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) { return null; } 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) { $allowOctal = $this->hasFlag('FILTER_FLAG_ALLOW_OCTAL', $flagsType); $allowHex = $this->hasFlag('FILTER_FLAG_ALLOW_HEX', $flagsType); if ($allowOctal->maybe() || $allowHex->maybe()) { return null; } $value = $in->getValue(); if ($allowOctal->yes() && preg_match('/\A0[oO][0-7]+\z/', $value) === 1) { $octalValue = octdec($value); return is_int($octalValue) ? new ConstantIntegerType($octalValue) : $defaultType; } if ($allowHex->yes() && 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)->no() && $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; } /** * @param non-empty-string $flagName */ public function hasFlag(string $flagName, ?Type $flagsType): TrinaryLogic { $flag = $this->getConstant($flagName); if ($flag === null) { return TrinaryLogic::createNo(); } if ($flagsType === null) { // Will default to 0 return TrinaryLogic::createNo(); } $type = $this->getFlagsValue($flagsType); $scalarValues = $type->getConstantScalarValues(); if ($scalarValues === []) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::lazyExtremeIdentity($scalarValues, static fn($scalar): TrinaryLogic => TrinaryLogic::createFromBoolean(((int) $scalar & $flag) === $flag)); } private function getFlagsValue(Type $exprType): Type { if (!$exprType->isConstantArray()->yes()) { return $exprType; } $hasOffsetValue = $exprType->hasOffsetValueType($this->flagsString); if ($hasOffsetValue->no()) { return new ConstantIntegerType(0); } if ($hasOffsetValue->yes()) { return $exprType->getOffsetValueType($this->flagsString); } return TypeCombinator::union(new ConstantIntegerType(0), $exprType->getOffsetValueType($this->flagsString)); } private function canStringBeSanitized(int $filterValue, ?Type $flagsType): TrinaryLogic { // If it is a validation filter, the string will not be changed if (($filterValue & self::VALIDATION_FILTER_BITMASK) !== 0) { return TrinaryLogic::createNo(); } // 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('FILTER_FLAG_STRIP_LOW', $flagsType)->or($this->hasFlag('FILTER_FLAG_STRIP_HIGH', $flagsType))->or($this->hasFlag('FILTER_FLAG_STRIP_BACKTICK', $flagsType)); } return TrinaryLogic::createYes(); } } filterFunctionReturnTypeHelper = $filterFunctionReturnTypeHelper; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'filter_input'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) < 2) { return null; } return $this->filterFunctionReturnTypeHelper->getInputType($scope->getType($args[0]->value), $scope->getType($args[1]->value), isset($args[2]) ? $scope->getType($args[2]->value) : null, isset($args[3]) ? $scope->getType($args[3]->value) : null); } } 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 { $args = $functionCall->getArgs(); if (count($args) < 2) { return null; } $functionName = strtolower($functionReflection->getName()); $inputArgType = $scope->getType($args[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($args[1]->value); $filterConstantArrayType = $filterArgType->getConstantArrays()[0] ?? null; $addEmptyType = isset($args[2]) ? $scope->getType($args[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 ? TypeCombinator::intersect($arrayType, new AccessoryArrayListType()) : $arrayType; } // Override $add_empty option $addEmpty = \false; $keysType = $inputConstantArrayType; $inputKeysList = array_map(static fn($type) => $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 ? TypeCombinator::intersect($arrayType, new AccessoryArrayListType()) : $arrayType; } return null; } else { $keysType = $filterConstantArrayType; $filterKeyTypes = $filterConstantArrayType->getKeyTypes(); $filterKeysList = array_map(static fn($type) => $type->getValue(), $filterKeyTypes); $filterTypesMap = array_combine($filterKeysList, $keysType->getValueTypes()); if ($inputConstantArrayType !== null) { $inputKeysList = array_map(static fn($type) => $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} */ private 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]; } } filterFunctionReturnTypeHelper = $filterFunctionReturnTypeHelper; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return strtolower($functionReflection->getName()) === 'filter_var'; } 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); $filterType = isset($args[1]) ? $scope->getType($args[1]->value) : null; $flagsType = isset($args[2]) ? $scope->getType($args[2]->value) : null; return $this->filterFunctionReturnTypeHelper->getType($inputType, $filterType, $flagsType); } } reflectionProvider = $reflectionProvider; $this->phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'filter_var'; } public function getThrowTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $funcCall, Scope $scope): ?Type { if (!isset($funcCall->getArgs()[3])) { return null; } if (!$this->phpVersion->hasFilterThrowOnFailureConstant() || !$this->reflectionProvider->hasConstant(new Name\FullyQualified('FILTER_THROW_ON_FAILURE'), null)) { return null; } $flagsExpr = $funcCall->getArgs()[3]->value; $flagsType = $scope->getType($flagsExpr); if ($flagsType->isConstantArray()->yes()) { $flagsType = $flagsType->getOffsetValueType(new ConstantStringType('flags')); } $flag = $this->getConstant(); if ($flag !== null && $flagsType instanceof ConstantIntegerType && ($flagsType->getValue() & $flag) === $flag) { return new ObjectType('_PHPStan_33c983f26\Filter\FilterFailedException'); } return null; } private function getConstant(): ?int { $constant = $this->reflectionProvider->getConstant(new Name('FILTER_THROW_ON_FAILURE'), null); $valueType = $constant->getValueType(); if (!$valueType instanceof ConstantIntegerType) { return null; } return $valueType->getValue(); } } 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, $scope); } return $this->typeSpecifier->create($node->getArgs()[0]->value, new CallableType(), $context, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void { $this->typeSpecifier = $typeSpecifier; } } 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); } } 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 $argType->toGetClassResultType(); } } 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 TypeCombinator::union(...array_map(static fn(Type $type) => self::resolveOneType($type), $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 TypeCombinator::union(...$types); } } return new StringType(); } } 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) { if ($variable === 'this') { continue; } $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(); } } 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(fn(ConstantStringType $stringType): Type => $this->findParentClassNameType($stringType->getValue()), $constantStrings)); } $classNames = $argType->getObjectClassNames(); if (count($classNames) > 0) { return TypeCombinator::union(...array_map(fn(string $classNames): Type => $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); } } 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() === '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 new UnionType([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')]); }); } } >', '<', '<=', '>', '>=', '==', '!=', '<=>'], \true) && ($gmpType->isSuperTypeOf($leftSide)->yes() || $gmpType->isSuperTypeOf($rightSide)->yes()); } public function specifyType(string $operatorSigil, Type $leftSide, Type $rightSide): Type { $gmpType = new ObjectType('GMP'); $otherSide = $gmpType->isSuperTypeOf($leftSide)->yes() ? $rightSide : $leftSide; // Comparison operators return bool or int (for spaceship) if (in_array($operatorSigil, ['<', '<=', '>', '>=', '==', '!='], \true)) { return new BooleanType(); } if ($operatorSigil === '<=>') { return IntegerRangeType::fromInterval(-1, 1); } // GMP can operate with: GMP, int, or numeric-string if ($otherSide->isInteger()->yes() || $otherSide->isNumericString()->yes() || $gmpType->isSuperTypeOf($otherSide)->yes()) { return $gmpType; } return new ErrorType(); } } isSuperTypeOf($operand)->yes(); } public function specifyType(string $operatorSigil, Type $operand): Type { return new ObjectType('GMP'); } } ['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 array $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 { $args = $functionCall->getArgs(); if (!isset($args[0])) { return null; } $lowerFunctionName = strtolower($functionReflection->getName()); if (!array_key_exists($lowerFunctionName, self::SUPPORTED_FUNCTIONS)) { throw new ShouldNotHappenException(); } $functionData = self::SUPPORTED_FUNCTIONS[$lowerFunctionName]; if (is_bool($functionData['binary'])) { $binaryType = new ConstantBooleanType($functionData['binary']); } elseif (isset($args[$functionData['binary']])) { $binaryType = $scope->getType($args[$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($args[0]->value); $constantAlgorithmTypes = $algorithmType->getConstantStrings(); if (count($constantAlgorithmTypes) === 0) { if ($functionData['possiblyFalse'] || !$this->phpVersion->throwsValueErrorForInternalFunctions()) { return new BenevolentUnionType([$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; } } 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() === 'hrtime'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): Type { $arrayType = new ConstantArrayType([new ConstantIntegerType(0), new ConstantIntegerType(1)], [IntegerRangeType::fromInterval(1, null), IntegerRangeType::fromInterval(0, 999999999)], [2], [], TrinaryLogic::createYes()); $numberType = new BenevolentUnionType([IntegerRangeType::fromInterval(1, null), 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); } } idateFunctionReturnTypeHelper = $idateFunctionReturnTypeHelper; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'idate'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if ($args === []) { return new ConstantBooleanType(\false); } return $this->idateFunctionReturnTypeHelper->getTypeFromFormatType($scope->getType($args[0]->value)); } } getConstantStrings() as $formatString) { $types[] = $this->buildReturnTypeFromFormat($formatString->getValue()); } if ($types === []) { return null; } return TypeCombinator::union(...$types); } private function buildReturnTypeFromFormat(string $formatString): Type { // see https://www.php.net/idate and https://www.php.net/manual/de/datetime.format switch ($formatString) { case 'd': case 'j': return IntegerRangeType::fromInterval(1, 31); case 'h': case 'g': return IntegerRangeType::fromInterval(1, 12); case 'H': case 'G': return IntegerRangeType::fromInterval(0, 23); case 'i': return IntegerRangeType::fromInterval(0, 59); case 'I': return IntegerRangeType::fromInterval(0, 1); case 'L': return IntegerRangeType::fromInterval(0, 1); case 'm': case 'n': return IntegerRangeType::fromInterval(1, 12); case 'N': return IntegerRangeType::fromInterval(1, 7); case 's': return IntegerRangeType::fromInterval(0, 59); case 't': return IntegerRangeType::fromInterval(28, 31); case 'w': return IntegerRangeType::fromInterval(0, 6); case 'W': return IntegerRangeType::fromInterval(1, 53); case 'y': return IntegerRangeType::fromInterval(0, 99); case 'z': return IntegerRangeType::fromInterval(0, 365); case 'B': case 'o': case 'U': case 'Y': case 'Z': return new IntegerType(); default: return new ConstantBooleanType(\false); } } } 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) { $isNonEmpty = $arrayType->isIterableAtLeastOnce()->yes(); $result = []; foreach ($separatorType->getConstantStrings() as $separator) { foreach ($arrayType->getConstantArrays() as $constantArray) { $constantType = $this->inferConstantType($constantArray, $separator, $isNonEmpty); 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, bool $isNonEmpty): ?Type { $sep = $separatorType->getValue(); $valueTypes = $arrayType->getValueTypes(); $limit = InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT; // Build implode results incrementally, processing one key at a time. // For optional keys, fork each partial result into with/without variants. // This avoids generating 2^N ConstantArrayType objects via getAllArrays(). /** @var list> $partials */ $partials = [[]]; foreach ($valueTypes as $i => $valueType) { $constScalars = $valueType->getConstantScalarValues(); if (count($constScalars) === 0) { return null; } $isOptional = $arrayType->isOptionalKey($i); $newPartials = []; foreach ($partials as $partial) { if ($isOptional) { $newPartials[] = $partial; } foreach ($constScalars as $scalar) { $newPartial = $partial; $newPartial[] = $scalar; $newPartials[] = $newPartial; } } $partials = $newPartials; if (count($partials) > $limit) { return null; } } $strings = []; foreach ($partials as $partial) { if ($partial === [] && $isNonEmpty) { continue; } $strings[] = new ConstantStringType(implode($sep, $partial)); } if ($strings === []) { return null; } return TypeCombinator::union(...$strings); } } 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 { $args = $node->getArgs(); $argsCount = count($args); if ($argsCount < 2) { return new SpecifiedTypes(); } $isStrictComparison = \false; if ($argsCount >= 3) { $strictNodeType = $scope->getType($args[2]->value); $isStrictComparison = $strictNodeType->isTrue()->yes(); } $needleExpr = $args[0]->value; $arrayExpr = $args[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->unpack) { $types = null; break; } if ($isStrictComparison) { $itemTypes = $this->typeSpecifier->specifyTypesInCondition($scope, new Identical($needleExpr, $item->value), $context); } else { $itemTypes = $this->typeSpecifier->specifyTypesInCondition($scope, new Equal($needleExpr, $item->value), $context); } 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($args[1]->value, TypeCombinator::intersect($arrayType, new NonEmptyArrayType()), $context, $scope); } return new SpecifiedTypes(); } $specifiedTypes = new SpecifiedTypes(); $narrowingValueType = $this->computeNeedleNarrowingType($context, $needleType, $arrayType, $arrayValueType); if ($narrowingValueType !== null) { $specifiedTypes = $this->typeSpecifier->create($needleExpr, $narrowingValueType, $context, $scope); if ($needleExpr instanceof AlwaysRememberedExpr) { $specifiedTypes = $specifiedTypes->unionWith($this->typeSpecifier->create($needleExpr->getExpr(), $narrowingValueType, $context, $scope)); } } if ($context->true() || $context->false() && count($needleType->getFiniteTypes()) === 1) { if ($context->true()) { $arrayValueType = TypeCombinator::union($arrayValueType, $needleType); } else { $arrayValueType = TypeCombinator::remove($arrayValueType, $needleType); } $specifiedTypes = $specifiedTypes->unionWith($this->typeSpecifier->create($args[1]->value, new ArrayType(new MixedType(), $arrayValueType), TypeSpecifierContext::createTrue(), $scope)); } if ($context->true() && $arrayType->isArray()->yes()) { $specifiedTypes = $specifiedTypes->unionWith($this->typeSpecifier->create($args[1]->value, TypeCombinator::intersect($arrayType, new NonEmptyArrayType()), $context, $scope)); } return $specifiedTypes; } /** * Computes the type to narrow the needle against, or null if no narrowing should occur. * In true context, returns the array value type directly. * In false context, returns only the values guaranteed to be in every possible variant of the array. */ private function computeNeedleNarrowingType(TypeSpecifierContext $context, Type $needleType, Type $arrayType, Type $arrayValueType): ?Type { if ($context->true()) { return $arrayValueType; } if (!$context->false() || count($needleType->getFiniteTypes()) === 0 || !$arrayType->isIterableAtLeastOnce()->yes()) { return null; } $arrays = $arrayType->getArrays(); $guaranteedValueTypePerArray = []; foreach ($arrays as $array) { if ($array instanceof ConstantArrayType) { $innerGuaranteeValueType = []; foreach ($array->getValueTypes() as $i => $valueType) { if ($array->isOptionalKey($i)) { continue; } $finiteTypes = $valueType->getFiniteTypes(); if (count($finiteTypes) !== 1) { continue; } $innerGuaranteeValueType[] = $finiteTypes[0]; } if (count($innerGuaranteeValueType) === 0) { return null; } $guaranteedValueTypePerArray[] = TypeCombinator::union(...$innerGuaranteeValueType); } else { $finiteValueType = $array->getIterableValueType()->getFiniteTypes(); if (count($finiteValueType) !== 1) { return null; } $guaranteedValueTypePerArray[] = $finiteValueType[0]; } } if (count($guaranteedValueTypePerArray) === 0) { return null; } $guaranteedValueType = $guaranteedValueTypePerArray[0]; for ($i = 1, $count = count($guaranteedValueTypePerArray); $i < $count; $i++) { $guaranteedValueType = TypeCombinator::intersect($guaranteedValueType, $guaranteedValueTypePerArray[$i]); } if (count($guaranteedValueType->getFiniteTypes()) === 0) { return null; } return $guaranteedValueType; } } getName() === 'ini_get'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) < 1) { return null; } $numericString = new IntersectionType([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]; if ($scope->getPhpVersion()->supportsMaxMemoryLimit()->yes()) { $types['max_memory_limit'] = new StringType(); } $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() === 'intdiv'; } public function getThrowTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $funcCall, Scope $scope): ?Type { $args = $funcCall->getArgs(); if (count($args) < 2) { return $functionReflection->getThrowType(); } $valueType = $scope->getType($args[0]->value)->toInteger(); $containsMin = $valueType->isSuperTypeOf(new ConstantIntegerType(PHP_INT_MIN)); $divisorType = $scope->getType($args[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; } } 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 { $args = $node->getArgs(); if (count($args) < 2) { return new SpecifiedTypes(); } $classType = $scope->getType($args[1]->value); if (!$classType instanceof ConstantStringType && !$context->true()) { return new SpecifiedTypes([], []); } $objectOrClassType = $scope->getType($args[0]->value); $allowStringType = isset($args[2]) ? $scope->getType($args[2]->value) : new ConstantBooleanType(\false); $allowString = !$allowStringType->equals(new ConstantBooleanType(\false)); $resultType = $this->isAFunctionTypeSpecifyingHelper->determineType($objectOrClassType, $classType, $allowString, \true); if ($resultType === null) { return new SpecifiedTypes([], []); } return $this->typeSpecifier->create($args[0]->value, $resultType, $context, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void { $this->typeSpecifier = $typeSpecifier; } } toObjectTypeForIsACheck($objectOrClassType, $allowString, $allowSameClass); // `getConstantStrings() === []` propagates uncertainty from // the input as a whole — preserved from the original // `$isUncertain` initial state to keep the false-positive // suppression below identical. $isUncertain = $result->uncertainty || $classType->getConstantStrings() === []; // prevent false-positives if ($isUncertain && $result->type->isSuperTypeOf($objectOrClassType)->yes()) { return null; } return $result->type; } } 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(\true), new MixedType(\true)), $context, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void { $this->typeSpecifier = $typeSpecifier; } } 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()) { $functionCall = new FuncCall(new Name('method_exists'), [new Arg($value->items[0]->value), new Arg($value->items[1]->value)]); $methodExistsTypes = $this->methodExistsExtension->specifyTypes($functionReflection, $functionCall, $scope, $context); return $methodExistsTypes->unionWith($this->typeSpecifier->create(new FuncCall(new FullyQualified('is_callable'), [new Arg($value)]), new ConstantBooleanType(\true), $context, $scope)); } return $this->typeSpecifier->create($value, new CallableType(), $context, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void { $this->typeSpecifier = $typeSpecifier; } } 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, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void { $this->typeSpecifier = $typeSpecifier; } } 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 { $args = $node->getArgs(); if (!$context->true() || count($args) < 2) { return new SpecifiedTypes(); } $objectOrClassType = $scope->getType($args[0]->value); $classType = $scope->getType($args[1]->value); $allowStringType = isset($args[2]) ? $scope->getType($args[2]->value) : new ConstantBooleanType(\true); $allowString = !$allowStringType->equals(new ConstantBooleanType(\false)); $resultType = $this->isAFunctionTypeSpecifyingHelper->determineType($objectOrClassType, $classType, $allowString, \false); if ($resultType === null) { return new SpecifiedTypes([], []); } return $this->typeSpecifier->create($args[0]->value, $resultType, $context, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void { $this->typeSpecifier = $typeSpecifier; } } 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 new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $traversableType->getIterableValueType()), new AccessoryArrayListType()]); } } $arrayKeyType = $traversableType->getIterableKeyType()->toArrayKey(); if ($arrayKeyType instanceof ErrorType) { return new NeverType(\true); } return new ArrayType($arrayKeyType, $traversableType->getIterableValueType()); } } */ private array $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()]; $args = $functionCall->getArgs(); $defaultReturnType = ParametersAcceptorSelector::selectFromArgs($scope, $args, $functionReflection->getVariants())->getReturnType(); if ($functionReflection->getName() === 'json_decode') { $defaultReturnType = $this->narrowTypeForJsonDecode($functionCall, $scope, $defaultReturnType); } if (!isset($args[$argumentPosition])) { return $defaultReturnType; } $optionsExpr = $args[$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->getConstantStrings() !== []) { $types = []; foreach ($firstValueType->getConstantStrings() as $constantString) { $types[] = $this->resolveConstantStringType($constantString, $isForceArray); } return TypeCombinator::union(...$types); } if ($isForceArray->yes()) { return TypeCombinator::remove($fallbackType, new ObjectWithoutClassType()); } return $fallbackType; } /** * Is "json_decode(..., true)"? */ private function isForceArray(FuncCall $funcCall, Scope $scope): TrinaryLogic { $args = $funcCall->getArgs(); $flagValue = $this->getFlagValue($funcCall, $scope); if (!isset($args[1])) { return TrinaryLogic::createNo(); } $secondArgType = $scope->getType($args[1]->value); $secondArgValues = []; foreach ($secondArgType->getConstantScalarValues() as $value) { if ($value === null) { $secondArgValues[] = $flagValue; continue; } if (!is_bool($value)) { return TrinaryLogic::createNo(); } $secondArgValues[] = TrinaryLogic::createFromBoolean($value); } if ($secondArgValues === []) { return TrinaryLogic::createNo(); } return TrinaryLogic::extremeIdentity(...$secondArgValues); } private function resolveConstantStringType(ConstantStringType $constantStringType, TrinaryLogic $isForceArray): Type { $types = []; /** @var bool $asArray */ foreach ($isForceArray->toBooleanType()->getConstantScalarValues() as $asArray) { $decodedValue = json_decode($constantStringType->getValue(), $asArray); $types[] = ConstantTypeHelper::getTypeFromValue($decodedValue); } return TypeCombinator::union(...$types); } private function getFlagValue(FuncCall $funcCall, Scope $scope): TrinaryLogic { $args = $funcCall->getArgs(); if (!isset($args[3])) { return TrinaryLogic::createNo(); } // 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'); } } 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 { if (!array_key_exists($functionReflection->getName(), self::ARGUMENTS_POSITIONS)) { throw new ShouldNotHappenException(); } $argumentPosition = self::ARGUMENTS_POSITIONS[$functionReflection->getName()]; $args = $functionCall->getArgs(); if (!isset($args[$argumentPosition])) { return null; } $optionsExpr = $args[$argumentPosition]->value; if (!$this->bitwiseFlagAnalyser->bitwiseOrContainsConstant($optionsExpr, $scope, 'JSON_THROW_ON_ERROR')->no()) { return new ObjectType('JsonException'); } return null; } } getName() === 'ltrim'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) < 1) { return null; } $string = $scope->getType($args[0]->value); $accessory = []; $defaultType = new StringType(); if ($string->isLowercaseString()->yes()) { $accessory[] = new AccessoryLowercaseStringType(); } if ($string->isUppercaseString()->yes()) { $accessory[] = new AccessoryUppercaseStringType(); } if (count($accessory) > 0) { $accessory[] = new StringType(); $defaultType = new IntersectionType($accessory); } if (count($args) !== 2) { return $defaultType; } $trimChars = $scope->getType($args[1]->value); $trimConstantStrings = $trimChars->getConstantStrings(); if (count($trimConstantStrings) > 0) { $result = []; $stringConstantStrings = $string->getConstantStrings(); foreach ($trimConstantStrings as $trimConstantString) { if (count($stringConstantStrings) > 0) { foreach ($stringConstantStrings as $stringConstantString) { $result[] = new ConstantStringType(ltrim($stringConstantString->getValue(), $trimConstantString->getValue()), \true); } } elseif ($trimConstantString->getValue() === '\\' && $string->isClassString()->yes()) { $result[] = new ClassStringType(); } elseif (preg_match('/\d/', $trimConstantString->getValue()) === 0 && $string->isNumericString()->yes()) { $result[] = new IntersectionType([new StringType(), new AccessoryNumericStringType()]); } else { return $defaultType; } } return TypeCombinator::union(...$result); } return $defaultType; } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'mb_convert_encoding'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (!isset($args[0])) { return null; } $argType = $scope->getType($args[0]->value); $initialReturnType = ParametersAcceptorSelector::selectFromArgs($scope, $args, $functionReflection->getVariants())->getReturnType(); $result = TypeCombinator::intersect($initialReturnType, $this->generalizeStringType($argType)); if ($result instanceof NeverType) { $result = $initialReturnType; } if ($this->phpVersion->throwsValueErrorForInternalFunctions()) { if (!isset($args[2])) { return TypeCombinator::remove($result, new ConstantBooleanType(\false)); } $fromEncodingArgType = $scope->getType($args[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(), ',') || trim(strtolower($constantString->getValue())) === 'auto') { $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; } } 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 { $args = $functionCall->getArgs(); $returnType = ParametersAcceptorSelector::selectFromArgs($scope, $args, $functionReflection->getVariants())->getReturnType(); $positionEncodingParam = $this->encodingPositionMap[$functionReflection->getName()]; if (count($args) < $positionEncodingParam) { return TypeCombinator::remove($returnType, new BooleanType()); } $strings = $scope->getType($args[$positionEncodingParam - 1]->value)->getConstantStrings(); $results = array_unique(array_map(fn(ConstantStringType $encoding): bool => $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; } } 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 fn(string $enc) => !in_array($enc, ['PASS', 'NONE'], \true)); } return $this->supportedEncodings; } } 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($args) === 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($args) === 2) { // custom encoding is specified $encodings = array_map(static fn(ConstantStringType $t) => $t->getValue(), $scope->getType($args[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); $constantScalars = $argType->getConstantScalarValues(); $lengths = []; foreach ($constantScalars as $constantScalar) { $stringScalar = (string) $constantScalar; foreach ($encodings as $encoding) { if (!$this->isSupportedEncoding($encoding)) { continue; } $length = @mb_strlen($stringScalar, $encoding); if ($length === \false) { throw new ShouldNotHappenException(sprintf('Got false on a supported encoding %s and value %s', $encoding, var_export($stringScalar, \true))); } $lengths[] = $length; } } $isNonEmpty = $argType->isNonEmptyString(); $numeric = new UnionType([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 fn($l) => 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, $args, $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; } } 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() === 'method_exists' && $context->true() && count($node->getArgs()) >= 2; } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes { $args = $node->getArgs(); $methodNameType = $scope->getType($args[1]->value); if (!$methodNameType instanceof ConstantStringType) { return $this->typeSpecifier->create(new FuncCall(new FullyQualified('method_exists'), $node->getRawArgs()), new ConstantBooleanType(\true), $context, $scope); } $objectType = $scope->getType($args[0]->value); if ($objectType->isString()->yes()) { if ($objectType->isClassString()->yes()) { return $this->typeSpecifier->create($args[0]->value, new IntersectionType([$objectType, new HasMethodType($methodNameType->getValue())]), $context, $scope); } return new SpecifiedTypes([], []); } return $this->typeSpecifier->create($args[0]->value, new UnionType([new IntersectionType([new ObjectWithoutClassType(), new HasMethodType($methodNameType->getValue())]), new ClassStringType()]), $context, $scope); } } getName() === 'microtime'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): Type { $stringType = new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); if (count($functionCall->getArgs()) < 1) { return $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 $stringType; } if ($argType instanceof MixedType) { return new BenevolentUnionType([$stringType, new FloatType()]); } return new UnionType([$stringType, new FloatType()]); } } 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 { $args = $functionCall->getArgs(); if (!isset($args[0])) { return null; } if (count($args) === 1) { $argType = $scope->getType($args[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(); if (count($args) === 2) { $argType0 = $scope->getType($args[0]->value); $argType1 = $scope->getType($args[1]->value); if ($argType0->isArray()->no() && $argType1->isArray()->no()) { $comparisonExpr = new Smaller(new AlwaysRememberedExpr($args[0]->value, $argType0, $scope->getNativeType($args[0]->value)), new AlwaysRememberedExpr($args[1]->value, $argType1, $scope->getNativeType($args[1]->value))); if ($functionName === 'min') { return $scope->getType(new Ternary($comparisonExpr, $args[0]->value, $args[1]->value)); } elseif ($functionName === 'max') { return $scope->getType(new Ternary($comparisonExpr, $args[1]->value, $args[0]->value)); } } } $argumentTypes = []; foreach ($args 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 list $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(), ['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; } if (in_array($functionReflection->getName(), ['htmlspecialchars', 'htmlentities'], \true)) { if (!$this->isSubstituteFlagSet($args, $scope)) { return new StringType(); } } $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(); } /** * @param Arg[] $args */ private function isSubstituteFlagSet(array $args, Scope $scope): bool { if (!isset($args[1])) { return \true; } $flagsType = $scope->getType($args[1]->value); if (!$flagsType instanceof ConstantIntegerType) { return \false; } return (bool) ($flagsType->getValue() & ENT_SUBSTITUTE); } } 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()]); } } |null */ private ?array $supportedCipherMethods = null; /** * Returns supported cipher methods in lowercase. * * Filters out methods that openssl_get_cipher_methods() reports * but are not actually usable due to https://github.com/php/php-src/issues/19994 * * @return list */ public function getSupportedCipherMethods(): array { if ($this->supportedCipherMethods !== null) { return $this->supportedCipherMethods; } $methods = []; if (function_exists('openssl_get_cipher_methods')) { // openssl_get_cipher_methods() reports algorithms that are not actually // supported on PHP 8.0-8.4 due to https://github.com/php/php-src/issues/19994 // Filter by actually testing each algorithm with openssl_cipher_iv_length(). $methods = array_values(array_filter(openssl_get_cipher_methods(\true), static fn(string $algorithm): bool => @openssl_cipher_iv_length($algorithm) !== \false)); } $this->supportedCipherMethods = array_map('strtolower', $methods); return $this->supportedCipherMethods; } public function isSupportedCipherMethod(string $method): bool { return in_array(strtolower($method), $this->getSupportedCipherMethods(), \true); } } cipherMethodsProvider = $cipherMethodsProvider; } public function isFunctionSupported(FunctionReflection $functionReflection, ParameterReflection $parameter): bool { return $functionReflection->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 (!$this->cipherMethodsProvider->isSupportedCipherMethod($cipher)) { $tagTypes[] = new NullType(); continue; } if (in_array($mode, ['gcm', 'ccm'], \true)) { $tagTypes[] = new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]); continue; } $tagTypes[] = new NullType(); } if ($tagTypes === []) { return new UnionType([new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]), new NullType()]); } return TypeCombinator::union(...$tagTypes); } } phpVersion = $phpVersion; $this->cipherMethodsProvider = $cipherMethodsProvider; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return in_array($functionReflection->getName(), ['openssl_cipher_iv_length', 'openssl_cipher_key_length'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { if (!$this->phpVersion->throwsValueErrorForInternalFunctions()) { return null; } if (count($functionCall->getArgs()) < 1) { return null; } $strings = $scope->getType($functionCall->getArgs()[0]->value)->getConstantStrings(); $results = array_unique(array_map(fn(ConstantStringType $algorithm): bool => $this->cipherMethodsProvider->isSupportedCipherMethod($algorithm->getValue()), $strings)); if (count($results) !== 1) { return null; } $returnType = ParametersAcceptorSelector::selectFromArgs($scope, $functionCall->getArgs(), $functionReflection->getVariants())->getReturnType(); return $results[0] ? TypeCombinator::remove($returnType, new ConstantBooleanType(\false)) : new ConstantBooleanType(\false); } } phpVersion = $phpVersion; } public function getClass(): string { return 'PDO'; } public function isStaticMethodSupported(MethodReflection $methodReflection): bool { return $this->phpVersion->hasPDOSubclasses() && $methodReflection->getName() === 'connect'; } public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope): ?Type { if (count($methodCall->getArgs()) < 1) { return null; } $valueType = $scope->getType($methodCall->getArgs()[0]->value); $constantStrings = $valueType->getConstantStrings(); if (count($constantStrings) === 0) { return null; } $subclasses = []; foreach ($constantStrings as $constantString) { if (str_starts_with($constantString->getValue(), 'mysql:')) { $subclasses['PDO\Mysql'] = '_PHPStan_33c983f26\PDO\Mysql'; } elseif (str_starts_with($constantString->getValue(), 'firebird:')) { $subclasses['PDO\Firebird'] = '_PHPStan_33c983f26\PDO\Firebird'; } elseif (str_starts_with($constantString->getValue(), 'dblib:')) { $subclasses['PDO\Dblib'] = '_PHPStan_33c983f26\PDO\Dblib'; } elseif (str_starts_with($constantString->getValue(), 'odbc:')) { $subclasses['PDO\Odbc'] = '_PHPStan_33c983f26\PDO\Odbc'; } elseif (str_starts_with($constantString->getValue(), 'pgsql:')) { $subclasses['PDO\Pgsql'] = '_PHPStan_33c983f26\PDO\Pgsql'; } elseif (str_starts_with($constantString->getValue(), 'sqlite:')) { $subclasses['PDO\Sqlite'] = '_PHPStan_33c983f26\PDO\Sqlite'; } else { return null; } } $returnTypes = []; foreach ($subclasses as $class) { $returnTypes[] = new ObjectType($class); } return TypeCombinator::union(...$returnTypes); } } 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])); } } |null */ private ?array $componentTypesPairedConstants = null; /** @var array|null */ private ?array $componentTypesPairedStrings = null; /** @var array|null */ private ?array $componentTypesPairedConstantsForLowercaseString = null; /** @var array|null */ private ?array $componentTypesPairedStringsForLowercaseString = null; private ?Type $allComponentsTogetherType = null; private ?Type $allComponentsTogetherTypeForLowercaseString = null; public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'parse_url'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) < 1) { return null; } $this->cacheReturnTypes(); $urlType = $scope->getType($args[0]->value); if (count($args) > 1) { $componentType = $scope->getType($args[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 new UnionType([$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]; } } reflectionProvider = $reflectionProvider; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'pathinfo'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, Node\Expr\FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); $argsCount = count($args); if ($argsCount === 0) { return null; } $pathType = $scope->getType($args[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($args[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 new UnionType([$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(); } } getName() === 'fetchAll'; } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type { $args = $methodCall->getArgs(); if (count($args) < 1) { return null; } $modeType = $scope->getType($args[0]->value); $constantIntegers = TypeUtils::getConstantIntegers($modeType); if (count($constantIntegers) === 0) { return null; } foreach ($constantIntegers as $constantInteger) { $mode = $constantInteger->getValue(); if (($mode & 0xffff) === PDO::FETCH_KEY_PAIR || ($mode & PDO::FETCH_GROUP) !== 0 || ($mode & PDO::FETCH_UNIQUE) !== 0) { return null; } } $variant = ParametersAcceptorSelector::selectFromArgs($scope, $args, $methodReflection->getVariants()); $returnType = $variant->getReturnType(); $listType = TypeCombinator::intersect(new ArrayType(new IntegerType(), new MixedType()), new AccessoryArrayListType()); if (!$returnType->isFalse()->no()) { return TypeCombinator::union($listType, new ConstantBooleanType(\false)); } return $listType; } } 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)); } } getName() === 'preg_filter'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): Type { $args = $functionCall->getArgs(); $defaultReturn = ParametersAcceptorSelector::selectFromArgs($scope, $args, $functionReflection->getVariants())->getReturnType(); $argsCount = count($args); if ($argsCount < 3) { return $defaultReturn; } $subjectType = $scope->getType($args[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; } } 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') { $matchedType = $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createYes(), $scope); if ($matchedType === null) { return null; } return TypeCombinator::union(ConstantArrayTypeBuilder::createEmpty()->getArray(), $matchedType); } return $this->regexShapeMatcher->matchAllExpr($patternArg->value, $flagsType, TrinaryLogic::createMaybe(), $scope); } } 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 ($context->true() && $context->falsey()) { $wasMatched = TrinaryLogic::createMaybe(); } elseif ($context->true()) { $wasMatched = TrinaryLogic::createYes(); } else { $wasMatched = TrinaryLogic::createNo(); } if ($functionReflection->getName() === 'preg_match') { $matchedType = $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, $wasMatched, $scope); } else { $matchedType = $this->regexShapeMatcher->matchAllExpr($patternArg->value, $flagsType, $wasMatched, $scope); } if ($matchedType === null) { return new SpecifiedTypes(); } $overwrite = \false; if ($context->false()) { $overwrite = \true; $context = $context->negate(); } $types = $this->typeSpecifier->create($matchesArg->value, $matchedType, $context, $scope)->setRootExpr($node); if ($overwrite) { $types = $types->setAlwaysOverwriteTypes(); } return $types; } } 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()); } } bitwiseFlagAnalyser = $bitwiseFlagAnalyser; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return strtolower($functionReflection->getName()) === 'preg_split'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) < 2) { return null; } $patternArg = $args[0]; $subjectArg = $args[1]; $limitArg = $args[2] ?? null; $capturesOffset = $args[3] ?? null; $patternType = $scope->getType($patternArg->value); $patternConstantTypes = $patternType->getConstantStrings(); if (count($patternConstantTypes) > 0) { foreach ($patternConstantTypes as $patternConstantType) { if ($this->isValidPattern($patternConstantType->getValue()) === \false) { return new ErrorType(); } } } $subjectType = $scope->getType($subjectArg->value); $subjectConstantTypes = $subjectType->getConstantStrings(); $limits = []; if ($limitArg === null) { $limits = [-1]; } else { $limitType = $scope->getType($limitArg->value); if (!$this->isIntOrStringValue($limitType)) { return new ErrorType(); } foreach ($limitType->getConstantScalarValues() as $limit) { if (!is_int($limit) && !is_numeric($limit)) { return new ErrorType(); } $limits[] = $limit; } } $flags = []; if ($capturesOffset === null) { $flags = [0]; } else { $flagType = $scope->getType($capturesOffset->value); if (!$this->isIntOrStringValue($flagType)) { return new ErrorType(); } foreach ($flagType->getConstantScalarValues() as $flag) { if (!is_int($flag) && !is_numeric($flag)) { return new ErrorType(); } $flags[] = $flag; } } if ($this->isPatternOrSubjectEmpty($patternConstantTypes, $subjectConstantTypes)) { if ($capturesOffset !== null && $this->bitwiseFlagAnalyser->bitwiseOrContainsConstant($capturesOffset->value, $scope, 'PREG_SPLIT_NO_EMPTY')->yes()) { $returnStringType = new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]); } else { $returnStringType = new StringType(); } $arrayTypeBuilder = ConstantArrayTypeBuilder::createEmpty(); $arrayTypeBuilder->setOffsetValueType(new ConstantIntegerType(0), $returnStringType); $arrayTypeBuilder->setOffsetValueType(new ConstantIntegerType(1), IntegerRangeType::fromInterval(0, null)); $capturedArrayType = $arrayTypeBuilder->getArray(); $returnInternalValueType = $returnStringType; if ($capturesOffset !== null) { $flagState = $this->bitwiseFlagAnalyser->bitwiseOrContainsConstant($capturesOffset->value, $scope, 'PREG_SPLIT_OFFSET_CAPTURE'); if ($flagState->yes()) { $capturedArrayListType = new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $capturedArrayType), new AccessoryArrayListType()]); if ($subjectType->isNonEmptyString()->yes()) { $capturedArrayListType = TypeCombinator::intersect($capturedArrayListType, new NonEmptyArrayType()); } return new UnionType([$capturedArrayListType, new ConstantBooleanType(\false)]); } if ($flagState->maybe()) { $returnInternalValueType = new UnionType([new StringType(), $capturedArrayType]); } } $returnListType = new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $returnInternalValueType), new AccessoryArrayListType()]); if ($subjectType->isNonEmptyString()->yes()) { $returnListType = new IntersectionType([new NonEmptyArrayType(), ...$returnListType->getTypes()]); } return new UnionType([$returnListType, new ConstantBooleanType(\false)]); } $resultTypes = []; foreach ($patternConstantTypes as $patternConstantType) { foreach ($subjectConstantTypes as $subjectConstantType) { foreach ($limits as $limit) { foreach ($flags as $flag) { $result = @preg_split($patternConstantType->getValue(), $subjectConstantType->getValue(), (int) $limit, (int) $flag); if ($result === \false) { return new ErrorType(); } $constantArray = ConstantArrayTypeBuilder::createEmpty(); foreach ($result as $key => $value) { if (is_array($value)) { $valueConstantArray = ConstantArrayTypeBuilder::createEmpty(); $valueConstantArray->setOffsetValueType(new ConstantIntegerType(0), new ConstantStringType($value[0])); $valueConstantArray->setOffsetValueType(new ConstantIntegerType(1), new ConstantIntegerType($value[1])); $returnInternalValueType = $valueConstantArray->getArray(); } else { $returnInternalValueType = new ConstantStringType($value); } $constantArray->setOffsetValueType(new ConstantIntegerType($key), $returnInternalValueType); } $resultTypes[] = $constantArray->getArray(); } } } } $resultTypes[] = new ConstantBooleanType(\false); return TypeCombinator::union(...$resultTypes); } /** * @param ConstantStringType[] $patternConstantArray * @param ConstantStringType[] $subjectConstantArray */ private function isPatternOrSubjectEmpty(array $patternConstantArray, array $subjectConstantArray): bool { return count($patternConstantArray) === 0 || count($subjectConstantArray) === 0; } private function isValidPattern(string $pattern): bool { try { Strings::match('', $pattern); } catch (RegexpException $e) { return \false; } return \true; } private function isIntOrStringValue(Type $type): bool { return (new UnionType([new IntegerType(), new StringType()]))->isSuperTypeOf($type)->yes(); } } 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 { $args = $node->getArgs(); $propertyNameType = $scope->getType($args[1]->value); if (!$propertyNameType instanceof ConstantStringType) { return $this->typeSpecifier->create(new FuncCall(new FullyQualified('property_exists'), $node->getRawArgs()), new ConstantBooleanType(\true), $context, $scope); } if ($propertyNameType->getValue() === '') { return new SpecifiedTypes([], []); } $objectType = $scope->getType($args[0]->value); if ($objectType instanceof ConstantStringType) { return new SpecifiedTypes([], []); } elseif ($objectType->isObject()->yes()) { $propertyNode = new PropertyFetch($args[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($args[0]->value, new IntersectionType([new ObjectWithoutClassType(), new HasPropertyType($propertyNameType->getValue())]), $context, $scope); } } getName(), ['random_int', 'rand', 'mt_rand'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (in_array($functionReflection->getName(), ['rand', 'mt_rand'], \true) && count($args) === 0) { return IntegerRangeType::fromInterval(0, null); } if (count($args) < 2) { return null; } $minType = $scope->getType($args[0]->value)->toInteger(); $maxType = $scope->getType($args[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() === 'range'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) < 2) { return null; } $startType = $scope->getType($args[0]->value); $endType = $scope->getType($args[1]->value); $stepType = count($args) >= 3 ? $scope->getType($args[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 self::getNonEmptyListOfType(IntegerRangeType::fromInterval($startConstant->getValue(), $endConstant->getValue())); } if ($stepType->isFloat()->yes()) { return self::getNonEmptyListOfType(new FloatType()); } return self::getNonEmptyListOfType(TypeCombinator::union($startConstant->generalize(GeneralizePrecision::moreSpecific()), $endConstant->generalize(GeneralizePrecision::moreSpecific()), $stepType->generalize(GeneralizePrecision::moreSpecific()))); } $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 self::getNonEmptyListOfType($argType); } return self::getNonEmptyListOfType(new IntegerType()); } if ($argType->isFloat()->yes()) { return self::getNonEmptyListOfType(new FloatType()); } $numberType = new UnionType([new IntegerType(), new FloatType()]); $isNumber = $numberType->isSuperTypeOf($argType)->yes(); $isNumericString = $argType->isNumericString()->yes(); if ($isNumber || $isNumericString) { return self::getNonEmptyListOfType($numberType); } if ($argType->isString()->yes()) { return self::getNonEmptyListOfType(new StringType()); } return self::getNonEmptyListOfType(new BenevolentUnionType([new IntegerType(), new FloatType(), new StringType()])); } private static function getNonEmptyListOfType(Type $type): IntersectionType { return new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $type), new NonEmptyArrayType(), new AccessoryArrayListType()]); } } 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(); } } 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->null(); } public function specifyTypes(MethodReflection $methodReflection, MethodCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes { $calledOnType = $scope->getType($node->var); $reflectionType = $calledOnType->getTemplateType(ReflectionClass::class, 'T'); if (!(new ObjectWithoutClassType())->isSuperTypeOf($reflectionType)->yes()) { return new SpecifiedTypes(); } $valueType = $scope->getType($node->getArgs()[0]->value); $objectType = $valueType->getClassStringObjectType(); $intersected = TypeCombinator::intersect($reflectionType, $objectType); $narrowingType = new GenericObjectType(ReflectionClass::class, [$intersected]); if ($reflectionType->isSuperTypeOf($objectType)->no()) { return $this->typeSpecifier->create($node->var, $narrowingType, $context, $scope); } return $this->typeSpecifier->create($node->var, $narrowingType, $context, $scope)->setAlwaysOverwriteTypes(); } } 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; } } className = $className; } public function getClass(): string { return $this->className; } public function isMethodSupported(MethodReflection $methodReflection): bool { return $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(); $variant = ParametersAcceptorSelector::selectFromArgs($scope, $methodCall->getArgs(), $methodReflection->getVariants()); $valueType = $this->resolveReflectionAttributeType($variant->getReturnType(), $classType); return new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $valueType), new AccessoryArrayListType()]); } private function resolveReflectionAttributeType(Type $returnType, Type $classType): Type { $nativeReflectionAttributeType = new ObjectType(ReflectionAttribute::class); $valueTypes = []; foreach ($returnType->getIterableValueType()->getObjectClassNames() as $className) { if (!$nativeReflectionAttributeType->isSuperTypeOf(new ObjectType($className))->yes()) { continue; } $valueTypes[] = new GenericObjectType($className, [$classType]); } if (count($valueTypes) === 0) { return new GenericObjectType(ReflectionAttribute::class, [$classType]); } if (count($valueTypes) === 1) { return $valueTypes[0]; } return TypeCombinator::union(...$valueTypes); } } 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; } } 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->hasInstanceProperty($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; } } 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); } private function matchPatternType(Type $patternType, ?Type $flagsType, TrinaryLogic $wasMatched, bool $matchesAll): ?Type { if ($wasMatched->no()) { return ConstantArrayTypeBuilder::createEmpty()->getArray(); } $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 { $astWalkResult = $this->regexGroupParser->parseGroups($regex); if ($astWalkResult === null) { // regex could not be parsed by Hoa/Regex return null; } $groupList = $astWalkResult->getCapturingGroups(); $markVerbs = $astWalkResult->getMarkVerbs(); $subjectBaseType = new StringType(); if ($wasMatched->yes()) { $subjectBaseType = $astWalkResult->getSubjectBaseType(); } $regexGroupList = new RegexGroupList($groupList); $trailingOptionals = $regexGroupList->countTrailingOptionals(); $onlyOptionalTopLevelGroup = $regexGroupList->getOnlyOptionalTopLevelGroup(); $onlyTopLevelAlternation = $regexGroupList->getOnlyTopLevelAlternation(); $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 $regexGroupList = $regexGroupList->forceGroupNonOptional($onlyOptionalTopLevelGroup); $combiType = $this->buildArrayType($subjectBaseType, $regexGroupList, $wasMatched, $trailingOptionals, $flags, $markVerbs, $matchesAll); if (!$this->containsUnmatchedAsNull($flags, $matchesAll)) { // positive match has a subject but not any capturing group $builder = ConstantArrayTypeBuilder::createEmpty(); $builder->setOffsetValueType(new ConstantIntegerType(0), $this->createSubjectValueType($subjectBaseType, $flags, $matchesAll)); $combiType = TypeCombinator::union($builder->getArray(), $combiType); } 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 = new RegexGroupList($groupList); $beforeCurrentCombo = \true; foreach ($comboList as $group) { if (in_array($group->getId(), $groupCombo, \true)) { $isOptionalAlternation = $group->inOptionalAlternation(); $comboList = $comboList->forceGroupNonOptional($group); $beforeCurrentCombo = \false; } elseif ($beforeCurrentCombo && !$group->resetsGroupCounter()) { $comboList = $comboList->forceGroupTypeAndNonOptional($group, $this->containsUnmatchedAsNull($flags, $matchesAll) ? new NullType() : new ConstantStringType('')); } elseif ($group->getAlternationId() === $onlyTopLevelAlternation->getId() && !$this->containsUnmatchedAsNull($flags, $matchesAll)) { $comboList = $comboList->removeGroup($group); } } $combiType = $this->buildArrayType($subjectBaseType, $comboList, $wasMatched, $trailingOptionals, $flags, $markVerbs, $matchesAll); $combiTypes[] = $combiType; } if (!$this->containsUnmatchedAsNull($flags, $matchesAll) && ($onlyTopLevelAlternation->getAlternationsCount() !== count($onlyTopLevelAlternation->getGroupCombinations()) || $isOptionalAlternation)) { // positive match has a subject but not any capturing group $builder = ConstantArrayTypeBuilder::createEmpty(); $builder->setOffsetValueType(new ConstantIntegerType(0), $this->createSubjectValueType($subjectBaseType, $flags, $matchesAll)); $combiTypes[] = $builder->getArray(); } 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($subjectBaseType, $regexGroupList, $wasMatched, $trailingOptionals, $flags, $markVerbs, $matchesAll); } /** * @param list $markVerbs */ private function buildArrayType(Type $subjectBaseType, RegexGroupList $captureGroups, TrinaryLogic $wasMatched, int $trailingOptionals, int $flags, array $markVerbs, bool $matchesAll): Type { $forceList = count($markVerbs) === 0; $builder = ConstantArrayTypeBuilder::createEmpty(); // first item in matches contains the overall match. $builder->setOffsetValueType($this->getKeyType(0), $this->createSubjectValueType($subjectBaseType, $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()) { $forceList = \false; $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)) { return new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $builder->getArray()), new AccessoryArrayListType()]); } if ($forceList) { return TypeCombinator::intersect($builder->getArray(), new AccessoryArrayListType()); } return $builder->getArray(); } private function isSubjectOptional(TrinaryLogic $wasMatched, bool $matchesAll): bool { if ($matchesAll) { return \false; } return !$wasMatched->yes(); } /** * @param Type $baseType A string type (or string variant) representing the subject of the match */ private function createSubjectValueType(Type $baseType, int $flags, bool $matchesAll): Type { $subjectValueType = TypeCombinator::removeNull($this->getValueType($baseType, $flags, $matchesAll)); if ($matchesAll) { $subjectValueType = TypeCombinator::removeNull($this->getValueType(new StringType(), $flags, $matchesAll)); if ($this->containsPatternOrder($flags)) { $subjectValueType = new IntersectionType([new ArrayType(new IntegerType(), $subjectValueType), new AccessoryArrayListType()]); } } 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 = new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $groupValueType), new AccessoryArrayListType()]); } 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); } } 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 ($type !== null && $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); $args = $functionCall->getArgs(); if ($subjectArgumentType === null) { return null; } if ($subjectArgumentType instanceof MixedType) { $defaultReturnType = ParametersAcceptorSelector::selectFromArgs($scope, $args, $functionReflection->getVariants())->getReturnType(); return TypeUtils::toBenevolentUnion($defaultReturnType); } $replaceArgumentType = null; if (array_key_exists($functionReflection->getName(), self::FUNCTIONS_REPLACE_POSITION)) { $replaceArgumentPosition = self::FUNCTIONS_REPLACE_POSITION[$functionReflection->getName()]; if (count($args) > $replaceArgumentPosition) { $replaceArgumentType = $scope->getType($args[$replaceArgumentPosition]->value); if ($replaceArgumentType->isArray()->yes()) { $replaceArgumentType = $replaceArgumentType->getIterableValueType(); } } elseif ($functionReflection->getName() === 'strtr' && isset($functionCall->getArgs()[1])) { // `strtr` has two signatures: `strtr($string1, $string2, $string3)` and `strtr($string1, $array)` $secondArgumentType = TypeCombinator::intersect(new ArrayType(new MixedType(), new MixedType()), $scope->getType($functionCall->getArgs()[1]->value)); $replaceArgumentType = $secondArgumentType->getIterableValueType(); } } $result = []; if ($subjectArgumentType->isString()->yes()) { $stringArgumentType = $subjectArgumentType; } else { $stringArgumentType = TypeCombinator::intersect(new StringType(), $subjectArgumentType); } if ($stringArgumentType->isString()->yes()) { $result[] = $this->getReplaceType($stringArgumentType, $replaceArgumentType); } if ($subjectArgumentType->isArray()->yes()) { $arrayArgumentType = $subjectArgumentType; } else { $arrayArgumentType = TypeCombinator::intersect(new ArrayType(new MixedType(), new MixedType()), $subjectArgumentType); } if ($arrayArgumentType->isArray()->yes()) { $keyShouldBeOptional = in_array($functionReflection->getName(), ['preg_replace', 'preg_replace_callback', 'preg_replace_callback_array'], \true); $mapped = $arrayArgumentType->mapValueType(fn(Type $value): Type => $this->getReplaceType($value, $replaceArgumentType)); if ($keyShouldBeOptional) { $mapped = $mapped->makeAllArrayKeysOptional(); } $result[] = $mapped; } return TypeCombinator::union(...$result); } private function getReplaceType(Type $subjectArgumentType, ?Type $replaceArgumentType): Type { if ($replaceArgumentType === null) { return new StringType(); } $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); } return new StringType(); } private function getSubjectType(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { if (!array_key_exists($functionReflection->getName(), self::FUNCTIONS_SUBJECT_POSITION)) { throw new ShouldNotHappenException(); } $argumentPosition = self::FUNCTIONS_SUBJECT_POSITION[$functionReflection->getName()]; $args = $functionCall->getArgs(); if (count($args) <= $argumentPosition) { return null; } return $scope->getType($args[$argumentPosition]->value); } private function canReturnNull(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): bool { $args = $functionCall->getArgs(); if (in_array($functionReflection->getName(), ['preg_replace', 'preg_replace_callback', 'preg_replace_callback_array'], \true) && count($args) > 0) { $subjectArgumentType = $this->getSubjectType($functionReflection, $functionCall, $scope); if ($subjectArgumentType !== null && $subjectArgumentType->isArray()->yes()) { return \false; } return \true; } return \false; } } 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()) { if (!$scope->isDeclareStrictTypes()) { $allowed = new UnionType([new IntegerType(), new FloatType(), new IntersectionType([new StringType(), new AccessoryNumericStringType()]), new NullType(), new BooleanType()]); } else { $allowed = new UnionType([new IntegerType(), new FloatType()]); } 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()) === 'settype' && count($node->getArgs()) > 1 && $context->null(); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes { $args = $node->getArgs(); $value = $args[0]->value; $valueType = $scope->getType($value); $castType = $scope->getType($args[1]->value); $constantStrings = $castType->getConstantStrings(); if (count($constantStrings) < 1) { $constantStrings = [new ConstantStringType('bool'), new ConstantStringType('int'), new ConstantStringType('float'), new ConstantStringType('string'), new ConstantStringType('array'), new ConstantStringType('object'), new ConstantStringType('null')]; } $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': $isObject = $valueType->isObject(); if ($isObject->yes()) { $types[] = $valueType; } elseif ($isObject->no()) { $types[] = new ObjectType(stdClass::class); } else { $types[] = TypeCombinator::union(TypeCombinator::intersect($valueType, new ObjectWithoutClassType()), 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(), $scope)->setAlwaysOverwriteTypes(); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void { $this->typeSpecifier = $typeSpecifier; } } 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)]); } } is('SimpleXMLElement'); } public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection { return new SimpleXMLElementProperty($propertyName, $classReflection, new BenevolentUnionType([new ObjectType($classReflection->getName()), new NullType()])); } } 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; } } getName() === 'xpath'; } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type { $args = $methodCall->getArgs(); if (!isset($args[0])) { return null; } $argType = $scope->getType($args[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; } $variant = ParametersAcceptorSelector::selectFromArgs($scope, $args, $methodReflection->getVariants()); return TypeCombinator::remove($variant->getReturnType(), new ConstantBooleanType(\false)); } } 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 fn(Type $type): bool => $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 fn(Type $type): bool => $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(), ['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; } } 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']; for ($i = 0; $i < count($keys); $i++) { $builder->setOffsetValueType(null, $valueType); } foreach ($keys as $key) { $builder->setOffsetValueType(new ConstantStringType($key), $valueType); } return $builder->getArray(); } } 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 (!array_key_exists($fnName, self::FUNCTIONS)) { throw new ShouldNotHappenException(); } $requiredArgs = self::FUNCTIONS[$fnName]; if (count($args) < $requiredArgs) { return null; } $argType = $scope->getType($args[0]->value); $modes = []; $keepLowercase = \false; $forceLowercase = \false; $keepUppercase = \false; $forceUppercase = \false; if ($fnName === 'mb_convert_case') { $modeType = $scope->getType($args[1]->value); $modes = array_map(static fn($mode) => $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 fn($mode) => $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 fn($type) => $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 fn($s) => [$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 fn($s) => 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(); } } [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]]; private TypeSpecifier $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) { $lowerFunctionName = strtolower($functionReflection->getName()); if (!array_key_exists($lowerFunctionName, self::STR_CONTAINING_FUNCTIONS)) { throw new ShouldNotHappenException(); } [$hackstackArg, $needleArg] = self::STR_CONTAINING_FUNCTIONS[$lowerFunctionName]; $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(); } return $this->typeSpecifier->create($args[$hackstackArg]->value, new IntersectionType($accessories), $context, $scope)->setRootExpr(new BooleanAnd(new NotIdentical($args[$needleArg]->value, new String_('')), new FuncCall(new Name('FAUX_FUNCTION'), [new Arg($args[$needleArg]->value)]))); } } return new SpecifiedTypes(); } } 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; $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 NeverType() : TypeCombinator::union(...$types); } private function increment(string $s): ?string { if ($s === '') { return null; } try { return str_increment($s); } catch (ValueError $e) { return null; } } private function decrement(string $s): ?string { if ($s === '') { return null; } try { return str_decrement($s); } catch (ValueError $e) { return null; } } } 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_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 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 { $args = $functionCall->getArgs(); if (count($args) < 1) { return null; } if (count($args) >= 2) { $splitLengthType = $scope->getType($args[1]->value); } else { $splitLengthType = new ConstantIntegerType(1); } if ($splitLengthType instanceof ConstantIntegerType) { $splitLength = $splitLengthType->getValue(); if ($splitLength < 1) { return $this->phpVersion->throwsValueErrorForInternalFunctions() ? new NeverType() : new ConstantBooleanType(\false); } } $encoding = null; if ($functionReflection->getName() === 'mb_str_split') { if (count($args) >= 3) { $strings = $scope->getType($args[2]->value)->getConstantStrings(); $values = array_unique(array_map(static fn(ConstantStringType $encoding): string => $encoding->getValue(), $strings)); if (count($values) === 1) { $encoding = $values[0]; if (!$this->isSupportedEncoding($encoding)) { return $this->phpVersion->throwsValueErrorForInternalFunctions() ? new NeverType() : new ConstantBooleanType(\false); } } } else { $encoding = mb_internal_encoding(); } } $stringType = $scope->getType($args[0]->value); if (isset($splitLength) && ($functionReflection->getName() === 'str_split' || $encoding !== null)) { $constantStrings = $stringType->getConstantStrings(); if (count($constantStrings) > 0) { $results = []; foreach ($constantStrings as $constantString) { $value = $constantString->getValue(); if ($encoding === null && $value === '') { // Simulate the str_split call with the analysed PHP Version instead of the runtime one. $items = $this->phpVersion->strSplitReturnsEmptyArray() ? [] : ['']; } else { $items = $encoding === null ? str_split($value, $splitLength) : @mb_str_split($value, $splitLength, $encoding); } $results[] = self::createConstantArrayFrom($items, $scope); } return TypeCombinator::union(...$results); } } $isInputNonEmptyString = $stringType->isNonEmptyString()->yes(); if ($isInputNonEmptyString || $this->phpVersion->strSplitReturnsEmptyArray()) { $returnValueType = new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]); } else { $returnValueType = new StringType(); } $returnType = new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $returnValueType), new AccessoryArrayListType()]); if ($isInputNonEmptyString || $functionReflection->getName() === 'str_split' && !$this->phpVersion->strSplitReturnsEmptyArray()) { $returnType = TypeCombinator::intersect($returnType, new NonEmptyArrayType()); } if (!$this->phpVersion->throwsValueErrorForInternalFunctions() && !IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($splitLengthType)->yes()) { $returnType = new UnionType([$returnType, new ConstantBooleanType(\false)]); } return $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))); } } 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; } } 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 (in_array($argsCount, [2, 3], \true)) { $formatType = $scope->getType($functionCall->getArgs()[1]->value); if ($formatType instanceof ConstantIntegerType) { $val = $formatType->getValue(); if ($val === 0) { // return word count return new IntegerType(); } elseif (in_array($val, [1, 2], \true)) { // 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(); } } 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); $constantScalars = $argType->getConstantScalarValues(); $lengths = []; foreach ($constantScalars as $constantScalar) { $stringScalar = (string) $constantScalar; $length = strlen($stringScalar); $lengths[] = $length; } $isNonEmpty = $argType->isNonEmptyString(); $numeric = new UnionType([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 fn($l) => 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; } } 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; } } getName() === 'strtotime'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): Type { $args = $functionCall->getArgs(); $defaultReturnType = ParametersAcceptorSelector::selectFromArgs($scope, $args, $functionReflection->getVariants())->getReturnType(); if (count($args) === 0) { return $defaultReturnType; } $argType = $scope->getType($args[0]->value); if ($argType instanceof MixedType) { return TypeUtils::toBenevolentUnion($defaultReturnType); } $results = array_unique(array_map(static fn(ConstantStringType $string) => strtotime($string->getValue()), $argType->getConstantStrings())); $resultTypes = array_unique(array_map(static fn($value): string => 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($args) > 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(), 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(); } } } 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()); } elseif ($this->phpVersion->substrReturnFalseInsteadOfEmptyString()) { $substr = $this->substrOrFalse($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()); } elseif ($this->phpVersion->substrReturnFalseInsteadOfEmptyString()) { // Simulate substr call on an older PHP version if the runtime one is too new. $substr = $this->substrOrFalse($constantString->getValue(), $offset->getValue()); } else { $substr = substr($constantString->getValue(), $offset->getValue()); } if (is_bool($substr)) { if ($this->phpVersion->substrReturnFalseInsteadOfEmptyString()) { $results[] = new ConstantBooleanType($substr); } else { // Simulate substr call on a recent PHP version if the runtime one is too old. $results[] = new ConstantStringType(''); } } 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 new UnionType([new ConstantBooleanType(\false), new IntersectionType($accessoryTypes)]); } return new IntersectionType($accessoryTypes); } return null; } /** * @return false|string */ private function substrOrFalse(string $string, int $offset, ?int $length = null) { $strlen = strlen($string); if ($offset > $strlen) { return \false; } if ($length !== null && $length < 0) { if ($offset < 0 && -$length > $strlen) { return \false; } if ($offset >= 0 && -$length > $strlen - $offset) { return \false; } } if ($length === null) { return substr($string, $offset); } return substr($string, $offset, $length); } } 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); } } 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(), ['trim', 'rtrim', 'chop'], \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 = []; $defaultType = new StringType(); if ($stringType->isLowercaseString()->yes()) { $accessory[] = new AccessoryLowercaseStringType(); } if ($stringType->isUppercaseString()->yes()) { $accessory[] = new AccessoryUppercaseStringType(); } if (count($accessory) > 0) { $accessory[] = new StringType(); $defaultType = new IntersectionType($accessory); } if (count($args) !== 2) { return $defaultType; } $trimChars = $scope->getType($args[1]->value); $trimConstantStrings = $trimChars->getConstantStrings(); if (count($trimConstantStrings) > 0) { $result = []; $stringConstantStrings = $stringType->getConstantStrings(); $functionName = $functionReflection->getName(); foreach ($trimConstantStrings as $trimConstantString) { if (count($stringConstantStrings) > 0) { foreach ($stringConstantStrings as $stringConstantString) { $result[] = new ConstantStringType($functionName === 'rtrim' ? rtrim($stringConstantString->getValue(), $trimConstantString->getValue()) : trim($stringConstantString->getValue(), $trimConstantString->getValue()), \true); } } elseif (preg_match('/\d/', $trimConstantString->getValue()) === 0 && $stringType->isNumericString()->yes()) { $result[] = new IntersectionType([new StringType(), new AccessoryNumericStringType()]); } else { return $defaultType; } } return TypeCombinator::union(...$result); } return $defaultType; } } reflectionProvider = $reflectionProvider; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; } 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 { return $this->helper ??= new ImpossibleCheckTypeHelper($this->reflectionProvider, $this->typeSpecifier, $this->treatPhpDocTypesAsCertain); } } ', 'gt', '>=', 'ge', '==', '=', 'eq', '!=', '<>', 'ne']; /** * @param int|array{min: int, max: int}|null $configPhpVersion */ public function __construct( #[AutowiredParameter('%phpVersion%')] $configPhpVersion, ComposerPhpVersionFactory $composerPhpVersionFactory, PhpVersion $phpVersion ) { $this->configPhpVersion = $configPhpVersion; $this->composerPhpVersionFactory = $composerPhpVersionFactory; $this->phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'version_compare'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type { $args = $functionCall->getArgs(); if (count($args) < 2) { return null; } $version1Strings = $this->getVersionStrings($args[0]->value, $scope); $version2Strings = $this->getVersionStrings($args[1]->value, $scope); $counts = [count($version1Strings), count($version2Strings)]; if (isset($args[2])) { $operatorStrings = $scope->getType($args[2]->value)->getConstantStrings(); $counts[] = count($operatorStrings); $returnType = $this->phpVersion->throwsValueErrorForInternalFunctions() ? new BooleanType() : new BenevolentUnionType([new BooleanType(), new NullType()]); } else { $returnType = new UnionType([new ConstantIntegerType(-1), new ConstantIntegerType(0), new ConstantIntegerType(1)]); } if (count(array_filter($counts, static fn(int $count): bool => $count === 0)) > 0) { return $returnType; // one of the arguments is not a constant string } if (count(array_filter($counts, static fn(int $count): bool => $count > 1)) > 1) { return $returnType; // more than one argument can have multiple possibilities, avoid combinatorial explosion } $types = []; $canBeNull = \false; foreach ($version1Strings as $version1String) { foreach ($version2Strings as $version2String) { if (isset($operatorStrings)) { foreach ($operatorStrings as $operatorString) { $operatorValue = $operatorString->getValue(); if (!in_array($operatorValue, self::VALID_OPERATORS, \true)) { if (!$this->phpVersion->throwsValueErrorForInternalFunctions()) { $canBeNull = \true; } continue; } $value = version_compare($version1String->getValue(), $version2String->getValue(), $operatorValue); $types[(int) $value] = new ConstantBooleanType($value); } } else { $value = version_compare($version1String->getValue(), $version2String->getValue()); $types[$value] = new ConstantIntegerType($value); } } } if ($canBeNull) { $types[] = new NullType(); } return TypeCombinator::union(...$types); } /** * @return ConstantStringType[] */ private function getVersionStrings(Expr $expr, Scope $scope): array { if ($expr instanceof Expr\ConstFetch && $expr->name->toString() === 'PHP_VERSION') { if (is_array($this->configPhpVersion)) { $minVersion = new PhpVersion($this->configPhpVersion['min']); $maxVersion = new PhpVersion($this->configPhpVersion['max']); } else { $minVersion = $this->composerPhpVersionFactory->getMinVersion(); $maxVersion = $this->composerPhpVersionFactory->getMaxVersion(); } if ($minVersion !== null && $maxVersion !== null) { return [new ConstantStringType($minVersion->getVersionString()), new ConstantStringType($maxVersion->getVersionString())]; } } return $scope->getType($expr)->getConstantStrings(); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'version_compare'; } public function getThrowTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $funcCall, Scope $scope): ?Type { if (!$this->phpVersion->throwsValueErrorForInternalFunctions()) { return null; } $args = $funcCall->getArgs(); if (!isset($args[2])) { return null; } $operatorStrings = $scope->getType($args[2]->value)->getConstantStrings(); if (count($operatorStrings) === 0) { return $functionReflection->getThrowType(); } foreach ($operatorStrings as $operatorString) { $operatorValue = $operatorString->getValue(); if (!in_array($operatorValue, \PHPStan\Type\Php\VersionCompareFunctionDynamicReturnTypeExtension::VALID_OPERATORS, \true)) { return $functionReflection->getThrowType(); } } return null; } } 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)]); } } 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]); } } /** * @template T * @param callable(): T $callback * @return T|ErrorType */ public static function runOnObjectIdentity(\PHPStan\Type\Type $type, callable $callback) { $key = spl_object_id($type); if (isset(self::$context[$key])) { return new \PHPStan\Type\ErrorType(); } try { self::$context[$key] = \true; return $callback(); } finally { unset(self::$context[$key]); } } } > */ private array $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; } } */ private array $capturingGroups; /** * @var list */ private array $markVerbs; private Type $subjectBaseType; /** * @param array $capturingGroups * @param list $markVerbs */ public function __construct(int $alternationId, int $captureGroupId, array $capturingGroups, array $markVerbs, Type $subjectBaseType) { $this->alternationId = $alternationId; $this->captureGroupId = $captureGroupId; $this->capturingGroups = $capturingGroups; $this->markVerbs = $markVerbs; $this->subjectBaseType = $subjectBaseType; } 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, [], [], new StringType() ); } public function nextAlternationId(): self { return new self($this->alternationId + 1, $this->captureGroupId, $this->capturingGroups, $this->markVerbs, $this->subjectBaseType); } public function nextCaptureGroupId(): self { return new self($this->alternationId, $this->captureGroupId + 1, $this->capturingGroups, $this->markVerbs, $this->subjectBaseType); } 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, $this->subjectBaseType); } public function markVerb(string $markVerb): self { $verbs = $this->markVerbs; $verbs[] = $markVerb; return new self($this->alternationId, $this->captureGroupId, $this->capturingGroups, $verbs, $this->subjectBaseType); } public function withSubjectBaseType(Type $subjectBaseType): self { return new self($this->alternationId, $this->captureGroupId, $this->capturingGroups, $this->markVerbs, $subjectBaseType); } 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; } public function getSubjectBaseType(): Type { return $this->subjectBaseType; } } id = $id; $this->name = $name; $this->alternation = $alternation; $this->inOptionalQuantification = $inOptionalQuantification; $this->parent = $parent; $this->type = $type; $this->forceNonOptional = $forceNonOptional; $this->forceType = $forceType; } public function getId(): int { return $this->id; } public function forceNonOptional(): self { return new self($this->id, $this->name, $this->alternation, $this->inOptionalQuantification, $this->parent, $this->type, \true, $this->forceType); } public function forceType(Type $type): self { return new self($this->id, $this->name, $this->alternation, $this->inOptionalQuantification, $this->parent, $type, $this->forceNonOptional, $this->forceType); } /** * @param \PHPStan\Type\Regex\RegexCapturingGroup|\PHPStan\Type\Regex\RegexNonCapturingGroup $parent */ public function withParent($parent): self { return new self($this->id, $this->name, $this->alternation, $this->inOptionalQuantification, $parent, $this->type, $this->forceNonOptional, $this->forceType); } 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; } /** * @return \PHPStan\Type\Regex\RegexCapturingGroup|\PHPStan\Type\Regex\RegexNonCapturingGroup|null */ public function getParent() { return $this->parent; } } 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) { private Scope $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->isFirstClassCallable() && $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 fn(Expr $expr): Type => $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); } } */ final class RegexGroupList implements Countable, IteratorAggregate { /** * @readonly * @var array */ private array $groups; /** * @param array $groups */ public function __construct(array $groups) { $this->groups = $groups; } public function countTrailingOptionals(): int { $trailingOptionals = 0; foreach (array_reverse($this->groups) as $captureGroup) { if (!$captureGroup->isOptional()) { break; } $trailingOptionals++; } return $trailingOptionals; } public function forceGroupNonOptional(\PHPStan\Type\Regex\RegexCapturingGroup $group): self { return $this->cloneAndReParentList($group); } public function forceGroupTypeAndNonOptional(\PHPStan\Type\Regex\RegexCapturingGroup $group, Type $type): self { return $this->cloneAndReParentList($group, $type); } private function cloneAndReParentList(\PHPStan\Type\Regex\RegexCapturingGroup $target, ?Type $type = null): self { $groups = []; $forcedGroup = null; foreach ($this->groups as $i => $group) { if ($group->getId() === $target->getId()) { $forcedGroup = $group->forceNonOptional(); if ($type !== null) { $forcedGroup = $forcedGroup->forceType($type); } $groups[$i] = $forcedGroup; continue; } $groups[$i] = $group; } if ($forcedGroup === null) { throw new ShouldNotHappenException(); } foreach ($groups as $i => $group) { $parent = $group->getParent(); while ($parent !== null) { if ($parent instanceof \PHPStan\Type\Regex\RegexNonCapturingGroup) { $parent = $parent->getParent(); continue; } if ($parent->getId() === $target->getId()) { $groups[$i] = $groups[$i]->withParent($forcedGroup); } $parent = $parent->getParent(); } } return new self($groups); } public function removeGroup(\PHPStan\Type\Regex\RegexCapturingGroup $remove): self { $groups = []; foreach ($this->groups as $i => $group) { if ($group->getId() === $remove->getId()) { continue; } $groups[$i] = $group; } return new self($groups); } public function getOnlyOptionalTopLevelGroup(): ?\PHPStan\Type\Regex\RegexCapturingGroup { $group = null; foreach ($this->groups as $captureGroup) { if (!$captureGroup->isTopLevel()) { continue; } if (!$captureGroup->isOptional()) { return null; } if ($group !== null) { return null; } $group = $captureGroup; } return $group; } public function getOnlyTopLevelAlternation(): ?\PHPStan\Type\Regex\RegexAlternation { $alternation = null; foreach ($this->groups 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; } #[Override] public function count(): int { return count($this->groups); } /** * @return ArrayIterator */ #[Override] public function getIterator(): ArrayIterator { return new ArrayIterator($this->groups); } } */ private static array $parsedAst = []; public function __construct(PhpVersion $phpVersion, \PHPStan\Type\Regex\RegexExpressionHelper $regexExpressionHelper) { $this->phpVersion = $phpVersion; $this->regexExpressionHelper = $regexExpressionHelper; } public function parseGroups(string $regex): ?\PHPStan\Type\Regex\RegexAstWalkResult { /** @throws void */ self::$parser ??= Llk::load(new Read(__DIR__ . '/../../../resources/RegexGrammar.pp')); if (array_key_exists($regex, self::$parsedAst)) { $ast = self::$parsedAst[$regex]; if ($ast === null) { return null; } $modifiers = $this->regexExpressionHelper->getPatternModifiers($regex) ?? ''; } else { try { Strings::match('', $regex); } catch (RegexpException $e) { // pattern is invalid, so let the RegularExpressionPatternRule report it return self::$parsedAst[$regex] = null; } $modifiers = $this->regexExpressionHelper->getPatternModifiers($regex) ?? ''; foreach (self::NOT_SUPPORTED_MODIFIERS as $notSupportedModifier) { if (str_contains($modifiers, $notSupportedModifier)) { return self::$parsedAst[$regex] = null; } } if (str_contains($modifiers, 'x')) { // in freespacing mode the # character starts a comment and runs until the end of the line // but \# is an escaped literal hash, and (?#...) is an inline comment - neither starts a line comment $regex = preg_replace('/(?regexExpressionHelper->removeDelimitersAndModifiers($regex); try { $ast = self::$parsedAst[$regex] = self::$parser->parse($rawRegex); } catch (Exception $e) { return self::$parsedAst[$regex] = 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()); $subjectAsGroupResult = $this->walkGroupAst($ast, \false, $modifiers, \PHPStan\Type\Regex\RegexGroupWalkResult::createEmpty()); if (!$subjectAsGroupResult->mightContainEmptyStringLiteral() && !$this->containsEscapeK($ast)) { // we could handle numeric-string, in case we know the regex is delimited by ^ and $ if ($subjectAsGroupResult->isNonFalsy()->yes()) { $astWalkResult = $astWalkResult->withSubjectBaseType(new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()])); } elseif ($subjectAsGroupResult->isNonEmpty()->yes()) { $astWalkResult = $astWalkResult->withSubjectBaseType(new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()])); } } return $astWalkResult; } 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]); } private function containsEscapeK(TreeNode $ast): bool { if ($ast->getId() === 'token' && $ast->getValueToken() === 'match_point_reset') { return \true; } foreach ($ast->getChildren() as $child) { if ($this->containsEscapeK($child)) { return \true; } } return \false; } /** * @param \PHPStan\Type\Regex\RegexCapturingGroup|\PHPStan\Type\Regex\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 \PHPStan\Type\Regex\RegexCapturingGroup|\PHPStan\Type\Regex\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, $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 new UnionType([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 $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) { 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) { $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) { $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') { if (count($children) === 0) { return $walkResult; } $newLiterals = []; $nonEmpty = TrinaryLogic::createYes(); $nonFalsy = TrinaryLogic::createYes(); $numeric = TrinaryLogic::createYes(); foreach ($children as $child) { $childResult = $this->walkGroupAst($child, $inClass, $patternModifiers, $walkResult->onlyLiterals([])->nonEmpty(TrinaryLogic::createMaybe())->nonFalsy(TrinaryLogic::createMaybe())->numeric(TrinaryLogic::createMaybe())); $nonEmpty = $nonEmpty->and($childResult->isNonEmpty()); $nonFalsy = $nonFalsy->and($childResult->isNonFalsy()); $numeric = $numeric->and($childResult->isNumeric()); if ($newLiterals === null) { continue; } if (count($childResult->getOnlyLiterals() ?? []) > 0) { foreach ($childResult->getOnlyLiterals() as $alternationLiterals) { $newLiterals[] = $alternationLiterals; } } else { $newLiterals = null; } } return $walkResult->onlyLiterals($newLiterals)->nonEmpty($walkResult->isNonEmpty()->or($nonEmpty))->nonFalsy($walkResult->isNonFalsy()->or($nonFalsy))->numeric($walkResult->isNumeric()->and($numeric)); } // [^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, $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 (in_array($token, ['anchor', 'match_point_reset'], \true)) { return ''; } return null; } } |null */ private ?array $onlyLiterals; private TrinaryLogic $isNonEmpty; private TrinaryLogic $isNonFalsy; private TrinaryLogic $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 mightContainEmptyStringLiteral(): bool { if ($this->onlyLiterals === null) { return \false; } foreach ($this->onlyLiterals as $onlyLiteral) { if ($onlyLiteral === '') { return \true; } } return \false; } 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() */ private 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 \PHPStan\Type\Regex\RegexCapturingGroup|\PHPStan\Type\Regex\RegexNonCapturingGroup|null */ public function getParent() { return $this->parent; } public function resetsGroupCounter(): bool { return $this->resetGroupCounter; } } 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']); } } */ private array $methodCache = []; /** * @api */ public function __construct(ClassReflection $classReflection, ?\PHPStan\Type\Type $subtractedType = null) { $this->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 fn(string $name, \PHPStan\Type\Type $type): \PHPStan\Type\Type => 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; } 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): \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } if (!$type instanceof static) { return \PHPStan\Type\AcceptsResult::createNo(); } return $this->getStaticObjectType()->accepts($type->getStaticObjectType(), $strictTypes); } public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return $this->getStaticObjectType()->isSuperTypeOf($type); } if ($type instanceof \PHPStan\Type\ObjectWithoutClassType) { return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } if ($type instanceof \PHPStan\Type\ObjectType) { $result = $this->getStaticObjectType()->isSuperTypeOf($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->isSubTypeOf($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 getClassStringType(): \PHPStan\Type\Type { return new GenericClassStringType($this); } 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): ExtendedPropertyReflection { 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, fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $this->transformStaticType($type, $scope)); } public function hasInstanceProperty(string $propertyName): TrinaryLogic { return $this->getStaticObjectType()->hasInstanceProperty($propertyName); } public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $staticObject = $this->getStaticObjectType(); $nakedProperty = $staticObject->getUnresolvedInstancePropertyPrototype($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, fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $this->transformStaticType($type, $scope)); } public function hasStaticProperty(string $propertyName): TrinaryLogic { return $this->getStaticObjectType()->hasStaticProperty($propertyName); } public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedStaticPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $staticObject = $this->getStaticObjectType(); $nakedProperty = $staticObject->getUnresolvedStaticPropertyPrototype($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, fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $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 { $key = $methodName; if ($scope->isInClass()) { $key = sprintf('%s-%s', $key, $scope->getClassReflection()->getCacheKey()); } return $this->methodCache[$key] ??= $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, fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $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); // When calling a method on a `static` type (not `$this`), // `$this` return type should be downgraded to `static` // because we can't guarantee the exact instance. if ($type instanceof \PHPStan\Type\ThisType && !$this instanceof \PHPStan\Type\ThisType) { $type = new self($type->getClassReflection(), $type->getSubtractedType()); } if ($this->getSubtractedType() !== null) { $type = $type->subtract($this->getSubtractedType()); if (!$type instanceof \PHPStan\Type\StaticType) { return $traverse($type); } } 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): ClassConstantReflection { 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()->getIterableKeyType(); } public function getLastIterableKeyType(): \PHPStan\Type\Type { return $this->getStaticObjectType()->getIterableKeyType(); } public function getIterableValueType(): \PHPStan\Type\Type { return $this->getStaticObjectType()->getIterableValueType(); } public function getFirstIterableValueType(): \PHPStan\Type\Type { return $this->getStaticObjectType()->getIterableValueType(); } public function getLastIterableValueType(): \PHPStan\Type\Type { return $this->getStaticObjectType()->getIterableValueType(); } 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 getKeysArrayFiltered(\PHPStan\Type\Type $filterValueType, TrinaryLogic $strict): \PHPStan\Type\Type { return $this->getStaticObjectType()->getKeysArrayFiltered($filterValueType, $strict); } 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, ?TrinaryLogic $strict = null): \PHPStan\Type\Type { return $this->getStaticObjectType()->searchArray($needleType, $strict); } 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 spliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, \PHPStan\Type\Type $replacementType): \PHPStan\Type\Type { return $this->getStaticObjectType()->spliceArray($offsetType, $lengthType, $replacementType); } public function makeListMaybe(): \PHPStan\Type\Type { return $this->getStaticObjectType()->makeListMaybe(); } public function mapValueType(callable $cb): \PHPStan\Type\Type { return $this->getStaticObjectType()->mapValueType($cb); } public function mapKeyType(callable $cb): \PHPStan\Type\Type { return $this->getStaticObjectType()->mapKeyType($cb); } public function makeAllArrayKeysOptional(): \PHPStan\Type\Type { return $this->getStaticObjectType()->makeAllArrayKeysOptional(); } public function changeKeyCaseArray(?int $case): \PHPStan\Type\Type { return $this->getStaticObjectType()->changeKeyCaseArray($case); } public function filterArrayRemovingFalsey(): \PHPStan\Type\Type { return $this->getStaticObjectType()->filterArrayRemovingFalsey(); } public function isCallable(): TrinaryLogic { return $this->getStaticObjectType()->isCallable(); } public function getEnumCases(): array { return $this->getStaticObjectType()->getEnumCases(); } public function getEnumCaseObject(): ?EnumCaseObjectType { return $this->getStaticObjectType()->getEnumCaseObject(); } 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 isClassString(): TrinaryLogic { return $this->getStaticObjectType()->isClassString(); } 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 toBitwiseNotType(): \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toGetClassResultType(): \PHPStan\Type\Type { // Preserve static binding (`class-string` / // `class-string<$this>`) by going through `getClassStringType()` // directly instead of delegating to the underlying object type, // which would resolve `static` away. return $this->getClassStringType(); } public function toClassConstantType(ReflectionProvider $reflectionProvider): \PHPStan\Type\Type { // Like `toGetClassResultType()`, project through this `StaticType`'s // own `getClassStringType()` so that `static::class` reads as // `class-string` rather than the underlying class. return new \PHPStan\Type\IntersectionType([$this->getClassStringType(), new AccessoryLiteralStringType()]); } public function toObjectTypeForInstanceofCheck(): \PHPStan\Type\ClassNameToObjectTypeResult { return new \PHPStan\Type\ClassNameToObjectTypeResult($this, \true); } public function toObjectTypeForIsACheck(\PHPStan\Type\Type $objectOrClassType, bool $allowString, bool $allowSameClass): \PHPStan\Type\ClassNameToObjectTypeResult { if ($allowString) { return new \PHPStan\Type\ClassNameToObjectTypeResult(new \PHPStan\Type\UnionType([new \PHPStan\Type\ObjectWithoutClassType(), new \PHPStan\Type\ClassStringType()]), \false); } return new \PHPStan\Type\ClassNameToObjectTypeResult(new \PHPStan\Type\ObjectWithoutClassType(), \false); } 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 toCoercedArgumentType(bool $strictTypes): \PHPStan\Type\Type { return $this->getStaticObjectType()->toCoercedArgumentType($strictTypes); } 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'); } public function hasTemplateOrLateResolvableType(): bool { return $this->getStaticObjectType()->hasTemplateOrLateResolvableType(); } } handle(static fn() => 'mixed', static fn() => 'mixed', static fn() => 'mixed', static fn() => '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 getClassStringType(): \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } 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): ExtendedPropertyReflection { throw new ShouldNotHappenException(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { throw new ShouldNotHappenException(); } public function hasInstanceProperty(string $propertyName): TrinaryLogic { return TrinaryLogic::createNo(); } public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { throw new ShouldNotHappenException(); } public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { throw new ShouldNotHappenException(); } public function hasStaticProperty(string $propertyName): TrinaryLogic { return TrinaryLogic::createNo(); } public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { throw new ShouldNotHappenException(); } public function getUnresolvedStaticPropertyPrototype(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): ClassConstantReflection { 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 isClassString(): 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 toBitwiseNotType(): \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toGetClassResultType(): \PHPStan\Type\Type { return new ConstantBooleanType(\false); } public function toClassConstantType(ReflectionProvider $reflectionProvider): \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toObjectTypeForInstanceofCheck(): \PHPStan\Type\ClassNameToObjectTypeResult { return new \PHPStan\Type\ClassNameToObjectTypeResult(new \PHPStan\Type\MixedType(), \false); } public function toObjectTypeForIsACheck(\PHPStan\Type\Type $objectOrClassType, bool $allowString, bool $allowSameClass): \PHPStan\Type\ClassNameToObjectTypeResult { if ($allowString) { return new \PHPStan\Type\ClassNameToObjectTypeResult(new \PHPStan\Type\UnionType([new \PHPStan\Type\ObjectWithoutClassType(), new \PHPStan\Type\ClassStringType()]), \false); } return new \PHPStan\Type\ClassNameToObjectTypeResult(new \PHPStan\Type\ObjectWithoutClassType(), \false); } 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 toCoercedArgumentType(bool $strictTypes): \PHPStan\Type\Type { return $this; } 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 getEnumCaseObject(): ?EnumCaseObjectType { return null; } 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'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } isSubTypeOf($this); } $thatClassNames = $type->getObjectClassNames(); if ($thatClassNames === []) { return parent::isSuperTypeOf($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 accepts(\PHPStan\Type\Type $type, bool $strictTypes): \PHPStan\Type\AcceptsResult { $thatClassNames = $type->getObjectClassNames(); if ($thatClassNames === []) { return parent::accepts($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; } } isSubTypeOf($this); } $result = parent::isSuperTypeOf($type); if (!$type instanceof self) { $result = $result->and(\PHPStan\Type\IsSuperTypeOfResult::createMaybe()); } return $result; } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes): \PHPStan\Type\AcceptsResult { return parent::accepts($type, \true); } } 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): \PHPStan\Type\AcceptsResult { if ($type instanceof self) { return \PHPStan\Type\AcceptsResult::createYes(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedBy($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 toBitwiseNotType(): \PHPStan\Type\Type { return new \PHPStan\Type\StringType(); } 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 toCoercedArgumentType(bool $strictTypes): \PHPStan\Type\Type { if (!$strictTypes) { if ($this->isNumericString()->no()) { return \PHPStan\Type\TypeCombinator::union($this, $this->toBoolean()); } return \PHPStan\Type\TypeCombinator::union($this->toInteger(), $this->toFloat(), $this, $this->toBoolean()); } 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 isClassString(): 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 { if ($type->isArray()->yes()) { return new ConstantBooleanType(\false); } return new \PHPStan\Type\BooleanType(); } public function hasMethod(string $methodName): TrinaryLogic { if ($this->isClassString()->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'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } getSubtractedType()); } public function describe(\PHPStan\Type\VerbosityLevel $level): string { return sprintf('$this(%s)', $this->getStaticObjectType()->describe($level)); } public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return $this->getStaticObjectType()->isSuperTypeOf($type); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOf($this); } $parent = new parent($this->getClassReflection(), $this->getSubtractedType()); return $parent->isSuperTypeOf($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(); } public function toClassConstantType(ReflectionProvider $reflectionProvider): \PHPStan\Type\Type { // `$this` in a `final` class is pinned to that one class, so // `$this::class` collapses to its literal name. For non-final // classes `$this` could still be a subclass, so fall back to the // `class-string<$this>` projection from the parent. $reflection = $this->getClassReflection(); if ($reflection->isFinalByKeyword()) { return new ConstantStringType($reflection->getName(), \true); } return parent::toClassConstantType($reflectionProvider); } } yes() ? $this : new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $this->getIterableValueType()), new AccessoryArrayListType()]); $chunkType = TypeCombinator::intersect($chunkType, new NonEmptyArrayType()); $arrayType = new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $chunkType), new AccessoryArrayListType()]); return $this->isIterableAtLeastOnce()->yes() ? TypeCombinator::intersect($arrayType, new NonEmptyArrayType()) : $arrayType; } } 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(PhpVersion $phpVersion): 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(PhpVersion $phpVersion): 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(PhpVersion $phpVersion): 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)); } } equals($type)); } if ($type instanceof CompoundType) { return $type->isAcceptedBy($this, $strictTypes); } return parent::accepts($type, $strictTypes)->and(AcceptsResult::createMaybe()); } public function isSuperTypeOf(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->isSubTypeOf($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, equal.alwaysFalse 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, PhpVersion $phpVersion): TrinaryLogic { if ($otherType instanceof ConstantScalarType) { return TrinaryLogic::createFromBoolean($this->value < $otherType->getValue()); } if ($otherType instanceof CompoundType) { return $otherType->isGreaterThan($this, $phpVersion); } return TrinaryLogic::createMaybe(); } public function isSmallerThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { if ($otherType instanceof ConstantScalarType) { return TrinaryLogic::createFromBoolean($this->value <= $otherType->getValue()); } if ($otherType instanceof CompoundType) { return $otherType->isGreaterThanOrEqual($this, $phpVersion); } 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]; } } 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): AcceptsResult { return $this->resolve()->accepts($type, $strictTypes); } public function isSuperTypeOf(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()->isSuperTypeOf($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 getClassStringType(): Type { return $this->resolve()->getClassStringType(); } 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): ExtendedPropertyReflection { return $this->resolve()->getProperty($propertyName, $scope); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { return $this->resolve()->getUnresolvedPropertyPrototype($propertyName, $scope); } public function hasInstanceProperty(string $propertyName): TrinaryLogic { return $this->resolve()->hasInstanceProperty($propertyName); } public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->resolve()->getInstanceProperty($propertyName, $scope); } public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { return $this->resolve()->getUnresolvedInstancePropertyPrototype($propertyName, $scope); } public function hasStaticProperty(string $propertyName): TrinaryLogic { return $this->resolve()->hasStaticProperty($propertyName); } public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->resolve()->getStaticProperty($propertyName, $scope); } public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { return $this->resolve()->getUnresolvedStaticPropertyPrototype($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): ClassConstantReflection { 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()->getIterableKeyType(); } public function getLastIterableKeyType(): Type { return $this->resolve()->getIterableKeyType(); } public function getIterableValueType(): Type { return $this->resolve()->getIterableValueType(); } public function getFirstIterableValueType(): Type { return $this->resolve()->getIterableValueType(); } public function getLastIterableValueType(): Type { return $this->resolve()->getIterableValueType(); } 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 getKeysArrayFiltered(Type $filterValueType, TrinaryLogic $strict): Type { return $this->resolve()->getKeysArrayFiltered($filterValueType, $strict); } 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, ?TrinaryLogic $strict = null): Type { return $this->resolve()->searchArray($needleType, $strict); } 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 spliceArray(Type $offsetType, Type $lengthType, Type $replacementType): Type { return $this->resolve()->spliceArray($offsetType, $lengthType, $replacementType); } public function makeListMaybe(): Type { return $this->resolve()->makeListMaybe(); } public function mapValueType(callable $cb): Type { return $this->resolve()->mapValueType($cb); } public function mapKeyType(callable $cb): Type { return $this->resolve()->mapKeyType($cb); } public function makeAllArrayKeysOptional(): Type { return $this->resolve()->makeAllArrayKeysOptional(); } public function changeKeyCaseArray(?int $case): Type { return $this->resolve()->changeKeyCaseArray($case); } public function filterArrayRemovingFalsey(): Type { return $this->resolve()->filterArrayRemovingFalsey(); } public function isCallable(): TrinaryLogic { return $this->resolve()->isCallable(); } public function getEnumCases(): array { return $this->resolve()->getEnumCases(); } public function getEnumCaseObject(): ?EnumCaseObjectType { return $this->resolve()->getEnumCaseObject(); } 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 toBitwiseNotType(): Type { return $this->resolve()->toBitwiseNotType(); } public function toGetClassResultType(): Type { return $this->resolve()->toGetClassResultType(); } public function toClassConstantType(ReflectionProvider $reflectionProvider): Type { return $this->resolve()->toClassConstantType($reflectionProvider); } public function toObjectTypeForInstanceofCheck(): ClassNameToObjectTypeResult { return $this->resolve()->toObjectTypeForInstanceofCheck(); } public function toObjectTypeForIsACheck(Type $objectOrClassType, bool $allowString, bool $allowSameClass): ClassNameToObjectTypeResult { return $this->resolve()->toObjectTypeForIsACheck($objectOrClassType, $allowString, $allowSameClass); } 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 toCoercedArgumentType(bool $strictTypes): Type { return $this->resolve()->toCoercedArgumentType($strictTypes); } public function isSmallerThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return $this->resolve()->isSmallerThan($otherType, $phpVersion); } public function isSmallerThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return $this->resolve()->isSmallerThanOrEqual($otherType, $phpVersion); } 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 isClassString(): TrinaryLogic { return $this->resolve()->isClassString(); } 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(PhpVersion $phpVersion): Type { return $this->resolve()->getSmallerType($phpVersion); } public function getSmallerOrEqualType(PhpVersion $phpVersion): Type { return $this->resolve()->getSmallerOrEqualType($phpVersion); } public function getGreaterType(PhpVersion $phpVersion): Type { return $this->resolve()->getGreaterType($phpVersion); } public function getGreaterOrEqualType(PhpVersion $phpVersion): Type { return $this->resolve()->getGreaterOrEqualType($phpVersion); } 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): IsSuperTypeOfResult { $result = $this->resolve(); if ($result instanceof CompoundType) { return $result->isSubTypeOf($otherType); } return $otherType->isSuperTypeOf($result); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { $result = $this->resolve(); if ($result instanceof CompoundType) { return $result->isAcceptedBy($acceptingType, $strictTypes); } return $acceptingType->accepts($result, $strictTypes); } public function isGreaterThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { $result = $this->resolve(); if ($result instanceof CompoundType) { return $result->isGreaterThan($otherType, $phpVersion); } return $otherType->isSmallerThan($result, $phpVersion); } public function isGreaterThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { $result = $this->resolve(); if ($result instanceof CompoundType) { return $result->isGreaterThanOrEqual($otherType, $phpVersion); } return $otherType->isSmallerThanOrEqual($result, $phpVersion); } public function exponentiate(Type $exponent): Type { return $this->resolve()->exponentiate($exponent); } public function getFiniteTypes(): array { return $this->resolve()->getFiniteTypes(); } public function resolve(): Type { return $this->result ??= $this->getResult(); } abstract protected function getResult(): Type; public function hasTemplateOrLateResolvableType(): bool { return \true; } } getKeysArray(); } public function getKeysArray(): Type { return new ErrorType(); } public function getValuesArray(): Type { return new ErrorType(); } public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys): Type { return new ErrorType(); } public function fillKeysArray(Type $valueType): Type { return new ErrorType(); } public function flipArray(): Type { return new ErrorType(); } public function intersectKeyArray(Type $otherArraysType): Type { return new ErrorType(); } public function popArray(): Type { return new ErrorType(); } public function reverseArray(TrinaryLogic $preserveKeys): Type { return new ErrorType(); } public function searchArray(Type $needleType, ?TrinaryLogic $strict = null): Type { return new ErrorType(); } public function shiftArray(): Type { return new ErrorType(); } public function shuffleArray(): Type { return new ErrorType(); } public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $preserveKeys): Type { return new ErrorType(); } public function spliceArray(Type $offsetType, Type $lengthType, Type $replacementType): Type { return new ErrorType(); } public function makeListMaybe(): Type { return $this; } public function mapValueType(callable $cb): Type { return $this; } public function mapKeyType(callable $cb): Type { return $this; } public function makeAllArrayKeysOptional(): Type { return $this; } public function changeKeyCaseArray(?int $case): Type { return new ErrorType(); } public function filterArrayRemovingFalsey(): Type { return new ErrorType(); } } 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(); } } getClassStringType(), new ConstantBooleanType(\false)]); } public function toClassConstantType(ReflectionProvider $reflectionProvider): Type { return new ErrorType(); } public function toObjectTypeForInstanceofCheck(): ClassNameToObjectTypeResult { return new ClassNameToObjectTypeResult(new MixedType(), \false); } public function toObjectTypeForIsACheck(Type $objectOrClassType, bool $allowString, bool $allowSameClass): ClassNameToObjectTypeResult { if ($allowString) { return new ClassNameToObjectTypeResult(new UnionType([new ObjectWithoutClassType(), new ClassStringType()]), \false); } return new ClassNameToObjectTypeResult(new ObjectWithoutClassType(), \false); } public function isEnum(): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function canAccessProperties(): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function hasProperty(string $propertyName): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $property = new DummyPropertyReflection($propertyName); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static fn(Type $type): Type => $type); } public function hasInstanceProperty(string $propertyName): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $property = new DummyPropertyReflection($propertyName); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static fn(Type $type): Type => $type); } public function hasStaticProperty(string $propertyName): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedStaticPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $property = new DummyPropertyReflection($propertyName); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static fn(Type $type): Type => $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 fn(Type $type): Type => $type); } public function canAccessConstants(): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function hasConstant(string $constantName): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getConstant(string $constantName): ClassConstantReflection { return new DummyClassConstantReflection($constantName); } public function isCloneable(): TrinaryLogic { return TrinaryLogic::createMaybe(); } } getKeysArray(); } public function getKeysArray(): Type { return new ErrorType(); } public function getValuesArray(): Type { return new ErrorType(); } public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys): Type { return new ErrorType(); } public function fillKeysArray(Type $valueType): Type { return new ErrorType(); } public function flipArray(): Type { return new ErrorType(); } public function intersectKeyArray(Type $otherArraysType): Type { return new ErrorType(); } public function popArray(): Type { return new ErrorType(); } public function reverseArray(TrinaryLogic $preserveKeys): Type { return new ErrorType(); } public function searchArray(Type $needleType, ?TrinaryLogic $strict = null): Type { return new ErrorType(); } public function shiftArray(): Type { return new ErrorType(); } public function shuffleArray(): Type { return new ErrorType(); } public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $preserveKeys): Type { return new ErrorType(); } public function spliceArray(Type $offsetType, Type $lengthType, Type $replacementType): Type { return new ErrorType(); } public function makeListMaybe(): Type { return $this; } public function mapValueType(callable $cb): Type { return $this; } public function mapKeyType(callable $cb): Type { return $this; } public function makeAllArrayKeysOptional(): Type { return $this; } public function changeKeyCaseArray(?int $case): Type { return new ErrorType(); } public function filterArrayRemovingFalsey(): Type { return new ErrorType(); } } traverse(static fn(Type $type) => $type->generalize($precision)); } } getClassStringType(); } public function toClassConstantType(ReflectionProvider $reflectionProvider): Type { $classNames = $this->getObjectClassNames(); if (count($classNames) === 1 && $reflectionProvider->hasClass($classNames[0])) { $reflection = $reflectionProvider->getClass($classNames[0]); if ($reflection->isFinalByKeyword()) { return new ConstantStringType($reflection->getName(), \true); } } return new IntersectionType([$this->getClassStringType(), new AccessoryLiteralStringType()]); } public function toObjectTypeForInstanceofCheck(): ClassNameToObjectTypeResult { // Definite-object types keep themselves as the comparison target — // they're already an `ObjectType` (or its accessory). The // uncertainty flag is set because the `instanceof` decision can // only be made at runtime when comparing against a class name // computed from the value. return new ClassNameToObjectTypeResult($this, \true); } public function toObjectTypeForIsACheck(Type $objectOrClassType, bool $allowString, bool $allowSameClass): ClassNameToObjectTypeResult { if ($allowString) { return new ClassNameToObjectTypeResult(new UnionType([new ObjectWithoutClassType(), new ClassStringType()]), \false); } return new ClassNameToObjectTypeResult(new ObjectWithoutClassType(), \false); } public function isEnum(): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function canAccessProperties(): TrinaryLogic { return TrinaryLogic::createYes(); } public function hasProperty(string $propertyName): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $property = new DummyPropertyReflection($propertyName); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static fn(Type $type): Type => $type); } public function hasInstanceProperty(string $propertyName): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $property = new DummyPropertyReflection($propertyName); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static fn(Type $type): Type => $type); } public function hasStaticProperty(string $propertyName): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedStaticPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $property = new DummyPropertyReflection($propertyName); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static fn(Type $type): Type => $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 fn(Type $type): Type => $type); } public function canAccessConstants(): TrinaryLogic { return TrinaryLogic::createYes(); } public function hasConstant(string $constantName): TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getConstant(string $constantName): ClassConstantReflection { return new DummyClassConstantReflection($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 isClassString(): 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 toBitwiseNotType(): 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 ErrorType(); } public function toCoercedArgumentType(bool $strictTypes): Type { if (!$strictTypes) { return TypeCombinator::union($this, $this->toString()); } return $this; } } getSubtractedType() !== null) { return sprintf('~(%s)', $subtractedType->describe($level)); } return sprintf('~%s', $subtractedType->describe($level)); } } isNull()->yes() && $this->isObject()->yes()) { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } public function isGreaterThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { if ($otherType->isNull()->yes()) { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } } isNull()->yes()) { return TrinaryLogic::createNo(); } return TrinaryLogic::createMaybe(); } public function isSmallerThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { if ($otherType->isNull()->yes() && $this->isObject()->yes()) { return TrinaryLogic::createNo(); } return TrinaryLogic::createMaybe(); } public function getSmallerType(PhpVersion $phpVersion): Type { return new MixedType(); } public function getSmallerOrEqualType(PhpVersion $phpVersion): Type { return new MixedType(); } public function getGreaterType(PhpVersion $phpVersion): Type { return new MixedType(\false, new NullType()); } public function getGreaterOrEqualType(PhpVersion $phpVersion): Type { if ($this->isObject()->yes()) { return new MixedType(\false, new NullType()); } return new MixedType(); } } resolveUnresolvableTypes = $resolveUnresolvableTypes; $this->ignoreResolveUnresolvableTypesLevel = 0; } /** * @param callable(Type): Type $traverse */ public function traverse(Type $type, callable $traverse): Type { while ($type instanceof LateResolvableType && ($this->resolveUnresolvableTypes && $this->ignoreResolveUnresolvableTypesLevel === 0 || $type->isResolvable())) { $type = $type->resolve(); } if ($type instanceof CallableType || $type instanceof ClosureType) { $this->ignoreResolveUnresolvableTypesLevel++; $result = $traverse($type); $this->ignoreResolveUnresolvableTypesLevel--; return $result; } return $traverse($type); } } isString()->yes()) { ... } * * @api * @api-do-not-implement * @see https://phpstan.org/developing-extensions/type-system */ interface Type { /** * Returns all class names referenced anywhere in this type, recursively * (including generic arguments, callable signatures, etc.). * * @see Type::getObjectClassNames() for only direct object type class names * * @return list */ public function getReferencedClasses(): array; /** * Returns class names of the object types this type directly represents. * Unlike getReferencedClasses(), excludes classes in generic arguments, etc. * * @return list */ public function getObjectClassNames(): array; /** @return list */ public function getObjectClassReflections(): array; /** * Return class-string for object type Foo. */ public function getClassStringType(): \PHPStan\Type\Type; /** * Returns the object type for a class-string or literal class name string. * For non-class-string types, returns ErrorType. */ public function getClassStringObjectType(): \PHPStan\Type\Type; /** * Like getClassStringObjectType(), but also returns object types as-is. * Used for `$classOrObject::method()` where the left side can be either. */ public function getObjectTypeOrClassStringObjectType(): \PHPStan\Type\Type; public function isObject(): TrinaryLogic; public function isEnum(): TrinaryLogic; /** @return list */ public function getArrays(): array; /** * Only ConstantArrayType instances (array shapes with known keys). * * @return list */ public function getConstantArrays(): array; /** @return list */ public function getConstantStrings(): array; /** * Unlike isSuperTypeOf(), accepts() takes into account PHP's implicit type coercion. * With $strictTypes = false, int is accepted by float, and Stringable objects are * accepted by string. */ public function accepts(\PHPStan\Type\Type $type, bool $strictTypes): \PHPStan\Type\AcceptsResult; /** * "Does every value of $type belong to $this type?" * * Preferable to instanceof checks because it correctly handles * union types, intersection types, and all other composite types. */ public function isSuperTypeOf(\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; /** @deprecated Use hasInstanceProperty or hasStaticProperty instead */ public function hasProperty(string $propertyName): TrinaryLogic; /** @deprecated Use getInstanceProperty or getStaticProperty instead */ public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection; /** @deprecated Use getUnresolvedInstancePropertyPrototype or getUnresolvedStaticPropertyPrototype instead */ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection; public function hasInstanceProperty(string $propertyName): TrinaryLogic; public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection; /** * Unlike getInstanceProperty(), this defers template type resolution. * Use getInstanceProperty() in most rule implementations. */ public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection; public function hasStaticProperty(string $propertyName): TrinaryLogic; public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection; public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection; public function canCallMethods(): TrinaryLogic; public function hasMethod(string $methodName): TrinaryLogic; public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope): ExtendedMethodReflection; /** * Unlike getMethod(), this defers template type and static type resolution. * Use getMethod() in most rule implementations. */ public function getUnresolvedMethodPrototype(string $methodName, ClassMemberAccessAnswerer $scope): UnresolvedMethodPrototypeReflection; public function canAccessConstants(): TrinaryLogic; public function hasConstant(string $constantName): TrinaryLogic; public function getConstant(string $constantName): ClassConstantReflection; public function isIterable(): TrinaryLogic; public function isIterableAtLeastOnce(): TrinaryLogic; /** * Returns the count of elements as a Type (typically IntegerRangeType). */ public function getArraySize(): \PHPStan\Type\Type; /** * Works for both arrays and Traversable objects. */ public function getIterableKeyType(): \PHPStan\Type\Type; /** @deprecated use getIterableKeyType */ public function getFirstIterableKeyType(): \PHPStan\Type\Type; /** @deprecated use getIterableKeyType */ public function getLastIterableKeyType(): \PHPStan\Type\Type; public function getIterableValueType(): \PHPStan\Type\Type; /** @deprecated use getIterableValueType */ public function getFirstIterableValueType(): \PHPStan\Type\Type; /** @deprecated use getIterableValueType */ public function getLastIterableValueType(): \PHPStan\Type\Type; public function isArray(): TrinaryLogic; public function isConstantArray(): TrinaryLogic; /** * An oversized array is a constant array shape that grew too large to track * precisely and was degraded to a generic array type. */ public function isOversizedArray(): TrinaryLogic; /** * A list is an array with sequential integer keys starting from 0 with no gaps. */ public function isList(): TrinaryLogic; public function isOffsetAccessible(): TrinaryLogic; /** * Whether accessing a non-existent offset is safe (won't cause errors). * Unlike isOffsetAccessible() which checks if offset access is supported at all. */ public function isOffsetAccessLegal(): TrinaryLogic; public function hasOffsetValueType(\PHPStan\Type\Type $offsetType): TrinaryLogic; public function getOffsetValueType(\PHPStan\Type\Type $offsetType): \PHPStan\Type\Type; /** * May add a new key. When $offsetType is null, appends (like $a[] = $value). * * @see Type::setExistingOffsetValueType() for modifying an existing key without widening */ public function setOffsetValueType(?\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType, bool $unionValues = \true): \PHPStan\Type\Type; /** * Unlike setOffsetValueType(), assumes the key already exists. * Preserves the array shape and list 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; /** Models array_keys($array, $searchValue, $strict). */ public function getKeysArrayFiltered(\PHPStan\Type\Type $filterValueType, TrinaryLogic $strict): \PHPStan\Type\Type; /** Models array_keys($array). */ public function getKeysArray(): \PHPStan\Type\Type; /** Models array_values($array). */ public function getValuesArray(): \PHPStan\Type\Type; /** Models array_chunk($array, $length, $preserveKeys). */ public function chunkArray(\PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys): \PHPStan\Type\Type; /** Models array_fill_keys($keys, $value). */ public function fillKeysArray(\PHPStan\Type\Type $valueType): \PHPStan\Type\Type; /** Models array_flip($array). */ public function flipArray(): \PHPStan\Type\Type; /** Models array_intersect_key($array, ...$otherArrays). */ public function intersectKeyArray(\PHPStan\Type\Type $otherArraysType): \PHPStan\Type\Type; /** Models array_pop() effect on the array. */ public function popArray(): \PHPStan\Type\Type; /** Models array_reverse($array, $preserveKeys). */ public function reverseArray(TrinaryLogic $preserveKeys): \PHPStan\Type\Type; /** Models array_search($needle, $array, $strict). */ public function searchArray(\PHPStan\Type\Type $needleType, ?TrinaryLogic $strict = null): \PHPStan\Type\Type; /** Models array_shift() effect on the array. */ public function shiftArray(): \PHPStan\Type\Type; /** * Models shuffle() effect on the array. Result is always a list. * * It's also used to model array after `sort` / `rsort` / `usort` calls. */ public function shuffleArray(): \PHPStan\Type\Type; /** Models array_slice($array, $offset, $length, $preserveKeys). */ public function sliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys): \PHPStan\Type\Type; /** Models array_splice() effect on the array (the modified array, not the removed portion). */ public function spliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, \PHPStan\Type\Type $replacementType): \PHPStan\Type\Type; /** * Downgrades the list-ness of the array from `Yes` to `Maybe` (e.g. for * `asort`/`uksort`/etc. which preserve keys but break list ordering). * Other shape information (keys, values, accessories like NonEmpty) is * preserved. */ public function makeListMaybe(): \PHPStan\Type\Type; /** * Models "same keys, every value transformed" (e.g. `array_walk`, * `array_map($cb, $a)`, `preg_replace*` over an array subject). Keys * and accessories like list-ness / non-emptiness are preserved. * * @param callable(Type): Type $cb */ public function mapValueType(callable $cb): \PHPStan\Type\Type; /** * Replaces the iterable key type via `$cb($currentKeyType)`. For * `ArrayType` rewrites the key type wholesale; for `ConstantArrayType` * the explicit keys (which are already precise constants) are preserved * — pass-through, matching the prior `TypeTraverser`-based callers. * Used to widen / narrow the key type after a foreach narrowed `$key` * via `is_int($key)` / `is_string($key)` checks. * * @param callable(Type): Type $cb */ public function mapKeyType(callable $cb): \PHPStan\Type\Type; /** * Marks every explicit key in a `ConstantArrayType` as optional (the * shape can have any subset of the original keys). For non-`CAT` arrays * this is a no-op — they already model arbitrary subsets. Used by * `preg_replace*` over array subjects, where the callback can drop * entries. */ public function makeAllArrayKeysOptional(): \PHPStan\Type\Type; /** * Models `array_change_key_case($a, $case)`. String keys are case-folded * (constant ones to a specific value, general ones via accessories); * non-string keys, values, accessories and list-ness are preserved. * `$case` matches PHP's `CASE_LOWER` / `CASE_UPPER`; `null` means the * case is non-constant and the result is the union of both folds. */ public function changeKeyCaseArray(?int $case): \PHPStan\Type\Type; /** * Models `array_filter($a)` (no callback): drops entries whose value is * definitely falsey, marks possibly-falsey entries optional, keeps * definitely-truthy entries unchanged. Keys are preserved; list-ness * is downgraded since gaps may appear. */ public function filterArrayRemovingFalsey(): \PHPStan\Type\Type; /** @return list */ public function getEnumCases(): array; /** * Returns the single enum case this type represents, or null if not exactly one case. */ public function getEnumCaseObject(): ?EnumCaseObjectType; /** * Returns a list of finite values this type can take. * * 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; /** Models the ** operator. */ public function exponentiate(\PHPStan\Type\Type $exponent): \PHPStan\Type\Type; public function isCallable(): TrinaryLogic; /** @return list */ public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope): array; public function isCloneable(): TrinaryLogic; /** Models the (bool) cast. */ public function toBoolean(): \PHPStan\Type\BooleanType; /** Models numeric coercion for arithmetic operators. */ public function toNumber(): \PHPStan\Type\Type; /** Models the bitwise-not (`~$x`) operator. Returns `ErrorType` for types where `~` is undefined. */ public function toBitwiseNotType(): \PHPStan\Type\Type; /** * Models `get_class($x)`'s return type per leaf: definite objects yield * their `class-string` projection, definite non-objects yield `false`, * and possibly-objects yield the union of both. */ public function toGetClassResultType(): \PHPStan\Type\Type; /** * Models the type of `$x::class`. For known final classes the literal * class name is returned; for everything else an * `IntersectionType[ClassString, AccessoryLiteralStringType]`. * `NullType` passes through (mirrors PHP's nullsafe `::class` semantics). * `ReflectionProvider` is needed for the final-class lookup. */ public function toClassConstantType(ReflectionProvider $reflectionProvider): \PHPStan\Type\Type; /** * Projects a class-name-or-object `Type` (the right-hand side of * `$x instanceof `) to the `ObjectType` it should be compared * against. Constant class strings collapse to their `ObjectType` * exactly; everything kept symbolically (object class names, * `class-string`) carries an uncertainty flag so the caller can * fall back to `BooleanType` instead of a definite yes/no. */ public function toObjectTypeForInstanceofCheck(): \PHPStan\Type\ClassNameToObjectTypeResult; /** * Projects a class-name-or-object `Type` (the second argument of * `is_a($x, $class, $allow_string)`) to the `ObjectType` to narrow * `$x` against. When `$allowString` is true, the `is_a()` result also * keeps the original class-string accepted alongside the object. * `$allowSameClass` controls whether matching the input's own class * collapses to `NeverType` for final classes (the call site's * "always-true" suppression). */ public function toObjectTypeForIsACheck(\PHPStan\Type\Type $objectOrClassType, bool $allowString, bool $allowSameClass): \PHPStan\Type\ClassNameToObjectTypeResult; /** Models the (int) cast. */ public function toInteger(): \PHPStan\Type\Type; /** Models the (float) cast. */ public function toFloat(): \PHPStan\Type\Type; /** Models the (string) cast. */ public function toString(): \PHPStan\Type\Type; /** Models the (array) cast. */ public function toArray(): \PHPStan\Type\Type; /** * Models PHP's implicit array key coercion: floats truncated to int, * booleans become 0/1, null becomes '', numeric strings become int. */ public function toArrayKey(): \PHPStan\Type\Type; /** * Returns how this type might change when passed to a typed parameter * or assigned to a typed property. * * With $strictTypes = true: int widens to int|float (since int is accepted * by float parameters in strict mode). * With $strictTypes = false: additional coercions apply, e.g. Stringable * objects are accepted by string parameters. * * Used internally to determine what types a value might be coerced to * when checking parameter acceptance. */ public function toCoercedArgumentType(bool $strictTypes): self; public function isSmallerThan(\PHPStan\Type\Type $otherType, PhpVersion $phpVersion): TrinaryLogic; public function isSmallerThanOrEqual(\PHPStan\Type\Type $otherType, PhpVersion $phpVersion): TrinaryLogic; /** * Is Type of a known constant value? Includes literal strings, integers, floats, true, false, null, and array shapes. * * Unlike isConstantScalarValue(), this also returns yes for constant array types (array shapes * with known keys and values). Use this when you need to detect any constant value including arrays. */ public function isConstantValue(): TrinaryLogic; /** * Is Type of a known constant scalar value? Includes literal strings, integers, floats, true, false, and null. * * Unlike isConstantValue(), this does NOT return yes for array shapes. * Use this when you specifically need scalar constants only. */ 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; /** * Non-falsy string is a non-empty string that is also not '0'. * Stricter subset of non-empty-string. */ public function isNonFalsyString(): TrinaryLogic; /** * A literal-string is a string composed entirely from string literals * in the source code (not from user input). Used for SQL injection prevention. */ public function isLiteralString(): TrinaryLogic; public function isLowercaseString(): TrinaryLogic; public function isUppercaseString(): TrinaryLogic; public function isClassString(): TrinaryLogic; public function isVoid(): TrinaryLogic; public function isScalar(): TrinaryLogic; public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion): \PHPStan\Type\BooleanType; /** * Type narrowing methods for comparison operators. * For example, for ConstantIntegerType(5), getSmallerType() returns int. */ public function getSmallerType(PhpVersion $phpVersion): \PHPStan\Type\Type; public function getSmallerOrEqualType(PhpVersion $phpVersion): \PHPStan\Type\Type; public function getGreaterType(PhpVersion $phpVersion): \PHPStan\Type\Type; public function getGreaterOrEqualType(PhpVersion $phpVersion): \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 the real types of TemplateTypes found in $this, based on * the received Type. E.g. if $this is array and $receivedType * is array, infers T = int. */ 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 list */ public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance): array; /** Models abs(). */ public function toAbsoluteNumber(): \PHPStan\Type\Type; /** * Returns a new instance with all inner types mapped through $cb. * Returns the same instance if inner types did not change. * * Not used directly — use TypeTraverser::map() instead. * * @param callable(Type):Type $cb */ public function traverse(callable $cb): \PHPStan\Type\Type; /** * Like traverse(), but walks two types simultaneously. * * Not used directly — use SimultaneousTypeTraverser::map() instead. * * @param callable(Type $left, Type $right): Type $cb */ public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb): \PHPStan\Type\Type; public function toPhpDocNode(): TypeNode; /** @see TypeCombinator::remove() */ public function tryRemove(\PHPStan\Type\Type $typeToRemove): ?\PHPStan\Type\Type; /** * Removes constant value information. E.g. 'foo' -> string, 1 -> int. * Used when types become too complex to track precisely (e.g. loop iterations). */ public function generalize(\PHPStan\Type\GeneralizePrecision $precision): \PHPStan\Type\Type; /** * Performance optimization to skip template resolution when no templates are present. */ public function hasTemplateOrLateResolvableType(): bool; } 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 { return $this->resolvedType ??= $typeNodeResolver->resolve($this->typeNode, $this->nameScope); } } 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) > 0) { $result = []; foreach ($fromFiniteTypes as $finiteType) { foreach ($finiteTypesToRemove as $finiteTypeToRemove) { if ($finiteType->equals($finiteTypeToRemove)) { continue 2; } } $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(); } // Fast path for single non-union type if ($typesCount === 1) { $singleType = $types[0]; if (!$singleType instanceof \PHPStan\Type\UnionType && !$singleType->isArray()->yes()) { return $singleType; } } // Fast path for common 2-type cases if ($typesCount === 2) { $a = $types[0]; $b = $types[1]; // union(never, X) = X and union(X, never) = X if ($a instanceof \PHPStan\Type\NeverType && !$a->isExplicit()) { return $b; } if ($b instanceof \PHPStan\Type\NeverType && !$b->isExplicit()) { return $a; } // union(mixed, X) = mixed (non-explicit, non-template, no subtracted) if ($a instanceof \PHPStan\Type\MixedType && !$a->isExplicitMixed() && !$a instanceof TemplateMixedType && $a->getSubtractedType() === null) { return $a; } if ($b instanceof \PHPStan\Type\MixedType && !$b->isExplicitMixed() && !$b instanceof TemplateMixedType && $b->getSubtractedType() === null) { return $b; } // union(X, X) = X (same object identity) if ($a === $b) { return $a; } } $alreadyNormalized = []; $alreadyNormalizedCounter = 0; $benevolentTypes = []; $benevolentUnionObject = null; $neverCount = 0; // transform A | (B | C) to A | B | C for ($i = 0; $i < $typesCount; $i++) { if ($types[$i] instanceof \PHPStan\Type\MixedType && !$types[$i]->isExplicitMixed() && !$types[$i] instanceof TemplateMixedType && $types[$i]->getSubtractedType() === null) { return $types[$i]; } if ($types[$i] instanceof \PHPStan\Type\NeverType && !$types[$i]->isExplicit()) { $neverCount++; continue; } 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(); $alreadyNormalized[$alreadyNormalizedCounter] = $typesInner; $alreadyNormalizedCounter++; array_splice($types, $i, 1, $typesInner); $typesCount += count($typesInner) - 1; } // Bulk-remove implicit NeverTypes (skipped during the loop above) if ($neverCount > 0) { if ($neverCount === $typesCount) { return new \PHPStan\Type\NeverType(); } $filtered = []; for ($i = 0; $i < $typesCount; $i++) { if ($types[$i] instanceof \PHPStan\Type\NeverType && !$types[$i]->isExplicit()) { continue; } $filtered[] = $types[$i]; } $types = $filtered; $typesCount = count($types); if ($typesCount === 0) { return new \PHPStan\Type\NeverType(); } if ($typesCount === 1 && !$types[0]->isArray()->yes()) { return $types[0]; } if ($typesCount === 2) { return self::union($types[0], $types[1]); } } if ($typesCount === 0) { return new \PHPStan\Type\NeverType(); } if ($typesCount === 1 && !$types[0]->isArray()->yes()) { return $types[0]; } $arrayTypes = []; $scalarTypes = []; $hasGenericScalarTypes = []; $enumCaseTypes = []; $integerRangeTypes = []; for ($i = 0; $i < $typesCount; $i++) { if ($types[$i]->isConstantScalarValue()->yes()) { $type = $types[$i]; $scalarTypes[get_class($type)][$type->describe(\PHPStan\Type\VerbosityLevel::cache())] = $type; unset($types[$i]); continue; } if ($types[$i]->isBoolean()->yes()) { $hasGenericScalarTypes[ConstantBooleanType::class] = \true; } elseif ($types[$i]->isFloat()->yes()) { $hasGenericScalarTypes[ConstantFloatType::class] = \true; } elseif ($types[$i]->isInteger()->yes() && !$types[$i] instanceof \PHPStan\Type\IntegerRangeType) { $hasGenericScalarTypes[ConstantIntegerType::class] = \true; } elseif ($types[$i]->isString()->yes() && $types[$i]->isClassString()->no() && \PHPStan\Type\TypeUtils::getAccessoryTypes($types[$i]) === []) { $hasGenericScalarTypes[ConstantStringType::class] = \true; } else { $enumCase = $types[$i]->getEnumCaseObject(); if ($enumCase !== null) { $enumCaseTypes[$types[$i]->describe(\PHPStan\Type\VerbosityLevel::cache())] = $types[$i]; unset($types[$i]); continue; } } if ($types[$i] instanceof \PHPStan\Type\IntegerRangeType) { $integerRangeTypes[] = $types[$i]; unset($types[$i]); continue; } if (!$types[$i]->isArray()->yes()) { continue; } $arrayTypes[] = $types[$i]; unset($types[$i]); } $enumCaseTypes = array_values($enumCaseTypes); usort($integerRangeTypes, static fn(\PHPStan\Type\IntegerRangeType $a, \PHPStan\Type\IntegerRangeType $b): int => ($a->getMin() ?? PHP_INT_MIN) <=> ($b->getMin() ?? PHP_INT_MIN) ?: ($a->getMax() ?? PHP_INT_MAX) <=> ($b->getMax() ?? PHP_INT_MAX)); $types = array_merge($types, $integerRangeTypes); $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; } $scalarTypeItems = array_values($scalarTypeItems); $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--; $j = -1; 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++) { if (self::isAlreadyNormalized($alreadyNormalized, $types[$i], $types[$j])) { continue; } $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(array_values($types)); } return new \PHPStan\Type\BenevolentUnionType(array_values($types), \true); } } return new \PHPStan\Type\UnionType(array_values($types), \true); } /** * @param array $alreadyNormalized */ private static function isAlreadyNormalized(array $alreadyNormalized, \PHPStan\Type\Type $a, \PHPStan\Type\Type $b): bool { foreach ($alreadyNormalized as $normalizedTypes) { foreach ($normalizedTypes as $i => $normalizedType) { if ($normalizedType !== $a) { continue; } foreach ($normalizedTypes as $j => $anotherNormalizedType) { if ($i === $j) { continue; } if ($anotherNormalizedType === $b) { return \true; } } } } return \false; } /** * @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 instanceof \PHPStan\Type\IntersectionType && $b instanceof \PHPStan\Type\IntersectionType) { $merged = self::mergeIntersectionsForUnion($a, $b); if ($merged !== null) { return [$merged, 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) { if ($a->getValue() === '') { $description = $b->describe(\PHPStan\Type\VerbosityLevel::value()); if (in_array($description, ['non-empty-string', 'non-falsy-string'], \true)) { return [null, self::intersect(new \PHPStan\Type\StringType(), ...self::getAccessoryCaseStringTypes($b))]; } } if ($a->getValue() === '0') { $description = $b->describe(\PHPStan\Type\VerbosityLevel::value()); if ($description === 'non-falsy-string') { return [null, new \PHPStan\Type\IntersectionType([new \PHPStan\Type\StringType(), new AccessoryNonEmptyStringType(), ...self::getAccessoryCaseStringTypes($b)])]; } } } if ($b instanceof ConstantStringType) { if ($b->getValue() === '') { $description = $a->describe(\PHPStan\Type\VerbosityLevel::value()); if (in_array($description, ['non-empty-string', 'non-falsy-string'], \true)) { return [self::intersect(new \PHPStan\Type\StringType(), ...self::getAccessoryCaseStringTypes($a)), null]; } } if ($b->getValue() === '0') { $description = $a->describe(\PHPStan\Type\VerbosityLevel::value()); if ($description === 'non-falsy-string') { return [new \PHPStan\Type\IntersectionType([new \PHPStan\Type\StringType(), new AccessoryNonEmptyStringType(), ...self::getAccessoryCaseStringTypes($a)]), null]; } } } return null; } /** * @return list */ 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 ($subtractedType instanceof \PHPStan\Type\SubtractableType) { $withoutSubtracted = $subtractedType->getTypeWithoutSubtractedType(); if ($withoutSubtracted->isSuperTypeOf($type)->yes()) { $subtractedSubtractedType = $subtractedType->getSubtractedType(); if ($subtractedSubtractedType === null) { return new \PHPStan\Type\NeverType(); } return self::intersect($type, $subtractedSubtractedType); } } if ($type instanceof \PHPStan\Type\SubtractableType) { $subtractedType = $type->getSubtractedType() === null ? $subtractedType : self::union($type->getSubtractedType(), $subtractedType); $subtractedType = self::intersect($type->getTypeWithoutSubtractedType(), $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 || $b instanceof \PHPStan\Type\NeverType) { 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); } else { $isBAlreadySubtracted = $a->getSubtractedType()->isSuperTypeOf($b); if ($isBAlreadySubtracted->no()) { return $a; } elseif ($isBAlreadySubtracted->yes()) { $subtractedType = self::remove($a->getSubtractedType(), $b); if ($subtractedType instanceof \PHPStan\Type\NeverType || !$subtractedType->isSuperTypeOf($b)->no()) { $subtractedType = null; } return $a->changeSubtractedType($subtractedType); } 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 list */ private static function processArrayAccessoryTypes(array $arrayTypes): array { $isIterableAtLeastOnce = []; $accessoryTypes = []; foreach ($arrayTypes as $i => $arrayType) { $isIterableAtLeastOnce[] = $arrayType->isIterableAtLeastOnce(); 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) { $innerType = new HasOffsetValueType($innerType->getOffsetType(), $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()) { $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]; } if (TrinaryLogic::createYes()->and(...$isIterableAtLeastOnce)->yes()) { $commonAccessoryTypes[] = new NonEmptyArrayType(); } 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; foreach ($arrayTypes as $arrayType) { $constantArrays = $arrayType->getConstantArrays(); $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; } foreach ($constantArrays as $constantArray) { $valueTypes = $constantArray->getValueTypes(); foreach ($constantArray->getKeyTypes() as $i => $keyType) { $valueTypesForGeneralArray[] = $valueTypes[$i]; $keyTypeValue = $keyType->getValue(); if (array_key_exists($keyTypeValue, $constantKeyTypesNumbered)) { continue; } $keyTypesForGeneralArray[] = $keyType; $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)]; } $templateArrayType = null; foreach ($arrayTypes as $arrayType) { if (!$arrayType instanceof TemplateArrayType) { $templateArrayType = null; break; } if ($templateArrayType !== null) { continue; } $templateArrayType = $arrayType; } $arrayType = new \PHPStan\Type\ArrayType(self::union(...$keyTypesForGeneralArray), self::union(...self::optimizeConstantArrays($valueTypesForGeneralArray))); if ($templateArrayType !== null) { $arrayType = new TemplateArrayType($templateArrayType->getScope(), $templateArrayType->getStrategy(), $templateArrayType->getVariance(), $templateArrayType->getName(), $arrayType, $templateArrayType->getDefault()); } return [self::intersect($arrayType, ...$accessoryTypes)]; } $reducedArrayTypes = self::optimizeConstantArrays(self::reduceArrays($arrayTypes, \true)); foreach ($reducedArrayTypes as $idx => $reducedArray) { $applied = $accessoryTypes; if ($reducedArray->isIterableAtLeastOnce()->no()) { // Empty arrays cannot satisfy non-empty / oversized constraints — // applying those accessories would produce a contradictory intersection // (e.g. `array{}&oversized-array`) that rejects the very value it // represents, breaking the super-type contract of the union. $applied = array_values(array_filter($applied, static fn(\PHPStan\Type\Type $t): bool => !$t instanceof OversizedArrayType && !$t instanceof NonEmptyArrayType)); } $reducedArrayTypes[$idx] = self::intersect($reducedArray, ...$applied); } return $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; } // Stage 1: collapse same-key-set ConstantArrayType variants per-position // before the (lossy) generalization below kicks in. Variants with the // same key signature mergeWith losslessly into a single shape whose // values at each position are the union of the variants' values, which // drops the count while keeping the per-position structure. Without // this, a list of N similarly-shaped records (e.g. bug-7963) hits the // limit and the generalization decomposes every nested constant array // into a flat `non-empty-list`, losing the // shape entirely. $signatureGroups = []; $nonConstantTypes = []; foreach ($types as $idx => $type) { if (!$type instanceof ConstantArrayType) { $nonConstantTypes[$idx] = $type; continue; } $signatureParts = []; $signatureParts[] = $type->isList()->yes() ? 'L' : 'A'; foreach ($type->getKeyTypes() as $i => $keyType) { $signatureParts[] = ($type->isOptionalKey($i) ? '?' : '!') . ($keyType instanceof ConstantIntegerType ? 'i' : 's') . $keyType->getValue(); } $signatureGroups[implode(',', $signatureParts)][] = $type; } if ($signatureGroups !== []) { $collapsed = $nonConstantTypes; $anyMerged = \false; foreach ($signatureGroups as $group) { if (count($group) === 1) { $collapsed[] = $group[0]; continue; } $merged = $group[0]; for ($i = 1, $count = count($group); $i < $count; $i++) { $merged = $merged->mergeWith($group[$i]); } $collapsed[] = $merged; $anyMerged = \true; } if ($anyMerged) { $types = array_values($collapsed); $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; $innerValueTypes = $type->getValueTypes(); 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; // Inner traversal of the value position. Two subtleties, both // of which produced types that failed to be super-types of // their contributors: // - Empty constant arrays must be left alone; wrapping them // builds a contradictory `array{}&oversized-array`. // - Fall through via `$innerTraverse`, not the outer // `$traverse`. The outer callback fully generalizes a // sealed `ConstantArrayType` into `array&...`, // which is correct at the top level but wrong inside a // value position: it would treat a sealed `array{a: 1}` // reached via `array{}|array{a: 1}` differently from one // reached directly, leaving `processArrayTypes` with a // mix of shapes it cannot unify cleanly. $generalizedValueType = \PHPStan\Type\TypeTraverser::map($innerValueTypes[$i], static function (\PHPStan\Type\Type $type, callable $innerTraverse): \PHPStan\Type\Type { if ($type instanceof ConstantArrayType && $type->isIterableAtLeastOnce()->no()) { return $type; } if ($type instanceof \PHPStan\Type\ArrayType || $type instanceof ConstantArrayType) { return new \PHPStan\Type\IntersectionType([$type, new OversizedArrayType()]); } if ($type instanceof \PHPStan\Type\ConstantScalarType) { return $type->generalize(\PHPStan\Type\GeneralizePrecision::moreSpecific()); } return $innerTraverse($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)); $accessories = []; if ($isList) { $accessories[] = new AccessoryArrayListType(); } $accessories[] = new NonEmptyArrayType(); $accessories[] = new OversizedArrayType(); return self::intersect(new \PHPStan\Type\ArrayType($keyType, $valueType), ...$accessories); }); if (!$isOversized) { $eachIsOversized = \false; } $results[] = $result; } if ($eachIsOversized) { $eachIsList = \true; $keyTypes = []; $valueTypes = []; foreach ($results as $result) { $keyTypes[] = $result->getIterableKeyType(); $valueTypes[] = $result->getIterableValueType(); if ($result->isList()->yes()) { continue; } $eachIsList = \false; } $keyType = self::union(...$keyTypes); $valueType = self::union(...$valueTypes); if ($valueType instanceof \PHPStan\Type\UnionType && count($valueType->getTypes()) > ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT) { $valueType = $valueType->generalize(\PHPStan\Type\GeneralizePrecision::lessSpecific()); } $accessories = []; if ($eachIsList) { $accessories[] = new AccessoryArrayListType(); } $accessories[] = new NonEmptyArrayType(); $accessories[] = new OversizedArrayType(); return [self::intersect(new \PHPStan\Type\ArrayType($keyType, $valueType), ...$accessories)]; } 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]] ??= 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; } // Merge two single-key arrays sharing the same key when their value // types union into a single type (not a UnionType). This is lossless // and prevents exponential union growth when narrowing nested // ArrayDimFetch expressions on a ConstantArrayType parent (see // phpstan/phpstan#14462). if ($preserveTaggedUnions && $overlappingKeysCount === 1 && count($arraysToProcess[$i]->getKeyTypes()) === 1 && count($arraysToProcess[$j]->getKeyTypes()) === 1) { $iValueType = $arraysToProcess[$i]->getValueTypes()[0]; $jValueType = $arraysToProcess[$j]->getValueTypes()[0]; $unionValueType = self::union($iValueType, $jValueType); if (!$unionValueType instanceof \PHPStan\Type\UnionType) { $arraysToProcess[$j] = $arraysToProcess[$j]->mergeWith($arraysToProcess[$i]); unset($arraysToProcess[$i]); continue 2; } } 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; } } } // Final pass: collapse the loop-accumulator pattern where each iteration // produced a longer non-empty list variant. When several non-empty list // ConstantArrayTypes survive earlier merging and together push the // constant-array value count past the limit, fold them into a single // non-empty-list so the result stays bounded without // going through the lossier optimizeConstantArrays generalization. // Skip when every list variant shares one key signature — those collapse // losslessly via the stage 1 same-key-set merge in optimizeConstantArrays // (each position keeps its own value union), which is strictly more // precise than this flat fold. if ($preserveTaggedUnions && count($arraysToProcess) > 1) { $listVariantIndices = []; $listValueTypes = []; $listVariants = []; $listVariantSignatures = []; foreach ($arraysToProcess as $idx => $arr) { if (!$arr->isList()->yes() || !$arr->isIterableAtLeastOnce()->yes()) { continue; } $listVariantIndices[] = $idx; $listValueTypes[] = $arr->getIterableValueType(); $listVariants[] = $arr; $signatureParts = []; foreach ($arr->getKeyTypes() as $i => $keyType) { $signatureParts[] = ($arr->isOptionalKey($i) ? '?' : '!') . ($keyType instanceof ConstantIntegerType ? 'i' : 's') . $keyType->getValue(); } $listVariantSignatures[implode(',', $signatureParts)] = \true; } if (count($listVariantIndices) >= 2 && count($listVariantSignatures) >= 2 && self::countConstantArrayValueTypes($listVariants) > ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT) { $mergedValueType = self::union(...$listValueTypes); $merged = self::intersect(new \PHPStan\Type\ArrayType(new \PHPStan\Type\IntegerType(), $mergedValueType), new NonEmptyArrayType(), new AccessoryArrayListType()); $newArrays[] = $merged; foreach ($listVariantIndices as $idx) { unset($arraysToProcess[$idx]); } } } return array_merge($newArrays, $arraysToProcess); } public static function intersect(\PHPStan\Type\Type ...$types): \PHPStan\Type\Type { $typesCount = count($types); if ($typesCount === 0) { return new \PHPStan\Type\NeverType(); } $types = array_values($types); if ($typesCount === 1) { return $types[0]; } foreach ($types as $type) { if ($type instanceof \PHPStan\Type\NeverType && !$type->isExplicit()) { return $type; } } $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; } $newTypes = []; $hasOffsetValueTypeCount = 0; $typesCount = count($types); for ($i = 0; $i < $typesCount; $i++) { $type = $types[$i]; if ($type instanceof \PHPStan\Type\IntersectionType && !$type instanceof TemplateType) { // transform A & (B & C) to A & B & C array_splice($types, $i--, 1, $type->getTypes()); $typesCount = count($types); } elseif ($type instanceof HasOffsetValueType) { $hasOffsetValueTypeCount++; } else { $newTypes[] = $type; } } 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 losing 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 AccessoryArrayListType) { $types[$i] = $types[$i]->makeList(); array_splice($types, $j--, 1); $typesCount--; continue; } if ($types[$j] instanceof ConstantArrayType && $types[$i] instanceof AccessoryArrayListType) { $types[$j] = $types[$j]->makeList(); array_splice($types, $i--, 1); $typesCount--; continue 2; } if ($types[$i] instanceof ConstantArrayType && $types[$j] instanceof NonEmptyArrayType && (count($types[$i]->getKeyTypes()) === 1 || $types[$i]->isList()->yes()) && $types[$i]->isOptionalKey(0)) { $types[$i] = $types[$i]->makeOffsetRequired($types[$i]->getKeyTypes()[0]); array_splice($types, $j--, 1); $typesCount--; continue; } if ($types[$j] instanceof ConstantArrayType && $types[$i] instanceof NonEmptyArrayType && (count($types[$j]->getKeyTypes()) === 1 || $types[$j]->isList()->yes()) && $types[$j]->isOptionalKey(0)) { $types[$j] = $types[$j]->makeOffsetRequired($types[$j]->getKeyTypes()[0]); 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 || $types[$j] instanceof ConstantArrayType)) { $newArray = ConstantArrayTypeBuilder::createEmpty(); $valueTypes = $types[$i]->getValueTypes(); foreach ($types[$i]->getKeyTypes() as $k => $keyType) { $hasOffset = $types[$j]->hasOffsetValueType($keyType); if ($hasOffset->no()) { continue; } $newArray->setOffsetValueType(self::intersect($keyType, $types[$j]->getIterableKeyType()), self::intersect($valueTypes[$k], $types[$j]->getOffsetValueType($keyType)), $types[$i]->isOptionalKey($k) && !$hasOffset->yes()); } $types[$i] = $newArray->getArray(); array_splice($types, $j--, 1); $typesCount--; continue 2; } if ($types[$j] instanceof ConstantArrayType && ($types[$i] instanceof \PHPStan\Type\ArrayType || $types[$i] instanceof ConstantArrayType)) { $newArray = ConstantArrayTypeBuilder::createEmpty(); $valueTypes = $types[$j]->getValueTypes(); foreach ($types[$j]->getKeyTypes() as $k => $keyType) { $hasOffset = $types[$i]->hasOffsetValueType($keyType); if ($hasOffset->no()) { continue; } $newArray->setOffsetValueType(self::intersect($keyType, $types[$i]->getIterableKeyType()), self::intersect($valueTypes[$k], $types[$i]->getOffsetValueType($keyType)), $types[$j]->isOptionalKey($k) && !$hasOffset->yes()); } $types[$j] = $newArray->getArray(); array_splice($types, $i--, 1); $typesCount--; continue 2; } if (($types[$i] instanceof \PHPStan\Type\ArrayType || $types[$i] instanceof ConstantArrayType || $types[$i] instanceof \PHPStan\Type\IterableType) && ($types[$j] instanceof \PHPStan\Type\ArrayType || $types[$j] instanceof ConstantArrayType || $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]; } $accessoryBaseTypes = []; foreach ($types as $type) { if (!$type instanceof AccessoryType) { $accessoryBaseTypes = null; break; } $accessoryBaseTypes[] = $type->getDefaultBaseType(); } if ($accessoryBaseTypes !== null) { // Accessory types never stand alone — supply the base type they refine. return self::intersect(self::intersect(...$accessoryBaseTypes), ...$types); } return new \PHPStan\Type\IntersectionType($types); } /** * Merge two IntersectionTypes that have the same structure but differ * in HasOffsetValueType value types (matched by offset key). * * E.g. (A & hasOV('k', X)) | (A & hasOV('k', Y)) → (A & hasOV('k', X|Y)) */ private static function mergeIntersectionsForUnion(\PHPStan\Type\IntersectionType $a, \PHPStan\Type\IntersectionType $b): ?\PHPStan\Type\Type { $aTypes = $a->getTypes(); $bTypes = $b->getTypes(); if (count($aTypes) !== count($bTypes)) { return null; } $mergedTypes = []; $hasDifference = \false; $bUsed = array_fill(0, count($bTypes), \false); foreach ($aTypes as $aType) { $matched = \false; foreach ($bTypes as $bIdx => $bType) { if ($bUsed[$bIdx]) { continue; } if ($aType->equals($bType)) { $mergedTypes[] = $aType; $bUsed[$bIdx] = \true; $matched = \true; break; } // HasOffsetValueType: merge value types when offset keys match if ($aType instanceof HasOffsetValueType && $bType instanceof HasOffsetValueType && $aType->getOffsetType()->equals($bType->getOffsetType())) { $mergedTypes[] = new HasOffsetValueType($aType->getOffsetType(), self::union($aType->getValueType(), $bType->getValueType())); $hasDifference = \true; $bUsed[$bIdx] = \true; $matched = \true; break; } // HasOffsetType, HasMethodType, HasPropertyType: only equal values match (no merging possible) } if (!$matched) { return null; } } if (!$hasDifference) { return null; } $result = $mergedTypes[0]; for ($i = 1, $count = count($mergedTypes); $i < $count; $i++) { $result = self::intersect($result, $mergedTypes[$i]); } return $result; } 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()); } } * @readonly */ public array $reasons; /** * @param T $type * @param list $reasons */ public function __construct(\PHPStan\Type\Type $type, array $reasons) { $this->type = $type; $this->reasons = $reasons; } } getValue()); * } * // Replaces the current type, and don't traverse * return new MixedType(); * }); * * @api * @param TypeTraverserCallable|callable(Type $type, callable(Type): Type $traverse): Type $cb */ public static function map(\PHPStan\Type\Type $type, $cb): \PHPStan\Type\Type { $self = new self($cb); return $self->mapInternal($type); } /** @param TypeTraverserCallable|callable(Type $type, callable(Type): Type $traverse): Type $cb */ private function __construct($cb) { if ($cb instanceof \PHPStan\Type\TypeTraverserCallable) { $this->cb = static fn(\PHPStan\Type\Type $type, callable $traverse): \PHPStan\Type\Type => $cb->traverse($type, $traverse); } else { $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']); } } */ public static function getConstantIntegers(\PHPStan\Type\Type $type): array { return self::map(ConstantIntegerType::class, $type, \false); } /** * @return list */ public static function getIntegerRanges(\PHPStan\Type\Type $type): array { return self::map(\PHPStan\Type\IntegerRangeType::class, $type, \false); } /** * @return list */ 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 \PHPStan\Type\UnionType) { $types = []; foreach ($type->getTypes() as $innerType) { $flattenTypes = self::flattenTypes($innerType); foreach ($flattenTypes as $flattenType) { $types[] = $flattenType; } } return $types; } $constantArrays = $type->getConstantArrays(); if ($constantArrays !== []) { // Estimate the total number of power-set variants before expanding. // Each ConstantArrayType with N optional keys produces 2^N variants // from getAllArrays(). The cartesian product across multiple constant // arrays multiplies these counts. Bail out to avoid O(2^N) allocation // when the total would be large. $estimatedCount = 1; $bail = \false; foreach ($constantArrays as $constantArray) { $optionalCount = count($constantArray->getOptionalKeys()); $arrayCount = $optionalCount <= 20 ? 1 << $optionalCount : PHP_INT_MAX; if ($arrayCount > 16384 || $estimatedCount > 16384 / max($arrayCount, 1)) { $bail = \true; break; } $estimatedCount *= $arrayCount; } if ($bail) { return [$type]; } $newTypes = []; foreach ($constantArrays as $constantArray) { $newTypes[] = $constantArray->getAllArrays(); } $result = []; foreach (CombinationsHelper::combinations($newTypes) as $combination) { $intersected = $combination[0]; for ($i = 1, $count = count($combination); $i < $count; $i++) { $intersected = \PHPStan\Type\TypeCombinator::intersect($intersected, $combination[$i]); } if ($intersected instanceof \PHPStan\Type\NeverType) { continue; } $result[] = $intersected; } return $result; } 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; } public static function findCallableType(\PHPStan\Type\Type $type): ?\PHPStan\Type\Type { if ($type->isCallable()->yes()) { return $type; } if ($type instanceof \PHPStan\Type\UnionType) { foreach ($type->getTypes() as $innerType) { $callableType = self::findCallableType($innerType); if ($callableType !== null) { return $callableType; } } } 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 list */ public static function getAccessoryTypes(\PHPStan\Type\Type $type): array { return self::map(AccessoryType::class, $type, \true, \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 { if (!$type->hasTemplateOrLateResolvableType()) { return $type; } return \PHPStan\Type\TypeTraverser::map($type, new LateResolvableTraverser($resolveUnresolvableTypes)); } } getObjectClassNames()` or `$type->isObject()` instead, which correctly * handles union types and intersection types. * * @api * @api-do-not-implement */ interface TypeWithClassName extends \PHPStan\Type\Type { public function getClassName(): string; /** * Returns this type projected onto an ancestor class, preserving generic type arguments. */ public function getAncestorWithClassName(string $className): ?self; public function getClassReflection(): ?ClassReflection; } getItemType(); } return $phpDocType ?? new \PHPStan\Type\MixedType(); } if ($reflectionType instanceof ReflectionUnionType) { $type = \PHPStan\Type\TypeCombinator::union(...array_map(static fn(ReflectionType $type): \PHPStan\Type\Type => self::decideTypeFromReflection($type, \null, $selfClass), $reflectionType->getTypes())); return self::decideType($type, $phpDocType); } if ($reflectionType instanceof ReflectionIntersectionType) { $types = []; foreach ($reflectionType->getTypes() as $innerReflectionType) { $innerType = self::decideTypeFromReflection($innerReflectionType, \null, $selfClass); 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))); } if ($reflectionType->isIdentifier()) { $typeNode = new Identifier($reflectionType->getName()); } else { $typeNode = new FullyQualified($reflectionType->getName()); } $type = \PHPStan\Type\ParserNodeTypeToPHPStanType::resolve($typeNode, $selfClass); if ($reflectionType->allowsNull()) { $type = \PHPStan\Type\TypeCombinator::addNull($type); } return self::decideType($type, $phpDocType); } public static function decideType(\PHPStan\Type\Type $type, ?\PHPStan\Type\Type $phpDocType): \PHPStan\Type\Type { if ($phpDocType !== null && $type->isNull()->no()) { $phpDocType = \PHPStan\Type\TypeCombinator::removeNull($phpDocType); } 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 && $innerType->getKeyType()->describe(\PHPStan\Type\VerbosityLevel::typeOnly()) === 'mixed') { $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->getKeyType()->describe(\PHPStan\Type\VerbosityLevel::typeOnly()) === 'mixed') { $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; } } extensions = $extensions; } /** * @return UnaryOperatorTypeSpecifyingExtension[] */ private function getOperatorTypeSpecifyingExtensions(string $operator, \PHPStan\Type\Type $operandType): array { return array_values(array_filter($this->extensions, static fn(\PHPStan\Type\UnaryOperatorTypeSpecifyingExtension $extension): bool => $extension->isOperatorSupported($operator, $operandType))); } public function callUnaryOperatorTypeSpecifyingExtensions(string $operatorSigil, \PHPStan\Type\Type $operandType): ?\PHPStan\Type\Type { $operatorTypeSpecifyingExtensions = $this->getOperatorTypeSpecifyingExtensions($operatorSigil, $operandType); /** @var list $extensionTypes */ $extensionTypes = []; foreach ($operatorTypeSpecifyingExtensions as $extension) { $extensionTypes[] = $extension->specifyType($operatorSigil, $operandType); } if (count($extensionTypes) > 0) { return \PHPStan\Type\TypeCombinator::union(...$extensionTypes); } return null; } } */ private array $types; private bool $normalized; use NonGeneralizableTypeTrait; public const EQUAL_UNION_CLASSES = [DateTimeInterface::class => [DateTimeImmutable::class, DateTime::class], Throwable::class => [Error::class, Exception::class]]; private bool $sortedTypes = \false; /** @var array */ private array $cachedDescriptions = []; /** * @api * @param list $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 fn(\PHPStan\Type\Type $type): string => $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 list */ 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 list */ protected 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 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 fn(\PHPStan\Type\Type $type) => $type->getObjectClassNames(), static fn(\PHPStan\Type\Type $type) => $type->isObject()->yes()))); } public function getObjectClassReflections(): array { return $this->pickFromTypes(static fn(\PHPStan\Type\Type $type) => $type->getObjectClassReflections(), static fn(\PHPStan\Type\Type $type) => $type->isObject()->yes()); } public function getArrays(): array { return $this->pickFromTypes(static fn(\PHPStan\Type\Type $type) => $type->getArrays(), static fn(\PHPStan\Type\Type $type) => $type->isArray()->yes()); } public function getConstantArrays(): array { return $this->pickFromTypes(static fn(\PHPStan\Type\Type $type) => $type->getConstantArrays(), static fn(\PHPStan\Type\Type $type) => $type->isArray()->yes()); } public function getConstantStrings(): array { return $this->pickFromTypes(static fn(\PHPStan\Type\Type $type) => $type->getConstantStrings(), static fn(\PHPStan\Type\Type $type) => $type->isString()->yes()); } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes): \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\IterableType) { return $this->accepts($type->toArrayOrTraversable(), $strictTypes); } foreach (self::EQUAL_UNION_CLASSES as $baseClass => $classes) { if (!$type->equals(new \PHPStan\Type\ObjectType($baseClass))) { continue; } $union = \PHPStan\Type\TypeCombinator::union(...array_map(static fn(string $objectClass): \PHPStan\Type\Type => new \PHPStan\Type\ObjectType($objectClass), $classes)); if ($this->accepts($union, $strictTypes)->yes()) { return \PHPStan\Type\AcceptsResult::createYes(); } break; } $innerAccepts = []; $result = \PHPStan\Type\AcceptsResult::createNo(); foreach ($this->getSortedTypes() as $i => $innerType) { $innerResult = $innerType->accepts($type, $strictTypes); $innerAccepts[$i] = $innerResult; $result = $result->or($innerResult->decorateReasons(static fn(string $reason) => sprintf('Type #%d from the union: %s', $i + 1, $reason))); } if ($result->yes()) { return $result; } $commonReasons = null; foreach ($innerAccepts as $innerResult) { if ($commonReasons === null) { $commonReasons = $innerResult->reasons; continue; } $commonReasons = array_values(array_intersect($commonReasons, $innerResult->reasons)); } if ($commonReasons !== null && count($commonReasons) > 0) { $decorated = []; foreach (array_keys($innerAccepts) as $i) { foreach ($commonReasons as $reason) { $decorated[] = sprintf('Type #%d from the union: %s', $i + 1, $reason); } } $result = new \PHPStan\Type\AcceptsResult($result->result, $decorated); } if ($type instanceof \PHPStan\Type\CompoundType && !$type instanceof \PHPStan\Type\CallableType && !$type instanceof TemplateType && !$type instanceof \PHPStan\Type\IntersectionType) { return $type->isAcceptedBy($this, $strictTypes); } if ($type instanceof TemplateUnionType) { return $result->or($type->isAcceptedBy($this, $strictTypes)); } if ($type->isEnum()->yes() && !$this->isEnum()->no()) { $enumCasesUnion = \PHPStan\Type\TypeCombinator::union(...$type->getEnumCases()); if (!$type->equals($enumCasesUnion)) { return $this->accepts($enumCasesUnion, $strictTypes); } } return $result; } public function isSuperTypeOf(\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\IntegerRangeType) { return $otherType->isSubTypeOf($this); } $results = []; foreach ($this->types as $innerType) { $result = $innerType->isSuperTypeOf($otherType); if ($result->yes()) { return $result; } $results[] = $result; } $result = \PHPStan\Type\IsSuperTypeOfResult::createNo()->or(...$results); if ($otherType instanceof TemplateUnionType || $otherType instanceof \PHPStan\Type\LateResolvableType && $otherType instanceof \PHPStan\Type\CompoundType && !$otherType instanceof TemplateType) { return $result->or($otherType->isSubTypeOf($this)); } return $result; } public function isSubTypeOf(\PHPStan\Type\Type $otherType): \PHPStan\Type\IsSuperTypeOfResult { return \PHPStan\Type\IsSuperTypeOfResult::extremeIdentity(...array_map(static fn(\PHPStan\Type\Type $innerType) => $otherType->isSuperTypeOf($innerType), $this->types)); } public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes): \PHPStan\Type\AcceptsResult { return \PHPStan\Type\AcceptsResult::extremeIdentity(...array_map(static fn(\PHPStan\Type\Type $innerType) => $acceptingType->accepts($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)', $intersectionDescription); } else { $typeNames[] = $intersectionDescription; } } else { $typeNames[] = $type->describe($level); } } if ($level->isPrecise() || $level->isCache()) { $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]); }, fn(): string => $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 fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getTemplateType($ancestorClassName, $templateTypeName)); } public function isObject(): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isObject()); } public function getClassStringType(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getClassStringType()); } public function isEnum(): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isEnum()); } public function canAccessProperties(): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->canAccessProperties()); } public function hasProperty(string $propertyName): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->hasProperty($propertyName)); } public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { 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 MissingPropertyFromReflectionException($this->describe(\PHPStan\Type\VerbosityLevel::typeOnly()), $propertyName); } if ($propertiesCount === 1) { return $propertyPrototypes[0]; } return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes); } public function hasInstanceProperty(string $propertyName): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->hasInstanceProperty($propertyName)); } public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $propertyPrototypes = []; foreach ($this->types as $type) { if (!$type->hasInstanceProperty($propertyName)->yes()) { continue; } $propertyPrototypes[] = $type->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->withFechedOnType($this); } $propertiesCount = count($propertyPrototypes); if ($propertiesCount === 0) { throw new MissingPropertyFromReflectionException($this->describe(\PHPStan\Type\VerbosityLevel::typeOnly()), $propertyName); } if ($propertiesCount === 1) { return $propertyPrototypes[0]; } return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes); } public function hasStaticProperty(string $propertyName): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->hasStaticProperty($propertyName)); } public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedStaticPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection { $propertyPrototypes = []; foreach ($this->types as $type) { if (!$type->hasStaticProperty($propertyName)->yes()) { continue; } $propertyPrototypes[] = $type->getUnresolvedStaticPropertyPrototype($propertyName, $scope)->withFechedOnType($this); } $propertiesCount = count($propertyPrototypes); if ($propertiesCount === 0) { throw new MissingPropertyFromReflectionException($this->describe(\PHPStan\Type\VerbosityLevel::typeOnly()), $propertyName); } if ($propertiesCount === 1) { return $propertyPrototypes[0]; } return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes); } public function canCallMethods(): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->canCallMethods()); } public function hasMethod(string $methodName): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $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; } $prototype = $type->getUnresolvedMethodPrototype($methodName, $scope); if ($this instanceof TemplateType) { $prototype = $prototype->withCalledOnType($this); } $methodPrototypes[] = $prototype; } $methodsCount = count($methodPrototypes); if ($methodsCount === 0) { throw new MissingMethodFromReflectionException($this->describe(\PHPStan\Type\VerbosityLevel::typeOnly()), $methodName); } if ($methodsCount === 1) { return $methodPrototypes[0]; } return new UnionTypeUnresolvedMethodPrototypeReflection($methodName, $methodPrototypes); } public function canAccessConstants(): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->canAccessConstants()); } public function hasConstant(string $constantName): TrinaryLogic { return $this->hasInternal(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->canAccessConstants(), static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->hasConstant($constantName)); } public function getConstant(string $constantName): ClassConstantReflection { return $this->getInternal(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->hasConstant($constantName), static fn(\PHPStan\Type\Type $type): ClassConstantReflection => $type->getConstant($constantName)); } public function isIterable(): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isIterable()); } public function isIterableAtLeastOnce(): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isIterableAtLeastOnce()); } public function getArraySize(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getArraySize()); } public function getIterableKeyType(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getIterableKeyType()); } public function getFirstIterableKeyType(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getIterableKeyType()); } public function getLastIterableKeyType(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getIterableKeyType()); } public function getIterableValueType(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getIterableValueType()); } public function getFirstIterableValueType(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getIterableValueType()); } public function getLastIterableValueType(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getIterableValueType()); } public function isArray(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isArray()); } public function isConstantArray(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isConstantArray()); } public function isOversizedArray(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isOversizedArray()); } public function isList(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isList()); } public function isString(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isString()); } public function isNumericString(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isNumericString()); } public function isNonEmptyString(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isNonEmptyString()); } public function isNonFalsyString(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isNonFalsyString()); } public function isLiteralString(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isLiteralString()); } public function isLowercaseString(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isLowercaseString()); } public function isUppercaseString(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isUppercaseString()); } public function isClassString(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isClassString()); } public function getClassStringObjectType(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getClassStringObjectType()); } public function getObjectTypeOrClassStringObjectType(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getObjectTypeOrClassStringObjectType()); } public function isVoid(): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isVoid()); } public function isScalar(): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isScalar()); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion): \PHPStan\Type\BooleanType { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $innerType): TrinaryLogic => $innerType->looseCompare($type, $phpVersion)->toTrinaryLogic())->toBooleanType(); } public function isOffsetAccessible(): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isOffsetAccessible()); } public function isOffsetAccessLegal(): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isOffsetAccessLegal()); } public function hasOffsetValueType(\PHPStan\Type\Type $offsetType): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $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 fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->setOffsetValueType($offsetType, $valueType, $unionValues)); } public function setExistingOffsetValueType(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->setExistingOffsetValueType($offsetType, $valueType)); } public function unsetOffset(\PHPStan\Type\Type $offsetType): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->unsetOffset($offsetType)); } public function getKeysArrayFiltered(\PHPStan\Type\Type $filterValueType, TrinaryLogic $strict): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getKeysArrayFiltered($filterValueType, $strict)); } public function getKeysArray(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getKeysArray()); } public function getValuesArray(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getValuesArray()); } public function chunkArray(\PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->chunkArray($lengthType, $preserveKeys)); } public function fillKeysArray(\PHPStan\Type\Type $valueType): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->fillKeysArray($valueType)); } public function flipArray(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->flipArray()); } public function intersectKeyArray(\PHPStan\Type\Type $otherArraysType): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->intersectKeyArray($otherArraysType)); } public function popArray(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->popArray()); } public function reverseArray(TrinaryLogic $preserveKeys): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->reverseArray($preserveKeys)); } public function searchArray(\PHPStan\Type\Type $needleType, ?TrinaryLogic $strict = null): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->searchArray($needleType, $strict)); } public function shiftArray(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->shiftArray()); } public function shuffleArray(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->shuffleArray()); } public function sliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->sliceArray($offsetType, $lengthType, $preserveKeys)); } public function spliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, \PHPStan\Type\Type $replacementType): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->spliceArray($offsetType, $lengthType, $replacementType)); } public function makeListMaybe(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->makeListMaybe()); } public function mapValueType(callable $cb): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->mapValueType($cb)); } public function mapKeyType(callable $cb): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->mapKeyType($cb)); } public function makeAllArrayKeysOptional(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->makeAllArrayKeysOptional()); } public function changeKeyCaseArray(?int $case): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->changeKeyCaseArray($case)); } public function filterArrayRemovingFalsey(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->filterArrayRemovingFalsey()); } public function getEnumCases(): array { return $this->pickFromTypes(static fn(\PHPStan\Type\Type $type) => $type->getEnumCases(), static fn(\PHPStan\Type\Type $type) => $type->isObject()->yes()); } public function getEnumCaseObject(): ?EnumCaseObjectType { $cases = $this->getEnumCases(); if (count($cases) === 1) { return $cases[0]; } return null; } public function isCallable(): TrinaryLogic { return $this->unionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $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 fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isCloneable()); } public function isSmallerThan(\PHPStan\Type\Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isSmallerThan($otherType, $phpVersion)); } public function isSmallerThanOrEqual(\PHPStan\Type\Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isSmallerThanOrEqual($otherType, $phpVersion)); } public function isNull(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isNull()); } public function isConstantValue(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isConstantValue()); } public function isConstantScalarValue(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isConstantScalarValue()); } public function getConstantScalarTypes(): array { return $this->notBenevolentPickFromTypes(static fn(\PHPStan\Type\Type $type) => $type->getConstantScalarTypes()); } public function getConstantScalarValues(): array { return $this->notBenevolentPickFromTypes(static fn(\PHPStan\Type\Type $type) => $type->getConstantScalarValues()); } public function isTrue(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isTrue()); } public function isFalse(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isFalse()); } public function isBoolean(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isBoolean()); } public function isFloat(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isFloat()); } public function isInteger(): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $type->isInteger()); } public function getSmallerType(PhpVersion $phpVersion): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getSmallerType($phpVersion)); } public function getSmallerOrEqualType(PhpVersion $phpVersion): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getSmallerOrEqualType($phpVersion)); } public function getGreaterType(PhpVersion $phpVersion): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getGreaterType($phpVersion)); } public function getGreaterOrEqualType(PhpVersion $phpVersion): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->getGreaterOrEqualType($phpVersion)); } public function isGreaterThan(\PHPStan\Type\Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $otherType->isSmallerThan($type, $phpVersion)); } public function isGreaterThanOrEqual(\PHPStan\Type\Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return $this->notBenevolentUnionResults(static fn(\PHPStan\Type\Type $type): TrinaryLogic => $otherType->isSmallerThanOrEqual($type, $phpVersion)); } public function toBoolean(): \PHPStan\Type\BooleanType { /** @var BooleanType $type */ $type = $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\BooleanType => $type->toBoolean()); return $type; } public function toNumber(): \PHPStan\Type\Type { $type = $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toNumber()); return $type; } public function toBitwiseNotType(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toBitwiseNotType()); } public function toGetClassResultType(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toGetClassResultType()); } public function toClassConstantType(ReflectionProvider $reflectionProvider): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toClassConstantType($reflectionProvider)); } public function toObjectTypeForInstanceofCheck(): \PHPStan\Type\ClassNameToObjectTypeResult { $types = []; $uncertainty = \false; foreach ($this->getTypes() as $innerType) { $result = $innerType->toObjectTypeForInstanceofCheck(); $types[] = $result->type; if (!$result->uncertainty) { continue; } $uncertainty = \true; } return new \PHPStan\Type\ClassNameToObjectTypeResult(\PHPStan\Type\TypeCombinator::union(...$types), $uncertainty); } public function toObjectTypeForIsACheck(\PHPStan\Type\Type $objectOrClassType, bool $allowString, bool $allowSameClass): \PHPStan\Type\ClassNameToObjectTypeResult { $types = []; $uncertainty = \false; foreach ($this->getTypes() as $innerType) { $result = $innerType->toObjectTypeForIsACheck($objectOrClassType, $allowString, $allowSameClass); $types[] = $result->type; if (!$result->uncertainty) { continue; } $uncertainty = \true; } return new \PHPStan\Type\ClassNameToObjectTypeResult(\PHPStan\Type\TypeCombinator::union(...$types), $uncertainty); } public function toAbsoluteNumber(): \PHPStan\Type\Type { $type = $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toAbsoluteNumber()); return $type; } public function toString(): \PHPStan\Type\Type { $type = $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toString()); return $type; } public function toInteger(): \PHPStan\Type\Type { $type = $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toInteger()); return $type; } public function toFloat(): \PHPStan\Type\Type { $type = $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toFloat()); return $type; } public function toArray(): \PHPStan\Type\Type { $type = $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toArray()); return $type; } public function toArrayKey(): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toArrayKey()); } public function toCoercedArgumentType(bool $strictTypes): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->toCoercedArgumentType($strictTypes)); } public function inferTemplateTypes(\PHPStan\Type\Type $receivedType): TemplateTypeMap { if ($receivedType instanceof \PHPStan\Type\IterableType) { $receivedType = $receivedType->toArrayOrTraversable(); } $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 { $rightTypes = \PHPStan\Type\TypeUtils::flattenTypes($right); $newTypes = []; $changed = \false; foreach ($this->types as $innerType) { $candidates = []; foreach ($rightTypes as $i => $rightType) { if (!$innerType->isSuperTypeOf($rightType)->yes()) { continue; } $candidates[] = $rightType; unset($rightTypes[$i]); } if (count($candidates) === 0) { $newTypes[] = $innerType; continue; } $newType = $cb($innerType, \PHPStan\Type\TypeCombinator::union(...$candidates)); if ($innerType !== $newType) { $changed = \true; } $newTypes[] = $newType; } if ($changed) { return \PHPStan\Type\TypeCombinator::union(...$newTypes); } return $this; } public function tryRemove(\PHPStan\Type\Type $typeToRemove): ?\PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => \PHPStan\Type\TypeCombinator::remove($type, $typeToRemove)); } public function exponentiate(\PHPStan\Type\Type $exponent): \PHPStan\Type\Type { return $this->unionTypes(static fn(\PHPStan\Type\Type $type): \PHPStan\Type\Type => $type->exponentiate($exponent)); } public function getFiniteTypes(): array { $types = $this->notBenevolentPickFromTypes(static fn(\PHPStan\Type\Type $type) => $type->getFiniteTypes()); $uniquedTypes = []; foreach ($types as $type) { $uniquedTypes[$type->describe(\PHPStan\Type\VerbosityLevel::cache())] = $type; } if (count($uniquedTypes) > InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT) { return []; } return array_values($uniquedTypes); } /** * @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 { $newTypes = []; foreach ($this->types as $type) { $newTypes[] = $getType($type); } return \PHPStan\Type\TypeCombinator::union(...$newTypes); } /** * @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 fn(\PHPStan\Type\Type $type) => $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; } public function hasTemplateOrLateResolvableType(): bool { foreach ($this->types as $type) { if (!$type->hasTemplateOrLateResolvableType()) { continue; } return \true; } return \false; } } $types * @return list */ public static function sortTypes(array $types): array { if (count($types) > 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 array $globalTypeAliases; private TypeStringResolver $typeStringResolver; private TypeNodeResolver $typeNodeResolver; private ReflectionProvider $reflectionProvider; /** @var array */ private array $resolvedGlobalTypeAliases = []; /** @var array */ private array $resolvedLocalTypeAliases = []; /** @var array */ private array $resolvingClassTypeAliases = []; /** @var array */ private array $inProcess = []; /** * @param array $globalTypeAliases */ public function __construct( #[AutowiredParameter('%typeAliases%')] 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; } } 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()) { $enumCases = $this->type->getEnumCases(); if ($enumCases === [] && $this->type instanceof TemplateType && (new \PHPStan\Type\ObjectType('BackedEnum'))->isSuperTypeOf($this->type->getBound())->yes()) { return new \PHPStan\Type\UnionType([new \PHPStan\Type\IntegerType(), new \PHPStan\Type\StringType()]); } $valueTypes = []; foreach ($enumCases as $enumCase) { $valueType = $enumCase->getBackingValueType(); if ($valueType === null) { continue; } $valueTypes[] = $valueType; } if (count($valueTypes) === 0) { return new \PHPStan\Type\NeverType(); } if (count($valueTypes) === 1) { return $valueTypes[0]; } return new \PHPStan\Type\UnionType($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()]); } } describe(VerbosityLevel::typeOnly()) // "string" * $type->describe(VerbosityLevel::value()) // "'hello'" * $type->describe(VerbosityLevel::precise()) // "non-empty-lowercase-string" * * The getRecommendedLevelByType() factory method automatically chooses the right level * for error messages based on what types are involved — it picks the minimum verbosity * needed to distinguish the accepting type from the accepted type. */ final class VerbosityLevel { /** * @var self::* */ private int $value; private const TYPE_ONLY = 1; private const VALUE = 2; private const PRECISE = 3; private const CACHE = 4; /** @var self[] */ private static array $registry; /** * @param self::* $value */ private function __construct(int $value) { $this->value = $value; } /** * @param self::* $value */ private static function create(int $value): self { 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); } /** * Internal level for generating unique cache keys — not for user-facing messages. * * @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; } public function isCache(): bool { return $this->value === self::CACHE; } /** * Chooses the minimum verbosity needed to distinguish the two types in error messages. * * @api */ public static function getRecommendedLevelByType(\PHPStan\Type\Type $acceptingType, ?\PHPStan\Type\Type $acceptedType = null): self { $moreVerbose = \false; $veryVerbose = \false; $moreVerboseCallback = static function (\PHPStan\Type\Type $type, callable $traverse) use (&$moreVerbose, &$veryVerbose): \PHPStan\Type\Type { // stop deep traversal to not waste resources. if ($veryVerbose) { return $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); }; \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 { // stop deep traversal to not waste resources. if ($containsInvariantTemplateType) { return $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(); } } isAcceptedBy($this, $strictTypes); } return new \PHPStan\Type\AcceptsResult($type->isVoid()->or($type->isNull()), []); } public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOf($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 toBitwiseNotType(): \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 toCoercedArgumentType(bool $strictTypes): \PHPStan\Type\Type { return new \PHPStan\Type\NullType(); } 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 isClassString(): 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'); } public function hasTemplateOrLateResolvableType(): bool { return \false; } } */ function autoloadFunctions(): array { return $GLOBALS['__phpstanAutoloadFunctions'] ?? []; } * @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 $preserveKeys = true): SplFixedArray { } /** * @return array */ public function toArray(): array { } } ',args?:list,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?:list,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?:list,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 {} } , 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 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) {} /** * @return Iterator */ public function getIterator() {} } */ public function getName() : string { } /** * @return T */ public function newInstance() : object { } } */ public $name; /** * @param T|class-string $argument * @throws ReflectionException */ public function __construct($argument) {} /** * @return class-string */ public function getName() : string; /** * @return non-empty-string */ public function getShortName() : 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 getAttributes(?string $name = null, int $flags = 0) { } } */ public $name; /** * @param T|class-string $argument * @throws ReflectionException */ public function __construct($argument) {} /** * @return class-string */ public function getName() : string; /** * @return non-empty-string */ public function getShortName() : 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) { } /** * @param callable(T): void $initializer * @return T */ public function newLazyGhost(callable $initializer, int $options = 0): object { } /** * @param callable(T): T $factory * @return T */ public function newLazyProxy(callable $factory, int $options = 0): object { } /** * @param T $object * @param callable(T): void $initializer */ public function resetAsLazyGhost(object $object, callable $initializer, int $options = 0): void { } /** * @param T $object * @param callable(T): T $factory */ public function resetAsLazyProxy(object $object, callable $factory, int $options = 0): void { } /** * @param T $object * @return T */ public function initializeLazyObject(object $object): object { } /** * @param T $object * @return T */ public function markLazyObjectAsInitialized(object $object): object { } /** * @param T $object */ public function getLazyInitializer(object $object): ?callable { } /** * @param T $object */ public function isUninitializedLazyObject(object $object): bool { } } */ 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 getBackingType(): ?ReflectionNamedType {} } */ 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 getBackingType(): ?ReflectionNamedType {} } > */ public function getAttributes(?string $name = null, int $flags = 0) { } /** * @phpstan-assert-if-true !null $this->getReturnType() */ public function hasReturnType(): bool { } /** * @phpstan-assert-if-true !null $this->getTentativeReturnType() */ public function hasTentativeReturnType(): bool { } } > */ public function getAttributes(?string $name = null, int $flags = 0) { } /** * @phpstan-assert-if-true !null $this->getType() */ public function hasType(): bool { } } > */ public function getAttributes(?string $name = null, int $flags = 0) { } /** * @phpstan-assert-if-true !null $this->getType() */ public function hasType(): 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 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) {} } $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 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 {} $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|string[] $pattern * @param callable(string[]):string $callback * @param string|array $subject * @param int $count * @param-out 0|positive-int $count * @return ($subject is array ? array|null : string|null) */ function preg_replace_callback($pattern, $callback, $subject, int $limit = -1, &$count = null, int $flags = 0) {} /** * @param string|string[] $pattern * @param string|array $replacement * @param string|array $subject * @param int $count * @param-out 0|positive-int $count * @return ($subject is array ? array|null : string|null) */ function preg_replace($pattern, $replacement, $subject, int $limit = -1, &$count = null) {} /** * @param string|string[] $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 array|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 array|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 {} /** * @return ($associative is false ? list|false : array>|false) */ function get_headers(string $url, bool $associative = false, ?resource $context = null): array|false {} /** * @param array $long_options * @param mixed $rest_index * @param-out positive-int $rest_index * @return __benevolent|array|array>|false> */ function getopt(string $short_options, array $long_options = [], &$rest_index = null) {} /** * @param callable|int $handler * @param-later-invoked-callable $handler */ function pcntl_signal(int $signal, $handler, bool $restart_syscalls = true): bool {} /** * @param-later-invoked-callable $callback */ function set_error_handler(?callable $callback, int $error_levels = E_ALL): ?callable {} /** * @param-later-invoked-callable $callback */ function set_exception_handler(?callable $callback): ?callable {} /** * @param-later-invoked-callable $callback */ function spl_autoload_register(?callable $callback = null, bool $throw = true, bool $prepend = false): bool {} /** * @param-later-invoked-callable $callback */ function register_shutdown_function(callable $callback, mixed ...$args): void {} /** * @param-later-invoked-callable $callback */ function header_register_callback(callable $callback): bool {} /** * @param-later-invoked-callable $callback */ function register_tick_function(callable $callback, mixed ...$args): bool {} /** * @template P of int * * @param string|list $command * @param array|resource> $descriptor_spec * @param mixed $pipes * @param null|array $env_vars * @param null|array $options * * @param-out array $pipes * * @return resource|false */ function proc_open($command, array $descriptor_spec, &$pipes, ?string $cwd = null, ?array $env_vars = null, ?array $options = null) {} /** * @param mixed &$hosts * @param mixed &$weights * * @param-out list $hosts * @param-out list $weights */ function getmxrr(string $hostname, &$hosts, &$weights = null): bool {} * @implements \Traversable */ class DatePeriod implements \IteratorAggregate, \Traversable { /** * @return TEnd */ public function getEndDate() { } /** * @return TRecurrences */ public function getRecurrences() { } /** * @return TDate */ public function getStartDate(): DateTimeInterface { } } interface DateTimeInterface { /** @return \DateInterval&object{days:int} */ function diff(\DateTimeInterface $targetObject, bool $absolute = false): \DateInterval {} } /** @return \DateInterval&object{days:int} */ function date_diff(\DateTimeInterface $baseObject, \DateTimeInterface $targetObject, bool $absolute = false): \DateInterval {} */ public function getElementsByTagName ($name) {} /** * @param string $namespaceURI * @param string $localName * @return DOMNodeList */ public function getElementsByTagNameNS ($namespaceURI, $localName) {} } class DOMNode { /** * @var DOMNamedNodeMap|null */ public $attributes; /** * @phpstan-assert-if-true =DOMNamedNodeMap $this->attributes * @return bool */ public function hasAttributes() {} /** * @template TNode of DOMNode * @param TNode $node * @return __benevolent */ public function insertBefore(DOMNode $node, ?DOMNode $child = null) {} /** * @template TNode of DOMNode * @param TNode $node * @return __benevolent */ public function removeChild(DOMNode $node) {} /** * @template TNode of DOMNode * @param TNode $node * @return __benevolent */ public function appendChild(DOMNode $node) {} } class DOMElement extends DOMNode { /** @var DOMNamedNodeMap */ public $attributes; /** * @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 DOMNameSpaceNode|DOMNode * @implements IteratorAggregate */ class DOMNodeList implements IteratorAggregate, Countable { /** * @param int $index * @return TNode|null */ public function item ($index) {} } class DOMAttr extends DOMNode { } class DOMProcessingInstruction { /** * @var string */ public $target; /** * @var string */ public $data; } /** * @template-covariant TNode as DOMNode * @implements IteratorAggregate * * @property-read int $length */ class DOMNamedNodeMap implements IteratorAggregate, Countable { /** * @return Iterator */ public function getIterator(): Iterator {} /** * @param string $qualifiedName * @return TNode|null */ public function getNamedItem($qualifiedName): ?DOMNode {} /** * @param string|null $namespace * @param string $localName * @return TNode|null */ public function getNamedItemNS($namespace, $localName): ?DOMNode {} /** * @param int $index * @return TNode|null */ public function item($index): ?DOMNode {} } class DOMText { /** @var string */ public $wholeText; } */ 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 { } /** * @param (callable(TValue, TValue): int)|null $comparator * @return Deque */ public function sorted(?callable $comparator = null): 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 TKey * @template 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 { } } |false */ function scandir(string $directory, int $sorting_order = 0, $context = null) {} /** * @phpstan-assert-if-true =non-empty-string $filename */ function is_writable(string $filename): bool {} /** * @phpstan-assert-if-true =non-empty-string $filename */ function is_readable(string $filename): bool {} /** * @phpstan-assert-if-true =non-empty-string $filename */ function is_executable(string $filename): bool {} /** * @param ?resource $context * @phpstan-assert-if-true =non-empty-string $filename * @return list|false */ function file(string $filename, int $flags = 0, $context = null) {} /** * @param ?resource $context * @return string|false * @phpstan-assert-if-true =non-empty-string $filename */ function file_get_contents(string $filename, bool $use_include_path = false, $context = null, int $offset = 0, ?int $length = null) {} /** * @param ?resource $context * @return 0|positive-int|false * @phpstan-assert-if-true =non-empty-string $filename */ function file_put_contents(string $filename, mixed $data, int $flags = 0, $context = null) {} /** * @return 0|positive-int|false * @phpstan-assert-if-true =non-empty-string $filename */ function fileatime(string $filename) {} /** * @return 0|positive-int|false * @phpstan-assert-if-true =non-empty-string $filename */ function filectime(string $filename) {} /** * @return 0|positive-int|false * @phpstan-assert-if-true =non-empty-string $filename */ function filegroup(string $filename) {} /** * @return 0|positive-int|false * @phpstan-assert-if-true =non-empty-string $filename */ function fileinode(string $filename) {} /** * @return 0|positive-int|false * @phpstan-assert-if-true =non-empty-string $filename */ function filemtime(string $filename) {} /** * @return 0|positive-int|false * @phpstan-assert-if-true =non-empty-string $filename */ function fileowner(string $filename) {} /** * @return 0|positive-int|false * @phpstan-assert-if-true =non-empty-string $filename */ function fileperms(string $filename) {} /** * @return 0|positive-int|false * @phpstan-assert-if-true =non-empty-string $filename */ function filesize(string $filename) {} /** * @return string|false * @phpstan-assert-if-true =non-empty-string $filename */ function filetype(string $filename) {} /** * @param ?resource $context * @return resource|false * @phpstan-assert-if-true =non-empty-string $filename */ function fopen(string $filename, string $mode, bool $use_include_path = false, $context = null) {} /** * @return int|false * @phpstan-assert-if-true =non-empty-string $path */ function linkinfo(string $path) {} /** * @return array|false * @phpstan-assert-if-true =non-empty-string $filename */ function lstat(string $filename) {} /** * @param ?resource $context * @phpstan-assert-if-true =non-empty-string $directory */ function mkdir(string $directory, int $permissions = 0777, bool $recursive = false, $context = null): bool {} /** * @return 0|positive-int|false * @param ?resource $context * @phpstan-assert-if-true =non-empty-string $filename */ function readfile(string $filename, bool $use_include_path = false, $context = null) {} /** * @return non-empty-string|false * @phpstan-assert-if-true =non-empty-string $path */ function readlink(string $path) {} /** * @return non-empty-string|false * @phpstan-assert-if-true =non-empty-string $path */ function realpath(string $path) {} /** * @param ?resource $context * @phpstan-assert-if-true =non-empty-string $directory */ function rmdir(string $directory, $context): bool {} /** * @return array|false * @phpstan-assert-if-true =non-empty-string $filename */ function stat(string $filename) {} /** * @phpstan-assert-if-true =non-empty-string $filename */ function touch(string $filename, ?int $mtime, ?int $atime): bool {} /** * @param ?resource $context * @phpstan-assert-if-true =non-empty-string $filename */ function unlink(string $filename, $context = null): 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) { } /** * @param int|string|null $key * @param self|string|int|float|bool $value * @return void */ public function offsetSet($key, $value) {} } /** * @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() {} } $flags * @phpstan-assert-if-true =non-empty-string $json */ function json_validate(string $json, int $depth = 512, int $flags = 0): bool { } |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; } 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 { } } 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 { } } */ public static function cases(): array; } } */ public function getArguments(): array { } public function newInstance(): object { } private function __clone() { } private function __construct() { } } } |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) {} |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 {} * @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 () {} } |\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 ($value is resource ? bool : false) */ 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 { } new \_PHPStan_33c983f26\olvlvl\ComposerAttributeCollector\Collection( // classes array('PHPStan\DependencyInjection\AutowiredService' => array(0 => array(0 => array(), 1 => 'PHPStan\Cache\Cache'), 1 => array(0 => array(), 1 => 'PHPStan\Fixable\Patcher'), 2 => array(0 => array(), 1 => 'PHPStan\Fixable\PhpDoc\PhpDocEditor'), 3 => array(0 => array(), 1 => 'PHPStan\Internal\HttpClientFactory'), 4 => array(0 => array(), 1 => 'PHPStan\Parallel\ParallelAnalyser'), 5 => array(0 => array(), 1 => 'PHPStan\Parallel\ForkParallelChecker'), 6 => array(0 => array(), 1 => 'PHPStan\Parallel\WorkerRunner'), 7 => array(0 => array(), 1 => 'PHPStan\Parallel\Scheduler'), 8 => array(0 => array(), 1 => 'PHPStan\Rules\IssetCheck'), 9 => array(0 => array(), 1 => 'PHPStan\Rules\Pure\FunctionPurityCheck'), 10 => array(0 => array(), 1 => 'PHPStan\Rules\FunctionDefinitionCheck'), 11 => array(0 => array(), 1 => 'PHPStan\Rules\ParameterCastableToStringCheck'), 12 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\VarianceCheck'), 13 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\MethodTagTemplateTypeCheck'), 14 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\GenericAncestorsCheck'), 15 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\CrossCheckInterfacesHelper'), 16 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\GenericObjectTypeCheck'), 17 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\TemplateTypeCheck'), 18 => array(0 => array(), 1 => 'PHPStan\Rules\MissingTypehintCheck'), 19 => array(0 => array(), 1 => 'PHPStan\Rules\RuleLevelHelper'), 20 => array(0 => array(), 1 => 'PHPStan\Rules\RestrictedUsage\RestrictedStaticMethodUsageRule'), 21 => array(0 => array(), 1 => 'PHPStan\Rules\RestrictedUsage\RestrictedFunctionCallableUsageRule'), 22 => array(0 => array(), 1 => 'PHPStan\Rules\RestrictedUsage\RestrictedMethodUsageRule'), 23 => array(0 => array(), 1 => 'PHPStan\Rules\RestrictedUsage\RestrictedPropertyUsageRule'), 24 => array(0 => array(), 1 => 'PHPStan\Rules\RestrictedUsage\RestrictedUsageOfDeprecatedStringCastRule'), 25 => array(0 => array(), 1 => 'PHPStan\Rules\RestrictedUsage\RestrictedMethodCallableUsageRule'), 26 => array(0 => array(), 1 => 'PHPStan\Rules\RestrictedUsage\RestrictedStaticPropertyUsageRule'), 27 => array(0 => array(), 1 => 'PHPStan\Rules\RestrictedUsage\RestrictedClassConstantUsageRule'), 28 => array(0 => array(), 1 => 'PHPStan\Rules\RestrictedUsage\RestrictedStaticMethodCallableUsageRule'), 29 => array(0 => array(), 1 => 'PHPStan\Rules\RestrictedUsage\RestrictedFunctionUsageRule'), 30 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\LocalTypeAliasesCheck'), 31 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\MethodTagCheck'), 32 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\DuplicateDeclarationHelper'), 33 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\MixinCheck'), 34 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\PropertyTagCheck'), 35 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\ConsistentConstructorHelper'), 36 => array(0 => array(), 1 => 'PHPStan\Rules\Constants\LazyAlwaysUsedClassConstantsExtensionProvider'), 37 => array(0 => array(), 1 => 'PHPStan\Rules\Functions\PrintfHelper'), 38 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\PropertyDescriptor'), 39 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\PropertyReflectionFinder'), 40 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\AccessStaticPropertiesCheck'), 41 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\AccessPropertiesCheck'), 42 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\LazyReadWritePropertiesExtensionProvider'), 43 => array(0 => array(), 1 => 'PHPStan\Rules\Playground\NeverRuleHelper'), 44 => array(0 => array(), 1 => 'PHPStan\Rules\InternalTag\RestrictedInternalUsageHelper'), 45 => array(0 => array(), 1 => 'PHPStan\Rules\TooWideTypehints\TooWideTypeCheck'), 46 => array(0 => array(), 1 => 'PHPStan\Rules\TooWideTypehints\TooWideParameterOutTypeCheck'), 47 => array(0 => array(), 1 => 'PHPStan\Rules\Debug\DumpNativeTypeRule'), 48 => array(0 => array(), 1 => 'PHPStan\Rules\Debug\DumpPhpDocTypeRule'), 49 => array(0 => array(), 1 => 'PHPStan\Rules\Debug\FileAssertRule'), 50 => array(0 => array(), 1 => 'PHPStan\Rules\Debug\DumpTypeRule'), 51 => array(0 => array(), 1 => 'PHPStan\Rules\Debug\DebugScopeRule'), 52 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\StaticMethodCallCheck'), 53 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\LazyAlwaysUsedMethodExtensionProvider'), 54 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\MethodCallCheck'), 55 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\MethodParameterComparisonHelper'), 56 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\ParentMethodHelper'), 57 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\MethodPrototypeFinder'), 58 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\MethodVisibilityComparisonHelper'), 59 => array(0 => array(), 1 => 'PHPStan\Rules\ClassNameCheck'), 60 => array(0 => array(), 1 => 'PHPStan\Rules\ClassForbiddenNameCheck'), 61 => array(0 => array(), 1 => 'PHPStan\Rules\UnusedFunctionParametersCheck'), 62 => array(0 => array(), 1 => 'PHPStan\Rules\FunctionReturnTypeCheck'), 63 => array(0 => array(), 1 => 'PHPStan\Rules\FunctionCallParametersCheck'), 64 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\AssertRuleHelper'), 65 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\IncompatiblePhpDocTypeCheck'), 66 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\VarTagTypeRuleHelper'), 67 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\RequireExtendsCheck'), 68 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\GenericCallableRuleHelper'), 69 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\UnresolvableTypeHelper'), 70 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\ConditionalReturnTypeRuleHelper'), 71 => array(0 => array(0 => 'registry', 1 => NULL, 2 => 'PHPStan\Rules\Registry'), 1 => 'PHPStan\Rules\LazyRegistry'), 72 => array(0 => array(), 1 => 'PHPStan\Rules\NullsafeCheck'), 73 => array(0 => array(), 1 => 'PHPStan\Rules\Api\ApiRuleHelper'), 74 => array(0 => array(), 1 => 'PHPStan\Rules\AttributesCheck'), 75 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\Rules\Exceptions\DefaultExceptionTypeResolver'), 1 => 'PHPStan\Rules\Exceptions\DefaultExceptionTypeResolver'), 76 => array(0 => array(), 1 => 'PHPStan\Rules\Exceptions\TooWideThrowTypeCheck'), 77 => array(0 => array(), 1 => 'PHPStan\Rules\Exceptions\MissingCheckedExceptionInThrowsCheck'), 78 => array(0 => array(), 1 => 'PHPStan\Rules\Arrays\NonexistentOffsetInArrayDimFetchCheck'), 79 => array(0 => array(), 1 => 'PHPStan\Rules\ClassCaseSensitivityCheck'), 80 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\ConstantConditionRuleHelper'), 81 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\PossiblyImpureTipHelper'), 82 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\ImpossibleCheckTypeHelper'), 83 => array(0 => array(), 1 => 'PHPStan\Analyser\AnalyserResultFinalizer'), 84 => array(0 => array(), 1 => 'PHPStan\Analyser\RuleErrorTransformer'), 85 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\Analyser\Fiber\FiberNodeScopeResolver'), 1 => 'PHPStan\Analyser\Fiber\FiberNodeScopeResolver'), 86 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\FirstClassCallableFuncCallHandler'), 87 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\YieldHandler'), 88 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\CastHandler'), 89 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\EmptyHandler'), 90 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\PreDecHandler'), 91 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\EvalHandler'), 92 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\AssignHandler'), 93 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\StaticPropertyFetchHandler'), 94 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\CloneHandler'), 95 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\ThrowHandler'), 96 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\ScalarHandler'), 97 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\ErrorSuppressHandler'), 98 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\UnaryMinusHandler'), 99 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\InterpolatedStringHandler'), 100 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\VariableHandler'), 101 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\IncludeHandler'), 102 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\PipeHandler'), 103 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\NewHandler'), 104 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\AssignOpHandler'), 105 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\TernaryHandler'), 106 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\UnaryPlusHandler'), 107 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\FirstClassCallableNewHandler'), 108 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\PreIncHandler'), 109 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\ArrowFunctionHandler'), 110 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\IssetHandler'), 111 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\ClassConstFetchHandler'), 112 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\ExitHandler'), 113 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\FirstClassCallableMethodCallHandler'), 114 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\BitwiseNotHandler'), 115 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\MatchHandler'), 116 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\ClosureHandler'), 117 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\FirstClassCallableStaticCallHandler'), 118 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\YieldFromHandler'), 119 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\PostDecHandler'), 120 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Virtual\UnsetOffsetExprHandler'), 121 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Virtual\SetOffsetValueTypeExprHandler'), 122 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Virtual\GetIterableKeyTypeExprHandler'), 123 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Virtual\FunctionCallableNodeHandler'), 124 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Virtual\OriginalPropertyTypeExprHandler'), 125 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Virtual\InstantiationCallableNodeHandler'), 126 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Virtual\SetExistingOffsetValueTypeExprHandler'), 127 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Virtual\GetIterableValueTypeExprHandler'), 128 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Virtual\GetOffsetValueTypeExprHandler'), 129 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Virtual\TypeExprHandler'), 130 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Virtual\StaticMethodCallableNodeHandler'), 131 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Virtual\ExistingArrayDimFetchHandler'), 132 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Virtual\AlwaysRememberedExprHandler'), 133 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Virtual\NativeTypeExprHandler'), 134 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Virtual\MethodCallableNodeHandler'), 135 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\CoalesceHandler'), 136 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\BooleanOrHandler'), 137 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\ArrayHandler'), 138 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\PostIncHandler'), 139 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\BooleanAndHandler'), 140 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Helper\ImplicitToStringCallHelper'), 141 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Helper\ClosureTypeResolver'), 142 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Helper\NonNullabilityHelper'), 143 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Helper\MethodCallReturnTypeHelper'), 144 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\Helper\MethodThrowPointHelper'), 145 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\NullsafePropertyFetchHandler'), 146 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\MethodCallHandler'), 147 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\PropertyFetchHandler'), 148 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\CastStringHandler'), 149 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\ConstFetchHandler'), 150 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\BinaryOpHandler'), 151 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\StaticCallHandler'), 152 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\NullsafeMethodCallHandler'), 153 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\BooleanNotHandler'), 154 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\FuncCallHandler'), 155 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\PrintHandler'), 156 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\InstanceofHandler'), 157 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\ArrayDimFetchHandler'), 158 => array(0 => array(), 1 => 'PHPStan\Analyser\RicherScopeGetTypeHelper'), 159 => array(0 => array(0 => NULL, 1 => '@PHPStan\Analyser\ConstantResolverFactory::create'), 1 => 'PHPStan\Analyser\ConstantResolver'), 160 => array(0 => array(0 => 'typeSpecifier', 1 => '@typeSpecifierFactory::create'), 1 => 'PHPStan\Analyser\TypeSpecifier'), 161 => array(0 => array(), 1 => 'PHPStan\Analyser\ScopeFactory'), 162 => array(0 => array(), 1 => 'PHPStan\Analyser\FileAnalyser'), 163 => array(0 => array(), 1 => 'PHPStan\Analyser\LocalIgnoresProcessor'), 164 => array(0 => array(), 1 => 'PHPStan\Analyser\Analyser'), 165 => array(0 => array(), 1 => 'PHPStan\Analyser\IgnoreErrorExtensionProvider'), 166 => array(0 => array(), 1 => 'PHPStan\Analyser\ResultCache\ResultCacheClearer'), 167 => array(0 => array(), 1 => 'PHPStan\Analyser\ConstantResolverFactory'), 168 => array(0 => array(), 1 => 'PHPStan\Analyser\NodeScopeResolver'), 169 => array(0 => array(0 => 'typeSpecifierFactory'), 1 => 'PHPStan\Analyser\TypeSpecifierFactory'), 170 => array(0 => array(), 1 => 'PHPStan\Analyser\Ignore\IgnoredErrorHelper'), 171 => array(0 => array(), 1 => 'PHPStan\Analyser\Ignore\IgnoreLexer'), 172 => array(0 => array(), 1 => 'PHPStan\Node\Printer\ExprPrinter'), 173 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\Node\Printer\Printer'), 1 => 'PHPStan\Node\Printer\Printer'), 174 => array(0 => array(), 1 => 'PHPStan\Node\DeepNodeCloner'), 175 => array(0 => array(), 1 => 'PHPStan\File\FileHelper'), 176 => array(0 => array(), 1 => 'PHPStan\File\FileMonitor'), 177 => array(0 => array(0 => 'relativePathHelper', 1 => NULL, 2 => 'PHPStan\File\RelativePathHelper'), 1 => 'PHPStan\File\FuzzyRelativePathHelper'), 178 => array(0 => array(), 1 => 'PHPStan\File\FileExcluderFactory'), 179 => array(0 => array(), 1 => 'PHPStan\Dependency\ExportedNodeFetcher'), 180 => array(0 => array(), 1 => 'PHPStan\Dependency\ExportedNodeResolver'), 181 => array(0 => array(), 1 => 'PHPStan\Dependency\DependencyResolver'), 182 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\DependencyInjection\Container'), 1 => 'PHPStan\DependencyInjection\MemoizingContainer'), 183 => array(0 => array(), 1 => 'PHPStan\DependencyInjection\DerivativeContainerFactory'), 184 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\DependencyInjection\Nette\NetteContainer'), 1 => 'PHPStan\DependencyInjection\Nette\NetteContainer'), 185 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\DependencyInjection\Reflection\ClassReflectionExtensionRegistryProvider'), 1 => 'PHPStan\DependencyInjection\Reflection\LazyClassReflectionExtensionRegistryProvider'), 186 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\DependencyInjection\Type\ExpressionTypeResolverExtensionRegistryProvider'), 1 => 'PHPStan\DependencyInjection\Type\LazyExpressionTypeResolverExtensionRegistryProvider'), 187 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\DependencyInjection\Type\ParameterClosureTypeExtensionProvider'), 1 => 'PHPStan\DependencyInjection\Type\LazyParameterClosureTypeExtensionProvider'), 188 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\DependencyInjection\Type\ParameterOutTypeExtensionProvider'), 1 => 'PHPStan\DependencyInjection\Type\LazyParameterOutTypeExtensionProvider'), 189 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\DependencyInjection\Type\OperatorTypeSpecifyingExtensionRegistryProvider'), 1 => 'PHPStan\DependencyInjection\Type\LazyOperatorTypeSpecifyingExtensionRegistryProvider'), 190 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\DependencyInjection\Type\ParameterClosureThisExtensionProvider'), 1 => 'PHPStan\DependencyInjection\Type\LazyParameterClosureThisExtensionProvider'), 191 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\DependencyInjection\Type\DynamicReturnTypeExtensionRegistryProvider'), 1 => 'PHPStan\DependencyInjection\Type\LazyDynamicReturnTypeExtensionRegistryProvider'), 192 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\DependencyInjection\Type\UnaryOperatorTypeSpecifyingExtensionRegistryProvider'), 1 => 'PHPStan\DependencyInjection\Type\LazyUnaryOperatorTypeSpecifyingExtensionRegistryProvider'), 193 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\DependencyInjection\Type\DynamicThrowTypeExtensionProvider'), 1 => 'PHPStan\DependencyInjection\Type\LazyDynamicThrowTypeExtensionProvider'), 194 => array(0 => array(), 1 => 'PHPStan\Broker\AnonymousClassNameHelper'), 195 => array(0 => array(), 1 => 'PHPStan\Reflection\ConstructorsHelper'), 196 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\Reflection\ReflectionProvider\ReflectionProviderProvider'), 1 => 'PHPStan\Reflection\ReflectionProvider\LazyReflectionProviderProvider'), 197 => array(0 => array(0 => 'reflectionProviderFactory'), 1 => 'PHPStan\Reflection\ReflectionProvider\ReflectionProviderFactory'), 198 => array(0 => array(), 1 => 'PHPStan\Reflection\BetterReflection\SourceStubber\ReflectionSourceStubberFactory'), 199 => array(0 => array(), 1 => 'PHPStan\Reflection\BetterReflection\SourceStubber\PhpStormStubsSourceStubberFactory'), 200 => array(0 => array(0 => 'betterReflectionReflector', 1 => NULL, 2 => 'PHPStan\BetterReflection\Reflector\Reflector'), 1 => 'PHPStan\Reflection\BetterReflection\Reflector\MemoizingReflector'), 201 => array(0 => array(), 1 => 'PHPStan\Reflection\BetterReflection\BetterReflectionSourceLocatorFactory'), 202 => array(0 => array(), 1 => 'PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedSingleFileSourceLocatorRepository'), 203 => array(0 => array(), 1 => 'PHPStan\Reflection\BetterReflection\SourceLocator\FileNodesFetcher'), 204 => array(0 => array(), 1 => 'PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedDirectorySourceLocatorFactory'), 205 => array(0 => array(), 1 => 'PHPStan\Reflection\BetterReflection\SourceLocator\ComposerJsonAndInstalledJsonSourceLocatorMaker'), 206 => array(0 => array(), 1 => 'PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedDirectorySourceLocatorRepository'), 207 => array(0 => array(), 1 => 'PHPStan\Reflection\BetterReflection\Type\AdapterReflectionEnumDynamicReturnTypeExtension'), 208 => array(0 => array(), 1 => 'PHPStan\Reflection\AttributeReflectionFactory'), 209 => array(0 => array(), 1 => 'PHPStan\Reflection\InitializerExprTypeResolver'), 210 => array(0 => array(), 1 => 'PHPStan\Reflection\Deprecation\DeprecationProvider'), 211 => array(0 => array(), 1 => 'PHPStan\Reflection\SignatureMap\NativeFunctionReflectionProvider'), 212 => array(0 => array(), 1 => 'PHPStan\Reflection\SignatureMap\SignatureMapParser'), 213 => array(0 => array(0 => NULL, 1 => '@PHPStan\Reflection\SignatureMap\SignatureMapProviderFactory::create'), 1 => 'PHPStan\Reflection\SignatureMap\SignatureMapProvider'), 214 => array(0 => array(), 1 => 'PHPStan\Reflection\SignatureMap\SignatureMapProviderFactory'), 215 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\Reflection\SignatureMap\Php8SignatureMapProvider'), 1 => 'PHPStan\Reflection\SignatureMap\Php8SignatureMapProvider'), 216 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\Reflection\SignatureMap\FunctionSignatureMapProvider'), 1 => 'PHPStan\Reflection\SignatureMap\FunctionSignatureMapProvider'), 217 => array(0 => array(), 1 => 'PHPStan\Reflection\Php\EnumAllowedSubTypesClassReflectionExtension'), 218 => array(0 => array(), 1 => 'PHPStan\Reflection\Php\SealedAllowedSubTypesClassReflectionExtension'), 219 => array(0 => array(), 1 => 'PHPStan\Process\CpuCoreCounter'), 220 => array(0 => array(), 1 => 'PHPStan\Command\AnalyseApplication'), 221 => array(0 => array(), 1 => 'PHPStan\Command\AnalyserRunner'), 222 => array(0 => array(0 => 'errorFormatter.teamcity'), 1 => 'PHPStan\Command\ErrorFormatter\TeamcityErrorFormatter'), 223 => array(0 => array(0 => 'errorFormatter.junit'), 1 => 'PHPStan\Command\ErrorFormatter\JunitErrorFormatter'), 224 => array(0 => array(0 => 'errorFormatter.raw'), 1 => 'PHPStan\Command\ErrorFormatter\RawErrorFormatter'), 225 => array(0 => array(0 => 'errorFormatter.checkstyle'), 1 => 'PHPStan\Command\ErrorFormatter\CheckstyleErrorFormatter'), 226 => array(0 => array(0 => 'errorFormatter.table'), 1 => 'PHPStan\Command\ErrorFormatter\TableErrorFormatter'), 227 => array(0 => array(0 => 'errorFormatter.github'), 1 => 'PHPStan\Command\ErrorFormatter\GithubErrorFormatter'), 228 => array(0 => array(0 => 'errorFormatter.gitlab'), 1 => 'PHPStan\Command\ErrorFormatter\GitlabErrorFormatter'), 229 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\Command\ErrorFormatter\CiDetectedErrorFormatter'), 1 => 'PHPStan\Command\ErrorFormatter\CiDetectedErrorFormatter'), 230 => array(0 => array(), 1 => 'PHPStan\Command\FixerWorkerRunner'), 231 => array(0 => array(), 1 => 'PHPStan\Command\FixerApplication'), 232 => array(0 => array(0 => NULL, 1 => '@PHPStan\Collectors\RegistryFactory::create'), 1 => 'PHPStan\Collectors\Registry'), 233 => array(0 => array(), 1 => 'PHPStan\Collectors\RegistryFactory'), 234 => array(0 => array(), 1 => 'PHPStan\PhpDoc\PhpDocInheritanceResolver'), 235 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\PhpDoc\TypeNodeResolverExtensionRegistryProvider'), 1 => 'PHPStan\PhpDoc\LazyTypeNodeResolverExtensionRegistryProvider'), 236 => array(0 => array(), 1 => 'PHPStan\PhpDoc\BcMathNumberStubFilesExtension'), 237 => array(0 => array(), 1 => 'PHPStan\PhpDoc\SocketSelectStubFilesExtension'), 238 => array(0 => array(0 => 'stubPhpDocProvider'), 1 => 'PHPStan\PhpDoc\StubPhpDocProvider'), 239 => array(0 => array(), 1 => 'PHPStan\PhpDoc\StubValidator'), 240 => array(0 => array(), 1 => 'PHPStan\PhpDoc\ReflectionClassStubFilesExtension'), 241 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\PhpDoc\StubFilesProvider'), 1 => 'PHPStan\PhpDoc\DefaultStubFilesProvider'), 242 => array(0 => array(), 1 => 'PHPStan\PhpDoc\ReflectionEnumStubFilesExtension'), 243 => array(0 => array(), 1 => 'PHPStan\PhpDoc\JsonValidateStubFilesExtension'), 244 => array(0 => array(), 1 => 'PHPStan\PhpDoc\TypeStringResolver'), 245 => array(0 => array(), 1 => 'PHPStan\PhpDoc\PhpDocNodeResolver'), 246 => array(0 => array(), 1 => 'PHPStan\PhpDoc\TypeNodeResolver'), 247 => array(0 => array(), 1 => 'PHPStan\PhpDoc\PhpDocStringResolver'), 248 => array(0 => array(), 1 => 'PHPStan\PhpDoc\ConstExprNodeResolver'), 249 => array(0 => array(), 1 => 'PHPStan\Parser\UseAliasVisitor'), 250 => array(0 => array(), 1 => 'PHPStan\Parser\TypeTraverserInstanceofVisitor'), 251 => array(0 => array(), 1 => 'PHPStan\Parser\CurlSetOptArgVisitor'), 252 => array(0 => array(), 1 => 'PHPStan\Parser\ArrayMapArgVisitor'), 253 => array(0 => array(), 1 => 'PHPStan\Parser\MagicConstantParamDefaultVisitor'), 254 => array(0 => array(), 1 => 'PHPStan\Parser\ArrayFilterArgVisitor'), 255 => array(0 => array(), 1 => 'PHPStan\Parser\TryCatchTypeVisitor'), 256 => array(0 => array(), 1 => 'PHPStan\Parser\CurlSetOptArrayArgVisitor'), 257 => array(0 => array(), 1 => 'PHPStan\Parser\ClosureBindArgVisitor'), 258 => array(0 => array(), 1 => 'PHPStan\Parser\ArrayFindArgVisitor'), 259 => array(0 => array(), 1 => 'PHPStan\Parser\AnonymousClassVisitor'), 260 => array(0 => array(), 1 => 'PHPStan\Parser\ClosureArgVisitor'), 261 => array(0 => array(), 1 => 'PHPStan\Parser\StandaloneThrowExprVisitor'), 262 => array(0 => array(), 1 => 'PHPStan\Parser\ParentStmtTypesVisitor'), 263 => array(0 => array(), 1 => 'PHPStan\Parser\DeclarePositionVisitor'), 264 => array(0 => array(), 1 => 'PHPStan\Parser\ArrowFunctionArgVisitor'), 265 => array(0 => array(), 1 => 'PHPStan\Parser\ClosureBindToVarVisitor'), 266 => array(0 => array(), 1 => 'PHPStan\Parser\LexerFactory'), 267 => array(0 => array(), 1 => 'PHPStan\Parser\NewAssignedToPropertyVisitor'), 268 => array(0 => array(), 1 => 'PHPStan\Parser\ImplodeArgVisitor'), 269 => array(0 => array(), 1 => 'PHPStan\Parser\LastConditionVisitor'), 270 => array(0 => array(), 1 => 'PHPStan\Parser\ImmediatelyInvokedClosureVisitor'), 271 => array(0 => array(), 1 => 'PHPStan\Parser\ArrayWalkArgVisitor'), 272 => array(0 => array(), 1 => 'PHPStan\Type\BitwiseFlagHelper'), 273 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\Type\TypeAliasResolverProvider'), 1 => 'PHPStan\Type\LazyTypeAliasResolverProvider'), 274 => array(0 => array(), 1 => 'PHPStan\Type\Regex\RegexGroupParser'), 275 => array(0 => array(), 1 => 'PHPStan\Type\Regex\RegexExpressionHelper'), 276 => array(0 => array(), 1 => 'PHPStan\Type\Constant\OversizedArrayBuilder'), 277 => array(0 => array(), 1 => 'PHPStan\Type\ClosureTypeFactory'), 278 => array(0 => array(0 => NULL, 1 => NULL, 2 => 'PHPStan\Type\TypeAliasResolver'), 1 => 'PHPStan\Type\UsefulTypeAliasResolver'), 279 => array(0 => array(), 1 => 'PHPStan\Type\PHPStan\ClassNameUsageLocationCreateIdentifierDynamicReturnTypeExtension'), 280 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayKeyDynamicReturnTypeExtension'), 281 => array(0 => array(), 1 => 'PHPStan\Type\Php\DateFunctionReturnTypeExtension'), 282 => array(0 => array(), 1 => 'PHPStan\Type\Php\BackedEnumFromMethodDynamicReturnTypeExtension'), 283 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayPopFunctionReturnTypeExtension'), 284 => array(0 => array(), 1 => 'PHPStan\Type\Php\FilterVarDynamicReturnTypeExtension'), 285 => array(0 => array(), 1 => 'PHPStan\Type\Php\DateIntervalFormatDynamicReturnTypeExtension'), 286 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayColumnHelper'), 287 => array(0 => array(), 1 => 'PHPStan\Type\Php\CtypeDigitFunctionTypeSpecifyingExtension'), 288 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArraySumFunctionDynamicReturnTypeExtension'), 289 => array(0 => array(), 1 => 'PHPStan\Type\Php\IsCallableFunctionTypeSpecifyingExtension'), 290 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayFindKeyFunctionReturnTypeExtension'), 291 => array(0 => array(), 1 => 'PHPStan\Type\Php\SimpleXMLElementConstructorThrowTypeExtension'), 292 => array(0 => array(), 1 => 'PHPStan\Type\Php\PropertyExistsTypeSpecifyingExtension'), 293 => array(0 => array(), 1 => 'PHPStan\Type\Php\StrtotimeFunctionReturnTypeExtension'), 294 => array(0 => array(), 1 => 'PHPStan\Type\Php\PregReplaceCallbackClosureTypeExtension'), 295 => array(0 => array(), 1 => 'PHPStan\Type\Php\GetDefinedVarsFunctionReturnTypeExtension'), 296 => array(0 => array(), 1 => 'PHPStan\Type\Php\TypeSpecifyingFunctionsDynamicReturnTypeExtension'), 297 => array(0 => array(), 1 => 'PHPStan\Type\Php\BcMathStringOrNullReturnTypeExtension'), 298 => array(0 => array(), 1 => 'PHPStan\Type\Php\ClosureFromCallableDynamicReturnTypeExtension'), 299 => array(0 => array(), 1 => 'PHPStan\Type\Php\VersionCompareFunctionDynamicThrowTypeExtension'), 300 => array(0 => array(), 1 => 'PHPStan\Type\Php\StrPadFunctionReturnTypeExtension'), 301 => array(0 => array(), 1 => 'PHPStan\Type\Php\PathinfoFunctionDynamicReturnTypeExtension'), 302 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayKeysFunctionDynamicReturnTypeExtension'), 303 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayMapFunctionReturnTypeExtension'), 304 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayMergeFunctionDynamicReturnTypeExtension'), 305 => array(0 => array(), 1 => 'PHPStan\Type\Php\GettypeFunctionReturnTypeExtension'), 306 => array(0 => array(), 1 => 'PHPStan\Type\Php\DateTimeCreateDynamicReturnTypeExtension'), 307 => array(0 => array(), 1 => 'PHPStan\Type\Php\StrSplitFunctionReturnTypeExtension'), 308 => array(0 => array(), 1 => 'PHPStan\Type\Php\ReflectionMethodConstructorThrowTypeExtension'), 309 => array(0 => array(), 1 => 'PHPStan\Type\Php\PowFunctionReturnTypeExtension'), 310 => array(0 => array(), 1 => 'PHPStan\Type\Php\StrIncrementDecrementFunctionReturnTypeExtension'), 311 => array(0 => array(), 1 => 'PHPStan\Type\Php\StrWordCountFunctionDynamicReturnTypeExtension'), 312 => array(0 => array(), 1 => 'PHPStan\Type\Php\FilterVarThrowTypeExtension'), 313 => array(0 => array(), 1 => 'PHPStan\Type\Php\ReflectionPropertyConstructorThrowTypeExtension'), 314 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayCombineFunctionReturnTypeExtension'), 315 => array(0 => array(), 1 => 'PHPStan\Type\Php\GetParentClassDynamicFunctionReturnTypeExtension'), 316 => array(0 => array(), 1 => 'PHPStan\Type\Php\DateIntervalDynamicReturnTypeExtension'), 317 => array(0 => array(), 1 => 'PHPStan\Type\Php\SimpleXMLElementAsXMLMethodReturnTypeExtension'), 318 => array(0 => array(), 1 => 'PHPStan\Type\Php\FilterVarArrayDynamicReturnTypeExtension'), 319 => array(0 => array(), 1 => 'PHPStan\Type\Php\IsIterableFunctionTypeSpecifyingExtension'), 320 => array(0 => array(), 1 => 'PHPStan\Type\Php\MbSubstituteCharacterDynamicReturnTypeExtension'), 321 => array(0 => array(), 1 => 'PHPStan\Type\Php\OpenSslCipherMethodsProvider'), 322 => array(0 => array(), 1 => 'PHPStan\Type\Php\MicrotimeFunctionReturnTypeExtension'), 323 => array(0 => array(), 1 => 'PHPStan\Type\Php\ClassImplementsFunctionReturnTypeExtension'), 324 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayFilterFunctionReturnTypeExtension'), 325 => array(0 => array(), 1 => 'PHPStan\Type\Php\Base64DecodeDynamicFunctionReturnTypeExtension'), 326 => array(0 => array(), 1 => 'PHPStan\Type\Php\DateIntervalFormatReturnTypeHelper'), 327 => array(0 => array(), 1 => 'PHPStan\Type\Php\ClosureGetCurrentDynamicReturnTypeExtension'), 328 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayCountValuesDynamicReturnTypeExtension'), 329 => array(0 => array(), 1 => 'PHPStan\Type\Php\SimpleXMLElementClassPropertyReflectionExtension'), 330 => array(0 => array(), 1 => 'PHPStan\Type\Php\PDOConnectReturnTypeExtension'), 331 => array(0 => array(), 1 => 'PHPStan\Type\Php\MbStrlenFunctionReturnTypeExtension'), 332 => array(0 => array(), 1 => 'PHPStan\Type\Php\GetDebugTypeFunctionReturnTypeExtension'), 333 => array(0 => array(), 1 => 'PHPStan\Type\Php\DateTimeSubMethodThrowTypeExtension'), 334 => array(0 => array(), 1 => 'PHPStan\Type\Php\ConstantFunctionReturnTypeExtension'), 335 => array(0 => array(), 1 => 'PHPStan\Type\Php\PregFilterFunctionReturnTypeExtension'), 336 => array(0 => array(), 1 => 'PHPStan\Type\Php\VersionCompareFunctionDynamicReturnTypeExtension'), 337 => array(0 => array(), 1 => 'PHPStan\Type\Php\DateTimeZoneConstructorThrowTypeExtension'), 338 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayShiftFunctionReturnTypeExtension'), 339 => array(0 => array(), 1 => 'PHPStan\Type\Php\DatePeriodConstructorReturnTypeExtension'), 340 => array(0 => array(), 1 => 'PHPStan\Type\Php\ReflectionFunctionConstructorThrowTypeExtension'), 341 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArraySliceFunctionReturnTypeExtension'), 342 => array(0 => array(), 1 => 'PHPStan\Type\Php\FilterInputDynamicReturnTypeExtension'), 343 => array(0 => array(), 1 => 'PHPStan\Type\Php\CountFunctionTypeSpecifyingExtension'), 344 => array(0 => array(), 1 => 'PHPStan\Type\Php\StrlenFunctionReturnTypeExtension'), 345 => array(0 => array(), 1 => 'PHPStan\Type\Php\IteratorToArrayFunctionReturnTypeExtension'), 346 => array(0 => array(), 1 => 'PHPStan\Type\Php\AbsFunctionDynamicReturnTypeExtension'), 347 => array(0 => array(), 1 => 'PHPStan\Type\Php\IdateFunctionReturnTypeExtension'), 348 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayFilterFunctionReturnTypeHelper'), 349 => array(0 => array(), 1 => 'PHPStan\Type\Php\GmpOperatorTypeSpecifyingExtension'), 350 => array(0 => array(), 1 => 'PHPStan\Type\Php\ThrowableReturnTypeExtension'), 351 => array(0 => array(), 1 => 'PHPStan\Type\Php\DateIntervalCreateFromDateStringThrowTypeExtension'), 352 => array(0 => array(), 1 => 'PHPStan\Type\Php\RegexArrayShapeMatcher'), 353 => array(0 => array(), 1 => 'PHPStan\Type\Php\ClassExistsFunctionTypeSpecifyingExtension'), 354 => array(0 => array(), 1 => 'PHPStan\Type\Php\ImplodeFunctionReturnTypeExtension'), 355 => array(0 => array(), 1 => 'PHPStan\Type\Php\HighlightStringDynamicReturnTypeExtension'), 356 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayRandFunctionReturnTypeExtension'), 357 => array(0 => array(), 1 => 'PHPStan\Type\Php\DsMapDynamicMethodThrowTypeExtension'), 358 => array(0 => array(), 1 => 'PHPStan\Type\Php\RangeFunctionReturnTypeExtension'), 359 => array(0 => array(), 1 => 'PHPStan\Type\Php\GettimeofdayDynamicFunctionReturnTypeExtension'), 360 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayCombineHelper'), 361 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArraySearchFunctionDynamicReturnTypeExtension'), 362 => array(0 => array(), 1 => 'PHPStan\Type\Php\DateFunctionReturnTypeHelper'), 363 => array(0 => array(), 1 => 'PHPStan\Type\Php\DsMapDynamicReturnTypeExtension'), 364 => array(0 => array(), 1 => 'PHPStan\Type\Php\LtrimFunctionReturnTypeExtension'), 365 => array(0 => array(), 1 => 'PHPStan\Type\Php\RoundFunctionReturnTypeExtension'), 366 => array(0 => array(), 1 => 'PHPStan\Type\Php\DateTimeConstructorThrowTypeExtension'), 367 => array(0 => array(), 1 => 'PHPStan\Type\Php\JsonThrowOnErrorDynamicReturnTypeExtension'), 368 => array(0 => array(), 1 => 'PHPStan\Type\Php\StrvalFamilyFunctionReturnTypeExtension'), 369 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayReduceFunctionReturnTypeExtension'), 370 => array(0 => array(), 1 => 'PHPStan\Type\Php\RandomIntFunctionReturnTypeExtension'), 371 => array(0 => array(), 1 => 'PHPStan\Type\Php\IntdivThrowTypeExtension'), 372 => array(0 => array(), 1 => 'PHPStan\Type\Php\CountCharsFunctionDynamicReturnTypeExtension'), 373 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayFillFunctionReturnTypeExtension'), 374 => array(0 => array(), 1 => 'PHPStan\Type\Php\ReflectionClassIsSubclassOfTypeSpecifyingExtension'), 375 => array(0 => array(), 1 => 'PHPStan\Type\Php\MinMaxFunctionReturnTypeExtension'), 376 => array(0 => array(), 1 => 'PHPStan\Type\Php\SetTypeFunctionTypeSpecifyingExtension'), 377 => array(0 => array(), 1 => 'PHPStan\Type\Php\SubstrDynamicReturnTypeExtension'), 378 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayColumnFunctionReturnTypeExtension'), 379 => array(0 => array(), 1 => 'PHPStan\Type\Php\ParseUrlFunctionDynamicReturnTypeExtension'), 380 => array(0 => array(), 1 => 'PHPStan\Type\Php\DomDocumentCreateElementDynamicThrowTypeExtension'), 381 => array(0 => array(), 1 => 'PHPStan\Type\Php\HrtimeFunctionReturnTypeExtension'), 382 => array(0 => array(), 1 => 'PHPStan\Type\Php\ConstantHelper'), 383 => array(0 => array(), 1 => 'PHPStan\Type\Php\ExplodeFunctionDynamicReturnTypeExtension'), 384 => array(0 => array(), 1 => 'PHPStan\Type\Php\DateIntervalFormatFunctionReturnTypeExtension'), 385 => array(0 => array(), 1 => 'PHPStan\Type\Php\MethodExistsTypeSpecifyingExtension'), 386 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayChangeKeyCaseFunctionReturnTypeExtension'), 387 => array(0 => array(), 1 => 'PHPStan\Type\Php\StrTokFunctionReturnTypeExtension'), 388 => array(0 => array(), 1 => 'PHPStan\Type\Php\AssertThrowTypeExtension'), 389 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayPadDynamicReturnTypeExtension'), 390 => array(0 => array(), 1 => 'PHPStan\Type\Php\FunctionExistsFunctionTypeSpecifyingExtension'), 391 => array(0 => array(), 1 => 'PHPStan\Type\Php\BcMathNumberOperatorTypeSpecifyingExtension'), 392 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayCurrentDynamicReturnTypeExtension'), 393 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayFillKeysFunctionReturnTypeExtension'), 394 => array(0 => array(), 1 => 'PHPStan\Type\Php\IsAFunctionTypeSpecifyingExtension'), 395 => array(0 => array(), 1 => 'PHPStan\Type\Php\PregMatchParameterOutTypeExtension'), 396 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayPointerFunctionsDynamicReturnTypeExtension'), 397 => array(0 => array(), 1 => 'PHPStan\Type\Php\StrCaseFunctionsReturnTypeExtension'), 398 => array(0 => array(), 1 => 'PHPStan\Type\Php\SscanfFunctionDynamicReturnTypeExtension'), 399 => array(0 => array(), 1 => 'PHPStan\Type\Php\IsAFunctionTypeSpecifyingHelper'), 400 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayChunkFunctionReturnTypeExtension'), 401 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayKeyExistsFunctionTypeSpecifyingExtension'), 402 => array(0 => array(), 1 => 'PHPStan\Type\Php\NonEmptyStringFunctionsReturnTypeExtension'), 403 => array(0 => array(), 1 => 'PHPStan\Type\Php\SimpleXMLElementXpathMethodReturnTypeExtension'), 404 => array(0 => array(), 1 => 'PHPStan\Type\Php\ClosureBindDynamicReturnTypeExtension'), 405 => array(0 => array(), 1 => 'PHPStan\Type\Php\InArrayFunctionTypeSpecifyingExtension'), 406 => array(0 => array(), 1 => 'PHPStan\Type\Php\CompactFunctionReturnTypeExtension'), 407 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayFlipFunctionReturnTypeExtension'), 408 => array(0 => array(), 1 => 'PHPStan\Type\Php\DioStatDynamicFunctionReturnTypeExtension'), 409 => array(0 => array(), 1 => 'PHPStan\Type\Php\CurlGetinfoFunctionDynamicReturnTypeExtension'), 410 => array(0 => array(), 1 => 'PHPStan\Type\Php\CountFunctionReturnTypeExtension'), 411 => array(0 => array(), 1 => 'PHPStan\Type\Php\OpensslCipherFunctionsReturnTypeExtension'), 412 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArraySearchFunctionTypeSpecifyingExtension'), 413 => array(0 => array(), 1 => 'PHPStan\Type\Php\StatDynamicReturnTypeExtension'), 414 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArraySpliceFunctionReturnTypeExtension'), 415 => array(0 => array(), 1 => 'PHPStan\Type\Php\IsArrayFunctionTypeSpecifyingExtension'), 416 => array(0 => array(), 1 => 'PHPStan\Type\Php\StrrevFunctionReturnTypeExtension'), 417 => array(0 => array(), 1 => 'PHPStan\Type\Php\PdoStatementFetchAllReturnTypeExtension'), 418 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayIntersectKeyFunctionReturnTypeExtension'), 419 => array(0 => array(), 1 => 'PHPStan\Type\Php\OpenSslEncryptParameterOutTypeExtension'), 420 => array(0 => array(), 1 => 'PHPStan\Type\Php\JsonThrowTypeExtension'), 421 => array(0 => array(), 1 => 'PHPStan\Type\Php\NumberFormatFunctionDynamicReturnTypeExtension'), 422 => array(0 => array(), 1 => 'PHPStan\Type\Php\DefinedConstantTypeSpecifyingExtension'), 423 => array(0 => array(), 1 => 'PHPStan\Type\Php\GetCalledClassDynamicReturnTypeExtension'), 424 => array(0 => array(), 1 => 'PHPStan\Type\Php\HashFunctionsReturnTypeExtension'), 425 => array(0 => array(), 1 => 'PHPStan\Type\Php\DateTimeDynamicReturnTypeExtension'), 426 => array(0 => array(), 1 => 'PHPStan\Type\Php\AssertFunctionTypeSpecifyingExtension'), 427 => array(0 => array(), 1 => 'PHPStan\Type\Php\SprintfFunctionDynamicReturnTypeExtension'), 428 => array(0 => array(), 1 => 'PHPStan\Type\Php\MbFunctionsReturnTypeExtension'), 429 => array(0 => array(), 1 => 'PHPStan\Type\Php\DomDocumentCreateElementDynamicReturnTypeExtension'), 430 => array(0 => array(), 1 => 'PHPStan\Type\Php\ReflectionClassConstructorThrowTypeExtension'), 431 => array(0 => array(), 1 => 'PHPStan\Type\Php\TrimFunctionDynamicReturnTypeExtension'), 432 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayReverseFunctionReturnTypeExtension'), 433 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayFindFunctionReturnTypeExtension'), 434 => array(0 => array(), 1 => 'PHPStan\Type\Php\TriggerErrorDynamicReturnTypeExtension'), 435 => array(0 => array(), 1 => 'PHPStan\Type\Php\MbConvertEncodingFunctionReturnTypeExtension'), 436 => array(0 => array(), 1 => 'PHPStan\Type\Php\StrRepeatFunctionReturnTypeExtension'), 437 => array(0 => array(), 1 => 'PHPStan\Type\Php\FilterFunctionReturnTypeHelper'), 438 => array(0 => array(), 1 => 'PHPStan\Type\Php\DateTimeModifyMethodThrowTypeExtension'), 439 => array(0 => array(), 1 => 'PHPStan\Type\Php\PregSplitDynamicReturnTypeExtension'), 440 => array(0 => array(), 1 => 'PHPStan\Type\Php\ParseStrParameterOutTypeExtension'), 441 => array(0 => array(), 1 => 'PHPStan\Type\Php\GmpUnaryOperatorTypeSpecifyingExtension'), 442 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayValuesFunctionDynamicReturnTypeExtension'), 443 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArgumentBasedFunctionReturnTypeExtension'), 444 => array(0 => array(), 1 => 'PHPStan\Type\Php\DateFormatFunctionReturnTypeExtension'), 445 => array(0 => array(), 1 => 'PHPStan\Type\Php\IdateFunctionReturnTypeHelper'), 446 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayNextDynamicReturnTypeExtension'), 447 => array(0 => array(), 1 => 'PHPStan\Type\Php\ClosureBindToDynamicReturnTypeExtension'), 448 => array(0 => array(), 1 => 'PHPStan\Type\Php\DefineConstantTypeSpecifyingExtension'), 449 => array(0 => array(), 1 => 'PHPStan\Type\Php\GetClassDynamicReturnTypeExtension'), 450 => array(0 => array(), 1 => 'PHPStan\Type\Php\DateFormatMethodReturnTypeExtension'), 451 => array(0 => array(), 1 => 'PHPStan\Type\Php\DateIntervalConstructorThrowTypeExtension'), 452 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayCombineFunctionThrowTypeExtension'), 453 => array(0 => array(), 1 => 'PHPStan\Type\Php\IniGetReturnTypeExtension'), 454 => array(0 => array(), 1 => 'PHPStan\Type\Php\PregMatchTypeSpecifyingExtension'), 455 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayFirstLastDynamicReturnTypeExtension'), 456 => array(0 => array(), 1 => 'PHPStan\Type\Php\XMLReaderOpenReturnTypeExtension'), 457 => array(0 => array(), 1 => 'PHPStan\Type\Php\ReplaceFunctionsDynamicReturnTypeExtension'), 458 => array(0 => array(), 1 => 'PHPStan\Type\Php\ArrayReplaceFunctionReturnTypeExtension'), 459 => array(0 => array(), 1 => 'PHPStan\Type\Php\StrContainingTypeSpecifyingExtension'), 460 => array(0 => array(), 1 => 'PHPStan\Type\Php\IsSubclassOfFunctionTypeSpecifyingExtension'), 461 => array(0 => array(), 1 => 'PHPStan\Type\FileTypeMapper'), 462 => array(0 => array(0 => NULL, 1 => '@PHPStan\Php\PhpVersionFactoryFactory::create'), 1 => 'PHPStan\Php\PhpVersionFactory'), 463 => array(0 => array(), 1 => 'PHPStan\Php\PhpVersionFactoryFactory'), 464 => array(0 => array(), 1 => 'PHPStan\Php\ComposerPhpVersionFactory'), 465 => array(0 => array(0 => NULL, 1 => '@PHPStan\Php\PhpVersionFactory::create'), 1 => 'PHPStan\Php\PhpVersion')), 'PHPStan\DependencyInjection\RegisteredRule' => array(0 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Variables\UnsetRule'), 1 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Variables\ThisInStaticStatementRule'), 2 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Variables\InvalidVariableAssignRule'), 3 => array(0 => array(0 => 1), 1 => 'PHPStan\Rules\Variables\EmptyRule'), 4 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Variables\ParameterOutAssignedTypeRule'), 5 => array(0 => array(0 => 1), 1 => 'PHPStan\Rules\Variables\NullCoalesceRule'), 6 => array(0 => array(0 => 1), 1 => 'PHPStan\Rules\Variables\IssetRule'), 7 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Variables\ThisInGlobalStatementRule'), 8 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Variables\ParameterOutExecutionEndTypeRule'), 9 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Variables\DefinedVariableRule'), 10 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Variables\CompactVariablesRule'), 11 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Variables\VariableCloningRule'), 12 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\EnumCases\EnumCaseAttributesRule'), 13 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\EnumCases\EnumCaseOutsideEnumRule'), 14 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Keywords\ContinueBreakInLoopRule'), 15 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Keywords\DeclareStrictTypesRule'), 16 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Keywords\RequireFileExistsRule'), 17 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Missing\MissingReturnRule'), 18 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Pure\PureMethodRule'), 19 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Pure\PureFunctionRule'), 20 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Names\UsedNamesRule'), 21 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Generics\MethodTagTemplateTypeTraitRule'), 22 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Generics\EnumTemplateTypeRule'), 23 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Generics\FunctionTemplateTypeRule'), 24 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Generics\MethodTagTemplateTypeRule'), 25 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Generics\MethodSignatureVarianceRule'), 26 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Generics\UsedTraitsRule'), 27 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Generics\TraitTemplateTypeRule'), 28 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Generics\MethodTemplateTypeRule'), 29 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Generics\PropertyVarianceRule'), 30 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Generics\EnumAncestorsRule'), 31 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Generics\ClassTemplateTypeRule'), 32 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Generics\FunctionSignatureVarianceRule'), 33 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Generics\ClassAncestorsRule'), 34 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Generics\InterfaceAncestorsRule'), 35 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Generics\InterfaceTemplateTypeRule'), 36 => array(0 => array(0 => 5), 1 => 'PHPStan\Rules\DateTimeInstantiationRule'), 37 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Namespaces\ExistingNamesInUseRule'), 38 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Namespaces\ExistingNamesInGroupUseRule'), 39 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Regexp\RegularExpressionPatternRule'), 40 => array(0 => array(0 => 5), 1 => 'PHPStan\Rules\Regexp\RegularExpressionQuotingRule'), 41 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Whitespace\FileWhitespaceRule'), 42 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\DuplicateTraitDeclarationRule'), 43 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Classes\AccessPrivateConstantThroughStaticRule'), 44 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\AllowedSubTypesRule'), 45 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Classes\MethodTagTraitUseRule'), 46 => array(0 => array(0 => 1), 1 => 'PHPStan\Rules\Classes\UnusedConstructorParametersRule'), 47 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\ClassAttributesRule'), 48 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\InstantiationRule'), 49 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Classes\PropertyTagTraitRule'), 50 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Classes\MixinTraitUseRule'), 51 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Classes\PropertyTagRule'), 52 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\ExistingClassesInInterfaceExtendsRule'), 53 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\ReadOnlyClassRule'), 54 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\ClassConstantRule'), 55 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\ExistingClassInInstanceOfRule'), 56 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Classes\MixinTraitRule'), 57 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Classes\RequireExtendsRule'), 58 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\InstantiationCallableRule'), 59 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\LocalTypeAliasesRule'), 60 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Classes\MixinRule'), 61 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\InvalidPromotedPropertiesRule'), 62 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\ClassConstantAttributesRule'), 63 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\LocalTypeTraitAliasesRule'), 64 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Classes\MethodTagRule'), 65 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Classes\MethodTagTraitRule'), 66 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Classes\ImpossibleInstanceOfRule'), 67 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Classes\RequireImplementsRule'), 68 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\ExistingClassesInClassImplementsRule'), 69 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\LocalTypeTraitUseAliasesRule'), 70 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\ExistingClassInClassExtendsRule'), 71 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\TraitAttributeClassRule'), 72 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\ExistingClassesInEnumImplementsRule'), 73 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\ExistingClassInTraitUseRule'), 74 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\EnumSanityRule'), 75 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\NonClassAttributeClassRule'), 76 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\NewStaticRule'), 77 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Classes\DuplicateDeclarationRule'), 78 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Classes\PropertyTagTraitUseRule'), 79 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Constants\ConstantAttributesRule'), 80 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Constants\OverridingConstantRule'), 81 => array(0 => array(0 => 1), 1 => 'PHPStan\Rules\Constants\ConstantRule'), 82 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Constants\NativeTypedClassConstantRule'), 83 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Constants\MagicConstantContextRule'), 84 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Constants\ClassAsClassConstantRule'), 85 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Constants\FinalPrivateConstantRule'), 86 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Constants\ValueAssignedToClassConstantRule'), 87 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Constants\FinalConstantRule'), 88 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Constants\DynamicClassConstantFetchRule'), 89 => array(0 => array(0 => 6), 1 => 'PHPStan\Rules\Constants\MissingClassConstantTypehintRule'), 90 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\ExistingClassesInArrowFunctionTypehintsRule'), 91 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\CallToFunctionParametersRule'), 92 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\ParamAttributesRule'), 93 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\ExistingClassesInTypehintsRule'), 94 => array(0 => array(0 => 5), 1 => 'PHPStan\Rules\Functions\ArrayValuesRule'), 95 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\PrintfArrayParametersRule'), 96 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Functions\UselessFunctionReturnValueRule'), 97 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\CallToFunctionStatementWithNoDiscardRule'), 98 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\FilterVarRule'), 99 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\ReturnNullsafeByRefRule'), 100 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\ExistingClassesInClosureTypehintsRule'), 101 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Functions\IncompatibleDefaultParameterTypeRule'), 102 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\CallToNonExistentFunctionRule'), 103 => array(0 => array(0 => 1), 1 => 'PHPStan\Rules\Functions\UnusedClosureUsesRule'), 104 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\PrintfParametersRule'), 105 => array(0 => array(0 => 6), 1 => 'PHPStan\Rules\Functions\MissingFunctionReturnTypehintRule'), 106 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\VariadicParametersDeclarationRule'), 107 => array(0 => array(0 => 5), 1 => 'PHPStan\Rules\Functions\CallUserFuncRule'), 108 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\InnerFunctionRule'), 109 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\FunctionCallableRule'), 110 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\DefineParametersRule'), 111 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\ArrowFunctionReturnNullsafeByRefRule'), 112 => array(0 => array(0 => 5), 1 => 'PHPStan\Rules\Functions\ImplodeParameterCastableToStringRule'), 113 => array(0 => array(0 => 5), 1 => 'PHPStan\Rules\Functions\SortParameterCastableToStringRule'), 114 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Functions\CallToFunctionStatementWithoutSideEffectsRule'), 115 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\InvalidParameterNameRule'), 116 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Functions\ArrowFunctionReturnTypeRule'), 117 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\InvalidLexicalVariablesInClosureUseRule'), 118 => array(0 => array(0 => 5), 1 => 'PHPStan\Rules\Functions\ParameterCastableToStringRule'), 119 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\FunctionAttributesRule'), 120 => array(0 => array(0 => 5), 1 => 'PHPStan\Rules\Functions\RandomIntParametersRule'), 121 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Functions\ReturnTypeRule'), 122 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Functions\CallCallablesRule'), 123 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Functions\ClosureReturnTypeRule'), 124 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Functions\IncompatibleArrowFunctionDefaultParameterTypeRule'), 125 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Functions\IncompatibleClosureDefaultParameterTypeRule'), 126 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\ArrowFunctionAttributesRule'), 127 => array(0 => array(0 => 6), 1 => 'PHPStan\Rules\Functions\MissingFunctionParameterTypehintRule'), 128 => array(0 => array(0 => 5), 1 => 'PHPStan\Rules\Functions\ArrayFilterRule'), 129 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\RedefinedParametersRule'), 130 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Functions\ClosureAttributesRule'), 131 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Operators\InvalidIncDecOperationRule'), 132 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Operators\InvalidBinaryOperationRule'), 133 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Operators\InvalidAssignVarRule'), 134 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Operators\BacktickRule'), 135 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Operators\PipeOperatorRule'), 136 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Operators\InvalidUnaryOperationRule'), 137 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Operators\InvalidComparisonOperationRule'), 138 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Generators\YieldTypeRule'), 139 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Generators\YieldInGeneratorRule'), 140 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Generators\YieldFromTypeRule'), 141 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyAssignRefRule'), 142 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Properties\GetNonVirtualPropertyHookReadRule'), 143 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyRule'), 144 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\ReadingWriteOnlyPropertiesRule'), 145 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\PropertyHookAttributesRule'), 146 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\InvalidCallablePropertyTypeRule'), 147 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\ExistingClassesInPropertyHookTypehintsRule'), 148 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\PropertyAttributesRule'), 149 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\AccessPropertiesRule'), 150 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Properties\NullsafePropertyFetchRule'), 151 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\PropertyAssignRefRule'), 152 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\SetPropertyHookParameterRule'), 153 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Properties\ReadOnlyPropertyAssignRefRule'), 154 => array(0 => array(0 => 6), 1 => 'PHPStan\Rules\Properties\MissingPropertyTypehintRule'), 155 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Properties\DefaultValueTypesAssignedToPropertiesRule'), 156 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\ExistingClassesInPropertiesRule'), 157 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\MissingReadOnlyByPhpDocPropertyAssignRule'), 158 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\OverridingPropertyRule'), 159 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Properties\TypesAssignedToPropertiesRule'), 160 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Properties\AccessPrivatePropertyThroughStaticRule'), 161 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\PropertyInClassRule'), 162 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\AccessStaticPropertiesRule'), 163 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\MissingReadOnlyPropertyAssignRule'), 164 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyAssignRule'), 165 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\AccessStaticPropertiesInAssignRule'), 166 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\WritingToReadOnlyPropertiesRule'), 167 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\ReadOnlyPropertyRule'), 168 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\AccessPropertiesInAssignRule'), 169 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Properties\ReadOnlyPropertyAssignRule'), 170 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Properties\PropertiesInInterfaceRule'), 171 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Properties\SetNonVirtualPropertyHookAssignRule'), 172 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Types\InvalidTypesInUnionRule'), 173 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Traits\ConflictingTraitConstantsRule'), 174 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Traits\TraitAttributesRule'), 175 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Traits\ConstantsInTraitsRule'), 176 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Traits\NotAnalysedTraitRule'), 177 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\TooWideTypehints\TooWideMethodReturnTypehintRule'), 178 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\TooWideTypehints\TooWideMethodParameterOutTypeRule'), 179 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\TooWideTypehints\TooWideFunctionReturnTypehintRule'), 180 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\TooWideTypehints\TooWideArrowFunctionReturnTypehintRule'), 181 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\TooWideTypehints\TooWideClosureReturnTypehintRule'), 182 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\TooWideTypehints\TooWideFunctionParameterOutTypeRule'), 183 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\TooWideTypehints\TooWidePropertyTypeRule'), 184 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\ExistingClassesInTypehintsRule'), 185 => array(0 => array(0 => 6), 1 => 'PHPStan\Rules\Methods\MissingMethodReturnTypehintRule'), 186 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Methods\CallToConstructorStatementWithoutSideEffectsRule'), 187 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\ConsistentConstructorDeclarationRule'), 188 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\CallToMethodStatementWithNoDiscardRule'), 189 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Methods\CallToStaticMethodStatementWithoutSideEffectsRule'), 190 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Methods\IncompatibleDefaultParameterTypeRule'), 191 => array(0 => array(0 => 6), 1 => 'PHPStan\Rules\Methods\MissingMethodParameterTypehintRule'), 192 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\MethodAttributesRule'), 193 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Methods\CallToMethodStatementWithoutSideEffectsRule'), 194 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Methods\NullsafeMethodCallRule'), 195 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\CallToStaticMethodStatementWithNoDiscardRule'), 196 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Methods\CallPrivateMethodThroughStaticRule'), 197 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\AbstractMethodInNonAbstractClassRule'), 198 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\AbstractPrivateMethodRule'), 199 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\StaticMethodCallableRule'), 200 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\CallMethodsRule'), 201 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Methods\ReturnTypeRule'), 202 => array(0 => array(0 => 6), 1 => 'PHPStan\Rules\Methods\MissingMethodSelfOutTypeRule'), 203 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\FinalPrivateMethodRule'), 204 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\OverridingMethodRule'), 205 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\ConstructorReturnTypeRule'), 206 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\MethodVisibilityInInterfaceRule'), 207 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\MissingMethodImplementationRule'), 208 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\ConsistentConstructorRule'), 209 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\MethodCallableRule'), 210 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\MissingMagicSerializationMethodsRule'), 211 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Methods\CallStaticMethodsRule'), 212 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\DeadCode\CallToConstructorStatementWithoutImpurePointsRule'), 213 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\DeadCode\CallToStaticMethodStatementWithoutImpurePointsRule'), 214 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\DeadCode\UnreachableStatementRule'), 215 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\DeadCode\CallToMethodStatementWithoutImpurePointsRule'), 216 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\DeadCode\NoopRule'), 217 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\DeadCode\UnusedPrivatePropertyRule'), 218 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\DeadCode\UnusedPrivateConstantRule'), 219 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\DeadCode\CallToFunctionStatementWithoutImpurePointsRule'), 220 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\DeadCode\UnusedPrivateMethodRule'), 221 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Cast\VoidCastRule'), 222 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Cast\PrintRule'), 223 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Cast\UnsetCastRule'), 224 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Cast\InvalidPartOfEncapsedStringRule'), 225 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Cast\DeprecatedCastRule'), 226 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Cast\InvalidCastRule'), 227 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Cast\EchoRule'), 228 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\WrongVariableNameInVarTagRule'), 229 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\InvalidPhpDocTagValueRule'), 230 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\RequireExtendsDefinitionTraitRule'), 231 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\IncompatiblePropertyPhpDocTypeRule'), 232 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\IncompatiblePhpDocTypeRule'), 233 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\SealedDefinitionClassRule'), 234 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\RequireImplementsDefinitionTraitRule'), 235 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\InvalidPHPStanDocTagRule'), 236 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\InvalidPhpDocVarTagTypeRule'), 237 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\IncompatibleClassConstantPhpDocTypeRule'), 238 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\FunctionConditionalReturnTypeRule'), 239 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\IncompatibleSelfOutTypeRule'), 240 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\InvalidThrowsPhpDocValueRule'), 241 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\RequireExtendsDefinitionClassRule'), 242 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\MethodAssertRule'), 243 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\IncompatiblePropertyHookPhpDocTypeRule'), 244 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\IncompatibleParamImmediatelyInvokedCallableRule'), 245 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\PhpDoc\SealedDefinitionTraitRule'), 246 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\MethodConditionalReturnTypeRule'), 247 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\VarTagChangedExpressionTypeRule'), 248 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\RequireImplementsDefinitionClassRule'), 249 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\PhpDoc\FunctionAssertRule'), 250 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Api\RuntimeReflectionFunctionRule'), 251 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Api\ApiInstantiationRule'), 252 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Api\NodeConnectingVisitorAttributesRule'), 253 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Api\ApiClassConstFetchRule'), 254 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Api\OldPhpParser4ClassRule'), 255 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Api\ApiClassExtendsRule'), 256 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Api\GetTemplateTypeRule'), 257 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Api\ApiInterfaceExtendsRule'), 258 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Api\ApiTraitUseRule'), 259 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Api\ApiMethodCallRule'), 260 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Api\ApiStaticCallRule'), 261 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Api\PhpStanNamespaceIn3rdPartyPackageRule'), 262 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Api\ApiInstanceofRule'), 263 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Api\RuntimeReflectionInstantiationRule'), 264 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Api\ApiInstanceofTypeRule'), 265 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Api\ApiClassImplementsRule'), 266 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Exceptions\ThrowsVoidMethodWithExplicitThrowPointRule'), 267 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Exceptions\ThrowsVoidFunctionWithExplicitThrowPointRule'), 268 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Exceptions\ThrowExprTypeRule'), 269 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Exceptions\CaughtExceptionExistenceRule'), 270 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Exceptions\OverwrittenExitPointByFinallyRule'), 271 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Exceptions\NoncapturingCatchRule'), 272 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Exceptions\ThrowsVoidPropertyHookWithExplicitThrowPointRule'), 273 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Exceptions\ThrowExpressionRule'), 274 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Exceptions\CatchWithUnthrownExceptionRule'), 275 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Arrays\OffsetAccessValueAssignmentRule'), 276 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Arrays\ArrayDestructuringRule'), 277 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Arrays\UnpackIterableInArrayRule'), 278 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Arrays\OffsetAccessAssignOpRule'), 279 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Arrays\InvalidKeyInArrayItemRule'), 280 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Arrays\OffsetAccessAssignmentRule'), 281 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Arrays\OffsetAccessWithoutDimForReadingRule'), 282 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Arrays\InvalidKeyInArrayDimFetchRule'), 283 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Arrays\DeadForeachRule'), 284 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Arrays\ArrayUnpackingRule'), 285 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Arrays\IterableInForeachRule'), 286 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Arrays\DuplicateKeysInLiteralArraysRule'), 287 => array(0 => array(0 => 3), 1 => 'PHPStan\Rules\Arrays\NonexistentOffsetInArrayDimFetchRule'), 288 => array(0 => array(0 => 0), 1 => 'PHPStan\Rules\Ignore\IgnoreParseErrorRule'), 289 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\ImpossibleCheckTypeFunctionCallRule'), 290 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\StrictComparisonOfDifferentTypesRule'), 291 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\ImpossibleCheckTypeStaticMethodCallRule'), 292 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\BooleanAndConstantConditionRule'), 293 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\WhileLoopAlwaysTrueConditionRule'), 294 => array(0 => array(0 => 2), 1 => 'PHPStan\Rules\Comparison\UsageOfVoidMatchExpressionRule'), 295 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\DoWhileLoopConstantConditionRule'), 296 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\BooleanOrConstantConditionRule'), 297 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\IfConstantConditionRule'), 298 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\ElseIfConstantConditionRule'), 299 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\BooleanNotConstantConditionRule'), 300 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\TernaryOperatorConstantConditionRule'), 301 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\WhileLoopAlwaysFalseConditionRule'), 302 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\MatchExpressionRule'), 303 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\ConstantLooseComparisonRule'), 304 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\LogicalXorConstantConditionRule'), 305 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\NumberComparisonOperatorsConstantConditionRule'), 306 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Comparison\ImpossibleCheckTypeMethodCallRule')), 'PHPStan\DependencyInjection\ValidatesStubFiles' => array(0 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\MethodTagTemplateTypeTraitRule'), 1 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\EnumTemplateTypeRule'), 2 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\FunctionTemplateTypeRule'), 3 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\MethodTagTemplateTypeRule'), 4 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\MethodSignatureVarianceRule'), 5 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\UsedTraitsRule'), 6 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\TraitTemplateTypeRule'), 7 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\MethodTemplateTypeRule'), 8 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\PropertyVarianceRule'), 9 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\EnumAncestorsRule'), 10 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\ClassTemplateTypeRule'), 11 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\FunctionSignatureVarianceRule'), 12 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\ClassAncestorsRule'), 13 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\InterfaceAncestorsRule'), 14 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\InterfaceTemplateTypeRule'), 15 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\MethodTagTraitUseRule'), 16 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\PropertyTagTraitRule'), 17 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\MixinTraitUseRule'), 18 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\PropertyTagRule'), 19 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\ExistingClassesInInterfaceExtendsRule'), 20 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\DuplicateClassDeclarationRule'), 21 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\MixinTraitRule'), 22 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\LocalTypeAliasesRule'), 23 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\MixinRule'), 24 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\LocalTypeTraitAliasesRule'), 25 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\MethodTagRule'), 26 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\MethodTagTraitRule'), 27 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\ExistingClassesInClassImplementsRule'), 28 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\LocalTypeTraitUseAliasesRule'), 29 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\ExistingClassInClassExtendsRule'), 30 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\ExistingClassInTraitUseRule'), 31 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\DuplicateDeclarationRule'), 32 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\PropertyTagTraitUseRule'), 33 => array(0 => array(), 1 => 'PHPStan\Rules\Functions\ExistingClassesInTypehintsRule'), 34 => array(0 => array(), 1 => 'PHPStan\Rules\Functions\MissingFunctionReturnTypehintRule'), 35 => array(0 => array(), 1 => 'PHPStan\Rules\Functions\DuplicateFunctionDeclarationRule'), 36 => array(0 => array(), 1 => 'PHPStan\Rules\Functions\MissingFunctionParameterTypehintRule'), 37 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\MissingPropertyTypehintRule'), 38 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\ExistingClassesInPropertiesRule'), 39 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\ExistingClassesInTypehintsRule'), 40 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\MissingMethodReturnTypehintRule'), 41 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\MissingMethodParameterTypehintRule'), 42 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\MissingMethodSelfOutTypeRule'), 43 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\OverridingMethodRule'), 44 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\InvalidPhpDocTagValueRule'), 45 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\RequireExtendsDefinitionTraitRule'), 46 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\IncompatiblePropertyPhpDocTypeRule'), 47 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\IncompatiblePhpDocTypeRule'), 48 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\SealedDefinitionClassRule'), 49 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\RequireImplementsDefinitionTraitRule'), 50 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\InvalidPHPStanDocTagRule'), 51 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\IncompatibleClassConstantPhpDocTypeRule'), 52 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\FunctionConditionalReturnTypeRule'), 53 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\IncompatibleSelfOutTypeRule'), 54 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\InvalidThrowsPhpDocValueRule'), 55 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\RequireExtendsDefinitionClassRule'), 56 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\MethodAssertRule'), 57 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\IncompatibleParamImmediatelyInvokedCallableRule'), 58 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\SealedDefinitionTraitRule'), 59 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\MethodConditionalReturnTypeRule'), 60 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\RequireImplementsDefinitionClassRule'), 61 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\FunctionAssertRule')), 'PHPStan\DependencyInjection\RegisteredCollector' => array(0 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Traits\TraitUseCollector'), 1 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\Traits\TraitDeclarationCollector'), 2 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\DeadCode\PossiblyPureStaticCallCollector'), 3 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\DeadCode\PossiblyPureMethodCallCollector'), 4 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\DeadCode\PossiblyPureFuncCallCollector'), 5 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\DeadCode\MethodWithoutImpurePointsCollector'), 6 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\DeadCode\FunctionWithoutImpurePointsCollector'), 7 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\DeadCode\ConstructorWithoutImpurePointsCollector'), 8 => array(0 => array(0 => 4), 1 => 'PHPStan\Rules\DeadCode\PossiblyPureNewCollector')), 'PHPStan\DependencyInjection\GenerateFactory' => array(0 => array(0 => array(0 => 'PHPStan\Analyser\ResultCache\ResultCacheManagerFactory'), 1 => 'PHPStan\Analyser\ResultCache\ResultCacheManager'), 1 => array(0 => array(0 => 'PHPStan\Analyser\InternalScopeFactoryFactory', 1 => 'PHPStan\Analyser\LazyInternalScopeFactory'), 1 => 'PHPStan\Analyser\LazyInternalScopeFactory'), 2 => array(0 => array(0 => 'PHPStan\File\FileExcluderRawFactory'), 1 => 'PHPStan\File\FileExcluder'), 3 => array(0 => array(0 => 'PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedSingleFileSourceLocatorFactory'), 1 => 'PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedSingleFileSourceLocator'), 4 => array(0 => array(0 => 'PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedPsrAutoloaderLocatorFactory'), 1 => 'PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedPsrAutoloaderLocator'), 5 => array(0 => array(0 => 'PHPStan\Reflection\ClassReflectionFactory'), 1 => 'PHPStan\Reflection\ClassReflection'), 6 => array(0 => array(0 => 'PHPStan\Reflection\Php\PhpMethodReflectionFactory'), 1 => 'PHPStan\Reflection\Php\PhpMethodReflection'), 7 => array(0 => array(0 => 'PHPStan\Reflection\FunctionReflectionFactory'), 1 => 'PHPStan\Reflection\Php\PhpFunctionReflection')), 'PHPStan\DependencyInjection\NonAutowiredService' => array(0 => array(0 => array(0 => 'parentDirectoryRelativePathHelper'), 1 => 'PHPStan\File\ParentDirectoryRelativePathHelper'), 1 => array(0 => array(0 => 'simpleRelativePathHelper'), 1 => 'PHPStan\File\SimpleRelativePathHelper'), 2 => array(0 => array(0 => 'betterReflectionProvider'), 1 => 'PHPStan\Reflection\BetterReflection\BetterReflectionProvider'))), // methods array(), // properties array(), // method parameters array('PHPStan\DependencyInjection\AutowiredParameter' => array(0 => array(0 => array(0 => '@cacheStorage'), 1 => 'PHPStan\Cache\Cache', 2 => 'storage', 3 => '__construct'), 1 => array(0 => array(), 1 => 'PHPStan\Parallel\ParallelAnalyser', 2 => 'internalErrorsCountLimit', 3 => '__construct'), 2 => array(0 => array(0 => '%parallel.processTimeout%'), 1 => 'PHPStan\Parallel\ParallelAnalyser', 2 => 'processTimeout', 3 => '__construct'), 3 => array(0 => array(0 => '%parallel.buffer%'), 1 => 'PHPStan\Parallel\ParallelAnalyser', 2 => 'decoderBufferSize', 3 => '__construct'), 4 => array(0 => array(0 => '%parallel.buffer%'), 1 => 'PHPStan\Parallel\WorkerRunner', 2 => 'decoderBufferSize', 3 => '__construct'), 5 => array(0 => array(0 => '%parallel.jobSize%'), 1 => 'PHPStan\Parallel\Scheduler', 2 => 'jobSize', 3 => '__construct'), 6 => array(0 => array(0 => '%parallel.maximumNumberOfProcesses%'), 1 => 'PHPStan\Parallel\Scheduler', 2 => 'maximumNumberOfProcesses', 3 => '__construct'), 7 => array(0 => array(0 => '%parallel.minimumNumberOfJobsPerProcess%'), 1 => 'PHPStan\Parallel\Scheduler', 2 => 'minimumNumberOfJobsPerProcess', 3 => '__construct'), 8 => array(0 => array(), 1 => 'PHPStan\Rules\IssetCheck', 2 => 'checkAdvancedIsset', 3 => '__construct'), 9 => array(0 => array(), 1 => 'PHPStan\Rules\IssetCheck', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 10 => array(0 => array(), 1 => 'PHPStan\Rules\Variables\DefinedVariableRule', 2 => 'cliArgumentsVariablesRegistered', 3 => '__construct'), 11 => array(0 => array(), 1 => 'PHPStan\Rules\Variables\DefinedVariableRule', 2 => 'checkMaybeUndefinedVariables', 3 => '__construct'), 12 => array(0 => array(), 1 => 'PHPStan\Rules\Variables\CompactVariablesRule', 2 => 'checkMaybeUndefinedVariables', 3 => '__construct'), 13 => array(0 => array(), 1 => 'PHPStan\Rules\Keywords\RequireFileExistsRule', 2 => 'currentWorkingDirectory', 3 => '__construct'), 14 => array(0 => array(), 1 => 'PHPStan\Rules\Missing\MissingReturnRule', 2 => 'checkExplicitMixedMissingReturn', 3 => '__construct'), 15 => array(0 => array(), 1 => 'PHPStan\Rules\Missing\MissingReturnRule', 2 => 'checkPhpDocMissingReturn', 3 => '__construct'), 16 => array(0 => array(), 1 => 'PHPStan\Rules\FunctionDefinitionCheck', 2 => 'checkClassCaseSensitivity', 3 => '__construct'), 17 => array(0 => array(), 1 => 'PHPStan\Rules\FunctionDefinitionCheck', 2 => 'checkThisOnly', 3 => '__construct'), 18 => array(0 => array(0 => '%featureToggles.skipCheckGenericClasses%'), 1 => 'PHPStan\Rules\Generics\GenericAncestorsCheck', 2 => 'skipCheckGenericClasses', 3 => '__construct'), 19 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\GenericAncestorsCheck', 2 => 'checkMissingTypehints', 3 => '__construct'), 20 => array(0 => array(), 1 => 'PHPStan\Rules\Generics\TemplateTypeCheck', 2 => 'checkClassCaseSensitivity', 3 => '__construct'), 21 => array(0 => array(), 1 => 'PHPStan\Rules\MissingTypehintCheck', 2 => 'checkMissingCallableSignature', 3 => '__construct'), 22 => array(0 => array(0 => '%featureToggles.skipCheckGenericClasses%'), 1 => 'PHPStan\Rules\MissingTypehintCheck', 2 => 'skipCheckGenericClasses', 3 => '__construct'), 23 => array(0 => array(0 => '%featureToggles.checkGenericIterableClasses%'), 1 => 'PHPStan\Rules\MissingTypehintCheck', 2 => 'checkGenericIterableClasses', 3 => '__construct'), 24 => array(0 => array(), 1 => 'PHPStan\Rules\Namespaces\ExistingNamesInUseRule', 2 => 'checkFunctionNameCase', 3 => '__construct'), 25 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Namespaces\ExistingNamesInUseRule', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 26 => array(0 => array(), 1 => 'PHPStan\Rules\Namespaces\ExistingNamesInGroupUseRule', 2 => 'checkFunctionNameCase', 3 => '__construct'), 27 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Namespaces\ExistingNamesInGroupUseRule', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 28 => array(0 => array(), 1 => 'PHPStan\Rules\RuleLevelHelper', 2 => 'checkNullables', 3 => '__construct'), 29 => array(0 => array(), 1 => 'PHPStan\Rules\RuleLevelHelper', 2 => 'checkThisOnly', 3 => '__construct'), 30 => array(0 => array(), 1 => 'PHPStan\Rules\RuleLevelHelper', 2 => 'checkUnionTypes', 3 => '__construct'), 31 => array(0 => array(), 1 => 'PHPStan\Rules\RuleLevelHelper', 2 => 'checkExplicitMixed', 3 => '__construct'), 32 => array(0 => array(), 1 => 'PHPStan\Rules\RuleLevelHelper', 2 => 'checkImplicitMixed', 3 => '__construct'), 33 => array(0 => array(), 1 => 'PHPStan\Rules\RuleLevelHelper', 2 => 'checkBenevolentUnionTypes', 3 => '__construct'), 34 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\RuleLevelHelper', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 35 => array(0 => array(0 => '%typeAliases%'), 1 => 'PHPStan\Rules\Classes\LocalTypeAliasesCheck', 2 => 'globalTypeAliases', 3 => '__construct'), 36 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\LocalTypeAliasesCheck', 2 => 'checkMissingTypehints', 3 => '__construct'), 37 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\LocalTypeAliasesCheck', 2 => 'checkClassCaseSensitivity', 3 => '__construct'), 38 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Classes\LocalTypeAliasesCheck', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 39 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\MethodTagCheck', 2 => 'checkClassCaseSensitivity', 3 => '__construct'), 40 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\MethodTagCheck', 2 => 'checkMissingTypehints', 3 => '__construct'), 41 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Classes\MethodTagCheck', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 42 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Classes\InstantiationRule', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 43 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Classes\ExistingClassesInInterfaceExtendsRule', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 44 => array(0 => array(0 => '%featureToggles.checkNonStringableDynamicAccess%'), 1 => 'PHPStan\Rules\Classes\ClassConstantRule', 2 => 'checkNonStringableDynamicAccess', 3 => '__construct'), 45 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\MixinCheck', 2 => 'checkClassCaseSensitivity', 3 => '__construct'), 46 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\MixinCheck', 2 => 'checkMissingTypehints', 3 => '__construct'), 47 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Classes\MixinCheck', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 48 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\ExistingClassInInstanceOfRule', 2 => 'checkClassCaseSensitivity', 3 => '__construct'), 49 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Classes\ExistingClassInInstanceOfRule', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 50 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\PropertyTagCheck', 2 => 'checkClassCaseSensitivity', 3 => '__construct'), 51 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\PropertyTagCheck', 2 => 'checkMissingTypehints', 3 => '__construct'), 52 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Classes\PropertyTagCheck', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 53 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\ImpossibleInstanceOfRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 54 => array(0 => array(), 1 => 'PHPStan\Rules\Classes\ImpossibleInstanceOfRule', 2 => 'reportAlwaysTrueInLastCondition', 3 => '__construct'), 55 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Classes\ImpossibleInstanceOfRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 56 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Classes\ExistingClassesInClassImplementsRule', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 57 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Classes\ExistingClassInClassExtendsRule', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 58 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Classes\ExistingClassesInEnumImplementsRule', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 59 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Classes\ExistingClassInTraitUseRule', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 60 => array(0 => array(), 1 => 'PHPStan\Rules\Constants\OverridingConstantRule', 2 => 'checkPhpDocMethodSignatures', 3 => '__construct'), 61 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Constants\ConstantRule', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 62 => array(0 => array(0 => '%featureToggles.checkDynamicConstantNameValues%'), 1 => 'PHPStan\Rules\Constants\ValueAssignedToClassConstantRule', 2 => 'checkDynamicConstantNameValues', 3 => '__construct'), 63 => array(0 => array(), 1 => 'PHPStan\Rules\Functions\ArrayValuesRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 64 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Functions\ArrayValuesRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 65 => array(0 => array(), 1 => 'PHPStan\Rules\Functions\CallToNonExistentFunctionRule', 2 => 'checkFunctionNameCase', 3 => '__construct'), 66 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Functions\CallToNonExistentFunctionRule', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 67 => array(0 => array(), 1 => 'PHPStan\Rules\Functions\FunctionCallableRule', 2 => 'checkFunctionNameCase', 3 => '__construct'), 68 => array(0 => array(), 1 => 'PHPStan\Rules\Functions\FunctionCallableRule', 2 => 'reportMaybes', 3 => '__construct'), 69 => array(0 => array(), 1 => 'PHPStan\Rules\Functions\RandomIntParametersRule', 2 => 'reportMaybes', 3 => '__construct'), 70 => array(0 => array(), 1 => 'PHPStan\Rules\Functions\CallCallablesRule', 2 => 'reportMaybes', 3 => '__construct'), 71 => array(0 => array(), 1 => 'PHPStan\Rules\Functions\ArrayFilterRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 72 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Functions\ArrayFilterRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 73 => array(0 => array(0 => '%featureToggles.checkExtensionsForComparisonOperators%'), 1 => 'PHPStan\Rules\Operators\InvalidComparisonOperationRule', 2 => 'checkExtensionsForComparisonOperators', 3 => '__construct'), 74 => array(0 => array(), 1 => 'PHPStan\Rules\Generators\YieldInGeneratorRule', 2 => 'reportMaybes', 3 => '__construct'), 75 => array(0 => array(), 1 => 'PHPStan\Rules\Generators\YieldFromTypeRule', 2 => 'reportMaybes', 3 => '__construct'), 76 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\ReadingWriteOnlyPropertiesRule', 2 => 'checkThisOnly', 3 => '__construct'), 77 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Properties\AccessStaticPropertiesCheck', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 78 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\SetPropertyHookParameterRule', 2 => 'checkPhpDocMethodSignatures', 3 => '__construct'), 79 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\SetPropertyHookParameterRule', 2 => 'checkMissingTypehints', 3 => '__construct'), 80 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\AccessPropertiesCheck', 2 => 'reportMagicProperties', 3 => '__construct'), 81 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\AccessPropertiesCheck', 2 => 'checkDynamicProperties', 3 => '__construct'), 82 => array(0 => array(0 => '%featureToggles.checkNonStringableDynamicAccess%'), 1 => 'PHPStan\Rules\Properties\AccessPropertiesCheck', 2 => 'checkNonStringableDynamicAccess', 3 => '__construct'), 83 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\ExistingClassesInPropertiesRule', 2 => 'checkClassCaseSensitivity', 3 => '__construct'), 84 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\ExistingClassesInPropertiesRule', 2 => 'checkThisOnly', 3 => '__construct'), 85 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Properties\ExistingClassesInPropertiesRule', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 86 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\OverridingPropertyRule', 2 => 'checkPhpDocMethodSignatures', 3 => '__construct'), 87 => array(0 => array(0 => '%reportMaybesInPropertyPhpDocTypes%'), 1 => 'PHPStan\Rules\Properties\OverridingPropertyRule', 2 => 'reportMaybes', 3 => '__construct'), 88 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\OverridingPropertyRule', 2 => 'checkMissingOverridePropertyAttribute', 3 => '__construct'), 89 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\OverridingPropertyRule', 2 => 'checkMissingOverrideMethodAttribute', 3 => '__construct'), 90 => array(0 => array(), 1 => 'PHPStan\Rules\Properties\WritingToReadOnlyPropertiesRule', 2 => 'checkThisOnly', 3 => '__construct'), 91 => array(0 => array(0 => '%featureToggles.reportTooWideBool%'), 1 => 'PHPStan\Rules\TooWideTypehints\TooWideTypeCheck', 2 => 'reportTooWideBool', 3 => '__construct'), 92 => array(0 => array(0 => '%featureToggles.reportNestedTooWideType%'), 1 => 'PHPStan\Rules\TooWideTypehints\TooWideTypeCheck', 2 => 'reportNestedTooWideType', 3 => '__construct'), 93 => array(0 => array(0 => '%checkTooWideReturnTypesInProtectedAndPublicMethods%'), 1 => 'PHPStan\Rules\TooWideTypehints\TooWideMethodReturnTypehintRule', 2 => 'checkProtectedAndPublicMethods', 3 => '__construct'), 94 => array(0 => array(0 => '%checkTooWideParameterOutInProtectedAndPublicMethods%'), 1 => 'PHPStan\Rules\TooWideTypehints\TooWideMethodParameterOutTypeRule', 2 => 'checkProtectedAndPublicMethods', 3 => '__construct'), 95 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\StaticMethodCallCheck', 2 => 'checkFunctionNameCase', 3 => '__construct'), 96 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Methods\StaticMethodCallCheck', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 97 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\StaticMethodCallCheck', 2 => 'reportMagicMethods', 3 => '__construct'), 98 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\MethodCallCheck', 2 => 'checkFunctionNameCase', 3 => '__construct'), 99 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\MethodCallCheck', 2 => 'reportMagicMethods', 3 => '__construct'), 100 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\OverridingMethodRule', 2 => 'checkPhpDocMethodSignatures', 3 => '__construct'), 101 => array(0 => array(), 1 => 'PHPStan\Rules\Methods\OverridingMethodRule', 2 => 'checkMissingOverrideMethodAttribute', 3 => '__construct'), 102 => array(0 => array(0 => '%propertyAlwaysWrittenTags%'), 1 => 'PHPStan\Rules\DeadCode\UnusedPrivatePropertyRule', 2 => 'alwaysWrittenTags', 3 => '__construct'), 103 => array(0 => array(0 => '%propertyAlwaysReadTags%'), 1 => 'PHPStan\Rules\DeadCode\UnusedPrivatePropertyRule', 2 => 'alwaysReadTags', 3 => '__construct'), 104 => array(0 => array(), 1 => 'PHPStan\Rules\DeadCode\UnusedPrivatePropertyRule', 2 => 'checkUninitializedProperties', 3 => '__construct'), 105 => array(0 => array(0 => '%featureToggles.reportPreciseLineForUnusedFunctionParameter%'), 1 => 'PHPStan\Rules\UnusedFunctionParametersCheck', 2 => 'reportExactLine', 3 => '__construct'), 106 => array(0 => array(0 => '%checkFunctionArgumentTypes%'), 1 => 'PHPStan\Rules\FunctionCallParametersCheck', 2 => 'checkArgumentTypes', 3 => '__construct'), 107 => array(0 => array(), 1 => 'PHPStan\Rules\FunctionCallParametersCheck', 2 => 'checkArgumentsPassedByReference', 3 => '__construct'), 108 => array(0 => array(), 1 => 'PHPStan\Rules\FunctionCallParametersCheck', 2 => 'checkExtraArguments', 3 => '__construct'), 109 => array(0 => array(), 1 => 'PHPStan\Rules\FunctionCallParametersCheck', 2 => 'checkMissingTypehints', 3 => '__construct'), 110 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\AssertRuleHelper', 2 => 'checkClassCaseSensitivity', 3 => '__construct'), 111 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\AssertRuleHelper', 2 => 'checkMissingTypehints', 3 => '__construct'), 112 => array(0 => array(0 => '%reportWrongPhpDocTypeInVarTag%'), 1 => 'PHPStan\Rules\PhpDoc\VarTagTypeRuleHelper', 2 => 'checkTypeAgainstPhpDocType', 3 => '__construct'), 113 => array(0 => array(0 => '%reportAnyTypeWideningInVarTag%'), 1 => 'PHPStan\Rules\PhpDoc\VarTagTypeRuleHelper', 2 => 'strictWideningCheck', 3 => '__construct'), 114 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\RequireExtendsCheck', 2 => 'checkClassCaseSensitivity', 3 => '__construct'), 115 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\PhpDoc\RequireExtendsCheck', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 116 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\SealedDefinitionClassRule', 2 => 'checkClassCaseSensitivity', 3 => '__construct'), 117 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\PhpDoc\SealedDefinitionClassRule', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 118 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\RequireImplementsDefinitionTraitRule', 2 => 'checkClassCaseSensitivity', 3 => '__construct'), 119 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\PhpDoc\RequireImplementsDefinitionTraitRule', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 120 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\InvalidPhpDocVarTagTypeRule', 2 => 'checkClassCaseSensitivity', 3 => '__construct'), 121 => array(0 => array(), 1 => 'PHPStan\Rules\PhpDoc\InvalidPhpDocVarTagTypeRule', 2 => 'checkMissingVarTagTypehint', 3 => '__construct'), 122 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\PhpDoc\InvalidPhpDocVarTagTypeRule', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 123 => array(0 => array(), 1 => 'PHPStan\Rules\AttributesCheck', 2 => 'deprecationRulesInstalled', 3 => '__construct'), 124 => array(0 => array(0 => '@exceptionTypeResolver'), 1 => 'PHPStan\Rules\Exceptions\ThrowsVoidMethodWithExplicitThrowPointRule', 2 => 'exceptionTypeResolver', 3 => '__construct'), 125 => array(0 => array(0 => '%exceptions.check.missingCheckedExceptionInThrows%'), 1 => 'PHPStan\Rules\Exceptions\ThrowsVoidMethodWithExplicitThrowPointRule', 2 => 'missingCheckedExceptionInThrows', 3 => '__construct'), 126 => array(0 => array(0 => '%exceptions.uncheckedExceptionRegexes%'), 1 => 'PHPStan\Rules\Exceptions\DefaultExceptionTypeResolver', 2 => 'uncheckedExceptionRegexes', 3 => '__construct'), 127 => array(0 => array(0 => '%exceptions.uncheckedExceptionClasses%'), 1 => 'PHPStan\Rules\Exceptions\DefaultExceptionTypeResolver', 2 => 'uncheckedExceptionClasses', 3 => '__construct'), 128 => array(0 => array(0 => '%exceptions.checkedExceptionRegexes%'), 1 => 'PHPStan\Rules\Exceptions\DefaultExceptionTypeResolver', 2 => 'checkedExceptionRegexes', 3 => '__construct'), 129 => array(0 => array(0 => '%exceptions.checkedExceptionClasses%'), 1 => 'PHPStan\Rules\Exceptions\DefaultExceptionTypeResolver', 2 => 'checkedExceptionClasses', 3 => '__construct'), 130 => array(0 => array(0 => '@exceptionTypeResolver'), 1 => 'PHPStan\Rules\Exceptions\ThrowsVoidFunctionWithExplicitThrowPointRule', 2 => 'exceptionTypeResolver', 3 => '__construct'), 131 => array(0 => array(0 => '%exceptions.check.missingCheckedExceptionInThrows%'), 1 => 'PHPStan\Rules\Exceptions\ThrowsVoidFunctionWithExplicitThrowPointRule', 2 => 'missingCheckedExceptionInThrows', 3 => '__construct'), 132 => array(0 => array(), 1 => 'PHPStan\Rules\Exceptions\CaughtExceptionExistenceRule', 2 => 'checkClassCaseSensitivity', 3 => '__construct'), 133 => array(0 => array(0 => '%tips.discoveringSymbols%'), 1 => 'PHPStan\Rules\Exceptions\CaughtExceptionExistenceRule', 2 => 'discoveringSymbolsTip', 3 => '__construct'), 134 => array(0 => array(0 => '%exceptions.implicitThrows%'), 1 => 'PHPStan\Rules\Exceptions\TooWideThrowTypeCheck', 2 => 'implicitThrows', 3 => '__construct'), 135 => array(0 => array(0 => '@exceptionTypeResolver'), 1 => 'PHPStan\Rules\Exceptions\ThrowsVoidPropertyHookWithExplicitThrowPointRule', 2 => 'exceptionTypeResolver', 3 => '__construct'), 136 => array(0 => array(0 => '%exceptions.check.missingCheckedExceptionInThrows%'), 1 => 'PHPStan\Rules\Exceptions\ThrowsVoidPropertyHookWithExplicitThrowPointRule', 2 => 'missingCheckedExceptionInThrows', 3 => '__construct'), 137 => array(0 => array(0 => '@exceptionTypeResolver'), 1 => 'PHPStan\Rules\Exceptions\MissingCheckedExceptionInThrowsCheck', 2 => 'exceptionTypeResolver', 3 => '__construct'), 138 => array(0 => array(0 => '@exceptionTypeResolver'), 1 => 'PHPStan\Rules\Exceptions\CatchWithUnthrownExceptionRule', 2 => 'exceptionTypeResolver', 3 => '__construct'), 139 => array(0 => array(0 => '%exceptions.reportUncheckedExceptionDeadCatch%'), 1 => 'PHPStan\Rules\Exceptions\CatchWithUnthrownExceptionRule', 2 => 'reportUncheckedExceptionDeadCatch', 3 => '__construct'), 140 => array(0 => array(), 1 => 'PHPStan\Rules\Arrays\InvalidKeyInArrayItemRule', 2 => 'reportNonIntStringArrayKey', 3 => '__construct'), 141 => array(0 => array(), 1 => 'PHPStan\Rules\Arrays\NonexistentOffsetInArrayDimFetchCheck', 2 => 'reportMaybes', 3 => '__construct'), 142 => array(0 => array(), 1 => 'PHPStan\Rules\Arrays\NonexistentOffsetInArrayDimFetchCheck', 2 => 'reportPossiblyNonexistentGeneralArrayOffset', 3 => '__construct'), 143 => array(0 => array(), 1 => 'PHPStan\Rules\Arrays\NonexistentOffsetInArrayDimFetchCheck', 2 => 'reportPossiblyNonexistentConstantArrayOffset', 3 => '__construct'), 144 => array(0 => array(), 1 => 'PHPStan\Rules\Arrays\InvalidKeyInArrayDimFetchRule', 2 => 'reportMaybes', 3 => '__construct'), 145 => array(0 => array(), 1 => 'PHPStan\Rules\Arrays\InvalidKeyInArrayDimFetchRule', 2 => 'reportNonIntStringArrayKey', 3 => '__construct'), 146 => array(0 => array(), 1 => 'PHPStan\Rules\Arrays\NonexistentOffsetInArrayDimFetchRule', 2 => 'reportMaybes', 3 => '__construct'), 147 => array(0 => array(), 1 => 'PHPStan\Rules\ClassCaseSensitivityCheck', 2 => 'checkInternalClassCaseSensitivity', 3 => '__construct'), 148 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\ImpossibleCheckTypeFunctionCallRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 149 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\ImpossibleCheckTypeFunctionCallRule', 2 => 'reportAlwaysTrueInLastCondition', 3 => '__construct'), 150 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Comparison\ImpossibleCheckTypeFunctionCallRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 151 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\StrictComparisonOfDifferentTypesRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 152 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\StrictComparisonOfDifferentTypesRule', 2 => 'reportAlwaysTrueInLastCondition', 3 => '__construct'), 153 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Comparison\StrictComparisonOfDifferentTypesRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 154 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\ImpossibleCheckTypeStaticMethodCallRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 155 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\ImpossibleCheckTypeStaticMethodCallRule', 2 => 'reportAlwaysTrueInLastCondition', 3 => '__construct'), 156 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Comparison\ImpossibleCheckTypeStaticMethodCallRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 157 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\ConstantConditionRuleHelper', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 158 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\BooleanAndConstantConditionRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 159 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\BooleanAndConstantConditionRule', 2 => 'reportAlwaysTrueInLastCondition', 3 => '__construct'), 160 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Comparison\BooleanAndConstantConditionRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 161 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\WhileLoopAlwaysTrueConditionRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 162 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Comparison\WhileLoopAlwaysTrueConditionRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 163 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\DoWhileLoopConstantConditionRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 164 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Comparison\DoWhileLoopConstantConditionRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 165 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\BooleanOrConstantConditionRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 166 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\BooleanOrConstantConditionRule', 2 => 'reportAlwaysTrueInLastCondition', 3 => '__construct'), 167 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Comparison\BooleanOrConstantConditionRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 168 => array(0 => array(0 => '%tips.possiblyImpure%'), 1 => 'PHPStan\Rules\Comparison\PossiblyImpureTipHelper', 2 => 'possiblyImpureTip', 3 => '__construct'), 169 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\IfConstantConditionRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 170 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Comparison\IfConstantConditionRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 171 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\ElseIfConstantConditionRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 172 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\ElseIfConstantConditionRule', 2 => 'reportAlwaysTrueInLastCondition', 3 => '__construct'), 173 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Comparison\ElseIfConstantConditionRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 174 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\BooleanNotConstantConditionRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 175 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\BooleanNotConstantConditionRule', 2 => 'reportAlwaysTrueInLastCondition', 3 => '__construct'), 176 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Comparison\BooleanNotConstantConditionRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 177 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\TernaryOperatorConstantConditionRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 178 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Comparison\TernaryOperatorConstantConditionRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 179 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\WhileLoopAlwaysFalseConditionRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 180 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Comparison\WhileLoopAlwaysFalseConditionRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 181 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\MatchExpressionRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 182 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\ConstantLooseComparisonRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 183 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\ConstantLooseComparisonRule', 2 => 'reportAlwaysTrueInLastCondition', 3 => '__construct'), 184 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Comparison\ConstantLooseComparisonRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 185 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\LogicalXorConstantConditionRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 186 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\LogicalXorConstantConditionRule', 2 => 'reportAlwaysTrueInLastCondition', 3 => '__construct'), 187 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Comparison\LogicalXorConstantConditionRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 188 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\NumberComparisonOperatorsConstantConditionRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 189 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Comparison\NumberComparisonOperatorsConstantConditionRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 190 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\ImpossibleCheckTypeHelper', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 191 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\ImpossibleCheckTypeMethodCallRule', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 192 => array(0 => array(), 1 => 'PHPStan\Rules\Comparison\ImpossibleCheckTypeMethodCallRule', 2 => 'reportAlwaysTrueInLastCondition', 3 => '__construct'), 193 => array(0 => array(0 => '%tips.treatPhpDocTypesAsCertain%'), 1 => 'PHPStan\Rules\Comparison\ImpossibleCheckTypeMethodCallRule', 2 => 'treatPhpDocTypesAsCertainTip', 3 => '__construct'), 194 => array(0 => array(), 1 => 'PHPStan\Analyser\AnalyserResultFinalizer', 2 => 'reportUnmatchedIgnoredErrors', 3 => '__construct'), 195 => array(0 => array(0 => '@currentPhpVersionPhpParser'), 1 => 'PHPStan\Analyser\RuleErrorTransformer', 2 => 'parser', 3 => '__construct'), 196 => array(0 => array(0 => '@nodeScopeResolverReflector'), 1 => 'PHPStan\Analyser\Fiber\FiberNodeScopeResolver', 2 => 'reflector', 3 => '__construct'), 197 => array(0 => array(0 => '@defaultAnalysisParser'), 1 => 'PHPStan\Analyser\Fiber\FiberNodeScopeResolver', 2 => 'parser', 3 => '__construct'), 198 => array(0 => array(), 1 => 'PHPStan\Analyser\Fiber\FiberNodeScopeResolver', 2 => 'polluteScopeWithLoopInitialAssignments', 3 => '__construct'), 199 => array(0 => array(), 1 => 'PHPStan\Analyser\Fiber\FiberNodeScopeResolver', 2 => 'polluteScopeWithAlwaysIterableForeach', 3 => '__construct'), 200 => array(0 => array(), 1 => 'PHPStan\Analyser\Fiber\FiberNodeScopeResolver', 2 => 'polluteScopeWithBlock', 3 => '__construct'), 201 => array(0 => array(), 1 => 'PHPStan\Analyser\Fiber\FiberNodeScopeResolver', 2 => 'earlyTerminatingMethodCalls', 3 => '__construct'), 202 => array(0 => array(), 1 => 'PHPStan\Analyser\Fiber\FiberNodeScopeResolver', 2 => 'earlyTerminatingFunctionCalls', 3 => '__construct'), 203 => array(0 => array(0 => '%exceptions.implicitThrows%'), 1 => 'PHPStan\Analyser\Fiber\FiberNodeScopeResolver', 2 => 'implicitThrows', 3 => '__construct'), 204 => array(0 => array(), 1 => 'PHPStan\Analyser\Fiber\FiberNodeScopeResolver', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 205 => array(0 => array(0 => '%exceptions.implicitThrows%'), 1 => 'PHPStan\Analyser\ExprHandler\NewHandler', 2 => 'implicitThrows', 3 => '__construct'), 206 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\MatchHandler', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 207 => array(0 => array(0 => '%exceptions.implicitThrows%'), 1 => 'PHPStan\Analyser\ExprHandler\Helper\MethodThrowPointHelper', 2 => 'implicitThrows', 3 => '__construct'), 208 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\MethodCallHandler', 2 => 'rememberPossiblyImpureFunctionValues', 3 => '__construct'), 209 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\StaticCallHandler', 2 => 'rememberPossiblyImpureFunctionValues', 3 => '__construct'), 210 => array(0 => array(0 => '%exceptions.implicitThrows%'), 1 => 'PHPStan\Analyser\ExprHandler\FuncCallHandler', 2 => 'implicitThrows', 3 => '__construct'), 211 => array(0 => array(), 1 => 'PHPStan\Analyser\ExprHandler\FuncCallHandler', 2 => 'rememberPossiblyImpureFunctionValues', 3 => '__construct'), 212 => array(0 => array(0 => '@PHPStan\Analyser\NodeScopeResolver'), 1 => 'PHPStan\Analyser\FileAnalyser', 2 => 'nodeScopeResolver', 3 => '__construct'), 213 => array(0 => array(0 => '@defaultAnalysisParser'), 1 => 'PHPStan\Analyser\FileAnalyser', 2 => 'parser', 3 => '__construct'), 214 => array(0 => array(), 1 => 'PHPStan\Analyser\FileAnalyser', 2 => 'reportIgnoresWithoutComments', 3 => '__construct'), 215 => array(0 => array(0 => '@PHPStan\Analyser\NodeScopeResolver'), 1 => 'PHPStan\Analyser\Analyser', 2 => 'nodeScopeResolver', 3 => '__construct'), 216 => array(0 => array(), 1 => 'PHPStan\Analyser\Analyser', 2 => 'internalErrorsCountLimit', 3 => '__construct'), 217 => array(0 => array(0 => '%resultCachePath%'), 1 => 'PHPStan\Analyser\ResultCache\ResultCacheClearer', 2 => 'cacheFilePath', 3 => '__construct'), 218 => array(0 => array(0 => '@fileFinderScan'), 1 => 'PHPStan\Analyser\ResultCache\ResultCacheManager', 2 => 'scanFileFinder', 3 => '__construct'), 219 => array(0 => array(0 => '%resultCachePath%'), 1 => 'PHPStan\Analyser\ResultCache\ResultCacheManager', 2 => 'cacheFilePath', 3 => '__construct'), 220 => array(0 => array(), 1 => 'PHPStan\Analyser\ResultCache\ResultCacheManager', 2 => 'analysedPaths', 3 => '__construct'), 221 => array(0 => array(), 1 => 'PHPStan\Analyser\ResultCache\ResultCacheManager', 2 => 'analysedPathsFromConfig', 3 => '__construct'), 222 => array(0 => array(), 1 => 'PHPStan\Analyser\ResultCache\ResultCacheManager', 2 => 'composerAutoloaderProjectPaths', 3 => '__construct'), 223 => array(0 => array(), 1 => 'PHPStan\Analyser\ResultCache\ResultCacheManager', 2 => 'usedLevel', 3 => '__construct'), 224 => array(0 => array(), 1 => 'PHPStan\Analyser\ResultCache\ResultCacheManager', 2 => 'cliAutoloadFile', 3 => '__construct'), 225 => array(0 => array(), 1 => 'PHPStan\Analyser\ResultCache\ResultCacheManager', 2 => 'bootstrapFiles', 3 => '__construct'), 226 => array(0 => array(), 1 => 'PHPStan\Analyser\ResultCache\ResultCacheManager', 2 => 'scanFiles', 3 => '__construct'), 227 => array(0 => array(), 1 => 'PHPStan\Analyser\ResultCache\ResultCacheManager', 2 => 'scanDirectories', 3 => '__construct'), 228 => array(0 => array(0 => '%resultCacheChecksProjectExtensionFilesDependencies%'), 1 => 'PHPStan\Analyser\ResultCache\ResultCacheManager', 2 => 'checkDependenciesOfProjectExtensionFiles', 3 => '__construct'), 229 => array(0 => array(), 1 => 'PHPStan\Analyser\ResultCache\ResultCacheManager', 2 => 'parametersNotInvalidatingCache', 3 => '__construct'), 230 => array(0 => array(0 => '%resultCacheSkipIfOlderThanDays%'), 1 => 'PHPStan\Analyser\ResultCache\ResultCacheManager', 2 => 'skipResultCacheIfOlderThanDays', 3 => '__construct'), 231 => array(0 => array(0 => '@nodeScopeResolverReflector'), 1 => 'PHPStan\Analyser\NodeScopeResolver', 2 => 'reflector', 3 => '__construct'), 232 => array(0 => array(0 => '@defaultAnalysisParser'), 1 => 'PHPStan\Analyser\NodeScopeResolver', 2 => 'parser', 3 => '__construct'), 233 => array(0 => array(), 1 => 'PHPStan\Analyser\NodeScopeResolver', 2 => 'polluteScopeWithLoopInitialAssignments', 3 => '__construct'), 234 => array(0 => array(), 1 => 'PHPStan\Analyser\NodeScopeResolver', 2 => 'polluteScopeWithAlwaysIterableForeach', 3 => '__construct'), 235 => array(0 => array(), 1 => 'PHPStan\Analyser\NodeScopeResolver', 2 => 'polluteScopeWithBlock', 3 => '__construct'), 236 => array(0 => array(), 1 => 'PHPStan\Analyser\NodeScopeResolver', 2 => 'earlyTerminatingMethodCalls', 3 => '__construct'), 237 => array(0 => array(), 1 => 'PHPStan\Analyser\NodeScopeResolver', 2 => 'earlyTerminatingFunctionCalls', 3 => '__construct'), 238 => array(0 => array(0 => '%exceptions.implicitThrows%'), 1 => 'PHPStan\Analyser\NodeScopeResolver', 2 => 'implicitThrows', 3 => '__construct'), 239 => array(0 => array(), 1 => 'PHPStan\Analyser\NodeScopeResolver', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 240 => array(0 => array(), 1 => 'PHPStan\Analyser\Ignore\IgnoredErrorHelper', 2 => 'ignoreErrors', 3 => '__construct'), 241 => array(0 => array(), 1 => 'PHPStan\Analyser\Ignore\IgnoredErrorHelper', 2 => 'reportUnmatchedIgnoredErrors', 3 => '__construct'), 242 => array(0 => array(0 => '%currentWorkingDirectory%'), 1 => 'PHPStan\File\FileHelper', 2 => 'workingDirectory', 3 => '__construct'), 243 => array(0 => array(0 => '@fileFinderAnalyse'), 1 => 'PHPStan\File\FileMonitor', 2 => 'analyseFileFinder', 3 => '__construct'), 244 => array(0 => array(0 => '@fileFinderScan'), 1 => 'PHPStan\File\FileMonitor', 2 => 'scanFileFinder', 3 => '__construct'), 245 => array(0 => array(), 1 => 'PHPStan\File\FileMonitor', 2 => 'analysedPaths', 3 => '__construct'), 246 => array(0 => array(), 1 => 'PHPStan\File\FileMonitor', 2 => 'analysedPathsFromConfig', 3 => '__construct'), 247 => array(0 => array(), 1 => 'PHPStan\File\FileMonitor', 2 => 'scanFiles', 3 => '__construct'), 248 => array(0 => array(), 1 => 'PHPStan\File\FileMonitor', 2 => 'scanDirectories', 3 => '__construct'), 249 => array(0 => array(0 => '@parentDirectoryRelativePathHelper'), 1 => 'PHPStan\File\FuzzyRelativePathHelper', 2 => 'fallbackRelativePathHelper', 3 => '__construct'), 250 => array(0 => array(), 1 => 'PHPStan\File\FuzzyRelativePathHelper', 2 => 'currentWorkingDirectory', 3 => '__construct'), 251 => array(0 => array(), 1 => 'PHPStan\File\FuzzyRelativePathHelper', 2 => 'analysedPaths', 3 => '__construct'), 252 => array(0 => array(), 1 => 'PHPStan\File\FileExcluderFactory', 2 => 'excludePaths', 3 => '__construct'), 253 => array(0 => array(0 => '%currentWorkingDirectory%'), 1 => 'PHPStan\File\ParentDirectoryRelativePathHelper', 2 => 'parentDirectory', 3 => '__construct'), 254 => array(0 => array(0 => '%currentWorkingDirectory%'), 1 => 'PHPStan\File\SimpleRelativePathHelper', 2 => 'currentWorkingDirectory', 3 => '__construct'), 255 => array(0 => array(0 => '@defaultAnalysisParser'), 1 => 'PHPStan\Dependency\ExportedNodeFetcher', 2 => 'parser', 3 => '__construct'), 256 => array(0 => array(0 => '@PHPStan\DependencyInjection\Nette\NetteContainer'), 1 => 'PHPStan\DependencyInjection\MemoizingContainer', 2 => 'originalContainer', 3 => '__construct'), 257 => array(0 => array(), 1 => 'PHPStan\DependencyInjection\DerivativeContainerFactory', 2 => 'currentWorkingDirectory', 3 => '__construct'), 258 => array(0 => array(0 => '%tempDir%'), 1 => 'PHPStan\DependencyInjection\DerivativeContainerFactory', 2 => 'tempDirectory', 3 => '__construct'), 259 => array(0 => array(), 1 => 'PHPStan\DependencyInjection\DerivativeContainerFactory', 2 => 'additionalConfigFiles', 3 => '__construct'), 260 => array(0 => array(), 1 => 'PHPStan\DependencyInjection\DerivativeContainerFactory', 2 => 'analysedPaths', 3 => '__construct'), 261 => array(0 => array(), 1 => 'PHPStan\DependencyInjection\DerivativeContainerFactory', 2 => 'composerAutoloaderProjectPaths', 3 => '__construct'), 262 => array(0 => array(), 1 => 'PHPStan\DependencyInjection\DerivativeContainerFactory', 2 => 'analysedPathsFromConfig', 3 => '__construct'), 263 => array(0 => array(), 1 => 'PHPStan\DependencyInjection\DerivativeContainerFactory', 2 => 'usedLevel', 3 => '__construct'), 264 => array(0 => array(), 1 => 'PHPStan\DependencyInjection\DerivativeContainerFactory', 2 => 'generateBaselineFile', 3 => '__construct'), 265 => array(0 => array(), 1 => 'PHPStan\DependencyInjection\DerivativeContainerFactory', 2 => 'cliAutoloadFile', 3 => '__construct'), 266 => array(0 => array(), 1 => 'PHPStan\DependencyInjection\DerivativeContainerFactory', 2 => 'singleReflectionFile', 3 => '__construct'), 267 => array(0 => array(), 1 => 'PHPStan\DependencyInjection\DerivativeContainerFactory', 2 => 'singleReflectionInsteadOfFile', 3 => '__construct'), 268 => array(0 => array(0 => '@simpleRelativePathHelper'), 1 => 'PHPStan\Broker\AnonymousClassNameHelper', 2 => 'relativePathHelper', 3 => '__construct'), 269 => array(0 => array(), 1 => 'PHPStan\Reflection\ConstructorsHelper', 2 => 'additionalConstructors', 3 => '__construct'), 270 => array(0 => array(0 => '@betterReflectionProvider'), 1 => 'PHPStan\Reflection\ReflectionProvider\ReflectionProviderFactory', 2 => 'staticReflectionProvider', 3 => '__construct'), 271 => array(0 => array(0 => '@php8PhpParser'), 1 => 'PHPStan\Reflection\BetterReflection\SourceStubber\PhpStormStubsSourceStubberFactory', 2 => 'phpParser', 3 => '__construct'), 272 => array(0 => array(0 => '@originalBetterReflectionReflector'), 1 => 'PHPStan\Reflection\BetterReflection\Reflector\MemoizingReflector', 2 => 'reflector', 3 => '__construct'), 273 => array(0 => array(0 => '@phpParserDecorator'), 1 => 'PHPStan\Reflection\BetterReflection\BetterReflectionSourceLocatorFactory', 2 => 'parser', 3 => '__construct'), 274 => array(0 => array(0 => '@php8PhpParser'), 1 => 'PHPStan\Reflection\BetterReflection\BetterReflectionSourceLocatorFactory', 2 => 'php8Parser', 3 => '__construct'), 275 => array(0 => array(), 1 => 'PHPStan\Reflection\BetterReflection\BetterReflectionSourceLocatorFactory', 2 => 'scanFiles', 3 => '__construct'), 276 => array(0 => array(), 1 => 'PHPStan\Reflection\BetterReflection\BetterReflectionSourceLocatorFactory', 2 => 'scanDirectories', 3 => '__construct'), 277 => array(0 => array(), 1 => 'PHPStan\Reflection\BetterReflection\BetterReflectionSourceLocatorFactory', 2 => 'analysedPaths', 3 => '__construct'), 278 => array(0 => array(), 1 => 'PHPStan\Reflection\BetterReflection\BetterReflectionSourceLocatorFactory', 2 => 'composerAutoloaderProjectPaths', 3 => '__construct'), 279 => array(0 => array(), 1 => 'PHPStan\Reflection\BetterReflection\BetterReflectionSourceLocatorFactory', 2 => 'analysedPathsFromConfig', 3 => '__construct'), 280 => array(0 => array(0 => '%sourceLocatorPlaygroundMode%'), 1 => 'PHPStan\Reflection\BetterReflection\BetterReflectionSourceLocatorFactory', 2 => 'playgroundMode', 3 => '__construct'), 281 => array(0 => array(), 1 => 'PHPStan\Reflection\BetterReflection\BetterReflectionSourceLocatorFactory', 2 => 'singleReflectionFile', 3 => '__construct'), 282 => array(0 => array(0 => '@defaultAnalysisParser'), 1 => 'PHPStan\Reflection\BetterReflection\SourceLocator\FileNodesFetcher', 2 => 'parser', 3 => '__construct'), 283 => array(0 => array(0 => '@fileFinderScan'), 1 => 'PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedDirectorySourceLocatorFactory', 2 => 'fileFinder', 3 => '__construct'), 284 => array(0 => array(0 => '@betterReflectionReflector'), 1 => 'PHPStan\Reflection\BetterReflection\BetterReflectionProvider', 2 => 'reflector', 3 => '__construct'), 285 => array(0 => array(0 => '%universalObjectCratesClasses%'), 1 => 'PHPStan\Reflection\BetterReflection\BetterReflectionProvider', 2 => 'universalObjectCratesClasses', 3 => '__construct'), 286 => array(0 => array(), 1 => 'PHPStan\Reflection\InitializerExprTypeResolver', 2 => 'usePathConstantsAsConstantString', 3 => '__construct'), 287 => array(0 => array(0 => '@betterReflectionReflector'), 1 => 'PHPStan\Reflection\SignatureMap\NativeFunctionReflectionProvider', 2 => 'reflector', 3 => '__construct'), 288 => array(0 => array(0 => '%featureToggles.stricterFunctionMap%'), 1 => 'PHPStan\Reflection\SignatureMap\FunctionSignatureMapProvider', 2 => 'stricterFunctionMap', 3 => '__construct'), 289 => array(0 => array(0 => '%parallel.loadLimit%'), 1 => 'PHPStan\Process\CpuCoreCounter', 2 => 'loadLimit', 3 => '__construct'), 290 => array(0 => array(0 => '@simpleRelativePathHelper'), 1 => 'PHPStan\Command\ErrorFormatter\TeamcityErrorFormatter', 2 => 'relativePathHelper', 3 => '__construct'), 291 => array(0 => array(0 => '@simpleRelativePathHelper'), 1 => 'PHPStan\Command\ErrorFormatter\JunitErrorFormatter', 2 => 'relativePathHelper', 3 => '__construct'), 292 => array(0 => array(0 => '@simpleRelativePathHelper'), 1 => 'PHPStan\Command\ErrorFormatter\CheckstyleErrorFormatter', 2 => 'relativePathHelper', 3 => '__construct'), 293 => array(0 => array(0 => '@simpleRelativePathHelper'), 1 => 'PHPStan\Command\ErrorFormatter\TableErrorFormatter', 2 => 'simpleRelativePathHelper', 3 => '__construct'), 294 => array(0 => array(0 => '%tipsOfTheDay%'), 1 => 'PHPStan\Command\ErrorFormatter\TableErrorFormatter', 2 => 'showTipsOfTheDay', 3 => '__construct'), 295 => array(0 => array(), 1 => 'PHPStan\Command\ErrorFormatter\TableErrorFormatter', 2 => 'editorUrl', 3 => '__construct'), 296 => array(0 => array(), 1 => 'PHPStan\Command\ErrorFormatter\TableErrorFormatter', 2 => 'editorUrlTitle', 3 => '__construct'), 297 => array(0 => array(), 1 => 'PHPStan\Command\ErrorFormatter\TableErrorFormatter', 2 => 'usedLevel', 3 => '__construct'), 298 => array(0 => array(0 => '@simpleRelativePathHelper'), 1 => 'PHPStan\Command\ErrorFormatter\GithubErrorFormatter', 2 => 'relativePathHelper', 3 => '__construct'), 299 => array(0 => array(0 => '@simpleRelativePathHelper'), 1 => 'PHPStan\Command\ErrorFormatter\GitlabErrorFormatter', 2 => 'relativePathHelper', 3 => '__construct'), 300 => array(0 => array(), 1 => 'PHPStan\Command\FixerApplication', 2 => 'analysedPaths', 3 => '__construct'), 301 => array(0 => array(), 1 => 'PHPStan\Command\FixerApplication', 2 => 'currentWorkingDirectory', 3 => '__construct'), 302 => array(0 => array(0 => '%pro.tmpDir%'), 1 => 'PHPStan\Command\FixerApplication', 2 => 'proTmpDir', 3 => '__construct'), 303 => array(0 => array(), 1 => 'PHPStan\Command\FixerApplication', 2 => 'composerAutoloaderProjectPaths', 3 => '__construct'), 304 => array(0 => array(), 1 => 'PHPStan\Command\FixerApplication', 2 => 'allConfigFiles', 3 => '__construct'), 305 => array(0 => array(), 1 => 'PHPStan\Command\FixerApplication', 2 => 'cliAutoloadFile', 3 => '__construct'), 306 => array(0 => array(), 1 => 'PHPStan\Command\FixerApplication', 2 => 'bootstrapFiles', 3 => '__construct'), 307 => array(0 => array(), 1 => 'PHPStan\Command\FixerApplication', 2 => 'editorUrl', 3 => '__construct'), 308 => array(0 => array(), 1 => 'PHPStan\Command\FixerApplication', 2 => 'usedLevel', 3 => '__construct'), 309 => array(0 => array(0 => '@stubParser'), 1 => 'PHPStan\PhpDoc\StubPhpDocProvider', 2 => 'parser', 3 => '__construct'), 310 => array(0 => array(0 => '@stubFileTypeMapper'), 1 => 'PHPStan\PhpDoc\StubPhpDocProvider', 2 => 'fileTypeMapper', 3 => '__construct'), 311 => array(0 => array(), 1 => 'PHPStan\PhpDoc\DefaultStubFilesProvider', 2 => 'stubFiles', 3 => '__construct'), 312 => array(0 => array(), 1 => 'PHPStan\PhpDoc\DefaultStubFilesProvider', 2 => 'composerAutoloaderProjectPaths', 3 => '__construct'), 313 => array(0 => array(0 => '@currentPhpVersionPhpParser'), 1 => 'PHPStan\Type\ClosureTypeFactory', 2 => 'parser', 3 => '__construct'), 314 => array(0 => array(0 => '%typeAliases%'), 1 => 'PHPStan\Type\UsefulTypeAliasResolver', 2 => 'globalTypeAliases', 3 => '__construct'), 315 => array(0 => array(), 1 => 'PHPStan\Type\Php\TypeSpecifyingFunctionsDynamicReturnTypeExtension', 2 => 'treatPhpDocTypesAsCertain', 3 => '__construct'), 316 => array(0 => array(0 => '%phpVersion%'), 1 => 'PHPStan\Type\Php\VersionCompareFunctionDynamicReturnTypeExtension', 2 => 'configPhpVersion', 3 => '__construct'), 317 => array(0 => array(), 1 => 'PHPStan\Type\Php\CompactFunctionReturnTypeExtension', 2 => 'checkMaybeUndefinedVariables', 3 => '__construct'), 318 => array(0 => array(0 => '@defaultAnalysisParser'), 1 => 'PHPStan\Type\FileTypeMapper', 2 => 'phpParser', 3 => '__construct'), 319 => array(0 => array(0 => '%cache.resolvedPhpDocBlockCacheCountMax%'), 1 => 'PHPStan\Type\FileTypeMapper', 2 => 'resolvedPhpDocBlockCacheCountMax', 3 => '__construct'), 320 => array(0 => array(0 => '%cache.nameScopeMapMemoryCacheCountMax%'), 1 => 'PHPStan\Type\FileTypeMapper', 2 => 'nameScopeMapMemoryCacheCountMax', 3 => '__construct'), 321 => array(0 => array(), 1 => 'PHPStan\Php\PhpVersionFactoryFactory', 2 => 'phpVersion', 3 => '__construct'), 322 => array(0 => array(), 1 => 'PHPStan\Php\PhpVersionFactoryFactory', 2 => 'composerAutoloaderProjectPaths', 3 => '__construct'), 323 => array(0 => array(), 1 => 'PHPStan\Php\ComposerPhpVersionFactory', 2 => 'composerAutoloaderProjectPaths', 3 => '__construct'))) )); input = $input; if (!$input->isReadable()) { $this->close(); return; } $this->assoc = $assoc; $this->depth = $depth; $this->options = $options; $this->maxlength = $maxlength; $this->input->on('data', array($this, 'handleData')); $this->input->on('end', array($this, 'handleEnd')); $this->input->on('error', array($this, 'handleError')); $this->input->on('close', array($this, 'close')); } public function isReadable() { return !$this->closed; } public function close() { if ($this->closed) { return; } $this->closed = \true; $this->buffer = ''; $this->input->close(); $this->emit('close'); $this->removeAllListeners(); } public function pause() { $this->input->pause(); } public function resume() { $this->input->resume(); } public function pipe(WritableStreamInterface $dest, array $options = array()) { Util::pipe($this, $dest, $options); return $dest; } /** @internal */ public function handleData($data) { if (!\is_string($data)) { $this->handleError(new \UnexpectedValueException('Expected stream to emit string, but got ' . \gettype($data))); return; } $this->buffer .= $data; // keep parsing while a newline has been found while (($newline = \strpos($this->buffer, "\n")) !== \false && $newline <= $this->maxlength) { // read data up until newline and remove from buffer $data = (string) \substr($this->buffer, 0, $newline); $this->buffer = (string) \substr($this->buffer, $newline + 1); // decode data with options given in ctor // @codeCoverageIgnoreStart if ($this->options === 0) { $data = \json_decode($data, $this->assoc, $this->depth); } else { assert(\PHP_VERSION_ID >= 50400); $data = \json_decode($data, $this->assoc, $this->depth, $this->options); } // @codeCoverageIgnoreEnd // abort stream if decoding failed if ($data === null && \json_last_error() !== \JSON_ERROR_NONE) { // @codeCoverageIgnoreStart if (\PHP_VERSION_ID > 50500) { $errstr = \json_last_error_msg(); } elseif (\json_last_error() === \JSON_ERROR_SYNTAX) { $errstr = 'Syntax error'; } else { $errstr = 'Unknown error'; } // @codeCoverageIgnoreEnd return $this->handleError(new \RuntimeException('Unable to decode JSON: ' . $errstr, \json_last_error())); } $this->emit('data', array($data)); } if (isset($this->buffer[$this->maxlength])) { $this->handleError(new \OverflowException('Buffer size exceeded')); } } /** @internal */ public function handleEnd() { if ($this->buffer !== '') { $this->handleData("\n"); } if (!$this->closed) { $this->emit('end'); $this->close(); } } /** @internal */ public function handleError(\Exception $error) { $this->emit('error', array($error)); $this->close(); } } output = $output; if (!$output->isWritable()) { $this->close(); return; } $this->options = $options; $this->depth = $depth; $this->output->on('drain', array($this, 'handleDrain')); $this->output->on('error', array($this, 'handleError')); $this->output->on('close', array($this, 'close')); } public function write($data) { if ($this->closed) { return \false; } // we have to handle PHP warnings for legacy PHP < 5.5 // certain values (such as INF etc.) emit a warning, but still encode successfully // @codeCoverageIgnoreStart if (\PHP_VERSION_ID < 50500) { $errstr = null; \set_error_handler(function ($_, $error) use (&$errstr) { $errstr = $error; }); // encode data with options given in ctor (depth not supported) $data = \json_encode($data, $this->options); // always check error code and match missing error messages \restore_error_handler(); $errno = \json_last_error(); if (\defined('JSON_ERROR_UTF8') && $errno === \JSON_ERROR_UTF8) { // const JSON_ERROR_UTF8 added in PHP 5.3.3, but no error message assigned in legacy PHP < 5.5 // this overrides PHP 5.3.14 only: https://3v4l.org/IGP8Z#v5314 $errstr = 'Malformed UTF-8 characters, possibly incorrectly encoded'; } elseif ($errno !== \JSON_ERROR_NONE && $errstr === null) { // error number present, but no error message applicable $errstr = 'Unknown error'; } // abort stream if encoding fails if ($errno !== \JSON_ERROR_NONE || $errstr !== null) { $this->handleError(new \RuntimeException('Unable to encode JSON: ' . $errstr, $errno)); return \false; } } else { // encode data with options given in ctor $data = \json_encode($data, $this->options, $this->depth); // abort stream if encoding fails if ($data === \false && \json_last_error() !== \JSON_ERROR_NONE) { $this->handleError(new \RuntimeException('Unable to encode JSON: ' . \json_last_error_msg(), \json_last_error())); return \false; } } // @codeCoverageIgnoreEnd return $this->output->write($data . "\n"); } public function end($data = null) { if ($data !== null) { $this->write($data); } $this->output->end(); } public function isWritable() { return !$this->closed; } public function close() { if ($this->closed) { return; } $this->closed = \true; $this->output->close(); $this->emit('close'); $this->removeAllListeners(); } /** @internal */ public function handleDrain() { $this->emit('drain'); } /** @internal */ public function handleError(\Exception $error) { $this->emit('error', array($error)); $this->close(); } } * 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; } } Copyright (c) Nils Adermann, Jordi Boggiano Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'CURLStringFile' => $vendorDir . '/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php', 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'DateError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateError.php', 'DateException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateException.php', 'DateInvalidOperationException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateInvalidOperationException.php', 'DateInvalidTimeZoneException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateInvalidTimeZoneException.php', 'DateMalformedIntervalStringException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateMalformedIntervalStringException.php', 'DateMalformedPeriodStringException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateMalformedPeriodStringException.php', 'DateMalformedStringException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateMalformedStringException.php', 'DateObjectError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateObjectError.php', 'DateRangeError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateRangeError.php', 'DelayedTargetValidation' => $vendorDir . '/symfony/polyfill-php85/Resources/stubs/DelayedTargetValidation.php', 'Deprecated' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php', 'Filter\\FilterException' => $vendorDir . '/symfony/polyfill-php85/Resources/stubs/Filter/FilterException.php', 'Filter\\FilterFailedException' => $vendorDir . '/symfony/polyfill-php85/Resources/stubs/Filter/FilterFailedException.php', 'Hoa\\Compiler\\Bin\\Pp' => $vendorDir . '/hoa/compiler/Bin/Pp.php', 'Hoa\\Compiler\\Exception\\Exception' => $vendorDir . '/hoa/compiler/Exception/Exception.php', 'Hoa\\Compiler\\Exception\\FinalStateHasNotBeenReached' => $vendorDir . '/hoa/compiler/Exception/FinalStateHasNotBeenReached.php', 'Hoa\\Compiler\\Exception\\IllegalToken' => $vendorDir . '/hoa/compiler/Exception/IllegalToken.php', 'Hoa\\Compiler\\Exception\\Lexer' => $vendorDir . '/hoa/compiler/Exception/Lexer.php', 'Hoa\\Compiler\\Exception\\Rule' => $vendorDir . '/hoa/compiler/Exception/Rule.php', 'Hoa\\Compiler\\Exception\\UnexpectedToken' => $vendorDir . '/hoa/compiler/Exception/UnexpectedToken.php', 'Hoa\\Compiler\\Exception\\UnrecognizedToken' => $vendorDir . '/hoa/compiler/Exception/UnrecognizedToken.php', 'Hoa\\Compiler\\Ll1' => $vendorDir . '/hoa/compiler/Ll1.php', 'Hoa\\Compiler\\Llk\\Lexer' => $vendorDir . '/hoa/compiler/Llk/Lexer.php', 'Hoa\\Compiler\\Llk\\Llk' => $vendorDir . '/hoa/compiler/Llk/Llk.php', 'Hoa\\Compiler\\Llk\\Parser' => $vendorDir . '/hoa/compiler/Llk/Parser.php', 'Hoa\\Compiler\\Llk\\Rule\\Analyzer' => $vendorDir . '/hoa/compiler/Llk/Rule/Analyzer.php', 'Hoa\\Compiler\\Llk\\Rule\\Choice' => $vendorDir . '/hoa/compiler/Llk/Rule/Choice.php', 'Hoa\\Compiler\\Llk\\Rule\\Concatenation' => $vendorDir . '/hoa/compiler/Llk/Rule/Concatenation.php', 'Hoa\\Compiler\\Llk\\Rule\\Ekzit' => $vendorDir . '/hoa/compiler/Llk/Rule/Ekzit.php', 'Hoa\\Compiler\\Llk\\Rule\\Entry' => $vendorDir . '/hoa/compiler/Llk/Rule/Entry.php', 'Hoa\\Compiler\\Llk\\Rule\\Invocation' => $vendorDir . '/hoa/compiler/Llk/Rule/Invocation.php', 'Hoa\\Compiler\\Llk\\Rule\\Repetition' => $vendorDir . '/hoa/compiler/Llk/Rule/Repetition.php', 'Hoa\\Compiler\\Llk\\Rule\\Rule' => $vendorDir . '/hoa/compiler/Llk/Rule/Rule.php', 'Hoa\\Compiler\\Llk\\Rule\\Token' => $vendorDir . '/hoa/compiler/Llk/Rule/Token.php', 'Hoa\\Compiler\\Llk\\Sampler\\BoundedExhaustive' => $vendorDir . '/hoa/compiler/Llk/Sampler/BoundedExhaustive.php', 'Hoa\\Compiler\\Llk\\Sampler\\Coverage' => $vendorDir . '/hoa/compiler/Llk/Sampler/Coverage.php', 'Hoa\\Compiler\\Llk\\Sampler\\Exception' => $vendorDir . '/hoa/compiler/Llk/Sampler/Exception.php', 'Hoa\\Compiler\\Llk\\Sampler\\Sampler' => $vendorDir . '/hoa/compiler/Llk/Sampler/Sampler.php', 'Hoa\\Compiler\\Llk\\Sampler\\Uniform' => $vendorDir . '/hoa/compiler/Llk/Sampler/Uniform.php', 'Hoa\\Compiler\\Llk\\TreeNode' => $vendorDir . '/hoa/compiler/Llk/TreeNode.php', 'Hoa\\Compiler\\Test\\Integration\\Documentation' => $vendorDir . '/hoa/compiler/Test/Integration/Documentation.php', 'Hoa\\Compiler\\Test\\Integration\\Llk\\Documentation' => $vendorDir . '/hoa/compiler/Test/Integration/Llk/Documentation.php', 'Hoa\\Compiler\\Test\\Integration\\Llk\\Rule\\Analyzer' => $vendorDir . '/hoa/compiler/Test/Integration/Llk/Rule/Analyzer.php', 'Hoa\\Compiler\\Test\\Integration\\Llk\\Soundness' => $vendorDir . '/hoa/compiler/Test/Integration/Llk/Soundness.php', 'Hoa\\Compiler\\Test\\Unit\\Exception\\Exception' => $vendorDir . '/hoa/compiler/Test/Unit/Exception/Exception.php', 'Hoa\\Compiler\\Test\\Unit\\Exception\\FinalStateHasNotBeenReached' => $vendorDir . '/hoa/compiler/Test/Unit/Exception/FinalStateHasNotBeenReached.php', 'Hoa\\Compiler\\Test\\Unit\\Exception\\IllegalToken' => $vendorDir . '/hoa/compiler/Test/Unit/Exception/IllegalToken.php', 'Hoa\\Compiler\\Test\\Unit\\Exception\\Lexer' => $vendorDir . '/hoa/compiler/Test/Unit/Exception/Lexer.php', 'Hoa\\Compiler\\Test\\Unit\\Exception\\Rule' => $vendorDir . '/hoa/compiler/Test/Unit/Exception/Rule.php', 'Hoa\\Compiler\\Test\\Unit\\Exception\\UnexpectedToken' => $vendorDir . '/hoa/compiler/Test/Unit/Exception/UnexpectedToken.php', 'Hoa\\Compiler\\Test\\Unit\\Exception\\UnrecognizedToken' => $vendorDir . '/hoa/compiler/Test/Unit/Exception/UnrecognizedToken.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Lexer' => $vendorDir . '/hoa/compiler/Test/Unit/Llk/Lexer.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Llk' => $vendorDir . '/hoa/compiler/Test/Unit/Llk/Llk.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Rule\\Choice' => $vendorDir . '/hoa/compiler/Test/Unit/Llk/Rule/Choice.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Rule\\Concatenation' => $vendorDir . '/hoa/compiler/Test/Unit/Llk/Rule/Concatenation.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Rule\\Ekzit' => $vendorDir . '/hoa/compiler/Test/Unit/Llk/Rule/Ekzit.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Rule\\Entry' => $vendorDir . '/hoa/compiler/Test/Unit/Llk/Rule/Entry.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Rule\\Invocation' => $vendorDir . '/hoa/compiler/Test/Unit/Llk/Rule/Invocation.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Rule\\Repetition' => $vendorDir . '/hoa/compiler/Test/Unit/Llk/Rule/Repetition.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Rule\\Rule' => $vendorDir . '/hoa/compiler/Test/Unit/Llk/Rule/Rule.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Rule\\Token' => $vendorDir . '/hoa/compiler/Test/Unit/Llk/Rule/Token.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Sampler\\Exception' => $vendorDir . '/hoa/compiler/Test/Unit/Llk/Sampler/Exception.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\TreeNode' => $vendorDir . '/hoa/compiler/Test/Unit/Llk/TreeNode.php', 'Hoa\\Compiler\\Visitor\\Dump' => $vendorDir . '/hoa/compiler/Visitor/Dump.php', 'Hoa\\Consistency\\Autoloader' => $vendorDir . '/hoa/consistency/Autoloader.php', 'Hoa\\Consistency\\Consistency' => $vendorDir . '/hoa/consistency/Consistency.php', 'Hoa\\Consistency\\Exception' => $vendorDir . '/hoa/consistency/Exception.php', 'Hoa\\Consistency\\Test\\Unit\\Autoloader' => $vendorDir . '/hoa/consistency/Test/Unit/Autoloader.php', 'Hoa\\Consistency\\Test\\Unit\\Consistency' => $vendorDir . '/hoa/consistency/Test/Unit/Consistency.php', 'Hoa\\Consistency\\Test\\Unit\\Exception' => $vendorDir . '/hoa/consistency/Test/Unit/Exception.php', 'Hoa\\Consistency\\Test\\Unit\\Xcallable' => $vendorDir . '/hoa/consistency/Test/Unit/Xcallable.php', 'Hoa\\Consistency\\Xcallable' => $vendorDir . '/hoa/consistency/Xcallable.php', 'Hoa\\Event\\Bucket' => $vendorDir . '/hoa/event/Bucket.php', 'Hoa\\Event\\Event' => $vendorDir . '/hoa/event/Event.php', 'Hoa\\Event\\Exception' => $vendorDir . '/hoa/event/Exception.php', 'Hoa\\Event\\Listenable' => $vendorDir . '/hoa/event/Listenable.php', 'Hoa\\Event\\Listener' => $vendorDir . '/hoa/event/Listener.php', 'Hoa\\Event\\Listens' => $vendorDir . '/hoa/event/Listens.php', 'Hoa\\Event\\Source' => $vendorDir . '/hoa/event/Source.php', 'Hoa\\Event\\Test\\Unit\\Bucket' => $vendorDir . '/hoa/event/Test/Unit/Bucket.php', 'Hoa\\Event\\Test\\Unit\\Event' => $vendorDir . '/hoa/event/Test/Unit/Event.php', 'Hoa\\Event\\Test\\Unit\\Exception' => $vendorDir . '/hoa/event/Test/Unit/Exception.php', 'Hoa\\Event\\Test\\Unit\\Listenable' => $vendorDir . '/hoa/event/Test/Unit/Listenable.php', 'Hoa\\Event\\Test\\Unit\\Listener' => $vendorDir . '/hoa/event/Test/Unit/Listener.php', 'Hoa\\Event\\Test\\Unit\\Listens' => $vendorDir . '/hoa/event/Test/Unit/Listens.php', 'Hoa\\Event\\Test\\Unit\\Source' => $vendorDir . '/hoa/event/Test/Unit/Source.php', 'Hoa\\Exception\\Error' => $vendorDir . '/hoa/exception/Error.php', 'Hoa\\Exception\\Exception' => $vendorDir . '/hoa/exception/Exception.php', 'Hoa\\Exception\\Group' => $vendorDir . '/hoa/exception/Group.php', 'Hoa\\Exception\\Idle' => $vendorDir . '/hoa/exception/Idle.php', 'Hoa\\Exception\\Test\\Unit\\Error' => $vendorDir . '/hoa/exception/Test/Unit/Error.php', 'Hoa\\Exception\\Test\\Unit\\Exception' => $vendorDir . '/hoa/exception/Test/Unit/Exception.php', 'Hoa\\Exception\\Test\\Unit\\Group' => $vendorDir . '/hoa/exception/Test/Unit/Group.php', 'Hoa\\Exception\\Test\\Unit\\Idle' => $vendorDir . '/hoa/exception/Test/Unit/Idle.php', 'Hoa\\File\\Directory' => $vendorDir . '/hoa/file/Directory.php', 'Hoa\\File\\Exception\\Exception' => $vendorDir . '/hoa/file/Exception/Exception.php', 'Hoa\\File\\Exception\\FileDoesNotExist' => $vendorDir . '/hoa/file/Exception/FileDoesNotExist.php', 'Hoa\\File\\File' => $vendorDir . '/hoa/file/File.php', 'Hoa\\File\\Finder' => $vendorDir . '/hoa/file/Finder.php', 'Hoa\\File\\Generic' => $vendorDir . '/hoa/file/Generic.php', 'Hoa\\File\\Link\\Link' => $vendorDir . '/hoa/file/Link/Link.php', 'Hoa\\File\\Link\\Read' => $vendorDir . '/hoa/file/Link/Read.php', 'Hoa\\File\\Link\\ReadWrite' => $vendorDir . '/hoa/file/Link/ReadWrite.php', 'Hoa\\File\\Link\\Write' => $vendorDir . '/hoa/file/Link/Write.php', 'Hoa\\File\\Read' => $vendorDir . '/hoa/file/Read.php', 'Hoa\\File\\ReadWrite' => $vendorDir . '/hoa/file/ReadWrite.php', 'Hoa\\File\\SplFileInfo' => $vendorDir . '/hoa/file/SplFileInfo.php', 'Hoa\\File\\Temporary\\Read' => $vendorDir . '/hoa/file/Temporary/Read.php', 'Hoa\\File\\Temporary\\ReadWrite' => $vendorDir . '/hoa/file/Temporary/ReadWrite.php', 'Hoa\\File\\Temporary\\Temporary' => $vendorDir . '/hoa/file/Temporary/Temporary.php', 'Hoa\\File\\Temporary\\Write' => $vendorDir . '/hoa/file/Temporary/Write.php', 'Hoa\\File\\Watcher' => $vendorDir . '/hoa/file/Watcher.php', 'Hoa\\File\\Write' => $vendorDir . '/hoa/file/Write.php', 'Hoa\\Iterator\\Aggregate' => $vendorDir . '/hoa/iterator/Aggregate.php', 'Hoa\\Iterator\\Append' => $vendorDir . '/hoa/iterator/Append.php', 'Hoa\\Iterator\\Buffer' => $vendorDir . '/hoa/iterator/Buffer.php', 'Hoa\\Iterator\\CallbackFilter' => $vendorDir . '/hoa/iterator/CallbackFilter.php', 'Hoa\\Iterator\\CallbackGenerator' => $vendorDir . '/hoa/iterator/CallbackGenerator.php', 'Hoa\\Iterator\\Counter' => $vendorDir . '/hoa/iterator/Counter.php', 'Hoa\\Iterator\\Demultiplexer' => $vendorDir . '/hoa/iterator/Demultiplexer.php', 'Hoa\\Iterator\\Directory' => $vendorDir . '/hoa/iterator/Directory.php', 'Hoa\\Iterator\\Exception' => $vendorDir . '/hoa/iterator/Exception.php', 'Hoa\\Iterator\\FileSystem' => $vendorDir . '/hoa/iterator/FileSystem.php', 'Hoa\\Iterator\\Filter' => $vendorDir . '/hoa/iterator/Filter.php', 'Hoa\\Iterator\\Glob' => $vendorDir . '/hoa/iterator/Glob.php', 'Hoa\\Iterator\\Infinite' => $vendorDir . '/hoa/iterator/Infinite.php', 'Hoa\\Iterator\\Iterator' => $vendorDir . '/hoa/iterator/Iterator.php', 'Hoa\\Iterator\\IteratorIterator' => $vendorDir . '/hoa/iterator/IteratorIterator.php', 'Hoa\\Iterator\\Limit' => $vendorDir . '/hoa/iterator/Limit.php', 'Hoa\\Iterator\\Lookahead' => $vendorDir . '/hoa/iterator/Lookahead.php', 'Hoa\\Iterator\\Lookbehind' => $vendorDir . '/hoa/iterator/Lookbehind.php', 'Hoa\\Iterator\\Map' => $vendorDir . '/hoa/iterator/Map.php', 'Hoa\\Iterator\\Mock' => $vendorDir . '/hoa/iterator/Mock.php', 'Hoa\\Iterator\\Multiple' => $vendorDir . '/hoa/iterator/Multiple.php', 'Hoa\\Iterator\\NoRewind' => $vendorDir . '/hoa/iterator/NoRewind.php', 'Hoa\\Iterator\\Outer' => $vendorDir . '/hoa/iterator/Outer.php', 'Hoa\\Iterator\\Recursive\\CallbackFilter' => $vendorDir . '/hoa/iterator/Recursive/CallbackFilter.php', 'Hoa\\Iterator\\Recursive\\Directory' => $vendorDir . '/hoa/iterator/Recursive/Directory.php', 'Hoa\\Iterator\\Recursive\\Filter' => $vendorDir . '/hoa/iterator/Recursive/Filter.php', 'Hoa\\Iterator\\Recursive\\Iterator' => $vendorDir . '/hoa/iterator/Recursive/Iterator.php', 'Hoa\\Iterator\\Recursive\\Map' => $vendorDir . '/hoa/iterator/Recursive/Map.php', 'Hoa\\Iterator\\Recursive\\Mock' => $vendorDir . '/hoa/iterator/Recursive/Mock.php', 'Hoa\\Iterator\\Recursive\\Recursive' => $vendorDir . '/hoa/iterator/Recursive/Recursive.php', 'Hoa\\Iterator\\Recursive\\RegularExpression' => $vendorDir . '/hoa/iterator/Recursive/RegularExpression.php', 'Hoa\\Iterator\\RegularExpression' => $vendorDir . '/hoa/iterator/RegularExpression.php', 'Hoa\\Iterator\\Repeater' => $vendorDir . '/hoa/iterator/Repeater.php', 'Hoa\\Iterator\\Seekable' => $vendorDir . '/hoa/iterator/Seekable.php', 'Hoa\\Iterator\\SplFileInfo' => $vendorDir . '/hoa/iterator/SplFileInfo.php', 'Hoa\\Iterator\\Test\\Unit\\Append' => $vendorDir . '/hoa/iterator/Test/Unit/Append.php', 'Hoa\\Iterator\\Test\\Unit\\Buffer' => $vendorDir . '/hoa/iterator/Test/Unit/Buffer.php', 'Hoa\\Iterator\\Test\\Unit\\CallbackFilter' => $vendorDir . '/hoa/iterator/Test/Unit/CallbackFilter.php', 'Hoa\\Iterator\\Test\\Unit\\CallbackGenerator' => $vendorDir . '/hoa/iterator/Test/Unit/CallbackGenerator.php', 'Hoa\\Iterator\\Test\\Unit\\Counter' => $vendorDir . '/hoa/iterator/Test/Unit/Counter.php', 'Hoa\\Iterator\\Test\\Unit\\Demultiplexer' => $vendorDir . '/hoa/iterator/Test/Unit/Demultiplexer.php', 'Hoa\\Iterator\\Test\\Unit\\Directory' => $vendorDir . '/hoa/iterator/Test/Unit/Directory.php', 'Hoa\\Iterator\\Test\\Unit\\FileSystem' => $vendorDir . '/hoa/iterator/Test/Unit/FileSystem.php', 'Hoa\\Iterator\\Test\\Unit\\Filter' => $vendorDir . '/hoa/iterator/Test/Unit/Filter.php', 'Hoa\\Iterator\\Test\\Unit\\Infinite' => $vendorDir . '/hoa/iterator/Test/Unit/Infinite.php', 'Hoa\\Iterator\\Test\\Unit\\IteratorIterator' => $vendorDir . '/hoa/iterator/Test/Unit/IteratorIterator.php', 'Hoa\\Iterator\\Test\\Unit\\Limit' => $vendorDir . '/hoa/iterator/Test/Unit/Limit.php', 'Hoa\\Iterator\\Test\\Unit\\Lookahead' => $vendorDir . '/hoa/iterator/Test/Unit/Lookahead.php', 'Hoa\\Iterator\\Test\\Unit\\Lookbehind' => $vendorDir . '/hoa/iterator/Test/Unit/Lookbehind.php', 'Hoa\\Iterator\\Test\\Unit\\Map' => $vendorDir . '/hoa/iterator/Test/Unit/Map.php', 'Hoa\\Iterator\\Test\\Unit\\Mock' => $vendorDir . '/hoa/iterator/Test/Unit/Mock.php', 'Hoa\\Iterator\\Test\\Unit\\Multiple' => $vendorDir . '/hoa/iterator/Test/Unit/Multiple.php', 'Hoa\\Iterator\\Test\\Unit\\NoRewind' => $vendorDir . '/hoa/iterator/Test/Unit/NoRewind.php', 'Hoa\\Iterator\\Test\\Unit\\RegularExpression' => $vendorDir . '/hoa/iterator/Test/Unit/RegularExpression.php', 'Hoa\\Iterator\\Test\\Unit\\Repeater' => $vendorDir . '/hoa/iterator/Test/Unit/Repeater.php', 'Hoa\\Iterator\\Test\\Unit\\SplFileInfo' => $vendorDir . '/hoa/iterator/Test/Unit/SplFileInfo.php', 'Hoa\\Math\\Bin\\Calc' => $vendorDir . '/hoa/math/Bin/Calc.php', 'Hoa\\Math\\Combinatorics\\Combination\\CartesianProduct' => $vendorDir . '/hoa/math/Combinatorics/Combination/CartesianProduct.php', 'Hoa\\Math\\Combinatorics\\Combination\\Combination' => $vendorDir . '/hoa/math/Combinatorics/Combination/Combination.php', 'Hoa\\Math\\Combinatorics\\Combination\\Gamma' => $vendorDir . '/hoa/math/Combinatorics/Combination/Gamma.php', 'Hoa\\Math\\Context' => $vendorDir . '/hoa/math/Context.php', 'Hoa\\Math\\Exception\\AlreadyDefinedConstant' => $vendorDir . '/hoa/math/Exception/AlreadyDefinedConstant.php', 'Hoa\\Math\\Exception\\Exception' => $vendorDir . '/hoa/math/Exception/Exception.php', 'Hoa\\Math\\Exception\\UnknownConstant' => $vendorDir . '/hoa/math/Exception/UnknownConstant.php', 'Hoa\\Math\\Exception\\UnknownFunction' => $vendorDir . '/hoa/math/Exception/UnknownFunction.php', 'Hoa\\Math\\Exception\\UnknownVariable' => $vendorDir . '/hoa/math/Exception/UnknownVariable.php', 'Hoa\\Math\\Sampler\\Random' => $vendorDir . '/hoa/math/Sampler/Random.php', 'Hoa\\Math\\Sampler\\Sampler' => $vendorDir . '/hoa/math/Sampler/Sampler.php', 'Hoa\\Math\\Test\\Unit\\Combinatorics\\Combination\\CartesianProduct' => $vendorDir . '/hoa/math/Test/Unit/Combinatorics/Combination/CartesianProduct.php', 'Hoa\\Math\\Test\\Unit\\Combinatorics\\Combination\\Combination' => $vendorDir . '/hoa/math/Test/Unit/Combinatorics/Combination/Combination.php', 'Hoa\\Math\\Test\\Unit\\Combinatorics\\Combination\\Gamma' => $vendorDir . '/hoa/math/Test/Unit/Combinatorics/Combination/Gamma.php', 'Hoa\\Math\\Test\\Unit\\Context' => $vendorDir . '/hoa/math/Test/Unit/Context.php', 'Hoa\\Math\\Test\\Unit\\Issue' => $vendorDir . '/hoa/math/Test/Unit/Issue.php', 'Hoa\\Math\\Test\\Unit\\Sampler\\Random' => $vendorDir . '/hoa/math/Test/Unit/Sampler/Random.php', 'Hoa\\Math\\Test\\Unit\\Visitor\\Arithmetic' => $vendorDir . '/hoa/math/Test/Unit/Visitor/Arithmetic.php', 'Hoa\\Math\\Util' => $vendorDir . '/hoa/math/Util.php', 'Hoa\\Math\\Visitor\\Arithmetic' => $vendorDir . '/hoa/math/Visitor/Arithmetic.php', 'Hoa\\Protocol\\Bin\\Resolve' => $vendorDir . '/hoa/protocol/Bin/Resolve.php', 'Hoa\\Protocol\\Exception' => $vendorDir . '/hoa/protocol/Exception.php', 'Hoa\\Protocol\\Node\\Library' => $vendorDir . '/hoa/protocol/Node/Library.php', 'Hoa\\Protocol\\Node\\Node' => $vendorDir . '/hoa/protocol/Node/Node.php', 'Hoa\\Protocol\\Protocol' => $vendorDir . '/hoa/protocol/Protocol.php', 'Hoa\\Protocol\\Test\\Unit\\Exception' => $vendorDir . '/hoa/protocol/Test/Unit/Exception.php', 'Hoa\\Protocol\\Test\\Unit\\Node\\Library' => $vendorDir . '/hoa/protocol/Test/Unit/Node/Library.php', 'Hoa\\Protocol\\Test\\Unit\\Node\\Node' => $vendorDir . '/hoa/protocol/Test/Unit/Node/Node.php', 'Hoa\\Protocol\\Test\\Unit\\Protocol' => $vendorDir . '/hoa/protocol/Test/Unit/Protocol.php', 'Hoa\\Protocol\\Test\\Unit\\Wrapper' => $vendorDir . '/hoa/protocol/Test/Unit/Wrapper.php', 'Hoa\\Protocol\\Wrapper' => $vendorDir . '/hoa/protocol/Wrapper.php', 'Hoa\\Regex\\Exception' => $vendorDir . '/hoa/regex/Exception.php', 'Hoa\\Regex\\Visitor\\Isotropic' => $vendorDir . '/hoa/regex/Visitor/Isotropic.php', 'Hoa\\Stream\\Bucket' => $vendorDir . '/hoa/stream/Bucket.php', 'Hoa\\Stream\\Composite' => $vendorDir . '/hoa/stream/Composite.php', 'Hoa\\Stream\\Context' => $vendorDir . '/hoa/stream/Context.php', 'Hoa\\Stream\\Exception' => $vendorDir . '/hoa/stream/Exception.php', 'Hoa\\Stream\\Filter\\Basic' => $vendorDir . '/hoa/stream/Filter/Basic.php', 'Hoa\\Stream\\Filter\\Exception' => $vendorDir . '/hoa/stream/Filter/Exception.php', 'Hoa\\Stream\\Filter\\Filter' => $vendorDir . '/hoa/stream/Filter/Filter.php', 'Hoa\\Stream\\Filter\\LateComputed' => $vendorDir . '/hoa/stream/Filter/LateComputed.php', 'Hoa\\Stream\\IStream\\Bufferable' => $vendorDir . '/hoa/stream/IStream/Bufferable.php', 'Hoa\\Stream\\IStream\\In' => $vendorDir . '/hoa/stream/IStream/In.php', 'Hoa\\Stream\\IStream\\Lockable' => $vendorDir . '/hoa/stream/IStream/Lockable.php', 'Hoa\\Stream\\IStream\\Out' => $vendorDir . '/hoa/stream/IStream/Out.php', 'Hoa\\Stream\\IStream\\Pathable' => $vendorDir . '/hoa/stream/IStream/Pathable.php', 'Hoa\\Stream\\IStream\\Pointable' => $vendorDir . '/hoa/stream/IStream/Pointable.php', 'Hoa\\Stream\\IStream\\Statable' => $vendorDir . '/hoa/stream/IStream/Statable.php', 'Hoa\\Stream\\IStream\\Stream' => $vendorDir . '/hoa/stream/IStream/Stream.php', 'Hoa\\Stream\\IStream\\Structural' => $vendorDir . '/hoa/stream/IStream/Structural.php', 'Hoa\\Stream\\IStream\\Touchable' => $vendorDir . '/hoa/stream/IStream/Touchable.php', 'Hoa\\Stream\\Stream' => $vendorDir . '/hoa/stream/Stream.php', 'Hoa\\Stream\\Test\\Integration\\Filter\\Filter' => $vendorDir . '/hoa/stream/Test/Integration/Filter/Filter.php', 'Hoa\\Stream\\Test\\Integration\\Filter\\LateComputed' => $vendorDir . '/hoa/stream/Test/Integration/Filter/LateComputed.php', 'Hoa\\Stream\\Test\\Integration\\Stream' => $vendorDir . '/hoa/stream/Test/Integration/Stream.php', 'Hoa\\Stream\\Test\\Unit\\Bucket' => $vendorDir . '/hoa/stream/Test/Unit/Bucket.php', 'Hoa\\Stream\\Test\\Unit\\Composite' => $vendorDir . '/hoa/stream/Test/Unit/Composite.php', 'Hoa\\Stream\\Test\\Unit\\Context' => $vendorDir . '/hoa/stream/Test/Unit/Context.php', 'Hoa\\Stream\\Test\\Unit\\Exception' => $vendorDir . '/hoa/stream/Test/Unit/Exception.php', 'Hoa\\Stream\\Test\\Unit\\Filter\\Basic' => $vendorDir . '/hoa/stream/Test/Unit/Filter/Basic.php', 'Hoa\\Stream\\Test\\Unit\\Filter\\Exception' => $vendorDir . '/hoa/stream/Test/Unit/Filter/Exception.php', 'Hoa\\Stream\\Test\\Unit\\Filter\\Filter' => $vendorDir . '/hoa/stream/Test/Unit/Filter/Filter.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Bufferable' => $vendorDir . '/hoa/stream/Test/Unit/IStream/Bufferable.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\In' => $vendorDir . '/hoa/stream/Test/Unit/IStream/In.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Lockable' => $vendorDir . '/hoa/stream/Test/Unit/IStream/Lockable.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Out' => $vendorDir . '/hoa/stream/Test/Unit/IStream/Out.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Pathable' => $vendorDir . '/hoa/stream/Test/Unit/IStream/Pathable.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Pointable' => $vendorDir . '/hoa/stream/Test/Unit/IStream/Pointable.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Statable' => $vendorDir . '/hoa/stream/Test/Unit/IStream/Statable.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Stream' => $vendorDir . '/hoa/stream/Test/Unit/IStream/Stream.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Structural' => $vendorDir . '/hoa/stream/Test/Unit/IStream/Structural.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Touchable' => $vendorDir . '/hoa/stream/Test/Unit/IStream/Touchable.php', 'Hoa\\Stream\\Test\\Unit\\Stream' => $vendorDir . '/hoa/stream/Test/Unit/Stream.php', 'Hoa\\Stream\\Test\\Unit\\Wrapper\\Exception' => $vendorDir . '/hoa/stream/Test/Unit/Wrapper/Exception.php', 'Hoa\\Stream\\Test\\Unit\\Wrapper\\IWrapper\\File' => $vendorDir . '/hoa/stream/Test/Unit/Wrapper/IWrapper/File.php', 'Hoa\\Stream\\Test\\Unit\\Wrapper\\IWrapper\\IWrapper' => $vendorDir . '/hoa/stream/Test/Unit/Wrapper/IWrapper/IWrapper.php', 'Hoa\\Stream\\Test\\Unit\\Wrapper\\IWrapper\\Stream' => $vendorDir . '/hoa/stream/Test/Unit/Wrapper/IWrapper/Stream.php', 'Hoa\\Stream\\Test\\Unit\\Wrapper\\Wrapper' => $vendorDir . '/hoa/stream/Test/Unit/Wrapper/Wrapper.php', 'Hoa\\Stream\\Wrapper\\Exception' => $vendorDir . '/hoa/stream/Wrapper/Exception.php', 'Hoa\\Stream\\Wrapper\\IWrapper\\File' => $vendorDir . '/hoa/stream/Wrapper/IWrapper/File.php', 'Hoa\\Stream\\Wrapper\\IWrapper\\IWrapper' => $vendorDir . '/hoa/stream/Wrapper/IWrapper/IWrapper.php', 'Hoa\\Stream\\Wrapper\\IWrapper\\Stream' => $vendorDir . '/hoa/stream/Wrapper/IWrapper/Stream.php', 'Hoa\\Stream\\Wrapper\\Wrapper' => $vendorDir . '/hoa/stream/Wrapper/Wrapper.php', 'Hoa\\Ustring\\Bin\\Fromcode' => $vendorDir . '/hoa/ustring/Bin/Fromcode.php', 'Hoa\\Ustring\\Bin\\Tocode' => $vendorDir . '/hoa/ustring/Bin/Tocode.php', 'Hoa\\Ustring\\Exception' => $vendorDir . '/hoa/ustring/Exception.php', 'Hoa\\Ustring\\Search' => $vendorDir . '/hoa/ustring/Search.php', 'Hoa\\Ustring\\Test\\Unit\\Issue' => $vendorDir . '/hoa/ustring/Test/Unit/Issue.php', 'Hoa\\Ustring\\Test\\Unit\\Search' => $vendorDir . '/hoa/ustring/Test/Unit/Search.php', 'Hoa\\Ustring\\Test\\Unit\\Ustring' => $vendorDir . '/hoa/ustring/Test/Unit/Ustring.php', 'Hoa\\Ustring\\Ustring' => $vendorDir . '/hoa/ustring/Ustring.php', 'Hoa\\Visitor\\Element' => $vendorDir . '/hoa/visitor/Element.php', 'Hoa\\Visitor\\Test\\Unit\\Element' => $vendorDir . '/hoa/visitor/Test/Unit/Element.php', 'Hoa\\Visitor\\Test\\Unit\\Visit' => $vendorDir . '/hoa/visitor/Test/Unit/Visit.php', 'Hoa\\Visitor\\Visit' => $vendorDir . '/hoa/visitor/Visit.php', 'Hoa\\Zformat\\Exception' => $vendorDir . '/hoa/zformat/Exception.php', 'Hoa\\Zformat\\Parameter' => $vendorDir . '/hoa/zformat/Parameter.php', 'Hoa\\Zformat\\Parameterizable' => $vendorDir . '/hoa/zformat/Parameterizable.php', 'NoDiscard' => $vendorDir . '/symfony/polyfill-php85/Resources/stubs/NoDiscard.php', 'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', 'Override' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/Override.php', 'PHPStan\\AnalysedCodeException' => $baseDir . '/src/AnalysedCodeException.php', 'PHPStan\\Analyser\\Analyser' => $baseDir . '/src/Analyser/Analyser.php', 'PHPStan\\Analyser\\AnalyserResult' => $baseDir . '/src/Analyser/AnalyserResult.php', 'PHPStan\\Analyser\\AnalyserResultFinalizer' => $baseDir . '/src/Analyser/AnalyserResultFinalizer.php', 'PHPStan\\Analyser\\ArgumentsNormalizer' => $baseDir . '/src/Analyser/ArgumentsNormalizer.php', 'PHPStan\\Analyser\\ConditionalExpressionHolder' => $baseDir . '/src/Analyser/ConditionalExpressionHolder.php', 'PHPStan\\Analyser\\ConstantResolver' => $baseDir . '/src/Analyser/ConstantResolver.php', 'PHPStan\\Analyser\\ConstantResolverFactory' => $baseDir . '/src/Analyser/ConstantResolverFactory.php', 'PHPStan\\Analyser\\DirectInternalScopeFactory' => $baseDir . '/src/Analyser/DirectInternalScopeFactory.php', 'PHPStan\\Analyser\\DirectInternalScopeFactoryFactory' => $baseDir . '/src/Analyser/DirectInternalScopeFactoryFactory.php', 'PHPStan\\Analyser\\EndStatementResult' => $baseDir . '/src/Analyser/EndStatementResult.php', 'PHPStan\\Analyser\\EnsuredNonNullabilityResult' => $baseDir . '/src/Analyser/EnsuredNonNullabilityResult.php', 'PHPStan\\Analyser\\EnsuredNonNullabilityResultExpression' => $baseDir . '/src/Analyser/EnsuredNonNullabilityResultExpression.php', 'PHPStan\\Analyser\\Error' => $baseDir . '/src/Analyser/Error.php', 'PHPStan\\Analyser\\ExprHandler' => $baseDir . '/src/Analyser/ExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ArrayDimFetchHandler' => $baseDir . '/src/Analyser/ExprHandler/ArrayDimFetchHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ArrayHandler' => $baseDir . '/src/Analyser/ExprHandler/ArrayHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ArrowFunctionHandler' => $baseDir . '/src/Analyser/ExprHandler/ArrowFunctionHandler.php', 'PHPStan\\Analyser\\ExprHandler\\AssignHandler' => $baseDir . '/src/Analyser/ExprHandler/AssignHandler.php', 'PHPStan\\Analyser\\ExprHandler\\AssignOpHandler' => $baseDir . '/src/Analyser/ExprHandler/AssignOpHandler.php', 'PHPStan\\Analyser\\ExprHandler\\BinaryOpHandler' => $baseDir . '/src/Analyser/ExprHandler/BinaryOpHandler.php', 'PHPStan\\Analyser\\ExprHandler\\BitwiseNotHandler' => $baseDir . '/src/Analyser/ExprHandler/BitwiseNotHandler.php', 'PHPStan\\Analyser\\ExprHandler\\BooleanAndHandler' => $baseDir . '/src/Analyser/ExprHandler/BooleanAndHandler.php', 'PHPStan\\Analyser\\ExprHandler\\BooleanNotHandler' => $baseDir . '/src/Analyser/ExprHandler/BooleanNotHandler.php', 'PHPStan\\Analyser\\ExprHandler\\BooleanOrHandler' => $baseDir . '/src/Analyser/ExprHandler/BooleanOrHandler.php', 'PHPStan\\Analyser\\ExprHandler\\CastHandler' => $baseDir . '/src/Analyser/ExprHandler/CastHandler.php', 'PHPStan\\Analyser\\ExprHandler\\CastStringHandler' => $baseDir . '/src/Analyser/ExprHandler/CastStringHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ClassConstFetchHandler' => $baseDir . '/src/Analyser/ExprHandler/ClassConstFetchHandler.php', 'PHPStan\\Analyser\\ExprHandler\\CloneHandler' => $baseDir . '/src/Analyser/ExprHandler/CloneHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ClosureHandler' => $baseDir . '/src/Analyser/ExprHandler/ClosureHandler.php', 'PHPStan\\Analyser\\ExprHandler\\CoalesceHandler' => $baseDir . '/src/Analyser/ExprHandler/CoalesceHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ConstFetchHandler' => $baseDir . '/src/Analyser/ExprHandler/ConstFetchHandler.php', 'PHPStan\\Analyser\\ExprHandler\\EmptyHandler' => $baseDir . '/src/Analyser/ExprHandler/EmptyHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ErrorSuppressHandler' => $baseDir . '/src/Analyser/ExprHandler/ErrorSuppressHandler.php', 'PHPStan\\Analyser\\ExprHandler\\EvalHandler' => $baseDir . '/src/Analyser/ExprHandler/EvalHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ExitHandler' => $baseDir . '/src/Analyser/ExprHandler/ExitHandler.php', 'PHPStan\\Analyser\\ExprHandler\\FirstClassCallableFuncCallHandler' => $baseDir . '/src/Analyser/ExprHandler/FirstClassCallableFuncCallHandler.php', 'PHPStan\\Analyser\\ExprHandler\\FirstClassCallableMethodCallHandler' => $baseDir . '/src/Analyser/ExprHandler/FirstClassCallableMethodCallHandler.php', 'PHPStan\\Analyser\\ExprHandler\\FirstClassCallableNewHandler' => $baseDir . '/src/Analyser/ExprHandler/FirstClassCallableNewHandler.php', 'PHPStan\\Analyser\\ExprHandler\\FirstClassCallableStaticCallHandler' => $baseDir . '/src/Analyser/ExprHandler/FirstClassCallableStaticCallHandler.php', 'PHPStan\\Analyser\\ExprHandler\\FuncCallHandler' => $baseDir . '/src/Analyser/ExprHandler/FuncCallHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Helper\\ClosureTypeResolver' => $baseDir . '/src/Analyser/ExprHandler/Helper/ClosureTypeResolver.php', 'PHPStan\\Analyser\\ExprHandler\\Helper\\ImplicitToStringCallHelper' => $baseDir . '/src/Analyser/ExprHandler/Helper/ImplicitToStringCallHelper.php', 'PHPStan\\Analyser\\ExprHandler\\Helper\\MethodCallReturnTypeHelper' => $baseDir . '/src/Analyser/ExprHandler/Helper/MethodCallReturnTypeHelper.php', 'PHPStan\\Analyser\\ExprHandler\\Helper\\MethodThrowPointHelper' => $baseDir . '/src/Analyser/ExprHandler/Helper/MethodThrowPointHelper.php', 'PHPStan\\Analyser\\ExprHandler\\Helper\\NonNullabilityHelper' => $baseDir . '/src/Analyser/ExprHandler/Helper/NonNullabilityHelper.php', 'PHPStan\\Analyser\\ExprHandler\\Helper\\NullsafeShortCircuitingHelper' => $baseDir . '/src/Analyser/ExprHandler/Helper/NullsafeShortCircuitingHelper.php', 'PHPStan\\Analyser\\ExprHandler\\Helper\\VoidToNullTypeTransformer' => $baseDir . '/src/Analyser/ExprHandler/Helper/VoidToNullTypeTransformer.php', 'PHPStan\\Analyser\\ExprHandler\\IncludeHandler' => $baseDir . '/src/Analyser/ExprHandler/IncludeHandler.php', 'PHPStan\\Analyser\\ExprHandler\\InstanceofHandler' => $baseDir . '/src/Analyser/ExprHandler/InstanceofHandler.php', 'PHPStan\\Analyser\\ExprHandler\\InterpolatedStringHandler' => $baseDir . '/src/Analyser/ExprHandler/InterpolatedStringHandler.php', 'PHPStan\\Analyser\\ExprHandler\\IssetHandler' => $baseDir . '/src/Analyser/ExprHandler/IssetHandler.php', 'PHPStan\\Analyser\\ExprHandler\\MatchHandler' => $baseDir . '/src/Analyser/ExprHandler/MatchHandler.php', 'PHPStan\\Analyser\\ExprHandler\\MethodCallHandler' => $baseDir . '/src/Analyser/ExprHandler/MethodCallHandler.php', 'PHPStan\\Analyser\\ExprHandler\\NewHandler' => $baseDir . '/src/Analyser/ExprHandler/NewHandler.php', 'PHPStan\\Analyser\\ExprHandler\\NullsafeMethodCallHandler' => $baseDir . '/src/Analyser/ExprHandler/NullsafeMethodCallHandler.php', 'PHPStan\\Analyser\\ExprHandler\\NullsafePropertyFetchHandler' => $baseDir . '/src/Analyser/ExprHandler/NullsafePropertyFetchHandler.php', 'PHPStan\\Analyser\\ExprHandler\\PipeHandler' => $baseDir . '/src/Analyser/ExprHandler/PipeHandler.php', 'PHPStan\\Analyser\\ExprHandler\\PostDecHandler' => $baseDir . '/src/Analyser/ExprHandler/PostDecHandler.php', 'PHPStan\\Analyser\\ExprHandler\\PostIncHandler' => $baseDir . '/src/Analyser/ExprHandler/PostIncHandler.php', 'PHPStan\\Analyser\\ExprHandler\\PreDecHandler' => $baseDir . '/src/Analyser/ExprHandler/PreDecHandler.php', 'PHPStan\\Analyser\\ExprHandler\\PreIncHandler' => $baseDir . '/src/Analyser/ExprHandler/PreIncHandler.php', 'PHPStan\\Analyser\\ExprHandler\\PrintHandler' => $baseDir . '/src/Analyser/ExprHandler/PrintHandler.php', 'PHPStan\\Analyser\\ExprHandler\\PropertyFetchHandler' => $baseDir . '/src/Analyser/ExprHandler/PropertyFetchHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ScalarHandler' => $baseDir . '/src/Analyser/ExprHandler/ScalarHandler.php', 'PHPStan\\Analyser\\ExprHandler\\StaticCallHandler' => $baseDir . '/src/Analyser/ExprHandler/StaticCallHandler.php', 'PHPStan\\Analyser\\ExprHandler\\StaticPropertyFetchHandler' => $baseDir . '/src/Analyser/ExprHandler/StaticPropertyFetchHandler.php', 'PHPStan\\Analyser\\ExprHandler\\TernaryHandler' => $baseDir . '/src/Analyser/ExprHandler/TernaryHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ThrowHandler' => $baseDir . '/src/Analyser/ExprHandler/ThrowHandler.php', 'PHPStan\\Analyser\\ExprHandler\\UnaryMinusHandler' => $baseDir . '/src/Analyser/ExprHandler/UnaryMinusHandler.php', 'PHPStan\\Analyser\\ExprHandler\\UnaryPlusHandler' => $baseDir . '/src/Analyser/ExprHandler/UnaryPlusHandler.php', 'PHPStan\\Analyser\\ExprHandler\\VariableHandler' => $baseDir . '/src/Analyser/ExprHandler/VariableHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\AlwaysRememberedExprHandler' => $baseDir . '/src/Analyser/ExprHandler/Virtual/AlwaysRememberedExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\ExistingArrayDimFetchHandler' => $baseDir . '/src/Analyser/ExprHandler/Virtual/ExistingArrayDimFetchHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\FunctionCallableNodeHandler' => $baseDir . '/src/Analyser/ExprHandler/Virtual/FunctionCallableNodeHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\GetIterableKeyTypeExprHandler' => $baseDir . '/src/Analyser/ExprHandler/Virtual/GetIterableKeyTypeExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\GetIterableValueTypeExprHandler' => $baseDir . '/src/Analyser/ExprHandler/Virtual/GetIterableValueTypeExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\GetOffsetValueTypeExprHandler' => $baseDir . '/src/Analyser/ExprHandler/Virtual/GetOffsetValueTypeExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\InstantiationCallableNodeHandler' => $baseDir . '/src/Analyser/ExprHandler/Virtual/InstantiationCallableNodeHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\MethodCallableNodeHandler' => $baseDir . '/src/Analyser/ExprHandler/Virtual/MethodCallableNodeHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\NativeTypeExprHandler' => $baseDir . '/src/Analyser/ExprHandler/Virtual/NativeTypeExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\OriginalPropertyTypeExprHandler' => $baseDir . '/src/Analyser/ExprHandler/Virtual/OriginalPropertyTypeExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\SetExistingOffsetValueTypeExprHandler' => $baseDir . '/src/Analyser/ExprHandler/Virtual/SetExistingOffsetValueTypeExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\SetOffsetValueTypeExprHandler' => $baseDir . '/src/Analyser/ExprHandler/Virtual/SetOffsetValueTypeExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\StaticMethodCallableNodeHandler' => $baseDir . '/src/Analyser/ExprHandler/Virtual/StaticMethodCallableNodeHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\TypeExprHandler' => $baseDir . '/src/Analyser/ExprHandler/Virtual/TypeExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\UnsetOffsetExprHandler' => $baseDir . '/src/Analyser/ExprHandler/Virtual/UnsetOffsetExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\YieldFromHandler' => $baseDir . '/src/Analyser/ExprHandler/YieldFromHandler.php', 'PHPStan\\Analyser\\ExprHandler\\YieldHandler' => $baseDir . '/src/Analyser/ExprHandler/YieldHandler.php', 'PHPStan\\Analyser\\ExpressionContext' => $baseDir . '/src/Analyser/ExpressionContext.php', 'PHPStan\\Analyser\\ExpressionResult' => $baseDir . '/src/Analyser/ExpressionResult.php', 'PHPStan\\Analyser\\ExpressionResultStorage' => $baseDir . '/src/Analyser/ExpressionResultStorage.php', 'PHPStan\\Analyser\\ExpressionTypeHolder' => $baseDir . '/src/Analyser/ExpressionTypeHolder.php', 'PHPStan\\Analyser\\Fiber\\BeforeScopeForExprRequest' => $baseDir . '/src/Analyser/Fiber/BeforeScopeForExprRequest.php', 'PHPStan\\Analyser\\Fiber\\FiberNodeScopeResolver' => $baseDir . '/src/Analyser/Fiber/FiberNodeScopeResolver.php', 'PHPStan\\Analyser\\Fiber\\FiberScope' => $baseDir . '/src/Analyser/Fiber/FiberScope.php', 'PHPStan\\Analyser\\Fiber\\ParkFiberRequest' => $baseDir . '/src/Analyser/Fiber/ParkFiberRequest.php', 'PHPStan\\Analyser\\FileAnalyser' => $baseDir . '/src/Analyser/FileAnalyser.php', 'PHPStan\\Analyser\\FileAnalyserCallback' => $baseDir . '/src/Analyser/FileAnalyserCallback.php', 'PHPStan\\Analyser\\FileAnalyserResult' => $baseDir . '/src/Analyser/FileAnalyserResult.php', 'PHPStan\\Analyser\\FinalizerResult' => $baseDir . '/src/Analyser/FinalizerResult.php', 'PHPStan\\Analyser\\FixedErrorDiff' => $baseDir . '/src/Analyser/FixedErrorDiff.php', 'PHPStan\\Analyser\\IgnoreErrorExtension' => $baseDir . '/src/Analyser/IgnoreErrorExtension.php', 'PHPStan\\Analyser\\IgnoreErrorExtensionProvider' => $baseDir . '/src/Analyser/IgnoreErrorExtensionProvider.php', 'PHPStan\\Analyser\\Ignore\\IgnoreLexer' => $baseDir . '/src/Analyser/Ignore/IgnoreLexer.php', 'PHPStan\\Analyser\\Ignore\\IgnoreParseException' => $baseDir . '/src/Analyser/Ignore/IgnoreParseException.php', 'PHPStan\\Analyser\\Ignore\\IgnoredError' => $baseDir . '/src/Analyser/Ignore/IgnoredError.php', 'PHPStan\\Analyser\\Ignore\\IgnoredErrorHelper' => $baseDir . '/src/Analyser/Ignore/IgnoredErrorHelper.php', 'PHPStan\\Analyser\\Ignore\\IgnoredErrorHelperProcessedResult' => $baseDir . '/src/Analyser/Ignore/IgnoredErrorHelperProcessedResult.php', 'PHPStan\\Analyser\\Ignore\\IgnoredErrorHelperResult' => $baseDir . '/src/Analyser/Ignore/IgnoredErrorHelperResult.php', 'PHPStan\\Analyser\\ImpurePoint' => $baseDir . '/src/Analyser/ImpurePoint.php', 'PHPStan\\Analyser\\IntermediaryNameScope' => $baseDir . '/src/Analyser/IntermediaryNameScope.php', 'PHPStan\\Analyser\\InternalEndStatementResult' => $baseDir . '/src/Analyser/InternalEndStatementResult.php', 'PHPStan\\Analyser\\InternalError' => $baseDir . '/src/Analyser/InternalError.php', 'PHPStan\\Analyser\\InternalScopeFactory' => $baseDir . '/src/Analyser/InternalScopeFactory.php', 'PHPStan\\Analyser\\InternalScopeFactoryFactory' => $baseDir . '/src/Analyser/InternalScopeFactoryFactory.php', 'PHPStan\\Analyser\\InternalStatementExitPoint' => $baseDir . '/src/Analyser/InternalStatementExitPoint.php', 'PHPStan\\Analyser\\InternalStatementResult' => $baseDir . '/src/Analyser/InternalStatementResult.php', 'PHPStan\\Analyser\\InternalThrowPoint' => $baseDir . '/src/Analyser/InternalThrowPoint.php', 'PHPStan\\Analyser\\LazyInternalScopeFactory' => $baseDir . '/src/Analyser/LazyInternalScopeFactory.php', 'PHPStan\\Analyser\\LocalIgnoresProcessor' => $baseDir . '/src/Analyser/LocalIgnoresProcessor.php', 'PHPStan\\Analyser\\LocalIgnoresProcessorResult' => $baseDir . '/src/Analyser/LocalIgnoresProcessorResult.php', 'PHPStan\\Analyser\\MutatingScope' => $baseDir . '/src/Analyser/MutatingScope.php', 'PHPStan\\Analyser\\NameScope' => $baseDir . '/src/Analyser/NameScope.php', 'PHPStan\\Analyser\\NodeCallbackInvoker' => $baseDir . '/src/Analyser/NodeCallbackInvoker.php', 'PHPStan\\Analyser\\NodeScopeResolver' => $baseDir . '/src/Analyser/NodeScopeResolver.php', 'PHPStan\\Analyser\\NoopNodeCallback' => $baseDir . '/src/Analyser/NoopNodeCallback.php', 'PHPStan\\Analyser\\NullsafeOperatorHelper' => $baseDir . '/src/Analyser/NullsafeOperatorHelper.php', 'PHPStan\\Analyser\\OutOfClassScope' => $baseDir . '/src/Analyser/OutOfClassScope.php', 'PHPStan\\Analyser\\ProcessClosureResult' => $baseDir . '/src/Analyser/ProcessClosureResult.php', 'PHPStan\\Analyser\\ResultCache\\ResultCache' => $baseDir . '/src/Analyser/ResultCache/ResultCache.php', 'PHPStan\\Analyser\\ResultCache\\ResultCacheClearer' => $baseDir . '/src/Analyser/ResultCache/ResultCacheClearer.php', 'PHPStan\\Analyser\\ResultCache\\ResultCacheManager' => $baseDir . '/src/Analyser/ResultCache/ResultCacheManager.php', 'PHPStan\\Analyser\\ResultCache\\ResultCacheManagerFactory' => $baseDir . '/src/Analyser/ResultCache/ResultCacheManagerFactory.php', 'PHPStan\\Analyser\\ResultCache\\ResultCacheMetaExtension' => $baseDir . '/src/Analyser/ResultCache/ResultCacheMetaExtension.php', 'PHPStan\\Analyser\\ResultCache\\ResultCacheProcessResult' => $baseDir . '/src/Analyser/ResultCache/ResultCacheProcessResult.php', 'PHPStan\\Analyser\\RicherScopeGetTypeHelper' => $baseDir . '/src/Analyser/RicherScopeGetTypeHelper.php', 'PHPStan\\Analyser\\RuleErrorTransformer' => $baseDir . '/src/Analyser/RuleErrorTransformer.php', 'PHPStan\\Analyser\\Scope' => $baseDir . '/src/Analyser/Scope.php', 'PHPStan\\Analyser\\ScopeContext' => $baseDir . '/src/Analyser/ScopeContext.php', 'PHPStan\\Analyser\\ScopeFactory' => $baseDir . '/src/Analyser/ScopeFactory.php', 'PHPStan\\Analyser\\ShallowNodeCallback' => $baseDir . '/src/Analyser/ShallowNodeCallback.php', 'PHPStan\\Analyser\\SpecifiedTypes' => $baseDir . '/src/Analyser/SpecifiedTypes.php', 'PHPStan\\Analyser\\StatementContext' => $baseDir . '/src/Analyser/StatementContext.php', 'PHPStan\\Analyser\\StatementExitPoint' => $baseDir . '/src/Analyser/StatementExitPoint.php', 'PHPStan\\Analyser\\StatementResult' => $baseDir . '/src/Analyser/StatementResult.php', 'PHPStan\\Analyser\\ThrowPoint' => $baseDir . '/src/Analyser/ThrowPoint.php', 'PHPStan\\Analyser\\Traverser\\CloneTypeTraverser' => $baseDir . '/src/Analyser/Traverser/CloneTypeTraverser.php', 'PHPStan\\Analyser\\Traverser\\ConstructorClassTemplateTraverser' => $baseDir . '/src/Analyser/Traverser/ConstructorClassTemplateTraverser.php', 'PHPStan\\Analyser\\Traverser\\GenericTypeTemplateTraverser' => $baseDir . '/src/Analyser/Traverser/GenericTypeTemplateTraverser.php', 'PHPStan\\Analyser\\Traverser\\TransformStaticTypeTraverser' => $baseDir . '/src/Analyser/Traverser/TransformStaticTypeTraverser.php', 'PHPStan\\Analyser\\Traverser\\VoidToNullTraverser' => $baseDir . '/src/Analyser/Traverser/VoidToNullTraverser.php', 'PHPStan\\Analyser\\TypeSpecifier' => $baseDir . '/src/Analyser/TypeSpecifier.php', 'PHPStan\\Analyser\\TypeSpecifierAwareExtension' => $baseDir . '/src/Analyser/TypeSpecifierAwareExtension.php', 'PHPStan\\Analyser\\TypeSpecifierContext' => $baseDir . '/src/Analyser/TypeSpecifierContext.php', 'PHPStan\\Analyser\\TypeSpecifierFactory' => $baseDir . '/src/Analyser/TypeSpecifierFactory.php', 'PHPStan\\Analyser\\UndefinedVariableException' => $baseDir . '/src/Analyser/UndefinedVariableException.php', 'PHPStan\\Analyser\\VirtualAssignNodeCallback' => $baseDir . '/src/Analyser/VirtualAssignNodeCallback.php', 'PHPStan\\BetterReflection\\BetterReflection' => $vendorDir . '/ondrejmirtes/better-reflection/src/BetterReflection.php', 'PHPStan\\BetterReflection\\Identifier\\Exception\\InvalidIdentifierName' => $vendorDir . '/ondrejmirtes/better-reflection/src/Identifier/Exception/InvalidIdentifierName.php', 'PHPStan\\BetterReflection\\Identifier\\Identifier' => $vendorDir . '/ondrejmirtes/better-reflection/src/Identifier/Identifier.php', 'PHPStan\\BetterReflection\\Identifier\\IdentifierType' => $vendorDir . '/ondrejmirtes/better-reflection/src/Identifier/IdentifierType.php', 'PHPStan\\BetterReflection\\NodeCompiler\\CompileNodeToValue' => $vendorDir . '/ondrejmirtes/better-reflection/src/NodeCompiler/CompileNodeToValue.php', 'PHPStan\\BetterReflection\\NodeCompiler\\CompiledValue' => $vendorDir . '/ondrejmirtes/better-reflection/src/NodeCompiler/CompiledValue.php', 'PHPStan\\BetterReflection\\NodeCompiler\\CompilerContext' => $vendorDir . '/ondrejmirtes/better-reflection/src/NodeCompiler/CompilerContext.php', 'PHPStan\\BetterReflection\\NodeCompiler\\Exception\\UnableToCompileNode' => $vendorDir . '/ondrejmirtes/better-reflection/src/NodeCompiler/Exception/UnableToCompileNode.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\Exception\\NotImplemented' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/Exception/NotImplemented.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\Exception\\NotImplementedBecauseItTriggersAutoloading' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/Exception/NotImplementedBecauseItTriggersAutoloading.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\FakeReflectionAttribute' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/FakeReflectionAttribute.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionAttribute' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionAttribute.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionAttributeFactory' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionAttributeFactory.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionClass' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionClass.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionClassConstant' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionClassConstant.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionEnum' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionEnum.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionEnumBackedCase' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionEnumBackedCase.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionEnumUnitCase' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionEnumUnitCase.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionFunction' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionFunction.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionIntersectionType' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionIntersectionType.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionMethod' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionMethod.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionNamedType' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionNamedType.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionObject' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionObject.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionParameter' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionParameter.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionProperty' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionProperty.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionType' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionType.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionUnionType' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionUnionType.php', 'PHPStan\\BetterReflection\\Reflection\\Annotation\\AnnotationHelper' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Annotation/AnnotationHelper.php', 'PHPStan\\BetterReflection\\Reflection\\Attribute\\ReflectionAttributeHelper' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Attribute/ReflectionAttributeHelper.php', 'PHPStan\\BetterReflection\\Reflection\\Deprecated\\DeprecatedHelper' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Deprecated/DeprecatedHelper.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\CircularReference' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Exception/CircularReference.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\ClassDoesNotExist' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Exception/ClassDoesNotExist.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\CodeLocationMissing' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Exception/CodeLocationMissing.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\FunctionDoesNotExist' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Exception/FunctionDoesNotExist.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\InvalidArrowFunctionBodyNode' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Exception/InvalidArrowFunctionBodyNode.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\InvalidConstantNode' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Exception/InvalidConstantNode.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\InvalidDefaultValueType' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Exception/InvalidDefaultValueType.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\MethodPrototypeNotFound' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Exception/MethodPrototypeNotFound.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\NoObjectProvided' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Exception/NoObjectProvided.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\NoParent' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Exception/NoParent.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\NotAnObject' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Exception/NotAnObject.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\ObjectNotInstanceOfClass' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Exception/ObjectNotInstanceOfClass.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\PropertyDoesNotExist' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Exception/PropertyDoesNotExist.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\PropertyIsNotStatic' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Exception/PropertyIsNotStatic.php', 'PHPStan\\BetterReflection\\Reflection\\ExprCacheHelper' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ExprCacheHelper.php', 'PHPStan\\BetterReflection\\Reflection\\Reflection' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Reflection.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionAttribute' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionAttribute.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionClass' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionClass.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionClassConstant' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionClassConstant.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionConstant' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionConstant.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionEnum' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionEnum.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionEnumCase' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionEnumCase.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionFunction' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionFunction.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionFunctionAbstract' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionFunctionAbstract.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionIntersectionType' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionIntersectionType.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionMethod' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionMethod.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionNamedType' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionNamedType.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionObject' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionObject.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionParameter' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionParameter.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionProperty' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionProperty.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionPropertyHookType' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionPropertyHookType.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionType' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionType.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionUnionType' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionUnionType.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionAttributeStringCast' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionAttributeStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionClassConstantStringCast' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionClassConstantStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionClassStringCast' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionClassStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionConstantStringCast' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionConstantStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionEnumCaseStringCast' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionEnumCaseStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionFunctionStringCast' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionFunctionStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionMethodStringCast' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionMethodStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionParameterStringCast' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionParameterStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionPropertyStringCast' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionPropertyStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionStringCastHelper' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionStringCastHelper.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionTypeStringCast' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionTypeStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\Support\\AlreadyVisitedClasses' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflection/Support/AlreadyVisitedClasses.php', 'PHPStan\\BetterReflection\\Reflector\\DefaultReflector' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflector/DefaultReflector.php', 'PHPStan\\BetterReflection\\Reflector\\Exception\\IdentifierNotFound' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflector/Exception/IdentifierNotFound.php', 'PHPStan\\BetterReflection\\Reflector\\Reflector' => $vendorDir . '/ondrejmirtes/better-reflection/src/Reflector/Reflector.php', 'PHPStan\\BetterReflection\\SourceLocator\\Ast\\Exception\\ParseToAstFailure' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Exception/ParseToAstFailure.php', 'PHPStan\\BetterReflection\\SourceLocator\\Ast\\FindReflectionsInTree' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Ast/FindReflectionsInTree.php', 'PHPStan\\BetterReflection\\SourceLocator\\Ast\\Locator' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Locator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Ast\\Parser\\MemoizingParser' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Parser/MemoizingParser.php', 'PHPStan\\BetterReflection\\SourceLocator\\Ast\\Strategy\\AstConversionStrategy' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Strategy/AstConversionStrategy.php', 'PHPStan\\BetterReflection\\SourceLocator\\Ast\\Strategy\\NodeToReflection' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Strategy/NodeToReflection.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\EvaledAnonymousClassCannotBeLocated' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/EvaledAnonymousClassCannotBeLocated.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\EvaledClosureCannotBeLocated' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/EvaledClosureCannotBeLocated.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\InvalidDirectory' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/InvalidDirectory.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\InvalidFileInfo' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/InvalidFileInfo.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\InvalidFileLocation' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/InvalidFileLocation.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\NoAnonymousClassOnLine' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/NoAnonymousClassOnLine.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\NoClosureOnLine' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/NoClosureOnLine.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\NotInternalClass' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/NotInternalClass.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\TwoAnonymousClassesOnSameLine' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/TwoAnonymousClassesOnSameLine.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\TwoClosuresOnSameLine' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/TwoClosuresOnSameLine.php', 'PHPStan\\BetterReflection\\SourceLocator\\FileChecker' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/FileChecker.php', 'PHPStan\\BetterReflection\\SourceLocator\\Located\\AliasLocatedSource' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Located/AliasLocatedSource.php', 'PHPStan\\BetterReflection\\SourceLocator\\Located\\AnonymousLocatedSource' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Located/AnonymousLocatedSource.php', 'PHPStan\\BetterReflection\\SourceLocator\\Located\\EvaledLocatedSource' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Located/EvaledLocatedSource.php', 'PHPStan\\BetterReflection\\SourceLocator\\Located\\InternalLocatedSource' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Located/InternalLocatedSource.php', 'PHPStan\\BetterReflection\\SourceLocator\\Located\\LocatedSource' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Located/LocatedSource.php', 'PHPStan\\BetterReflection\\SourceLocator\\SourceStubber\\AggregateSourceStubber' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/AggregateSourceStubber.php', 'PHPStan\\BetterReflection\\SourceLocator\\SourceStubber\\Exception\\CouldNotFindPhpStormStubs' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/Exception/CouldNotFindPhpStormStubs.php', 'PHPStan\\BetterReflection\\SourceLocator\\SourceStubber\\PhpStormStubsSourceStubber' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/PhpStormStubsSourceStubber.php', 'PHPStan\\BetterReflection\\SourceLocator\\SourceStubber\\PhpStormStubs\\CachingVisitor' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/PhpStormStubs/CachingVisitor.php', 'PHPStan\\BetterReflection\\SourceLocator\\SourceStubber\\ReflectionSourceStubber' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/ReflectionSourceStubber.php', 'PHPStan\\BetterReflection\\SourceLocator\\SourceStubber\\SourceStubber' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/SourceStubber.php', 'PHPStan\\BetterReflection\\SourceLocator\\SourceStubber\\StubData' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/StubData.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\AbstractSourceLocator' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/AbstractSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\AggregateSourceLocator' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/AggregateSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\AnonymousClassObjectSourceLocator' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/AnonymousClassObjectSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\AutoloadSourceLocator' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/AutoloadSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\AutoloadSourceLocator\\FileReadTrapStreamWrapper' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/AutoloadSourceLocator/FileReadTrapStreamWrapper.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\ClosureSourceLocator' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/ClosureSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\ComposerSourceLocator' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/ComposerSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Factory\\Exception\\Exception' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/Exception.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Factory\\Exception\\FailedToParseJson' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/FailedToParseJson.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Factory\\Exception\\InvalidProjectDirectory' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/InvalidProjectDirectory.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Factory\\Exception\\MissingComposerJson' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/MissingComposerJson.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Factory\\Exception\\MissingInstalledJson' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/MissingInstalledJson.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Factory\\MakeLocatorForComposerJson' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/MakeLocatorForComposerJson.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Factory\\MakeLocatorForComposerJsonAndInstalledJson' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/MakeLocatorForComposerJsonAndInstalledJson.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Factory\\MakeLocatorForInstalledJson' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/MakeLocatorForInstalledJson.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\PsrAutoloaderLocator' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/PsrAutoloaderLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Psr\\Exception\\Exception' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/Exception/Exception.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Psr\\Exception\\InvalidPrefixMapping' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/Exception/InvalidPrefixMapping.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Psr\\Psr0Mapping' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/Psr0Mapping.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Psr\\Psr4Mapping' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/Psr4Mapping.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Psr\\PsrAutoloaderMapping' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/PsrAutoloaderMapping.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\DirectoriesSourceLocator' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/DirectoriesSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\EvaledCodeSourceLocator' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/EvaledCodeSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\FileIteratorSourceLocator' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/FileIteratorSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\MemoizingSourceLocator' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/MemoizingSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\PhpInternalSourceLocator' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/PhpInternalSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\SingleFileSourceLocator' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/SingleFileSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\SourceLocator' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/SourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\StringSourceLocator' => $vendorDir . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/StringSourceLocator.php', 'PHPStan\\BetterReflection\\Util\\CalculateReflectionColumn' => $vendorDir . '/ondrejmirtes/better-reflection/src/Util/CalculateReflectionColumn.php', 'PHPStan\\BetterReflection\\Util\\ClassExistenceChecker' => $vendorDir . '/ondrejmirtes/better-reflection/src/Util/ClassExistenceChecker.php', 'PHPStan\\BetterReflection\\Util\\ConstantNodeChecker' => $vendorDir . '/ondrejmirtes/better-reflection/src/Util/ConstantNodeChecker.php', 'PHPStan\\BetterReflection\\Util\\Exception\\InvalidNodePosition' => $vendorDir . '/ondrejmirtes/better-reflection/src/Util/Exception/InvalidNodePosition.php', 'PHPStan\\BetterReflection\\Util\\Exception\\NoNodePosition' => $vendorDir . '/ondrejmirtes/better-reflection/src/Util/Exception/NoNodePosition.php', 'PHPStan\\BetterReflection\\Util\\FileHelper' => $vendorDir . '/ondrejmirtes/better-reflection/src/Util/FileHelper.php', 'PHPStan\\BetterReflection\\Util\\FindReflectionOnLine' => $vendorDir . '/ondrejmirtes/better-reflection/src/Util/FindReflectionOnLine.php', 'PHPStan\\BetterReflection\\Util\\GetLastDocComment' => $vendorDir . '/ondrejmirtes/better-reflection/src/Util/GetLastDocComment.php', 'PHPStan\\BetterReflection\\Util\\Memoize' => $vendorDir . '/ondrejmirtes/better-reflection/src/Util/Memoize.php', 'PHPStan\\Broker\\AnonymousClassNameHelper' => $baseDir . '/src/Broker/AnonymousClassNameHelper.php', 'PHPStan\\Broker\\BrokerFactory' => $baseDir . '/src/Broker/BrokerFactory.php', 'PHPStan\\Broker\\ClassNotFoundException' => $baseDir . '/src/Broker/ClassNotFoundException.php', 'PHPStan\\Broker\\ConstantNotFoundException' => $baseDir . '/src/Broker/ConstantNotFoundException.php', 'PHPStan\\Broker\\FunctionNotFoundException' => $baseDir . '/src/Broker/FunctionNotFoundException.php', 'PHPStan\\Cache\\Cache' => $baseDir . '/src/Cache/Cache.php', 'PHPStan\\Cache\\CacheItem' => $baseDir . '/src/Cache/CacheItem.php', 'PHPStan\\Cache\\CacheStorage' => $baseDir . '/src/Cache/CacheStorage.php', 'PHPStan\\Cache\\FileCacheStorage' => $baseDir . '/src/Cache/FileCacheStorage.php', 'PHPStan\\Cache\\MemoryCacheStorage' => $baseDir . '/src/Cache/MemoryCacheStorage.php', 'PHPStan\\Classes\\ForbiddenClassNameExtension' => $baseDir . '/src/Classes/ForbiddenClassNameExtension.php', 'PHPStan\\Collectors\\CollectedData' => $baseDir . '/src/Collectors/CollectedData.php', 'PHPStan\\Collectors\\Collector' => $baseDir . '/src/Collectors/Collector.php', 'PHPStan\\Collectors\\Registry' => $baseDir . '/src/Collectors/Registry.php', 'PHPStan\\Collectors\\RegistryFactory' => $baseDir . '/src/Collectors/RegistryFactory.php', 'PHPStan\\Command\\AnalyseApplication' => $baseDir . '/src/Command/AnalyseApplication.php', 'PHPStan\\Command\\AnalyseCommand' => $baseDir . '/src/Command/AnalyseCommand.php', 'PHPStan\\Command\\AnalyserRunner' => $baseDir . '/src/Command/AnalyserRunner.php', 'PHPStan\\Command\\AnalysisResult' => $baseDir . '/src/Command/AnalysisResult.php', 'PHPStan\\Command\\BisectCommand' => $baseDir . '/src/Command/BisectCommand.php', 'PHPStan\\Command\\Bisect\\BinarySearch' => $baseDir . '/src/Command/Bisect/BinarySearch.php', 'PHPStan\\Command\\Bisect\\BinarySearchStep' => $baseDir . '/src/Command/Bisect/BinarySearchStep.php', 'PHPStan\\Command\\ClearResultCacheCommand' => $baseDir . '/src/Command/ClearResultCacheCommand.php', 'PHPStan\\Command\\CommandHelper' => $baseDir . '/src/Command/CommandHelper.php', 'PHPStan\\Command\\DiagnoseCommand' => $baseDir . '/src/Command/DiagnoseCommand.php', 'PHPStan\\Command\\DumpParametersCommand' => $baseDir . '/src/Command/DumpParametersCommand.php', 'PHPStan\\Command\\ErrorFormatter\\BaselineNeonErrorFormatter' => $baseDir . '/src/Command/ErrorFormatter/BaselineNeonErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\BaselinePhpErrorFormatter' => $baseDir . '/src/Command/ErrorFormatter/BaselinePhpErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\CheckstyleErrorFormatter' => $baseDir . '/src/Command/ErrorFormatter/CheckstyleErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\CiDetectedErrorFormatter' => $baseDir . '/src/Command/ErrorFormatter/CiDetectedErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\ErrorFormatter' => $baseDir . '/src/Command/ErrorFormatter/ErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\GithubErrorFormatter' => $baseDir . '/src/Command/ErrorFormatter/GithubErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\GitlabErrorFormatter' => $baseDir . '/src/Command/ErrorFormatter/GitlabErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\JsonErrorFormatter' => $baseDir . '/src/Command/ErrorFormatter/JsonErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\JunitErrorFormatter' => $baseDir . '/src/Command/ErrorFormatter/JunitErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\RawErrorFormatter' => $baseDir . '/src/Command/ErrorFormatter/RawErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\TableErrorFormatter' => $baseDir . '/src/Command/ErrorFormatter/TableErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\TeamcityErrorFormatter' => $baseDir . '/src/Command/ErrorFormatter/TeamcityErrorFormatter.php', 'PHPStan\\Command\\ErrorsConsoleStyle' => $baseDir . '/src/Command/ErrorsConsoleStyle.php', 'PHPStan\\Command\\FixerApplication' => $baseDir . '/src/Command/FixerApplication.php', 'PHPStan\\Command\\FixerProcessException' => $baseDir . '/src/Command/FixerProcessException.php', 'PHPStan\\Command\\FixerWorkerCommand' => $baseDir . '/src/Command/FixerWorkerCommand.php', 'PHPStan\\Command\\FixerWorkerRunner' => $baseDir . '/src/Command/FixerWorkerRunner.php', 'PHPStan\\Command\\IgnoredRegexValidator' => $baseDir . '/src/Command/IgnoredRegexValidator.php', 'PHPStan\\Command\\IgnoredRegexValidatorResult' => $baseDir . '/src/Command/IgnoredRegexValidatorResult.php', 'PHPStan\\Command\\InceptionNotSuccessfulException' => $baseDir . '/src/Command/InceptionNotSuccessfulException.php', 'PHPStan\\Command\\InceptionResult' => $baseDir . '/src/Command/InceptionResult.php', 'PHPStan\\Command\\Output' => $baseDir . '/src/Command/Output.php', 'PHPStan\\Command\\OutputStyle' => $baseDir . '/src/Command/OutputStyle.php', 'PHPStan\\Command\\Symfony\\SymfonyOutput' => $baseDir . '/src/Command/Symfony/SymfonyOutput.php', 'PHPStan\\Command\\Symfony\\SymfonyStyle' => $baseDir . '/src/Command/Symfony/SymfonyStyle.php', 'PHPStan\\Command\\WorkerCommand' => $baseDir . '/src/Command/WorkerCommand.php', 'PHPStan\\DependencyInjection\\AutowiredAttributeServicesExtension' => $baseDir . '/src/DependencyInjection/AutowiredAttributeServicesExtension.php', 'PHPStan\\DependencyInjection\\AutowiredParameter' => $baseDir . '/src/DependencyInjection/AutowiredParameter.php', 'PHPStan\\DependencyInjection\\AutowiredService' => $baseDir . '/src/DependencyInjection/AutowiredService.php', 'PHPStan\\DependencyInjection\\BleedingEdgeToggle' => $baseDir . '/src/DependencyInjection/BleedingEdgeToggle.php', 'PHPStan\\DependencyInjection\\ConditionalTagsExtension' => $baseDir . '/src/DependencyInjection/ConditionalTagsExtension.php', 'PHPStan\\DependencyInjection\\Configurator' => $baseDir . '/src/DependencyInjection/Configurator.php', 'PHPStan\\DependencyInjection\\Container' => $baseDir . '/src/DependencyInjection/Container.php', 'PHPStan\\DependencyInjection\\ContainerFactory' => $baseDir . '/src/DependencyInjection/ContainerFactory.php', 'PHPStan\\DependencyInjection\\DerivativeContainerFactory' => $baseDir . '/src/DependencyInjection/DerivativeContainerFactory.php', 'PHPStan\\DependencyInjection\\DuplicateIncludedFilesException' => $baseDir . '/src/DependencyInjection/DuplicateIncludedFilesException.php', 'PHPStan\\DependencyInjection\\ExpandRelativePathExtension' => $baseDir . '/src/DependencyInjection/ExpandRelativePathExtension.php', 'PHPStan\\DependencyInjection\\FnsrExtension' => $baseDir . '/src/DependencyInjection/FnsrExtension.php', 'PHPStan\\DependencyInjection\\GenerateFactory' => $baseDir . '/src/DependencyInjection/GenerateFactory.php', 'PHPStan\\DependencyInjection\\InvalidExcludePathsException' => $baseDir . '/src/DependencyInjection/InvalidExcludePathsException.php', 'PHPStan\\DependencyInjection\\InvalidIgnoredErrorException' => $baseDir . '/src/DependencyInjection/InvalidIgnoredErrorException.php', 'PHPStan\\DependencyInjection\\InvalidIgnoredErrorPatternsException' => $baseDir . '/src/DependencyInjection/InvalidIgnoredErrorPatternsException.php', 'PHPStan\\DependencyInjection\\InvalidPhpVersionException' => $baseDir . '/src/DependencyInjection/InvalidPhpVersionException.php', 'PHPStan\\DependencyInjection\\LoaderFactory' => $baseDir . '/src/DependencyInjection/LoaderFactory.php', 'PHPStan\\DependencyInjection\\MemoizingContainer' => $baseDir . '/src/DependencyInjection/MemoizingContainer.php', 'PHPStan\\DependencyInjection\\MissingImplementedInterfaceInServiceWithTagException' => $baseDir . '/src/DependencyInjection/MissingImplementedInterfaceInServiceWithTagException.php', 'PHPStan\\DependencyInjection\\MissingServiceException' => $baseDir . '/src/DependencyInjection/MissingServiceException.php', 'PHPStan\\DependencyInjection\\NeonAdapter' => $baseDir . '/src/DependencyInjection/NeonAdapter.php', 'PHPStan\\DependencyInjection\\NeonCachedFileReader' => $baseDir . '/src/DependencyInjection/NeonCachedFileReader.php', 'PHPStan\\DependencyInjection\\NeonLoader' => $baseDir . '/src/DependencyInjection/NeonLoader.php', 'PHPStan\\DependencyInjection\\Neon\\OptionalPath' => $baseDir . '/src/DependencyInjection/Neon/OptionalPath.php', 'PHPStan\\DependencyInjection\\Nette\\NetteContainer' => $baseDir . '/src/DependencyInjection/Nette/NetteContainer.php', 'PHPStan\\DependencyInjection\\NonAutowiredService' => $baseDir . '/src/DependencyInjection/NonAutowiredService.php', 'PHPStan\\DependencyInjection\\ParameterNotFoundException' => $baseDir . '/src/DependencyInjection/ParameterNotFoundException.php', 'PHPStan\\DependencyInjection\\ParametersSchemaExtension' => $baseDir . '/src/DependencyInjection/ParametersSchemaExtension.php', 'PHPStan\\DependencyInjection\\ProjectConfigHelper' => $baseDir . '/src/DependencyInjection/ProjectConfigHelper.php', 'PHPStan\\DependencyInjection\\Reflection\\ClassReflectionExtensionRegistryProvider' => $baseDir . '/src/DependencyInjection/Reflection/ClassReflectionExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\Reflection\\LazyClassReflectionExtensionRegistryProvider' => $baseDir . '/src/DependencyInjection/Reflection/LazyClassReflectionExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\RegisteredCollector' => $baseDir . '/src/DependencyInjection/RegisteredCollector.php', 'PHPStan\\DependencyInjection\\RegisteredRule' => $baseDir . '/src/DependencyInjection/RegisteredRule.php', 'PHPStan\\DependencyInjection\\RulesExtension' => $baseDir . '/src/DependencyInjection/RulesExtension.php', 'PHPStan\\DependencyInjection\\StubValidatorRuleServicesExtension' => $baseDir . '/src/DependencyInjection/StubValidatorRuleServicesExtension.php', 'PHPStan\\DependencyInjection\\Type\\DynamicReturnTypeExtensionRegistryProvider' => $baseDir . '/src/DependencyInjection/Type/DynamicReturnTypeExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\Type\\DynamicThrowTypeExtensionProvider' => $baseDir . '/src/DependencyInjection/Type/DynamicThrowTypeExtensionProvider.php', 'PHPStan\\DependencyInjection\\Type\\ExpressionTypeResolverExtensionRegistryProvider' => $baseDir . '/src/DependencyInjection/Type/ExpressionTypeResolverExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\Type\\LazyDynamicReturnTypeExtensionRegistryProvider' => $baseDir . '/src/DependencyInjection/Type/LazyDynamicReturnTypeExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\Type\\LazyDynamicThrowTypeExtensionProvider' => $baseDir . '/src/DependencyInjection/Type/LazyDynamicThrowTypeExtensionProvider.php', 'PHPStan\\DependencyInjection\\Type\\LazyExpressionTypeResolverExtensionRegistryProvider' => $baseDir . '/src/DependencyInjection/Type/LazyExpressionTypeResolverExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\Type\\LazyOperatorTypeSpecifyingExtensionRegistryProvider' => $baseDir . '/src/DependencyInjection/Type/LazyOperatorTypeSpecifyingExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\Type\\LazyParameterClosureThisExtensionProvider' => $baseDir . '/src/DependencyInjection/Type/LazyParameterClosureThisExtensionProvider.php', 'PHPStan\\DependencyInjection\\Type\\LazyParameterClosureTypeExtensionProvider' => $baseDir . '/src/DependencyInjection/Type/LazyParameterClosureTypeExtensionProvider.php', 'PHPStan\\DependencyInjection\\Type\\LazyParameterOutTypeExtensionProvider' => $baseDir . '/src/DependencyInjection/Type/LazyParameterOutTypeExtensionProvider.php', 'PHPStan\\DependencyInjection\\Type\\LazyUnaryOperatorTypeSpecifyingExtensionRegistryProvider' => $baseDir . '/src/DependencyInjection/Type/LazyUnaryOperatorTypeSpecifyingExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\Type\\OperatorTypeSpecifyingExtensionRegistryProvider' => $baseDir . '/src/DependencyInjection/Type/OperatorTypeSpecifyingExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\Type\\ParameterClosureThisExtensionProvider' => $baseDir . '/src/DependencyInjection/Type/ParameterClosureThisExtensionProvider.php', 'PHPStan\\DependencyInjection\\Type\\ParameterClosureTypeExtensionProvider' => $baseDir . '/src/DependencyInjection/Type/ParameterClosureTypeExtensionProvider.php', 'PHPStan\\DependencyInjection\\Type\\ParameterOutTypeExtensionProvider' => $baseDir . '/src/DependencyInjection/Type/ParameterOutTypeExtensionProvider.php', 'PHPStan\\DependencyInjection\\Type\\UnaryOperatorTypeSpecifyingExtensionRegistryProvider' => $baseDir . '/src/DependencyInjection/Type/UnaryOperatorTypeSpecifyingExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\ValidateExcludePathsExtension' => $baseDir . '/src/DependencyInjection/ValidateExcludePathsExtension.php', 'PHPStan\\DependencyInjection\\ValidateIgnoredErrorsExtension' => $baseDir . '/src/DependencyInjection/ValidateIgnoredErrorsExtension.php', 'PHPStan\\DependencyInjection\\ValidateServiceTagsExtension' => $baseDir . '/src/DependencyInjection/ValidateServiceTagsExtension.php', 'PHPStan\\DependencyInjection\\ValidatesStubFiles' => $baseDir . '/src/DependencyInjection/ValidatesStubFiles.php', 'PHPStan\\Dependency\\DependencyResolver' => $baseDir . '/src/Dependency/DependencyResolver.php', 'PHPStan\\Dependency\\ExportedNode' => $baseDir . '/src/Dependency/ExportedNode.php', 'PHPStan\\Dependency\\ExportedNodeFetcher' => $baseDir . '/src/Dependency/ExportedNodeFetcher.php', 'PHPStan\\Dependency\\ExportedNodeResolver' => $baseDir . '/src/Dependency/ExportedNodeResolver.php', 'PHPStan\\Dependency\\ExportedNodeVisitor' => $baseDir . '/src/Dependency/ExportedNodeVisitor.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedAttributeNode' => $baseDir . '/src/Dependency/ExportedNode/ExportedAttributeNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedClassConstantNode' => $baseDir . '/src/Dependency/ExportedNode/ExportedClassConstantNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedClassConstantsNode' => $baseDir . '/src/Dependency/ExportedNode/ExportedClassConstantsNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedClassNode' => $baseDir . '/src/Dependency/ExportedNode/ExportedClassNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedEnumCaseNode' => $baseDir . '/src/Dependency/ExportedNode/ExportedEnumCaseNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedEnumNode' => $baseDir . '/src/Dependency/ExportedNode/ExportedEnumNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedFunctionNode' => $baseDir . '/src/Dependency/ExportedNode/ExportedFunctionNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedInterfaceNode' => $baseDir . '/src/Dependency/ExportedNode/ExportedInterfaceNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedMethodNode' => $baseDir . '/src/Dependency/ExportedNode/ExportedMethodNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedParameterNode' => $baseDir . '/src/Dependency/ExportedNode/ExportedParameterNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedPhpDocNode' => $baseDir . '/src/Dependency/ExportedNode/ExportedPhpDocNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedPropertiesNode' => $baseDir . '/src/Dependency/ExportedNode/ExportedPropertiesNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedPropertyHookNode' => $baseDir . '/src/Dependency/ExportedNode/ExportedPropertyHookNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedTraitNode' => $baseDir . '/src/Dependency/ExportedNode/ExportedTraitNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedTraitUseAdaptation' => $baseDir . '/src/Dependency/ExportedNode/ExportedTraitUseAdaptation.php', 'PHPStan\\Dependency\\NodeDependencies' => $baseDir . '/src/Dependency/NodeDependencies.php', 'PHPStan\\Dependency\\RootExportedNode' => $baseDir . '/src/Dependency/RootExportedNode.php', 'PHPStan\\Diagnose\\DiagnoseExtension' => $baseDir . '/src/Diagnose/DiagnoseExtension.php', 'PHPStan\\Diagnose\\PHPStanDiagnoseExtension' => $baseDir . '/src/Diagnose/PHPStanDiagnoseExtension.php', 'PHPStan\\File\\CouldNotReadFileException' => $baseDir . '/src/File/CouldNotReadFileException.php', 'PHPStan\\File\\CouldNotWriteFileException' => $baseDir . '/src/File/CouldNotWriteFileException.php', 'PHPStan\\File\\FileExcluder' => $baseDir . '/src/File/FileExcluder.php', 'PHPStan\\File\\FileExcluderFactory' => $baseDir . '/src/File/FileExcluderFactory.php', 'PHPStan\\File\\FileExcluderRawFactory' => $baseDir . '/src/File/FileExcluderRawFactory.php', 'PHPStan\\File\\FileFinder' => $baseDir . '/src/File/FileFinder.php', 'PHPStan\\File\\FileFinderResult' => $baseDir . '/src/File/FileFinderResult.php', 'PHPStan\\File\\FileHelper' => $baseDir . '/src/File/FileHelper.php', 'PHPStan\\File\\FileMonitor' => $baseDir . '/src/File/FileMonitor.php', 'PHPStan\\File\\FileMonitorResult' => $baseDir . '/src/File/FileMonitorResult.php', 'PHPStan\\File\\FileReader' => $baseDir . '/src/File/FileReader.php', 'PHPStan\\File\\FileWriter' => $baseDir . '/src/File/FileWriter.php', 'PHPStan\\File\\FuzzyRelativePathHelper' => $baseDir . '/src/File/FuzzyRelativePathHelper.php', 'PHPStan\\File\\NullRelativePathHelper' => $baseDir . '/src/File/NullRelativePathHelper.php', 'PHPStan\\File\\ParentDirectoryRelativePathHelper' => $baseDir . '/src/File/ParentDirectoryRelativePathHelper.php', 'PHPStan\\File\\PathNotFoundException' => $baseDir . '/src/File/PathNotFoundException.php', 'PHPStan\\File\\RelativePathHelper' => $baseDir . '/src/File/RelativePathHelper.php', 'PHPStan\\File\\SimpleRelativePathHelper' => $baseDir . '/src/File/SimpleRelativePathHelper.php', 'PHPStan\\File\\SystemAgnosticSimpleRelativePathHelper' => $baseDir . '/src/File/SystemAgnosticSimpleRelativePathHelper.php', 'PHPStan\\Fixable\\FileChangedException' => $baseDir . '/src/Fixable/FileChangedException.php', 'PHPStan\\Fixable\\MergeConflictException' => $baseDir . '/src/Fixable/MergeConflictException.php', 'PHPStan\\Fixable\\Patcher' => $baseDir . '/src/Fixable/Patcher.php', 'PHPStan\\Fixable\\PhpDoc\\CallbackVisitor' => $baseDir . '/src/Fixable/PhpDoc/CallbackVisitor.php', 'PHPStan\\Fixable\\PhpDoc\\PhpDocEditor' => $baseDir . '/src/Fixable/PhpDoc/PhpDocEditor.php', 'PHPStan\\Fixable\\PhpPrinter' => $baseDir . '/src/Fixable/PhpPrinter.php', 'PHPStan\\Fixable\\PhpPrinterIndentationDetectorVisitor' => $baseDir . '/src/Fixable/PhpPrinterIndentationDetectorVisitor.php', 'PHPStan\\Fixable\\ReplacingNodeVisitor' => $baseDir . '/src/Fixable/ReplacingNodeVisitor.php', 'PHPStan\\Internal\\AgentDetector' => $baseDir . '/src/Internal/AgentDetector.php', 'PHPStan\\Internal\\ArrayHelper' => $baseDir . '/src/Internal/ArrayHelper.php', 'PHPStan\\Internal\\BytesHelper' => $baseDir . '/src/Internal/BytesHelper.php', 'PHPStan\\Internal\\CombinationsHelper' => $baseDir . '/src/Internal/CombinationsHelper.php', 'PHPStan\\Internal\\ComposerHelper' => $baseDir . '/src/Internal/ComposerHelper.php', 'PHPStan\\Internal\\DeprecatedAttributeHelper' => $baseDir . '/src/Internal/DeprecatedAttributeHelper.php', 'PHPStan\\Internal\\DirectoryCreator' => $baseDir . '/src/Internal/DirectoryCreator.php', 'PHPStan\\Internal\\DirectoryCreatorException' => $baseDir . '/src/Internal/DirectoryCreatorException.php', 'PHPStan\\Internal\\HttpClientFactory' => $baseDir . '/src/Internal/HttpClientFactory.php', 'PHPStan\\Internal\\SprintfHelper' => $baseDir . '/src/Internal/SprintfHelper.php', 'PHPStan\\NeverException' => $baseDir . '/src/NeverException.php', 'PHPStan\\Node\\AnonymousClassNode' => $baseDir . '/src/Node/AnonymousClassNode.php', 'PHPStan\\Node\\BooleanAndNode' => $baseDir . '/src/Node/BooleanAndNode.php', 'PHPStan\\Node\\BooleanOrNode' => $baseDir . '/src/Node/BooleanOrNode.php', 'PHPStan\\Node\\BreaklessWhileLoopNode' => $baseDir . '/src/Node/BreaklessWhileLoopNode.php', 'PHPStan\\Node\\CatchWithUnthrownExceptionNode' => $baseDir . '/src/Node/CatchWithUnthrownExceptionNode.php', 'PHPStan\\Node\\ClassConstantsNode' => $baseDir . '/src/Node/ClassConstantsNode.php', 'PHPStan\\Node\\ClassMethod' => $baseDir . '/src/Node/ClassMethod.php', 'PHPStan\\Node\\ClassMethodsNode' => $baseDir . '/src/Node/ClassMethodsNode.php', 'PHPStan\\Node\\ClassPropertiesNode' => $baseDir . '/src/Node/ClassPropertiesNode.php', 'PHPStan\\Node\\ClassPropertyNode' => $baseDir . '/src/Node/ClassPropertyNode.php', 'PHPStan\\Node\\ClassStatementsGatherer' => $baseDir . '/src/Node/ClassStatementsGatherer.php', 'PHPStan\\Node\\ClosureReturnStatementsNode' => $baseDir . '/src/Node/ClosureReturnStatementsNode.php', 'PHPStan\\Node\\CollectedDataNode' => $baseDir . '/src/Node/CollectedDataNode.php', 'PHPStan\\Node\\Constant\\ClassConstantFetch' => $baseDir . '/src/Node/Constant/ClassConstantFetch.php', 'PHPStan\\Node\\DeepNodeCloner' => $baseDir . '/src/Node/DeepNodeCloner.php', 'PHPStan\\Node\\DoWhileLoopConditionNode' => $baseDir . '/src/Node/DoWhileLoopConditionNode.php', 'PHPStan\\Node\\ExecutionEndNode' => $baseDir . '/src/Node/ExecutionEndNode.php', 'PHPStan\\Node\\Expr\\AlwaysRememberedExpr' => $baseDir . '/src/Node/Expr/AlwaysRememberedExpr.php', 'PHPStan\\Node\\Expr\\ExistingArrayDimFetch' => $baseDir . '/src/Node/Expr/ExistingArrayDimFetch.php', 'PHPStan\\Node\\Expr\\ForeachValueByRefExpr' => $baseDir . '/src/Node/Expr/ForeachValueByRefExpr.php', 'PHPStan\\Node\\Expr\\GetIterableKeyTypeExpr' => $baseDir . '/src/Node/Expr/GetIterableKeyTypeExpr.php', 'PHPStan\\Node\\Expr\\GetIterableValueTypeExpr' => $baseDir . '/src/Node/Expr/GetIterableValueTypeExpr.php', 'PHPStan\\Node\\Expr\\GetOffsetValueTypeExpr' => $baseDir . '/src/Node/Expr/GetOffsetValueTypeExpr.php', 'PHPStan\\Node\\Expr\\IntertwinedVariableByReferenceWithExpr' => $baseDir . '/src/Node/Expr/IntertwinedVariableByReferenceWithExpr.php', 'PHPStan\\Node\\Expr\\NativeTypeExpr' => $baseDir . '/src/Node/Expr/NativeTypeExpr.php', 'PHPStan\\Node\\Expr\\OriginalForeachKeyExpr' => $baseDir . '/src/Node/Expr/OriginalForeachKeyExpr.php', 'PHPStan\\Node\\Expr\\OriginalForeachValueExpr' => $baseDir . '/src/Node/Expr/OriginalForeachValueExpr.php', 'PHPStan\\Node\\Expr\\OriginalPropertyTypeExpr' => $baseDir . '/src/Node/Expr/OriginalPropertyTypeExpr.php', 'PHPStan\\Node\\Expr\\ParameterVariableOriginalValueExpr' => $baseDir . '/src/Node/Expr/ParameterVariableOriginalValueExpr.php', 'PHPStan\\Node\\Expr\\PossiblyImpureCallExpr' => $baseDir . '/src/Node/Expr/PossiblyImpureCallExpr.php', 'PHPStan\\Node\\Expr\\PropertyInitializationExpr' => $baseDir . '/src/Node/Expr/PropertyInitializationExpr.php', 'PHPStan\\Node\\Expr\\SetExistingOffsetValueTypeExpr' => $baseDir . '/src/Node/Expr/SetExistingOffsetValueTypeExpr.php', 'PHPStan\\Node\\Expr\\SetOffsetValueTypeExpr' => $baseDir . '/src/Node/Expr/SetOffsetValueTypeExpr.php', 'PHPStan\\Node\\Expr\\TypeExpr' => $baseDir . '/src/Node/Expr/TypeExpr.php', 'PHPStan\\Node\\Expr\\UnsetOffsetExpr' => $baseDir . '/src/Node/Expr/UnsetOffsetExpr.php', 'PHPStan\\Node\\FileNode' => $baseDir . '/src/Node/FileNode.php', 'PHPStan\\Node\\FinallyExitPointsNode' => $baseDir . '/src/Node/FinallyExitPointsNode.php', 'PHPStan\\Node\\FunctionCallableNode' => $baseDir . '/src/Node/FunctionCallableNode.php', 'PHPStan\\Node\\FunctionReturnStatementsNode' => $baseDir . '/src/Node/FunctionReturnStatementsNode.php', 'PHPStan\\Node\\InArrowFunctionNode' => $baseDir . '/src/Node/InArrowFunctionNode.php', 'PHPStan\\Node\\InClassMethodNode' => $baseDir . '/src/Node/InClassMethodNode.php', 'PHPStan\\Node\\InClassNode' => $baseDir . '/src/Node/InClassNode.php', 'PHPStan\\Node\\InClosureNode' => $baseDir . '/src/Node/InClosureNode.php', 'PHPStan\\Node\\InForeachNode' => $baseDir . '/src/Node/InForeachNode.php', 'PHPStan\\Node\\InFunctionNode' => $baseDir . '/src/Node/InFunctionNode.php', 'PHPStan\\Node\\InPropertyHookNode' => $baseDir . '/src/Node/InPropertyHookNode.php', 'PHPStan\\Node\\InTraitNode' => $baseDir . '/src/Node/InTraitNode.php', 'PHPStan\\Node\\InstantiationCallableNode' => $baseDir . '/src/Node/InstantiationCallableNode.php', 'PHPStan\\Node\\InvalidateExprNode' => $baseDir . '/src/Node/InvalidateExprNode.php', 'PHPStan\\Node\\IssetExpr' => $baseDir . '/src/Node/IssetExpr.php', 'PHPStan\\Node\\LiteralArrayItem' => $baseDir . '/src/Node/LiteralArrayItem.php', 'PHPStan\\Node\\LiteralArrayNode' => $baseDir . '/src/Node/LiteralArrayNode.php', 'PHPStan\\Node\\MatchExpressionArm' => $baseDir . '/src/Node/MatchExpressionArm.php', 'PHPStan\\Node\\MatchExpressionArmBody' => $baseDir . '/src/Node/MatchExpressionArmBody.php', 'PHPStan\\Node\\MatchExpressionArmCondition' => $baseDir . '/src/Node/MatchExpressionArmCondition.php', 'PHPStan\\Node\\MatchExpressionNode' => $baseDir . '/src/Node/MatchExpressionNode.php', 'PHPStan\\Node\\MethodCallableNode' => $baseDir . '/src/Node/MethodCallableNode.php', 'PHPStan\\Node\\MethodReturnStatementsNode' => $baseDir . '/src/Node/MethodReturnStatementsNode.php', 'PHPStan\\Node\\Method\\MethodCall' => $baseDir . '/src/Node/Method/MethodCall.php', 'PHPStan\\Node\\NoopExpressionNode' => $baseDir . '/src/Node/NoopExpressionNode.php', 'PHPStan\\Node\\Printer\\ExprPrinter' => $baseDir . '/src/Node/Printer/ExprPrinter.php', 'PHPStan\\Node\\Printer\\NodeTypePrinter' => $baseDir . '/src/Node/Printer/NodeTypePrinter.php', 'PHPStan\\Node\\Printer\\Printer' => $baseDir . '/src/Node/Printer/Printer.php', 'PHPStan\\Node\\PropertyAssignNode' => $baseDir . '/src/Node/PropertyAssignNode.php', 'PHPStan\\Node\\PropertyHookReturnStatementsNode' => $baseDir . '/src/Node/PropertyHookReturnStatementsNode.php', 'PHPStan\\Node\\PropertyHookStatementNode' => $baseDir . '/src/Node/PropertyHookStatementNode.php', 'PHPStan\\Node\\Property\\PropertyAssign' => $baseDir . '/src/Node/Property/PropertyAssign.php', 'PHPStan\\Node\\Property\\PropertyRead' => $baseDir . '/src/Node/Property/PropertyRead.php', 'PHPStan\\Node\\Property\\PropertyWrite' => $baseDir . '/src/Node/Property/PropertyWrite.php', 'PHPStan\\Node\\ReturnStatement' => $baseDir . '/src/Node/ReturnStatement.php', 'PHPStan\\Node\\ReturnStatementsNode' => $baseDir . '/src/Node/ReturnStatementsNode.php', 'PHPStan\\Node\\StaticMethodCallableNode' => $baseDir . '/src/Node/StaticMethodCallableNode.php', 'PHPStan\\Node\\UnreachableStatementNode' => $baseDir . '/src/Node/UnreachableStatementNode.php', 'PHPStan\\Node\\VarTagChangedExpressionTypeNode' => $baseDir . '/src/Node/VarTagChangedExpressionTypeNode.php', 'PHPStan\\Node\\VariableAssignNode' => $baseDir . '/src/Node/VariableAssignNode.php', 'PHPStan\\Node\\VirtualNode' => $baseDir . '/src/Node/VirtualNode.php', 'PHPStan\\Parallel\\ForkParallelChecker' => $baseDir . '/src/Parallel/ForkParallelChecker.php', 'PHPStan\\Parallel\\ForkedProcess' => $baseDir . '/src/Parallel/ForkedProcess.php', 'PHPStan\\Parallel\\ParallelAnalyser' => $baseDir . '/src/Parallel/ParallelAnalyser.php', 'PHPStan\\Parallel\\Process' => $baseDir . '/src/Parallel/Process.php', 'PHPStan\\Parallel\\ProcessBase' => $baseDir . '/src/Parallel/ProcessBase.php', 'PHPStan\\Parallel\\ProcessPool' => $baseDir . '/src/Parallel/ProcessPool.php', 'PHPStan\\Parallel\\ProcessTimedOutException' => $baseDir . '/src/Parallel/ProcessTimedOutException.php', 'PHPStan\\Parallel\\Schedule' => $baseDir . '/src/Parallel/Schedule.php', 'PHPStan\\Parallel\\Scheduler' => $baseDir . '/src/Parallel/Scheduler.php', 'PHPStan\\Parallel\\SpawnedProcess' => $baseDir . '/src/Parallel/SpawnedProcess.php', 'PHPStan\\Parallel\\WorkerRunner' => $baseDir . '/src/Parallel/WorkerRunner.php', 'PHPStan\\Parser\\AnonymousClassVisitor' => $baseDir . '/src/Parser/AnonymousClassVisitor.php', 'PHPStan\\Parser\\ArrayFilterArgVisitor' => $baseDir . '/src/Parser/ArrayFilterArgVisitor.php', 'PHPStan\\Parser\\ArrayFindArgVisitor' => $baseDir . '/src/Parser/ArrayFindArgVisitor.php', 'PHPStan\\Parser\\ArrayMapArgVisitor' => $baseDir . '/src/Parser/ArrayMapArgVisitor.php', 'PHPStan\\Parser\\ArrayWalkArgVisitor' => $baseDir . '/src/Parser/ArrayWalkArgVisitor.php', 'PHPStan\\Parser\\ArrowFunctionArgVisitor' => $baseDir . '/src/Parser/ArrowFunctionArgVisitor.php', 'PHPStan\\Parser\\CachedParser' => $baseDir . '/src/Parser/CachedParser.php', 'PHPStan\\Parser\\CleaningParser' => $baseDir . '/src/Parser/CleaningParser.php', 'PHPStan\\Parser\\CleaningVisitor' => $baseDir . '/src/Parser/CleaningVisitor.php', 'PHPStan\\Parser\\ClosureArgVisitor' => $baseDir . '/src/Parser/ClosureArgVisitor.php', 'PHPStan\\Parser\\ClosureBindArgVisitor' => $baseDir . '/src/Parser/ClosureBindArgVisitor.php', 'PHPStan\\Parser\\ClosureBindToVarVisitor' => $baseDir . '/src/Parser/ClosureBindToVarVisitor.php', 'PHPStan\\Parser\\CurlSetOptArgVisitor' => $baseDir . '/src/Parser/CurlSetOptArgVisitor.php', 'PHPStan\\Parser\\CurlSetOptArrayArgVisitor' => $baseDir . '/src/Parser/CurlSetOptArrayArgVisitor.php', 'PHPStan\\Parser\\DeclarePositionVisitor' => $baseDir . '/src/Parser/DeclarePositionVisitor.php', 'PHPStan\\Parser\\ImmediatelyInvokedClosureVisitor' => $baseDir . '/src/Parser/ImmediatelyInvokedClosureVisitor.php', 'PHPStan\\Parser\\ImplodeArgVisitor' => $baseDir . '/src/Parser/ImplodeArgVisitor.php', 'PHPStan\\Parser\\LastConditionVisitor' => $baseDir . '/src/Parser/LastConditionVisitor.php', 'PHPStan\\Parser\\LexerFactory' => $baseDir . '/src/Parser/LexerFactory.php', 'PHPStan\\Parser\\LineAttributesVisitor' => $baseDir . '/src/Parser/LineAttributesVisitor.php', 'PHPStan\\Parser\\MagicConstantParamDefaultVisitor' => $baseDir . '/src/Parser/MagicConstantParamDefaultVisitor.php', 'PHPStan\\Parser\\NewAssignedToPropertyVisitor' => $baseDir . '/src/Parser/NewAssignedToPropertyVisitor.php', 'PHPStan\\Parser\\ParentStmtTypesVisitor' => $baseDir . '/src/Parser/ParentStmtTypesVisitor.php', 'PHPStan\\Parser\\Parser' => $baseDir . '/src/Parser/Parser.php', 'PHPStan\\Parser\\ParserErrorsException' => $baseDir . '/src/Parser/ParserErrorsException.php', 'PHPStan\\Parser\\PathRoutingParser' => $baseDir . '/src/Parser/PathRoutingParser.php', 'PHPStan\\Parser\\PhpParserDecorator' => $baseDir . '/src/Parser/PhpParserDecorator.php', 'PHPStan\\Parser\\PhpParserFactory' => $baseDir . '/src/Parser/PhpParserFactory.php', 'PHPStan\\Parser\\PipeTransformerVisitor' => $baseDir . '/src/Parser/PipeTransformerVisitor.php', 'PHPStan\\Parser\\RemoveUnusedCodeByPhpVersionIdVisitor' => $baseDir . '/src/Parser/RemoveUnusedCodeByPhpVersionIdVisitor.php', 'PHPStan\\Parser\\ReversePipeTransformerVisitor' => $baseDir . '/src/Parser/ReversePipeTransformerVisitor.php', 'PHPStan\\Parser\\RichParser' => $baseDir . '/src/Parser/RichParser.php', 'PHPStan\\Parser\\SimpleParser' => $baseDir . '/src/Parser/SimpleParser.php', 'PHPStan\\Parser\\StandaloneThrowExprVisitor' => $baseDir . '/src/Parser/StandaloneThrowExprVisitor.php', 'PHPStan\\Parser\\StubParser' => $baseDir . '/src/Parser/StubParser.php', 'PHPStan\\Parser\\TraitCollectingVisitor' => $baseDir . '/src/Parser/TraitCollectingVisitor.php', 'PHPStan\\Parser\\TryCatchTypeVisitor' => $baseDir . '/src/Parser/TryCatchTypeVisitor.php', 'PHPStan\\Parser\\TypeTraverserInstanceofVisitor' => $baseDir . '/src/Parser/TypeTraverserInstanceofVisitor.php', 'PHPStan\\Parser\\UseAliasVisitor' => $baseDir . '/src/Parser/UseAliasVisitor.php', 'PHPStan\\Php8StubsMap' => $vendorDir . '/phpstan/php-8-stubs/Php8StubsMap.php', 'PHPStan\\PhpDocParser\\Ast\\AbstractNodeVisitor' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php', 'PHPStan\\PhpDocParser\\Ast\\Attribute' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Attribute.php', 'PHPStan\\PhpDocParser\\Ast\\Comment' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Comment.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayItemNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFalseNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFloatNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprIntegerNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNullNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprStringNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprTrueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstFetchNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\DoctrineConstExprStringNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.php', 'PHPStan\\PhpDocParser\\Ast\\Node' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Node.php', 'PHPStan\\PhpDocParser\\Ast\\NodeAttributes' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeAttributes.php', 'PHPStan\\PhpDocParser\\Ast\\NodeTraverser' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php', 'PHPStan\\PhpDocParser\\Ast\\NodeVisitor' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php', 'PHPStan\\PhpDocParser\\Ast\\NodeVisitor\\CloningVisitor' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagMethodValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagPropertyValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\DeprecatedTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineAnnotation' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArgument' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArray' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArrayItem' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ExtendsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\GenericTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ImplementsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\InvalidTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueParameterNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MixinTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamClosureThisTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamImmediatelyInvokedCallableTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamLaterInvokedCallableTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamOutTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocChildNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTextNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PropertyTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PureUnlessCallableIsImpureTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\RequireExtendsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\RequireImplementsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ReturnTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\SealedTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/SealedTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\SelfOutTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TemplateTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ThrowsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasImportTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypelessParamTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\UsesTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\VarTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeItemNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeUnsealedTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeParameterNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeForParameterNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ConstTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\GenericTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\IntersectionTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\InvalidTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\NullableTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ObjectShapeItemNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ObjectShapeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\OffsetAccessTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ThisTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\TypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\UnionTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php', 'PHPStan\\PhpDocParser\\Lexer\\Lexer' => $vendorDir . '/phpstan/phpdoc-parser/src/Lexer/Lexer.php', 'PHPStan\\PhpDocParser\\ParserConfig' => $vendorDir . '/phpstan/phpdoc-parser/src/ParserConfig.php', 'PHPStan\\PhpDocParser\\Parser\\ConstExprParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php', 'PHPStan\\PhpDocParser\\Parser\\ParserException' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/ParserException.php', 'PHPStan\\PhpDocParser\\Parser\\PhpDocParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php', 'PHPStan\\PhpDocParser\\Parser\\StringUnescaper' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php', 'PHPStan\\PhpDocParser\\Parser\\TokenIterator' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/TokenIterator.php', 'PHPStan\\PhpDocParser\\Parser\\TypeParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/TypeParser.php', 'PHPStan\\PhpDocParser\\Printer\\DiffElem' => $vendorDir . '/phpstan/phpdoc-parser/src/Printer/DiffElem.php', 'PHPStan\\PhpDocParser\\Printer\\Differ' => $vendorDir . '/phpstan/phpdoc-parser/src/Printer/Differ.php', 'PHPStan\\PhpDocParser\\Printer\\Printer' => $vendorDir . '/phpstan/phpdoc-parser/src/Printer/Printer.php', 'PHPStan\\PhpDoc\\BcMathNumberStubFilesExtension' => $baseDir . '/src/PhpDoc/BcMathNumberStubFilesExtension.php', 'PHPStan\\PhpDoc\\ConstExprNodeResolver' => $baseDir . '/src/PhpDoc/ConstExprNodeResolver.php', 'PHPStan\\PhpDoc\\DefaultStubFilesProvider' => $baseDir . '/src/PhpDoc/DefaultStubFilesProvider.php', 'PHPStan\\PhpDoc\\DirectTypeNodeResolverExtensionRegistryProvider' => $baseDir . '/src/PhpDoc/DirectTypeNodeResolverExtensionRegistryProvider.php', 'PHPStan\\PhpDoc\\InheritedPhpDocParameterMapping' => $baseDir . '/src/PhpDoc/InheritedPhpDocParameterMapping.php', 'PHPStan\\PhpDoc\\JsonValidateStubFilesExtension' => $baseDir . '/src/PhpDoc/JsonValidateStubFilesExtension.php', 'PHPStan\\PhpDoc\\LazyTypeNodeResolverExtensionRegistryProvider' => $baseDir . '/src/PhpDoc/LazyTypeNodeResolverExtensionRegistryProvider.php', 'PHPStan\\PhpDoc\\NameScopeAlreadyBeingCreatedException' => $baseDir . '/src/PhpDoc/NameScopeAlreadyBeingCreatedException.php', 'PHPStan\\PhpDoc\\PhpDocInheritanceResolver' => $baseDir . '/src/PhpDoc/PhpDocInheritanceResolver.php', 'PHPStan\\PhpDoc\\PhpDocNodeResolver' => $baseDir . '/src/PhpDoc/PhpDocNodeResolver.php', 'PHPStan\\PhpDoc\\PhpDocStringResolver' => $baseDir . '/src/PhpDoc/PhpDocStringResolver.php', 'PHPStan\\PhpDoc\\ReflectionClassStubFilesExtension' => $baseDir . '/src/PhpDoc/ReflectionClassStubFilesExtension.php', 'PHPStan\\PhpDoc\\ReflectionEnumStubFilesExtension' => $baseDir . '/src/PhpDoc/ReflectionEnumStubFilesExtension.php', 'PHPStan\\PhpDoc\\ResolvedPhpDocBlock' => $baseDir . '/src/PhpDoc/ResolvedPhpDocBlock.php', 'PHPStan\\PhpDoc\\SocketSelectStubFilesExtension' => $baseDir . '/src/PhpDoc/SocketSelectStubFilesExtension.php', 'PHPStan\\PhpDoc\\StubFilesExtension' => $baseDir . '/src/PhpDoc/StubFilesExtension.php', 'PHPStan\\PhpDoc\\StubFilesProvider' => $baseDir . '/src/PhpDoc/StubFilesProvider.php', 'PHPStan\\PhpDoc\\StubPhpDocProvider' => $baseDir . '/src/PhpDoc/StubPhpDocProvider.php', 'PHPStan\\PhpDoc\\StubSourceLocatorFactory' => $baseDir . '/src/PhpDoc/StubSourceLocatorFactory.php', 'PHPStan\\PhpDoc\\StubValidator' => $baseDir . '/src/PhpDoc/StubValidator.php', 'PHPStan\\PhpDoc\\Tag\\AssertTag' => $baseDir . '/src/PhpDoc/Tag/AssertTag.php', 'PHPStan\\PhpDoc\\Tag\\AssertTagParameter' => $baseDir . '/src/PhpDoc/Tag/AssertTagParameter.php', 'PHPStan\\PhpDoc\\Tag\\DeprecatedTag' => $baseDir . '/src/PhpDoc/Tag/DeprecatedTag.php', 'PHPStan\\PhpDoc\\Tag\\ExtendsTag' => $baseDir . '/src/PhpDoc/Tag/ExtendsTag.php', 'PHPStan\\PhpDoc\\Tag\\ImplementsTag' => $baseDir . '/src/PhpDoc/Tag/ImplementsTag.php', 'PHPStan\\PhpDoc\\Tag\\MethodTag' => $baseDir . '/src/PhpDoc/Tag/MethodTag.php', 'PHPStan\\PhpDoc\\Tag\\MethodTagParameter' => $baseDir . '/src/PhpDoc/Tag/MethodTagParameter.php', 'PHPStan\\PhpDoc\\Tag\\MixinTag' => $baseDir . '/src/PhpDoc/Tag/MixinTag.php', 'PHPStan\\PhpDoc\\Tag\\ParamClosureThisTag' => $baseDir . '/src/PhpDoc/Tag/ParamClosureThisTag.php', 'PHPStan\\PhpDoc\\Tag\\ParamOutTag' => $baseDir . '/src/PhpDoc/Tag/ParamOutTag.php', 'PHPStan\\PhpDoc\\Tag\\ParamTag' => $baseDir . '/src/PhpDoc/Tag/ParamTag.php', 'PHPStan\\PhpDoc\\Tag\\PropertyTag' => $baseDir . '/src/PhpDoc/Tag/PropertyTag.php', 'PHPStan\\PhpDoc\\Tag\\RequireExtendsTag' => $baseDir . '/src/PhpDoc/Tag/RequireExtendsTag.php', 'PHPStan\\PhpDoc\\Tag\\RequireImplementsTag' => $baseDir . '/src/PhpDoc/Tag/RequireImplementsTag.php', 'PHPStan\\PhpDoc\\Tag\\ReturnTag' => $baseDir . '/src/PhpDoc/Tag/ReturnTag.php', 'PHPStan\\PhpDoc\\Tag\\SealedTypeTag' => $baseDir . '/src/PhpDoc/Tag/SealedTypeTag.php', 'PHPStan\\PhpDoc\\Tag\\SelfOutTypeTag' => $baseDir . '/src/PhpDoc/Tag/SelfOutTypeTag.php', 'PHPStan\\PhpDoc\\Tag\\TemplateTag' => $baseDir . '/src/PhpDoc/Tag/TemplateTag.php', 'PHPStan\\PhpDoc\\Tag\\ThrowsTag' => $baseDir . '/src/PhpDoc/Tag/ThrowsTag.php', 'PHPStan\\PhpDoc\\Tag\\TypeAliasImportTag' => $baseDir . '/src/PhpDoc/Tag/TypeAliasImportTag.php', 'PHPStan\\PhpDoc\\Tag\\TypeAliasTag' => $baseDir . '/src/PhpDoc/Tag/TypeAliasTag.php', 'PHPStan\\PhpDoc\\Tag\\TypedTag' => $baseDir . '/src/PhpDoc/Tag/TypedTag.php', 'PHPStan\\PhpDoc\\Tag\\UsesTag' => $baseDir . '/src/PhpDoc/Tag/UsesTag.php', 'PHPStan\\PhpDoc\\Tag\\VarTag' => $baseDir . '/src/PhpDoc/Tag/VarTag.php', 'PHPStan\\PhpDoc\\TypeNodeResolver' => $baseDir . '/src/PhpDoc/TypeNodeResolver.php', 'PHPStan\\PhpDoc\\TypeNodeResolverAwareExtension' => $baseDir . '/src/PhpDoc/TypeNodeResolverAwareExtension.php', 'PHPStan\\PhpDoc\\TypeNodeResolverExtension' => $baseDir . '/src/PhpDoc/TypeNodeResolverExtension.php', 'PHPStan\\PhpDoc\\TypeNodeResolverExtensionAwareRegistry' => $baseDir . '/src/PhpDoc/TypeNodeResolverExtensionAwareRegistry.php', 'PHPStan\\PhpDoc\\TypeNodeResolverExtensionRegistry' => $baseDir . '/src/PhpDoc/TypeNodeResolverExtensionRegistry.php', 'PHPStan\\PhpDoc\\TypeNodeResolverExtensionRegistryProvider' => $baseDir . '/src/PhpDoc/TypeNodeResolverExtensionRegistryProvider.php', 'PHPStan\\PhpDoc\\TypeStringResolver' => $baseDir . '/src/PhpDoc/TypeStringResolver.php', 'PHPStan\\Php\\ComposerPhpVersionFactory' => $baseDir . '/src/Php/ComposerPhpVersionFactory.php', 'PHPStan\\Php\\ComposerPhpVersionParser' => $baseDir . '/src/Php/ComposerPhpVersionParser.php', 'PHPStan\\Php\\PhpVersion' => $baseDir . '/src/Php/PhpVersion.php', 'PHPStan\\Php\\PhpVersionFactory' => $baseDir . '/src/Php/PhpVersionFactory.php', 'PHPStan\\Php\\PhpVersionFactoryFactory' => $baseDir . '/src/Php/PhpVersionFactoryFactory.php', 'PHPStan\\Php\\PhpVersions' => $baseDir . '/src/Php/PhpVersions.php', 'PHPStan\\Process\\CpuCoreCounter' => $baseDir . '/src/Process/CpuCoreCounter.php', 'PHPStan\\Process\\ForkedProcessPromise' => $baseDir . '/src/Process/ForkedProcessPromise.php', 'PHPStan\\Process\\ProcessCanceledException' => $baseDir . '/src/Process/ProcessCanceledException.php', 'PHPStan\\Process\\ProcessCrashedException' => $baseDir . '/src/Process/ProcessCrashedException.php', 'PHPStan\\Process\\ProcessHelper' => $baseDir . '/src/Process/ProcessHelper.php', 'PHPStan\\Process\\ProcessPromise' => $baseDir . '/src/Process/ProcessPromise.php', 'PHPStan\\Process\\SpawnedProcessPromise' => $baseDir . '/src/Process/SpawnedProcessPromise.php', 'PHPStan\\Reflection\\AdditionalConstructorsExtension' => $baseDir . '/src/Reflection/AdditionalConstructorsExtension.php', 'PHPStan\\Reflection\\AllowedSubTypesClassReflectionExtension' => $baseDir . '/src/Reflection/AllowedSubTypesClassReflectionExtension.php', 'PHPStan\\Reflection\\Annotations\\AnnotationMethodReflection' => $baseDir . '/src/Reflection/Annotations/AnnotationMethodReflection.php', 'PHPStan\\Reflection\\Annotations\\AnnotationPropertyReflection' => $baseDir . '/src/Reflection/Annotations/AnnotationPropertyReflection.php', 'PHPStan\\Reflection\\Annotations\\AnnotationsMethodParameterReflection' => $baseDir . '/src/Reflection/Annotations/AnnotationsMethodParameterReflection.php', 'PHPStan\\Reflection\\Annotations\\AnnotationsMethodsClassReflectionExtension' => $baseDir . '/src/Reflection/Annotations/AnnotationsMethodsClassReflectionExtension.php', 'PHPStan\\Reflection\\Annotations\\AnnotationsPropertiesClassReflectionExtension' => $baseDir . '/src/Reflection/Annotations/AnnotationsPropertiesClassReflectionExtension.php', 'PHPStan\\Reflection\\Assertions' => $baseDir . '/src/Reflection/Assertions.php', 'PHPStan\\Reflection\\AttributeReflection' => $baseDir . '/src/Reflection/AttributeReflection.php', 'PHPStan\\Reflection\\AttributeReflectionFactory' => $baseDir . '/src/Reflection/AttributeReflectionFactory.php', 'PHPStan\\Reflection\\BetterReflection\\BetterReflectionProvider' => $baseDir . '/src/Reflection/BetterReflection/BetterReflectionProvider.php', 'PHPStan\\Reflection\\BetterReflection\\BetterReflectionSourceLocatorFactory' => $baseDir . '/src/Reflection/BetterReflection/BetterReflectionSourceLocatorFactory.php', 'PHPStan\\Reflection\\BetterReflection\\Reflector\\MemoizingReflector' => $baseDir . '/src/Reflection/BetterReflection/Reflector/MemoizingReflector.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\AutoloadFunctionsSourceLocator' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/AutoloadFunctionsSourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\AutoloadSourceLocator' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\CachingVisitor' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/CachingVisitor.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\ComposerJsonAndInstalledJsonSourceLocatorMaker' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/ComposerJsonAndInstalledJsonSourceLocatorMaker.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\FetchedNode' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/FetchedNode.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\FetchedNodesResult' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/FetchedNodesResult.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\FileNodesFetcher' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/FileNodesFetcher.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\FileReadTrapStreamWrapper' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/FileReadTrapStreamWrapper.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\LazySourceLocator' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/LazySourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\OptimizedDirectorySourceLocator' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\OptimizedDirectorySourceLocatorFactory' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorFactory.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\OptimizedDirectorySourceLocatorRepository' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorRepository.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\OptimizedPsrAutoloaderLocator' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/OptimizedPsrAutoloaderLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\OptimizedPsrAutoloaderLocatorFactory' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/OptimizedPsrAutoloaderLocatorFactory.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\OptimizedSingleFileSourceLocator' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\OptimizedSingleFileSourceLocatorFactory' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocatorFactory.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\OptimizedSingleFileSourceLocatorRepository' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocatorRepository.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\PhpFileCleaner' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/PhpFileCleaner.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\PhpVersionBlacklistSourceLocator' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/PhpVersionBlacklistSourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\ReflectionClassSourceLocator' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/ReflectionClassSourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\RewriteClassAliasSourceLocator' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/RewriteClassAliasSourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\SkipClassAliasSourceLocator' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/SkipClassAliasSourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\SkipPolyfillSourceLocator' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/SkipPolyfillSourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\SymbolFinderInFiles' => $baseDir . '/src/Reflection/BetterReflection/SourceLocator/SymbolFinderInFiles.php', 'PHPStan\\Reflection\\BetterReflection\\SourceStubber\\PhpStormStubsSourceStubberFactory' => $baseDir . '/src/Reflection/BetterReflection/SourceStubber/PhpStormStubsSourceStubberFactory.php', 'PHPStan\\Reflection\\BetterReflection\\SourceStubber\\ReflectionSourceStubberFactory' => $baseDir . '/src/Reflection/BetterReflection/SourceStubber/ReflectionSourceStubberFactory.php', 'PHPStan\\Reflection\\BetterReflection\\Type\\AdapterReflectionEnumCaseDynamicReturnTypeExtension' => $baseDir . '/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php', 'PHPStan\\Reflection\\BetterReflection\\Type\\AdapterReflectionEnumDynamicReturnTypeExtension' => $baseDir . '/src/Reflection/BetterReflection/Type/AdapterReflectionEnumDynamicReturnTypeExtension.php', 'PHPStan\\Reflection\\Callables\\CallableParametersAcceptor' => $baseDir . '/src/Reflection/Callables/CallableParametersAcceptor.php', 'PHPStan\\Reflection\\Callables\\FunctionCallableVariant' => $baseDir . '/src/Reflection/Callables/FunctionCallableVariant.php', 'PHPStan\\Reflection\\Callables\\SimpleImpurePoint' => $baseDir . '/src/Reflection/Callables/SimpleImpurePoint.php', 'PHPStan\\Reflection\\Callables\\SimpleThrowPoint' => $baseDir . '/src/Reflection/Callables/SimpleThrowPoint.php', 'PHPStan\\Reflection\\ClassConstantReflection' => $baseDir . '/src/Reflection/ClassConstantReflection.php', 'PHPStan\\Reflection\\ClassMemberAccessAnswerer' => $baseDir . '/src/Reflection/ClassMemberAccessAnswerer.php', 'PHPStan\\Reflection\\ClassMemberReflection' => $baseDir . '/src/Reflection/ClassMemberReflection.php', 'PHPStan\\Reflection\\ClassNameHelper' => $baseDir . '/src/Reflection/ClassNameHelper.php', 'PHPStan\\Reflection\\ClassReflection' => $baseDir . '/src/Reflection/ClassReflection.php', 'PHPStan\\Reflection\\ClassReflectionExtensionRegistry' => $baseDir . '/src/Reflection/ClassReflectionExtensionRegistry.php', 'PHPStan\\Reflection\\ClassReflectionFactory' => $baseDir . '/src/Reflection/ClassReflectionFactory.php', 'PHPStan\\Reflection\\ConstantNameHelper' => $baseDir . '/src/Reflection/ConstantNameHelper.php', 'PHPStan\\Reflection\\ConstantReflection' => $baseDir . '/src/Reflection/ConstantReflection.php', 'PHPStan\\Reflection\\Constant\\RuntimeConstantReflection' => $baseDir . '/src/Reflection/Constant/RuntimeConstantReflection.php', 'PHPStan\\Reflection\\ConstructorsHelper' => $baseDir . '/src/Reflection/ConstructorsHelper.php', 'PHPStan\\Reflection\\Deprecation\\ClassConstantDeprecationExtension' => $baseDir . '/src/Reflection/Deprecation/ClassConstantDeprecationExtension.php', 'PHPStan\\Reflection\\Deprecation\\ClassDeprecationExtension' => $baseDir . '/src/Reflection/Deprecation/ClassDeprecationExtension.php', 'PHPStan\\Reflection\\Deprecation\\ConstantDeprecationExtension' => $baseDir . '/src/Reflection/Deprecation/ConstantDeprecationExtension.php', 'PHPStan\\Reflection\\Deprecation\\Deprecation' => $baseDir . '/src/Reflection/Deprecation/Deprecation.php', 'PHPStan\\Reflection\\Deprecation\\DeprecationProvider' => $baseDir . '/src/Reflection/Deprecation/DeprecationProvider.php', 'PHPStan\\Reflection\\Deprecation\\EnumCaseDeprecationExtension' => $baseDir . '/src/Reflection/Deprecation/EnumCaseDeprecationExtension.php', 'PHPStan\\Reflection\\Deprecation\\FunctionDeprecationExtension' => $baseDir . '/src/Reflection/Deprecation/FunctionDeprecationExtension.php', 'PHPStan\\Reflection\\Deprecation\\MethodDeprecationExtension' => $baseDir . '/src/Reflection/Deprecation/MethodDeprecationExtension.php', 'PHPStan\\Reflection\\Deprecation\\PropertyDeprecationExtension' => $baseDir . '/src/Reflection/Deprecation/PropertyDeprecationExtension.php', 'PHPStan\\Reflection\\Dummy\\ChangedTypeMethodReflection' => $baseDir . '/src/Reflection/Dummy/ChangedTypeMethodReflection.php', 'PHPStan\\Reflection\\Dummy\\ChangedTypePropertyReflection' => $baseDir . '/src/Reflection/Dummy/ChangedTypePropertyReflection.php', 'PHPStan\\Reflection\\Dummy\\DummyClassConstantReflection' => $baseDir . '/src/Reflection/Dummy/DummyClassConstantReflection.php', 'PHPStan\\Reflection\\Dummy\\DummyConstructorReflection' => $baseDir . '/src/Reflection/Dummy/DummyConstructorReflection.php', 'PHPStan\\Reflection\\Dummy\\DummyMethodReflection' => $baseDir . '/src/Reflection/Dummy/DummyMethodReflection.php', 'PHPStan\\Reflection\\Dummy\\DummyPropertyReflection' => $baseDir . '/src/Reflection/Dummy/DummyPropertyReflection.php', 'PHPStan\\Reflection\\EnumCaseReflection' => $baseDir . '/src/Reflection/EnumCaseReflection.php', 'PHPStan\\Reflection\\ExtendedCallableFunctionVariant' => $baseDir . '/src/Reflection/ExtendedCallableFunctionVariant.php', 'PHPStan\\Reflection\\ExtendedFunctionVariant' => $baseDir . '/src/Reflection/ExtendedFunctionVariant.php', 'PHPStan\\Reflection\\ExtendedMethodReflection' => $baseDir . '/src/Reflection/ExtendedMethodReflection.php', 'PHPStan\\Reflection\\ExtendedParameterReflection' => $baseDir . '/src/Reflection/ExtendedParameterReflection.php', 'PHPStan\\Reflection\\ExtendedParametersAcceptor' => $baseDir . '/src/Reflection/ExtendedParametersAcceptor.php', 'PHPStan\\Reflection\\ExtendedPropertyReflection' => $baseDir . '/src/Reflection/ExtendedPropertyReflection.php', 'PHPStan\\Reflection\\FunctionReflection' => $baseDir . '/src/Reflection/FunctionReflection.php', 'PHPStan\\Reflection\\FunctionReflectionFactory' => $baseDir . '/src/Reflection/FunctionReflectionFactory.php', 'PHPStan\\Reflection\\FunctionVariant' => $baseDir . '/src/Reflection/FunctionVariant.php', 'PHPStan\\Reflection\\GenericParametersAcceptorResolver' => $baseDir . '/src/Reflection/GenericParametersAcceptorResolver.php', 'PHPStan\\Reflection\\InaccessibleMethod' => $baseDir . '/src/Reflection/InaccessibleMethod.php', 'PHPStan\\Reflection\\InitializerExprContext' => $baseDir . '/src/Reflection/InitializerExprContext.php', 'PHPStan\\Reflection\\InitializerExprTypeResolver' => $baseDir . '/src/Reflection/InitializerExprTypeResolver.php', 'PHPStan\\Reflection\\MethodPrototypeReflection' => $baseDir . '/src/Reflection/MethodPrototypeReflection.php', 'PHPStan\\Reflection\\MethodReflection' => $baseDir . '/src/Reflection/MethodReflection.php', 'PHPStan\\Reflection\\MethodsClassReflectionExtension' => $baseDir . '/src/Reflection/MethodsClassReflectionExtension.php', 'PHPStan\\Reflection\\MissingConstantFromReflectionException' => $baseDir . '/src/Reflection/MissingConstantFromReflectionException.php', 'PHPStan\\Reflection\\MissingMethodFromReflectionException' => $baseDir . '/src/Reflection/MissingMethodFromReflectionException.php', 'PHPStan\\Reflection\\MissingPropertyFromReflectionException' => $baseDir . '/src/Reflection/MissingPropertyFromReflectionException.php', 'PHPStan\\Reflection\\MissingStaticAccessorInstanceException' => $baseDir . '/src/Reflection/MissingStaticAccessorInstanceException.php', 'PHPStan\\Reflection\\Mixin\\MixinMethodReflection' => $baseDir . '/src/Reflection/Mixin/MixinMethodReflection.php', 'PHPStan\\Reflection\\Mixin\\MixinMethodsClassReflectionExtension' => $baseDir . '/src/Reflection/Mixin/MixinMethodsClassReflectionExtension.php', 'PHPStan\\Reflection\\Mixin\\MixinPropertiesClassReflectionExtension' => $baseDir . '/src/Reflection/Mixin/MixinPropertiesClassReflectionExtension.php', 'PHPStan\\Reflection\\NamespaceAnswerer' => $baseDir . '/src/Reflection/NamespaceAnswerer.php', 'PHPStan\\Reflection\\Native\\ExtendedNativeParameterReflection' => $baseDir . '/src/Reflection/Native/ExtendedNativeParameterReflection.php', 'PHPStan\\Reflection\\Native\\NativeFunctionReflection' => $baseDir . '/src/Reflection/Native/NativeFunctionReflection.php', 'PHPStan\\Reflection\\Native\\NativeMethodReflection' => $baseDir . '/src/Reflection/Native/NativeMethodReflection.php', 'PHPStan\\Reflection\\Native\\NativeParameterReflection' => $baseDir . '/src/Reflection/Native/NativeParameterReflection.php', 'PHPStan\\Reflection\\PHPStan\\NativeReflectionEnumReturnDynamicReturnTypeExtension' => $baseDir . '/src/Reflection/PHPStan/NativeReflectionEnumReturnDynamicReturnTypeExtension.php', 'PHPStan\\Reflection\\ParameterReflection' => $baseDir . '/src/Reflection/ParameterReflection.php', 'PHPStan\\Reflection\\ParametersAcceptor' => $baseDir . '/src/Reflection/ParametersAcceptor.php', 'PHPStan\\Reflection\\ParametersAcceptorSelector' => $baseDir . '/src/Reflection/ParametersAcceptorSelector.php', 'PHPStan\\Reflection\\PassedByReference' => $baseDir . '/src/Reflection/PassedByReference.php', 'PHPStan\\Reflection\\PhpVersionStaticAccessor' => $baseDir . '/src/Reflection/PhpVersionStaticAccessor.php', 'PHPStan\\Reflection\\Php\\ClosureCallMethodReflection' => $baseDir . '/src/Reflection/Php/ClosureCallMethodReflection.php', 'PHPStan\\Reflection\\Php\\ClosureCallUnresolvedMethodPrototypeReflection' => $baseDir . '/src/Reflection/Php/ClosureCallUnresolvedMethodPrototypeReflection.php', 'PHPStan\\Reflection\\Php\\DummyParameter' => $baseDir . '/src/Reflection/Php/DummyParameter.php', 'PHPStan\\Reflection\\Php\\EnumAllowedSubTypesClassReflectionExtension' => $baseDir . '/src/Reflection/Php/EnumAllowedSubTypesClassReflectionExtension.php', 'PHPStan\\Reflection\\Php\\EnumCasesMethodReflection' => $baseDir . '/src/Reflection/Php/EnumCasesMethodReflection.php', 'PHPStan\\Reflection\\Php\\EnumPropertyReflection' => $baseDir . '/src/Reflection/Php/EnumPropertyReflection.php', 'PHPStan\\Reflection\\Php\\EnumUnresolvedPropertyPrototypeReflection' => $baseDir . '/src/Reflection/Php/EnumUnresolvedPropertyPrototypeReflection.php', 'PHPStan\\Reflection\\Php\\ExitFunctionReflection' => $baseDir . '/src/Reflection/Php/ExitFunctionReflection.php', 'PHPStan\\Reflection\\Php\\ExtendedDummyParameter' => $baseDir . '/src/Reflection/Php/ExtendedDummyParameter.php', 'PHPStan\\Reflection\\Php\\PhpClassReflectionExtension' => $baseDir . '/src/Reflection/Php/PhpClassReflectionExtension.php', 'PHPStan\\Reflection\\Php\\PhpFunctionFromParserNodeReflection' => $baseDir . '/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php', 'PHPStan\\Reflection\\Php\\PhpFunctionReflection' => $baseDir . '/src/Reflection/Php/PhpFunctionReflection.php', 'PHPStan\\Reflection\\Php\\PhpMethodFromParserNodeReflection' => $baseDir . '/src/Reflection/Php/PhpMethodFromParserNodeReflection.php', 'PHPStan\\Reflection\\Php\\PhpMethodReflection' => $baseDir . '/src/Reflection/Php/PhpMethodReflection.php', 'PHPStan\\Reflection\\Php\\PhpMethodReflectionFactory' => $baseDir . '/src/Reflection/Php/PhpMethodReflectionFactory.php', 'PHPStan\\Reflection\\Php\\PhpParameterFromParserNodeReflection' => $baseDir . '/src/Reflection/Php/PhpParameterFromParserNodeReflection.php', 'PHPStan\\Reflection\\Php\\PhpParameterReflection' => $baseDir . '/src/Reflection/Php/PhpParameterReflection.php', 'PHPStan\\Reflection\\Php\\PhpPropertyReflection' => $baseDir . '/src/Reflection/Php/PhpPropertyReflection.php', 'PHPStan\\Reflection\\Php\\SealedAllowedSubTypesClassReflectionExtension' => $baseDir . '/src/Reflection/Php/SealedAllowedSubTypesClassReflectionExtension.php', 'PHPStan\\Reflection\\Php\\SimpleXMLElementProperty' => $baseDir . '/src/Reflection/Php/SimpleXMLElementProperty.php', 'PHPStan\\Reflection\\Php\\Soap\\SoapClientMethodReflection' => $baseDir . '/src/Reflection/Php/Soap/SoapClientMethodReflection.php', 'PHPStan\\Reflection\\Php\\Soap\\SoapClientMethodsClassReflectionExtension' => $baseDir . '/src/Reflection/Php/Soap/SoapClientMethodsClassReflectionExtension.php', 'PHPStan\\Reflection\\Php\\UniversalObjectCrateProperty' => $baseDir . '/src/Reflection/Php/UniversalObjectCrateProperty.php', 'PHPStan\\Reflection\\Php\\UniversalObjectCratesClassReflectionExtension' => $baseDir . '/src/Reflection/Php/UniversalObjectCratesClassReflectionExtension.php', 'PHPStan\\Reflection\\PropertiesClassReflectionExtension' => $baseDir . '/src/Reflection/PropertiesClassReflectionExtension.php', 'PHPStan\\Reflection\\PropertyReflection' => $baseDir . '/src/Reflection/PropertyReflection.php', 'PHPStan\\Reflection\\RealClassClassConstantReflection' => $baseDir . '/src/Reflection/RealClassClassConstantReflection.php', 'PHPStan\\Reflection\\ReflectionProvider' => $baseDir . '/src/Reflection/ReflectionProvider.php', 'PHPStan\\Reflection\\ReflectionProviderStaticAccessor' => $baseDir . '/src/Reflection/ReflectionProviderStaticAccessor.php', 'PHPStan\\Reflection\\ReflectionProvider\\DirectReflectionProviderProvider' => $baseDir . '/src/Reflection/ReflectionProvider/DirectReflectionProviderProvider.php', 'PHPStan\\Reflection\\ReflectionProvider\\DummyReflectionProvider' => $baseDir . '/src/Reflection/ReflectionProvider/DummyReflectionProvider.php', 'PHPStan\\Reflection\\ReflectionProvider\\LazyReflectionProviderProvider' => $baseDir . '/src/Reflection/ReflectionProvider/LazyReflectionProviderProvider.php', 'PHPStan\\Reflection\\ReflectionProvider\\MemoizingReflectionProvider' => $baseDir . '/src/Reflection/ReflectionProvider/MemoizingReflectionProvider.php', 'PHPStan\\Reflection\\ReflectionProvider\\ReflectionProviderFactory' => $baseDir . '/src/Reflection/ReflectionProvider/ReflectionProviderFactory.php', 'PHPStan\\Reflection\\ReflectionProvider\\ReflectionProviderProvider' => $baseDir . '/src/Reflection/ReflectionProvider/ReflectionProviderProvider.php', 'PHPStan\\Reflection\\RequireExtension\\RequireExtendsMethodsClassReflectionExtension' => $baseDir . '/src/Reflection/RequireExtension/RequireExtendsMethodsClassReflectionExtension.php', 'PHPStan\\Reflection\\RequireExtension\\RequireExtendsPropertiesClassReflectionExtension' => $baseDir . '/src/Reflection/RequireExtension/RequireExtendsPropertiesClassReflectionExtension.php', 'PHPStan\\Reflection\\ResolvedFunctionVariant' => $baseDir . '/src/Reflection/ResolvedFunctionVariant.php', 'PHPStan\\Reflection\\ResolvedFunctionVariantWithCallable' => $baseDir . '/src/Reflection/ResolvedFunctionVariantWithCallable.php', 'PHPStan\\Reflection\\ResolvedFunctionVariantWithOriginal' => $baseDir . '/src/Reflection/ResolvedFunctionVariantWithOriginal.php', 'PHPStan\\Reflection\\ResolvedMethodReflection' => $baseDir . '/src/Reflection/ResolvedMethodReflection.php', 'PHPStan\\Reflection\\ResolvedPropertyReflection' => $baseDir . '/src/Reflection/ResolvedPropertyReflection.php', 'PHPStan\\Reflection\\SignatureMap\\FunctionSignature' => $baseDir . '/src/Reflection/SignatureMap/FunctionSignature.php', 'PHPStan\\Reflection\\SignatureMap\\FunctionSignatureMapProvider' => $baseDir . '/src/Reflection/SignatureMap/FunctionSignatureMapProvider.php', 'PHPStan\\Reflection\\SignatureMap\\NativeFunctionReflectionProvider' => $baseDir . '/src/Reflection/SignatureMap/NativeFunctionReflectionProvider.php', 'PHPStan\\Reflection\\SignatureMap\\ParameterSignature' => $baseDir . '/src/Reflection/SignatureMap/ParameterSignature.php', 'PHPStan\\Reflection\\SignatureMap\\Php8SignatureMapProvider' => $baseDir . '/src/Reflection/SignatureMap/Php8SignatureMapProvider.php', 'PHPStan\\Reflection\\SignatureMap\\SignatureMapParser' => $baseDir . '/src/Reflection/SignatureMap/SignatureMapParser.php', 'PHPStan\\Reflection\\SignatureMap\\SignatureMapProvider' => $baseDir . '/src/Reflection/SignatureMap/SignatureMapProvider.php', 'PHPStan\\Reflection\\SignatureMap\\SignatureMapProviderFactory' => $baseDir . '/src/Reflection/SignatureMap/SignatureMapProviderFactory.php', 'PHPStan\\Reflection\\TrivialParametersAcceptor' => $baseDir . '/src/Reflection/TrivialParametersAcceptor.php', 'PHPStan\\Reflection\\Type\\CallbackUnresolvedMethodPrototypeReflection' => $baseDir . '/src/Reflection/Type/CallbackUnresolvedMethodPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\CallbackUnresolvedPropertyPrototypeReflection' => $baseDir . '/src/Reflection/Type/CallbackUnresolvedPropertyPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\CalledOnTypeUnresolvedMethodPrototypeReflection' => $baseDir . '/src/Reflection/Type/CalledOnTypeUnresolvedMethodPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\CalledOnTypeUnresolvedPropertyPrototypeReflection' => $baseDir . '/src/Reflection/Type/CalledOnTypeUnresolvedPropertyPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\IntersectionTypeMethodReflection' => $baseDir . '/src/Reflection/Type/IntersectionTypeMethodReflection.php', 'PHPStan\\Reflection\\Type\\IntersectionTypePropertyReflection' => $baseDir . '/src/Reflection/Type/IntersectionTypePropertyReflection.php', 'PHPStan\\Reflection\\Type\\IntersectionTypeUnresolvedMethodPrototypeReflection' => $baseDir . '/src/Reflection/Type/IntersectionTypeUnresolvedMethodPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\IntersectionTypeUnresolvedPropertyPrototypeReflection' => $baseDir . '/src/Reflection/Type/IntersectionTypeUnresolvedPropertyPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\UnionTypeMethodReflection' => $baseDir . '/src/Reflection/Type/UnionTypeMethodReflection.php', 'PHPStan\\Reflection\\Type\\UnionTypePropertyReflection' => $baseDir . '/src/Reflection/Type/UnionTypePropertyReflection.php', 'PHPStan\\Reflection\\Type\\UnionTypeUnresolvedMethodPrototypeReflection' => $baseDir . '/src/Reflection/Type/UnionTypeUnresolvedMethodPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\UnionTypeUnresolvedPropertyPrototypeReflection' => $baseDir . '/src/Reflection/Type/UnionTypeUnresolvedPropertyPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\UnresolvedMethodPrototypeReflection' => $baseDir . '/src/Reflection/Type/UnresolvedMethodPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\UnresolvedPropertyPrototypeReflection' => $baseDir . '/src/Reflection/Type/UnresolvedPropertyPrototypeReflection.php', 'PHPStan\\Reflection\\WrappedExtendedMethodReflection' => $baseDir . '/src/Reflection/WrappedExtendedMethodReflection.php', 'PHPStan\\Reflection\\WrappedExtendedPropertyReflection' => $baseDir . '/src/Reflection/WrappedExtendedPropertyReflection.php', 'PHPStan\\Reflection\\WrapperPropertyReflection' => $baseDir . '/src/Reflection/WrapperPropertyReflection.php', 'PHPStan\\Rules\\Api\\ApiClassConstFetchRule' => $baseDir . '/src/Rules/Api/ApiClassConstFetchRule.php', 'PHPStan\\Rules\\Api\\ApiClassExtendsRule' => $baseDir . '/src/Rules/Api/ApiClassExtendsRule.php', 'PHPStan\\Rules\\Api\\ApiClassImplementsRule' => $baseDir . '/src/Rules/Api/ApiClassImplementsRule.php', 'PHPStan\\Rules\\Api\\ApiInstanceofRule' => $baseDir . '/src/Rules/Api/ApiInstanceofRule.php', 'PHPStan\\Rules\\Api\\ApiInstanceofTypeRule' => $baseDir . '/src/Rules/Api/ApiInstanceofTypeRule.php', 'PHPStan\\Rules\\Api\\ApiInstantiationRule' => $baseDir . '/src/Rules/Api/ApiInstantiationRule.php', 'PHPStan\\Rules\\Api\\ApiInterfaceExtendsRule' => $baseDir . '/src/Rules/Api/ApiInterfaceExtendsRule.php', 'PHPStan\\Rules\\Api\\ApiMethodCallRule' => $baseDir . '/src/Rules/Api/ApiMethodCallRule.php', 'PHPStan\\Rules\\Api\\ApiRuleHelper' => $baseDir . '/src/Rules/Api/ApiRuleHelper.php', 'PHPStan\\Rules\\Api\\ApiStaticCallRule' => $baseDir . '/src/Rules/Api/ApiStaticCallRule.php', 'PHPStan\\Rules\\Api\\ApiTraitUseRule' => $baseDir . '/src/Rules/Api/ApiTraitUseRule.php', 'PHPStan\\Rules\\Api\\GetTemplateTypeRule' => $baseDir . '/src/Rules/Api/GetTemplateTypeRule.php', 'PHPStan\\Rules\\Api\\NodeConnectingVisitorAttributesRule' => $baseDir . '/src/Rules/Api/NodeConnectingVisitorAttributesRule.php', 'PHPStan\\Rules\\Api\\OldPhpParser4ClassRule' => $baseDir . '/src/Rules/Api/OldPhpParser4ClassRule.php', 'PHPStan\\Rules\\Api\\PhpStanNamespaceIn3rdPartyPackageRule' => $baseDir . '/src/Rules/Api/PhpStanNamespaceIn3rdPartyPackageRule.php', 'PHPStan\\Rules\\Api\\RuntimeReflectionFunctionRule' => $baseDir . '/src/Rules/Api/RuntimeReflectionFunctionRule.php', 'PHPStan\\Rules\\Api\\RuntimeReflectionInstantiationRule' => $baseDir . '/src/Rules/Api/RuntimeReflectionInstantiationRule.php', 'PHPStan\\Rules\\Arrays\\AllowedArrayKeysTypes' => $baseDir . '/src/Rules/Arrays/AllowedArrayKeysTypes.php', 'PHPStan\\Rules\\Arrays\\ArrayDestructuringRule' => $baseDir . '/src/Rules/Arrays/ArrayDestructuringRule.php', 'PHPStan\\Rules\\Arrays\\ArrayUnpackingRule' => $baseDir . '/src/Rules/Arrays/ArrayUnpackingRule.php', 'PHPStan\\Rules\\Arrays\\DeadForeachRule' => $baseDir . '/src/Rules/Arrays/DeadForeachRule.php', 'PHPStan\\Rules\\Arrays\\DuplicateKeysInLiteralArraysRule' => $baseDir . '/src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.php', 'PHPStan\\Rules\\Arrays\\InvalidKeyInArrayDimFetchRule' => $baseDir . '/src/Rules/Arrays/InvalidKeyInArrayDimFetchRule.php', 'PHPStan\\Rules\\Arrays\\InvalidKeyInArrayItemRule' => $baseDir . '/src/Rules/Arrays/InvalidKeyInArrayItemRule.php', 'PHPStan\\Rules\\Arrays\\IterableInForeachRule' => $baseDir . '/src/Rules/Arrays/IterableInForeachRule.php', 'PHPStan\\Rules\\Arrays\\NonexistentOffsetInArrayDimFetchCheck' => $baseDir . '/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php', 'PHPStan\\Rules\\Arrays\\NonexistentOffsetInArrayDimFetchRule' => $baseDir . '/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchRule.php', 'PHPStan\\Rules\\Arrays\\OffsetAccessAssignOpRule' => $baseDir . '/src/Rules/Arrays/OffsetAccessAssignOpRule.php', 'PHPStan\\Rules\\Arrays\\OffsetAccessAssignmentRule' => $baseDir . '/src/Rules/Arrays/OffsetAccessAssignmentRule.php', 'PHPStan\\Rules\\Arrays\\OffsetAccessValueAssignmentRule' => $baseDir . '/src/Rules/Arrays/OffsetAccessValueAssignmentRule.php', 'PHPStan\\Rules\\Arrays\\OffsetAccessWithoutDimForReadingRule' => $baseDir . '/src/Rules/Arrays/OffsetAccessWithoutDimForReadingRule.php', 'PHPStan\\Rules\\Arrays\\UnpackIterableInArrayRule' => $baseDir . '/src/Rules/Arrays/UnpackIterableInArrayRule.php', 'PHPStan\\Rules\\AttributesCheck' => $baseDir . '/src/Rules/AttributesCheck.php', 'PHPStan\\Rules\\Cast\\DeprecatedCastRule' => $baseDir . '/src/Rules/Cast/DeprecatedCastRule.php', 'PHPStan\\Rules\\Cast\\EchoRule' => $baseDir . '/src/Rules/Cast/EchoRule.php', 'PHPStan\\Rules\\Cast\\InvalidCastRule' => $baseDir . '/src/Rules/Cast/InvalidCastRule.php', 'PHPStan\\Rules\\Cast\\InvalidPartOfEncapsedStringRule' => $baseDir . '/src/Rules/Cast/InvalidPartOfEncapsedStringRule.php', 'PHPStan\\Rules\\Cast\\PrintRule' => $baseDir . '/src/Rules/Cast/PrintRule.php', 'PHPStan\\Rules\\Cast\\UnsetCastRule' => $baseDir . '/src/Rules/Cast/UnsetCastRule.php', 'PHPStan\\Rules\\Cast\\VoidCastRule' => $baseDir . '/src/Rules/Cast/VoidCastRule.php', 'PHPStan\\Rules\\ClassCaseSensitivityCheck' => $baseDir . '/src/Rules/ClassCaseSensitivityCheck.php', 'PHPStan\\Rules\\ClassForbiddenNameCheck' => $baseDir . '/src/Rules/ClassForbiddenNameCheck.php', 'PHPStan\\Rules\\ClassNameCheck' => $baseDir . '/src/Rules/ClassNameCheck.php', 'PHPStan\\Rules\\ClassNameNodePair' => $baseDir . '/src/Rules/ClassNameNodePair.php', 'PHPStan\\Rules\\ClassNameUsageLocation' => $baseDir . '/src/Rules/ClassNameUsageLocation.php', 'PHPStan\\Rules\\Classes\\AccessPrivateConstantThroughStaticRule' => $baseDir . '/src/Rules/Classes/AccessPrivateConstantThroughStaticRule.php', 'PHPStan\\Rules\\Classes\\AllowedSubTypesRule' => $baseDir . '/src/Rules/Classes/AllowedSubTypesRule.php', 'PHPStan\\Rules\\Classes\\ClassAttributesRule' => $baseDir . '/src/Rules/Classes/ClassAttributesRule.php', 'PHPStan\\Rules\\Classes\\ClassConstantAttributesRule' => $baseDir . '/src/Rules/Classes/ClassConstantAttributesRule.php', 'PHPStan\\Rules\\Classes\\ClassConstantRule' => $baseDir . '/src/Rules/Classes/ClassConstantRule.php', 'PHPStan\\Rules\\Classes\\ConsistentConstructorHelper' => $baseDir . '/src/Rules/Classes/ConsistentConstructorHelper.php', 'PHPStan\\Rules\\Classes\\DuplicateClassDeclarationRule' => $baseDir . '/src/Rules/Classes/DuplicateClassDeclarationRule.php', 'PHPStan\\Rules\\Classes\\DuplicateDeclarationHelper' => $baseDir . '/src/Rules/Classes/DuplicateDeclarationHelper.php', 'PHPStan\\Rules\\Classes\\DuplicateDeclarationRule' => $baseDir . '/src/Rules/Classes/DuplicateDeclarationRule.php', 'PHPStan\\Rules\\Classes\\DuplicateTraitDeclarationRule' => $baseDir . '/src/Rules/Classes/DuplicateTraitDeclarationRule.php', 'PHPStan\\Rules\\Classes\\EnumSanityRule' => $baseDir . '/src/Rules/Classes/EnumSanityRule.php', 'PHPStan\\Rules\\Classes\\ExistingClassInClassExtendsRule' => $baseDir . '/src/Rules/Classes/ExistingClassInClassExtendsRule.php', 'PHPStan\\Rules\\Classes\\ExistingClassInInstanceOfRule' => $baseDir . '/src/Rules/Classes/ExistingClassInInstanceOfRule.php', 'PHPStan\\Rules\\Classes\\ExistingClassInTraitUseRule' => $baseDir . '/src/Rules/Classes/ExistingClassInTraitUseRule.php', 'PHPStan\\Rules\\Classes\\ExistingClassesInClassImplementsRule' => $baseDir . '/src/Rules/Classes/ExistingClassesInClassImplementsRule.php', 'PHPStan\\Rules\\Classes\\ExistingClassesInEnumImplementsRule' => $baseDir . '/src/Rules/Classes/ExistingClassesInEnumImplementsRule.php', 'PHPStan\\Rules\\Classes\\ExistingClassesInInterfaceExtendsRule' => $baseDir . '/src/Rules/Classes/ExistingClassesInInterfaceExtendsRule.php', 'PHPStan\\Rules\\Classes\\ImpossibleInstanceOfRule' => $baseDir . '/src/Rules/Classes/ImpossibleInstanceOfRule.php', 'PHPStan\\Rules\\Classes\\InstantiationCallableRule' => $baseDir . '/src/Rules/Classes/InstantiationCallableRule.php', 'PHPStan\\Rules\\Classes\\InstantiationRule' => $baseDir . '/src/Rules/Classes/InstantiationRule.php', 'PHPStan\\Rules\\Classes\\InvalidPromotedPropertiesRule' => $baseDir . '/src/Rules/Classes/InvalidPromotedPropertiesRule.php', 'PHPStan\\Rules\\Classes\\LocalTypeAliasesCheck' => $baseDir . '/src/Rules/Classes/LocalTypeAliasesCheck.php', 'PHPStan\\Rules\\Classes\\LocalTypeAliasesRule' => $baseDir . '/src/Rules/Classes/LocalTypeAliasesRule.php', 'PHPStan\\Rules\\Classes\\LocalTypeTraitAliasesRule' => $baseDir . '/src/Rules/Classes/LocalTypeTraitAliasesRule.php', 'PHPStan\\Rules\\Classes\\LocalTypeTraitUseAliasesRule' => $baseDir . '/src/Rules/Classes/LocalTypeTraitUseAliasesRule.php', 'PHPStan\\Rules\\Classes\\MethodTagCheck' => $baseDir . '/src/Rules/Classes/MethodTagCheck.php', 'PHPStan\\Rules\\Classes\\MethodTagRule' => $baseDir . '/src/Rules/Classes/MethodTagRule.php', 'PHPStan\\Rules\\Classes\\MethodTagTraitRule' => $baseDir . '/src/Rules/Classes/MethodTagTraitRule.php', 'PHPStan\\Rules\\Classes\\MethodTagTraitUseRule' => $baseDir . '/src/Rules/Classes/MethodTagTraitUseRule.php', 'PHPStan\\Rules\\Classes\\MixinCheck' => $baseDir . '/src/Rules/Classes/MixinCheck.php', 'PHPStan\\Rules\\Classes\\MixinRule' => $baseDir . '/src/Rules/Classes/MixinRule.php', 'PHPStan\\Rules\\Classes\\MixinTraitRule' => $baseDir . '/src/Rules/Classes/MixinTraitRule.php', 'PHPStan\\Rules\\Classes\\MixinTraitUseRule' => $baseDir . '/src/Rules/Classes/MixinTraitUseRule.php', 'PHPStan\\Rules\\Classes\\NewStaticInAbstractClassStaticMethodRule' => $baseDir . '/src/Rules/Classes/NewStaticInAbstractClassStaticMethodRule.php', 'PHPStan\\Rules\\Classes\\NewStaticRule' => $baseDir . '/src/Rules/Classes/NewStaticRule.php', 'PHPStan\\Rules\\Classes\\NonClassAttributeClassRule' => $baseDir . '/src/Rules/Classes/NonClassAttributeClassRule.php', 'PHPStan\\Rules\\Classes\\PropertyTagCheck' => $baseDir . '/src/Rules/Classes/PropertyTagCheck.php', 'PHPStan\\Rules\\Classes\\PropertyTagRule' => $baseDir . '/src/Rules/Classes/PropertyTagRule.php', 'PHPStan\\Rules\\Classes\\PropertyTagTraitRule' => $baseDir . '/src/Rules/Classes/PropertyTagTraitRule.php', 'PHPStan\\Rules\\Classes\\PropertyTagTraitUseRule' => $baseDir . '/src/Rules/Classes/PropertyTagTraitUseRule.php', 'PHPStan\\Rules\\Classes\\ReadOnlyClassRule' => $baseDir . '/src/Rules/Classes/ReadOnlyClassRule.php', 'PHPStan\\Rules\\Classes\\RequireExtendsRule' => $baseDir . '/src/Rules/Classes/RequireExtendsRule.php', 'PHPStan\\Rules\\Classes\\RequireImplementsRule' => $baseDir . '/src/Rules/Classes/RequireImplementsRule.php', 'PHPStan\\Rules\\Classes\\TraitAttributeClassRule' => $baseDir . '/src/Rules/Classes/TraitAttributeClassRule.php', 'PHPStan\\Rules\\Classes\\UnusedConstructorParametersRule' => $baseDir . '/src/Rules/Classes/UnusedConstructorParametersRule.php', 'PHPStan\\Rules\\Comparison\\BooleanAndConstantConditionRule' => $baseDir . '/src/Rules/Comparison/BooleanAndConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\BooleanNotConstantConditionRule' => $baseDir . '/src/Rules/Comparison/BooleanNotConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\BooleanOrConstantConditionRule' => $baseDir . '/src/Rules/Comparison/BooleanOrConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\ConstantConditionRuleHelper' => $baseDir . '/src/Rules/Comparison/ConstantConditionRuleHelper.php', 'PHPStan\\Rules\\Comparison\\ConstantLooseComparisonRule' => $baseDir . '/src/Rules/Comparison/ConstantLooseComparisonRule.php', 'PHPStan\\Rules\\Comparison\\DoWhileLoopConstantConditionRule' => $baseDir . '/src/Rules/Comparison/DoWhileLoopConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\ElseIfConstantConditionRule' => $baseDir . '/src/Rules/Comparison/ElseIfConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\IfConstantConditionRule' => $baseDir . '/src/Rules/Comparison/IfConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\ImpossibleCheckTypeFunctionCallRule' => $baseDir . '/src/Rules/Comparison/ImpossibleCheckTypeFunctionCallRule.php', 'PHPStan\\Rules\\Comparison\\ImpossibleCheckTypeHelper' => $baseDir . '/src/Rules/Comparison/ImpossibleCheckTypeHelper.php', 'PHPStan\\Rules\\Comparison\\ImpossibleCheckTypeMethodCallRule' => $baseDir . '/src/Rules/Comparison/ImpossibleCheckTypeMethodCallRule.php', 'PHPStan\\Rules\\Comparison\\ImpossibleCheckTypeStaticMethodCallRule' => $baseDir . '/src/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRule.php', 'PHPStan\\Rules\\Comparison\\LogicalXorConstantConditionRule' => $baseDir . '/src/Rules/Comparison/LogicalXorConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\MatchExpressionRule' => $baseDir . '/src/Rules/Comparison/MatchExpressionRule.php', 'PHPStan\\Rules\\Comparison\\NumberComparisonOperatorsConstantConditionRule' => $baseDir . '/src/Rules/Comparison/NumberComparisonOperatorsConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\PossiblyImpureTipHelper' => $baseDir . '/src/Rules/Comparison/PossiblyImpureTipHelper.php', 'PHPStan\\Rules\\Comparison\\StrictComparisonOfDifferentTypesRule' => $baseDir . '/src/Rules/Comparison/StrictComparisonOfDifferentTypesRule.php', 'PHPStan\\Rules\\Comparison\\TernaryOperatorConstantConditionRule' => $baseDir . '/src/Rules/Comparison/TernaryOperatorConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\UsageOfVoidMatchExpressionRule' => $baseDir . '/src/Rules/Comparison/UsageOfVoidMatchExpressionRule.php', 'PHPStan\\Rules\\Comparison\\WhileLoopAlwaysFalseConditionRule' => $baseDir . '/src/Rules/Comparison/WhileLoopAlwaysFalseConditionRule.php', 'PHPStan\\Rules\\Comparison\\WhileLoopAlwaysTrueConditionRule' => $baseDir . '/src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php', 'PHPStan\\Rules\\Constants\\AlwaysUsedClassConstantsExtension' => $baseDir . '/src/Rules/Constants/AlwaysUsedClassConstantsExtension.php', 'PHPStan\\Rules\\Constants\\AlwaysUsedClassConstantsExtensionProvider' => $baseDir . '/src/Rules/Constants/AlwaysUsedClassConstantsExtensionProvider.php', 'PHPStan\\Rules\\Constants\\ClassAsClassConstantRule' => $baseDir . '/src/Rules/Constants/ClassAsClassConstantRule.php', 'PHPStan\\Rules\\Constants\\ConstantAttributesRule' => $baseDir . '/src/Rules/Constants/ConstantAttributesRule.php', 'PHPStan\\Rules\\Constants\\ConstantRule' => $baseDir . '/src/Rules/Constants/ConstantRule.php', 'PHPStan\\Rules\\Constants\\DynamicClassConstantFetchRule' => $baseDir . '/src/Rules/Constants/DynamicClassConstantFetchRule.php', 'PHPStan\\Rules\\Constants\\FinalConstantRule' => $baseDir . '/src/Rules/Constants/FinalConstantRule.php', 'PHPStan\\Rules\\Constants\\FinalPrivateConstantRule' => $baseDir . '/src/Rules/Constants/FinalPrivateConstantRule.php', 'PHPStan\\Rules\\Constants\\LazyAlwaysUsedClassConstantsExtensionProvider' => $baseDir . '/src/Rules/Constants/LazyAlwaysUsedClassConstantsExtensionProvider.php', 'PHPStan\\Rules\\Constants\\MagicConstantContextRule' => $baseDir . '/src/Rules/Constants/MagicConstantContextRule.php', 'PHPStan\\Rules\\Constants\\MissingClassConstantTypehintRule' => $baseDir . '/src/Rules/Constants/MissingClassConstantTypehintRule.php', 'PHPStan\\Rules\\Constants\\NativeTypedClassConstantRule' => $baseDir . '/src/Rules/Constants/NativeTypedClassConstantRule.php', 'PHPStan\\Rules\\Constants\\OverridingConstantRule' => $baseDir . '/src/Rules/Constants/OverridingConstantRule.php', 'PHPStan\\Rules\\Constants\\ValueAssignedToClassConstantRule' => $baseDir . '/src/Rules/Constants/ValueAssignedToClassConstantRule.php', 'PHPStan\\Rules\\Constants\\ValueAssignedToDefineRule' => $baseDir . '/src/Rules/Constants/ValueAssignedToDefineRule.php', 'PHPStan\\Rules\\Constants\\ValueAssignedToGlobalConstantRule' => $baseDir . '/src/Rules/Constants/ValueAssignedToGlobalConstantRule.php', 'PHPStan\\Rules\\DateIntervalInstantiationRule' => $baseDir . '/src/Rules/DateIntervalInstantiationRule.php', 'PHPStan\\Rules\\DateTimeInstantiationRule' => $baseDir . '/src/Rules/DateTimeInstantiationRule.php', 'PHPStan\\Rules\\DeadCode\\CallToConstructorStatementWithoutImpurePointsRule' => $baseDir . '/src/Rules/DeadCode/CallToConstructorStatementWithoutImpurePointsRule.php', 'PHPStan\\Rules\\DeadCode\\CallToFunctionStatementWithoutImpurePointsRule' => $baseDir . '/src/Rules/DeadCode/CallToFunctionStatementWithoutImpurePointsRule.php', 'PHPStan\\Rules\\DeadCode\\CallToMethodStatementWithoutImpurePointsRule' => $baseDir . '/src/Rules/DeadCode/CallToMethodStatementWithoutImpurePointsRule.php', 'PHPStan\\Rules\\DeadCode\\CallToStaticMethodStatementWithoutImpurePointsRule' => $baseDir . '/src/Rules/DeadCode/CallToStaticMethodStatementWithoutImpurePointsRule.php', 'PHPStan\\Rules\\DeadCode\\ConstructorWithoutImpurePointsCollector' => $baseDir . '/src/Rules/DeadCode/ConstructorWithoutImpurePointsCollector.php', 'PHPStan\\Rules\\DeadCode\\FunctionWithoutImpurePointsCollector' => $baseDir . '/src/Rules/DeadCode/FunctionWithoutImpurePointsCollector.php', 'PHPStan\\Rules\\DeadCode\\MethodWithoutImpurePointsCollector' => $baseDir . '/src/Rules/DeadCode/MethodWithoutImpurePointsCollector.php', 'PHPStan\\Rules\\DeadCode\\NoopRule' => $baseDir . '/src/Rules/DeadCode/NoopRule.php', 'PHPStan\\Rules\\DeadCode\\PossiblyPureFuncCallCollector' => $baseDir . '/src/Rules/DeadCode/PossiblyPureFuncCallCollector.php', 'PHPStan\\Rules\\DeadCode\\PossiblyPureMethodCallCollector' => $baseDir . '/src/Rules/DeadCode/PossiblyPureMethodCallCollector.php', 'PHPStan\\Rules\\DeadCode\\PossiblyPureNewCollector' => $baseDir . '/src/Rules/DeadCode/PossiblyPureNewCollector.php', 'PHPStan\\Rules\\DeadCode\\PossiblyPureStaticCallCollector' => $baseDir . '/src/Rules/DeadCode/PossiblyPureStaticCallCollector.php', 'PHPStan\\Rules\\DeadCode\\UnreachableStatementRule' => $baseDir . '/src/Rules/DeadCode/UnreachableStatementRule.php', 'PHPStan\\Rules\\DeadCode\\UnusedPrivateConstantRule' => $baseDir . '/src/Rules/DeadCode/UnusedPrivateConstantRule.php', 'PHPStan\\Rules\\DeadCode\\UnusedPrivateMethodRule' => $baseDir . '/src/Rules/DeadCode/UnusedPrivateMethodRule.php', 'PHPStan\\Rules\\DeadCode\\UnusedPrivatePropertyRule' => $baseDir . '/src/Rules/DeadCode/UnusedPrivatePropertyRule.php', 'PHPStan\\Rules\\Debug\\DebugScopeRule' => $baseDir . '/src/Rules/Debug/DebugScopeRule.php', 'PHPStan\\Rules\\Debug\\DumpNativeTypeRule' => $baseDir . '/src/Rules/Debug/DumpNativeTypeRule.php', 'PHPStan\\Rules\\Debug\\DumpPhpDocTypeRule' => $baseDir . '/src/Rules/Debug/DumpPhpDocTypeRule.php', 'PHPStan\\Rules\\Debug\\DumpTypeRule' => $baseDir . '/src/Rules/Debug/DumpTypeRule.php', 'PHPStan\\Rules\\Debug\\FileAssertRule' => $baseDir . '/src/Rules/Debug/FileAssertRule.php', 'PHPStan\\Rules\\DirectRegistry' => $baseDir . '/src/Rules/DirectRegistry.php', 'PHPStan\\Rules\\EnumCases\\EnumCaseAttributesRule' => $baseDir . '/src/Rules/EnumCases/EnumCaseAttributesRule.php', 'PHPStan\\Rules\\EnumCases\\EnumCaseOutsideEnumRule' => $baseDir . '/src/Rules/EnumCases/EnumCaseOutsideEnumRule.php', 'PHPStan\\Rules\\Exceptions\\CatchWithUnthrownExceptionRule' => $baseDir . '/src/Rules/Exceptions/CatchWithUnthrownExceptionRule.php', 'PHPStan\\Rules\\Exceptions\\CaughtExceptionExistenceRule' => $baseDir . '/src/Rules/Exceptions/CaughtExceptionExistenceRule.php', 'PHPStan\\Rules\\Exceptions\\DefaultExceptionTypeResolver' => $baseDir . '/src/Rules/Exceptions/DefaultExceptionTypeResolver.php', 'PHPStan\\Rules\\Exceptions\\ExceptionTypeResolver' => $baseDir . '/src/Rules/Exceptions/ExceptionTypeResolver.php', 'PHPStan\\Rules\\Exceptions\\MethodThrowTypeCovarianceRule' => $baseDir . '/src/Rules/Exceptions/MethodThrowTypeCovarianceRule.php', 'PHPStan\\Rules\\Exceptions\\MissingCheckedExceptionInFunctionThrowsRule' => $baseDir . '/src/Rules/Exceptions/MissingCheckedExceptionInFunctionThrowsRule.php', 'PHPStan\\Rules\\Exceptions\\MissingCheckedExceptionInMethodThrowsRule' => $baseDir . '/src/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRule.php', 'PHPStan\\Rules\\Exceptions\\MissingCheckedExceptionInPropertyHookThrowsRule' => $baseDir . '/src/Rules/Exceptions/MissingCheckedExceptionInPropertyHookThrowsRule.php', 'PHPStan\\Rules\\Exceptions\\MissingCheckedExceptionInThrowsCheck' => $baseDir . '/src/Rules/Exceptions/MissingCheckedExceptionInThrowsCheck.php', 'PHPStan\\Rules\\Exceptions\\NoncapturingCatchRule' => $baseDir . '/src/Rules/Exceptions/NoncapturingCatchRule.php', 'PHPStan\\Rules\\Exceptions\\OverwrittenExitPointByFinallyRule' => $baseDir . '/src/Rules/Exceptions/OverwrittenExitPointByFinallyRule.php', 'PHPStan\\Rules\\Exceptions\\ThrowExprTypeRule' => $baseDir . '/src/Rules/Exceptions/ThrowExprTypeRule.php', 'PHPStan\\Rules\\Exceptions\\ThrowExpressionRule' => $baseDir . '/src/Rules/Exceptions/ThrowExpressionRule.php', 'PHPStan\\Rules\\Exceptions\\ThrowsVoidFunctionWithExplicitThrowPointRule' => $baseDir . '/src/Rules/Exceptions/ThrowsVoidFunctionWithExplicitThrowPointRule.php', 'PHPStan\\Rules\\Exceptions\\ThrowsVoidMethodWithExplicitThrowPointRule' => $baseDir . '/src/Rules/Exceptions/ThrowsVoidMethodWithExplicitThrowPointRule.php', 'PHPStan\\Rules\\Exceptions\\ThrowsVoidPropertyHookWithExplicitThrowPointRule' => $baseDir . '/src/Rules/Exceptions/ThrowsVoidPropertyHookWithExplicitThrowPointRule.php', 'PHPStan\\Rules\\Exceptions\\TooWideFunctionThrowTypeRule' => $baseDir . '/src/Rules/Exceptions/TooWideFunctionThrowTypeRule.php', 'PHPStan\\Rules\\Exceptions\\TooWideMethodThrowTypeRule' => $baseDir . '/src/Rules/Exceptions/TooWideMethodThrowTypeRule.php', 'PHPStan\\Rules\\Exceptions\\TooWidePropertyHookThrowTypeRule' => $baseDir . '/src/Rules/Exceptions/TooWidePropertyHookThrowTypeRule.php', 'PHPStan\\Rules\\Exceptions\\TooWideThrowTypeCheck' => $baseDir . '/src/Rules/Exceptions/TooWideThrowTypeCheck.php', 'PHPStan\\Rules\\FileRuleError' => $baseDir . '/src/Rules/FileRuleError.php', 'PHPStan\\Rules\\FixableNodeRuleError' => $baseDir . '/src/Rules/FixableNodeRuleError.php', 'PHPStan\\Rules\\FoundTypeResult' => $baseDir . '/src/Rules/FoundTypeResult.php', 'PHPStan\\Rules\\FunctionCallParametersCheck' => $baseDir . '/src/Rules/FunctionCallParametersCheck.php', 'PHPStan\\Rules\\FunctionDefinitionCheck' => $baseDir . '/src/Rules/FunctionDefinitionCheck.php', 'PHPStan\\Rules\\FunctionReturnTypeCheck' => $baseDir . '/src/Rules/FunctionReturnTypeCheck.php', 'PHPStan\\Rules\\Functions\\ArrayFilterRule' => $baseDir . '/src/Rules/Functions/ArrayFilterRule.php', 'PHPStan\\Rules\\Functions\\ArrayValuesRule' => $baseDir . '/src/Rules/Functions/ArrayValuesRule.php', 'PHPStan\\Rules\\Functions\\ArrowFunctionAttributesRule' => $baseDir . '/src/Rules/Functions/ArrowFunctionAttributesRule.php', 'PHPStan\\Rules\\Functions\\ArrowFunctionReturnNullsafeByRefRule' => $baseDir . '/src/Rules/Functions/ArrowFunctionReturnNullsafeByRefRule.php', 'PHPStan\\Rules\\Functions\\ArrowFunctionReturnTypeRule' => $baseDir . '/src/Rules/Functions/ArrowFunctionReturnTypeRule.php', 'PHPStan\\Rules\\Functions\\CallCallablesRule' => $baseDir . '/src/Rules/Functions/CallCallablesRule.php', 'PHPStan\\Rules\\Functions\\CallToFunctionParametersRule' => $baseDir . '/src/Rules/Functions/CallToFunctionParametersRule.php', 'PHPStan\\Rules\\Functions\\CallToFunctionStatementWithNoDiscardRule' => $baseDir . '/src/Rules/Functions/CallToFunctionStatementWithNoDiscardRule.php', 'PHPStan\\Rules\\Functions\\CallToFunctionStatementWithoutSideEffectsRule' => $baseDir . '/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php', 'PHPStan\\Rules\\Functions\\CallToNonExistentFunctionRule' => $baseDir . '/src/Rules/Functions/CallToNonExistentFunctionRule.php', 'PHPStan\\Rules\\Functions\\CallUserFuncRule' => $baseDir . '/src/Rules/Functions/CallUserFuncRule.php', 'PHPStan\\Rules\\Functions\\ClosureAttributesRule' => $baseDir . '/src/Rules/Functions/ClosureAttributesRule.php', 'PHPStan\\Rules\\Functions\\ClosureReturnTypeRule' => $baseDir . '/src/Rules/Functions/ClosureReturnTypeRule.php', 'PHPStan\\Rules\\Functions\\DefineParametersRule' => $baseDir . '/src/Rules/Functions/DefineParametersRule.php', 'PHPStan\\Rules\\Functions\\DuplicateFunctionDeclarationRule' => $baseDir . '/src/Rules/Functions/DuplicateFunctionDeclarationRule.php', 'PHPStan\\Rules\\Functions\\ExistingClassesInArrowFunctionTypehintsRule' => $baseDir . '/src/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRule.php', 'PHPStan\\Rules\\Functions\\ExistingClassesInClosureTypehintsRule' => $baseDir . '/src/Rules/Functions/ExistingClassesInClosureTypehintsRule.php', 'PHPStan\\Rules\\Functions\\ExistingClassesInTypehintsRule' => $baseDir . '/src/Rules/Functions/ExistingClassesInTypehintsRule.php', 'PHPStan\\Rules\\Functions\\FilterVarRule' => $baseDir . '/src/Rules/Functions/FilterVarRule.php', 'PHPStan\\Rules\\Functions\\FunctionAttributesRule' => $baseDir . '/src/Rules/Functions/FunctionAttributesRule.php', 'PHPStan\\Rules\\Functions\\FunctionCallableRule' => $baseDir . '/src/Rules/Functions/FunctionCallableRule.php', 'PHPStan\\Rules\\Functions\\ImplodeParameterCastableToStringRule' => $baseDir . '/src/Rules/Functions/ImplodeParameterCastableToStringRule.php', 'PHPStan\\Rules\\Functions\\IncompatibleArrowFunctionDefaultParameterTypeRule' => $baseDir . '/src/Rules/Functions/IncompatibleArrowFunctionDefaultParameterTypeRule.php', 'PHPStan\\Rules\\Functions\\IncompatibleClosureDefaultParameterTypeRule' => $baseDir . '/src/Rules/Functions/IncompatibleClosureDefaultParameterTypeRule.php', 'PHPStan\\Rules\\Functions\\IncompatibleDefaultParameterTypeRule' => $baseDir . '/src/Rules/Functions/IncompatibleDefaultParameterTypeRule.php', 'PHPStan\\Rules\\Functions\\InnerFunctionRule' => $baseDir . '/src/Rules/Functions/InnerFunctionRule.php', 'PHPStan\\Rules\\Functions\\InvalidLexicalVariablesInClosureUseRule' => $baseDir . '/src/Rules/Functions/InvalidLexicalVariablesInClosureUseRule.php', 'PHPStan\\Rules\\Functions\\InvalidParameterNameRule' => $baseDir . '/src/Rules/Functions/InvalidParameterNameRule.php', 'PHPStan\\Rules\\Functions\\MissingFunctionParameterTypehintRule' => $baseDir . '/src/Rules/Functions/MissingFunctionParameterTypehintRule.php', 'PHPStan\\Rules\\Functions\\MissingFunctionReturnTypehintRule' => $baseDir . '/src/Rules/Functions/MissingFunctionReturnTypehintRule.php', 'PHPStan\\Rules\\Functions\\ParamAttributesRule' => $baseDir . '/src/Rules/Functions/ParamAttributesRule.php', 'PHPStan\\Rules\\Functions\\ParameterCastableToNumberRule' => $baseDir . '/src/Rules/Functions/ParameterCastableToNumberRule.php', 'PHPStan\\Rules\\Functions\\ParameterCastableToStringRule' => $baseDir . '/src/Rules/Functions/ParameterCastableToStringRule.php', 'PHPStan\\Rules\\Functions\\PrintfArrayParametersRule' => $baseDir . '/src/Rules/Functions/PrintfArrayParametersRule.php', 'PHPStan\\Rules\\Functions\\PrintfHelper' => $baseDir . '/src/Rules/Functions/PrintfHelper.php', 'PHPStan\\Rules\\Functions\\PrintfParameterTypeRule' => $baseDir . '/src/Rules/Functions/PrintfParameterTypeRule.php', 'PHPStan\\Rules\\Functions\\PrintfParametersRule' => $baseDir . '/src/Rules/Functions/PrintfParametersRule.php', 'PHPStan\\Rules\\Functions\\PrintfPlaceholder' => $baseDir . '/src/Rules/Functions/PrintfPlaceholder.php', 'PHPStan\\Rules\\Functions\\RandomIntParametersRule' => $baseDir . '/src/Rules/Functions/RandomIntParametersRule.php', 'PHPStan\\Rules\\Functions\\RedefinedParametersRule' => $baseDir . '/src/Rules/Functions/RedefinedParametersRule.php', 'PHPStan\\Rules\\Functions\\ReturnNullsafeByRefRule' => $baseDir . '/src/Rules/Functions/ReturnNullsafeByRefRule.php', 'PHPStan\\Rules\\Functions\\ReturnTypeRule' => $baseDir . '/src/Rules/Functions/ReturnTypeRule.php', 'PHPStan\\Rules\\Functions\\SortParameterCastableToStringRule' => $baseDir . '/src/Rules/Functions/SortParameterCastableToStringRule.php', 'PHPStan\\Rules\\Functions\\UnusedClosureUsesRule' => $baseDir . '/src/Rules/Functions/UnusedClosureUsesRule.php', 'PHPStan\\Rules\\Functions\\UselessFunctionReturnValueRule' => $baseDir . '/src/Rules/Functions/UselessFunctionReturnValueRule.php', 'PHPStan\\Rules\\Functions\\VariadicParametersDeclarationRule' => $baseDir . '/src/Rules/Functions/VariadicParametersDeclarationRule.php', 'PHPStan\\Rules\\Generators\\YieldFromTypeRule' => $baseDir . '/src/Rules/Generators/YieldFromTypeRule.php', 'PHPStan\\Rules\\Generators\\YieldInGeneratorRule' => $baseDir . '/src/Rules/Generators/YieldInGeneratorRule.php', 'PHPStan\\Rules\\Generators\\YieldTypeRule' => $baseDir . '/src/Rules/Generators/YieldTypeRule.php', 'PHPStan\\Rules\\Generics\\ClassAncestorsRule' => $baseDir . '/src/Rules/Generics/ClassAncestorsRule.php', 'PHPStan\\Rules\\Generics\\ClassTemplateTypeRule' => $baseDir . '/src/Rules/Generics/ClassTemplateTypeRule.php', 'PHPStan\\Rules\\Generics\\CrossCheckInterfacesHelper' => $baseDir . '/src/Rules/Generics/CrossCheckInterfacesHelper.php', 'PHPStan\\Rules\\Generics\\EnumAncestorsRule' => $baseDir . '/src/Rules/Generics/EnumAncestorsRule.php', 'PHPStan\\Rules\\Generics\\EnumTemplateTypeRule' => $baseDir . '/src/Rules/Generics/EnumTemplateTypeRule.php', 'PHPStan\\Rules\\Generics\\FunctionSignatureVarianceRule' => $baseDir . '/src/Rules/Generics/FunctionSignatureVarianceRule.php', 'PHPStan\\Rules\\Generics\\FunctionTemplateTypeRule' => $baseDir . '/src/Rules/Generics/FunctionTemplateTypeRule.php', 'PHPStan\\Rules\\Generics\\GenericAncestorsCheck' => $baseDir . '/src/Rules/Generics/GenericAncestorsCheck.php', 'PHPStan\\Rules\\Generics\\GenericObjectTypeCheck' => $baseDir . '/src/Rules/Generics/GenericObjectTypeCheck.php', 'PHPStan\\Rules\\Generics\\InterfaceAncestorsRule' => $baseDir . '/src/Rules/Generics/InterfaceAncestorsRule.php', 'PHPStan\\Rules\\Generics\\InterfaceTemplateTypeRule' => $baseDir . '/src/Rules/Generics/InterfaceTemplateTypeRule.php', 'PHPStan\\Rules\\Generics\\MethodSignatureVarianceRule' => $baseDir . '/src/Rules/Generics/MethodSignatureVarianceRule.php', 'PHPStan\\Rules\\Generics\\MethodTagTemplateTypeCheck' => $baseDir . '/src/Rules/Generics/MethodTagTemplateTypeCheck.php', 'PHPStan\\Rules\\Generics\\MethodTagTemplateTypeRule' => $baseDir . '/src/Rules/Generics/MethodTagTemplateTypeRule.php', 'PHPStan\\Rules\\Generics\\MethodTagTemplateTypeTraitRule' => $baseDir . '/src/Rules/Generics/MethodTagTemplateTypeTraitRule.php', 'PHPStan\\Rules\\Generics\\MethodTemplateTypeRule' => $baseDir . '/src/Rules/Generics/MethodTemplateTypeRule.php', 'PHPStan\\Rules\\Generics\\PropertyVarianceRule' => $baseDir . '/src/Rules/Generics/PropertyVarianceRule.php', 'PHPStan\\Rules\\Generics\\TemplateTypeCheck' => $baseDir . '/src/Rules/Generics/TemplateTypeCheck.php', 'PHPStan\\Rules\\Generics\\TraitTemplateTypeRule' => $baseDir . '/src/Rules/Generics/TraitTemplateTypeRule.php', 'PHPStan\\Rules\\Generics\\UsedTraitsRule' => $baseDir . '/src/Rules/Generics/UsedTraitsRule.php', 'PHPStan\\Rules\\Generics\\VarianceCheck' => $baseDir . '/src/Rules/Generics/VarianceCheck.php', 'PHPStan\\Rules\\IdentifierRuleError' => $baseDir . '/src/Rules/IdentifierRuleError.php', 'PHPStan\\Rules\\Ignore\\IgnoreParseErrorRule' => $baseDir . '/src/Rules/Ignore/IgnoreParseErrorRule.php', 'PHPStan\\Rules\\InternalTag\\RestrictedInternalClassConstantUsageExtension' => $baseDir . '/src/Rules/InternalTag/RestrictedInternalClassConstantUsageExtension.php', 'PHPStan\\Rules\\InternalTag\\RestrictedInternalClassNameUsageExtension' => $baseDir . '/src/Rules/InternalTag/RestrictedInternalClassNameUsageExtension.php', 'PHPStan\\Rules\\InternalTag\\RestrictedInternalFunctionUsageExtension' => $baseDir . '/src/Rules/InternalTag/RestrictedInternalFunctionUsageExtension.php', 'PHPStan\\Rules\\InternalTag\\RestrictedInternalMethodUsageExtension' => $baseDir . '/src/Rules/InternalTag/RestrictedInternalMethodUsageExtension.php', 'PHPStan\\Rules\\InternalTag\\RestrictedInternalPropertyUsageExtension' => $baseDir . '/src/Rules/InternalTag/RestrictedInternalPropertyUsageExtension.php', 'PHPStan\\Rules\\InternalTag\\RestrictedInternalUsageHelper' => $baseDir . '/src/Rules/InternalTag/RestrictedInternalUsageHelper.php', 'PHPStan\\Rules\\IssetCheck' => $baseDir . '/src/Rules/IssetCheck.php', 'PHPStan\\Rules\\Keywords\\ContinueBreakInLoopRule' => $baseDir . '/src/Rules/Keywords/ContinueBreakInLoopRule.php', 'PHPStan\\Rules\\Keywords\\DeclareStrictTypesRule' => $baseDir . '/src/Rules/Keywords/DeclareStrictTypesRule.php', 'PHPStan\\Rules\\Keywords\\RequireFileExistsRule' => $baseDir . '/src/Rules/Keywords/RequireFileExistsRule.php', 'PHPStan\\Rules\\LazyRegistry' => $baseDir . '/src/Rules/LazyRegistry.php', 'PHPStan\\Rules\\LineRuleError' => $baseDir . '/src/Rules/LineRuleError.php', 'PHPStan\\Rules\\MetadataRuleError' => $baseDir . '/src/Rules/MetadataRuleError.php', 'PHPStan\\Rules\\Methods\\AbstractMethodInNonAbstractClassRule' => $baseDir . '/src/Rules/Methods/AbstractMethodInNonAbstractClassRule.php', 'PHPStan\\Rules\\Methods\\AbstractPrivateMethodRule' => $baseDir . '/src/Rules/Methods/AbstractPrivateMethodRule.php', 'PHPStan\\Rules\\Methods\\AlwaysUsedMethodExtension' => $baseDir . '/src/Rules/Methods/AlwaysUsedMethodExtension.php', 'PHPStan\\Rules\\Methods\\AlwaysUsedMethodExtensionProvider' => $baseDir . '/src/Rules/Methods/AlwaysUsedMethodExtensionProvider.php', 'PHPStan\\Rules\\Methods\\CallMethodsRule' => $baseDir . '/src/Rules/Methods/CallMethodsRule.php', 'PHPStan\\Rules\\Methods\\CallPrivateMethodThroughStaticRule' => $baseDir . '/src/Rules/Methods/CallPrivateMethodThroughStaticRule.php', 'PHPStan\\Rules\\Methods\\CallStaticMethodsRule' => $baseDir . '/src/Rules/Methods/CallStaticMethodsRule.php', 'PHPStan\\Rules\\Methods\\CallToConstructorStatementWithoutSideEffectsRule' => $baseDir . '/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php', 'PHPStan\\Rules\\Methods\\CallToMethodStatementWithNoDiscardRule' => $baseDir . '/src/Rules/Methods/CallToMethodStatementWithNoDiscardRule.php', 'PHPStan\\Rules\\Methods\\CallToMethodStatementWithoutSideEffectsRule' => $baseDir . '/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php', 'PHPStan\\Rules\\Methods\\CallToStaticMethodStatementWithNoDiscardRule' => $baseDir . '/src/Rules/Methods/CallToStaticMethodStatementWithNoDiscardRule.php', 'PHPStan\\Rules\\Methods\\CallToStaticMethodStatementWithoutSideEffectsRule' => $baseDir . '/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php', 'PHPStan\\Rules\\Methods\\ConsistentConstructorDeclarationRule' => $baseDir . '/src/Rules/Methods/ConsistentConstructorDeclarationRule.php', 'PHPStan\\Rules\\Methods\\ConsistentConstructorRule' => $baseDir . '/src/Rules/Methods/ConsistentConstructorRule.php', 'PHPStan\\Rules\\Methods\\ConstructorReturnTypeRule' => $baseDir . '/src/Rules/Methods/ConstructorReturnTypeRule.php', 'PHPStan\\Rules\\Methods\\DirectAlwaysUsedMethodExtensionProvider' => $baseDir . '/src/Rules/Methods/DirectAlwaysUsedMethodExtensionProvider.php', 'PHPStan\\Rules\\Methods\\ExistingClassesInTypehintsRule' => $baseDir . '/src/Rules/Methods/ExistingClassesInTypehintsRule.php', 'PHPStan\\Rules\\Methods\\FinalPrivateMethodRule' => $baseDir . '/src/Rules/Methods/FinalPrivateMethodRule.php', 'PHPStan\\Rules\\Methods\\IncompatibleDefaultParameterTypeRule' => $baseDir . '/src/Rules/Methods/IncompatibleDefaultParameterTypeRule.php', 'PHPStan\\Rules\\Methods\\LazyAlwaysUsedMethodExtensionProvider' => $baseDir . '/src/Rules/Methods/LazyAlwaysUsedMethodExtensionProvider.php', 'PHPStan\\Rules\\Methods\\MethodAttributesRule' => $baseDir . '/src/Rules/Methods/MethodAttributesRule.php', 'PHPStan\\Rules\\Methods\\MethodCallCheck' => $baseDir . '/src/Rules/Methods/MethodCallCheck.php', 'PHPStan\\Rules\\Methods\\MethodCallableRule' => $baseDir . '/src/Rules/Methods/MethodCallableRule.php', 'PHPStan\\Rules\\Methods\\MethodParameterComparisonHelper' => $baseDir . '/src/Rules/Methods/MethodParameterComparisonHelper.php', 'PHPStan\\Rules\\Methods\\MethodPrototypeFinder' => $baseDir . '/src/Rules/Methods/MethodPrototypeFinder.php', 'PHPStan\\Rules\\Methods\\MethodSignatureRule' => $baseDir . '/src/Rules/Methods/MethodSignatureRule.php', 'PHPStan\\Rules\\Methods\\MethodVisibilityComparisonHelper' => $baseDir . '/src/Rules/Methods/MethodVisibilityComparisonHelper.php', 'PHPStan\\Rules\\Methods\\MethodVisibilityInInterfaceRule' => $baseDir . '/src/Rules/Methods/MethodVisibilityInInterfaceRule.php', 'PHPStan\\Rules\\Methods\\MissingMagicSerializationMethodsRule' => $baseDir . '/src/Rules/Methods/MissingMagicSerializationMethodsRule.php', 'PHPStan\\Rules\\Methods\\MissingMethodImplementationRule' => $baseDir . '/src/Rules/Methods/MissingMethodImplementationRule.php', 'PHPStan\\Rules\\Methods\\MissingMethodParameterTypehintRule' => $baseDir . '/src/Rules/Methods/MissingMethodParameterTypehintRule.php', 'PHPStan\\Rules\\Methods\\MissingMethodReturnTypehintRule' => $baseDir . '/src/Rules/Methods/MissingMethodReturnTypehintRule.php', 'PHPStan\\Rules\\Methods\\MissingMethodSelfOutTypeRule' => $baseDir . '/src/Rules/Methods/MissingMethodSelfOutTypeRule.php', 'PHPStan\\Rules\\Methods\\NullsafeMethodCallRule' => $baseDir . '/src/Rules/Methods/NullsafeMethodCallRule.php', 'PHPStan\\Rules\\Methods\\OverridingMethodRule' => $baseDir . '/src/Rules/Methods/OverridingMethodRule.php', 'PHPStan\\Rules\\Methods\\ParentMethodHelper' => $baseDir . '/src/Rules/Methods/ParentMethodHelper.php', 'PHPStan\\Rules\\Methods\\ReturnTypeRule' => $baseDir . '/src/Rules/Methods/ReturnTypeRule.php', 'PHPStan\\Rules\\Methods\\StaticMethodCallCheck' => $baseDir . '/src/Rules/Methods/StaticMethodCallCheck.php', 'PHPStan\\Rules\\Methods\\StaticMethodCallableRule' => $baseDir . '/src/Rules/Methods/StaticMethodCallableRule.php', 'PHPStan\\Rules\\MissingTypehintCheck' => $baseDir . '/src/Rules/MissingTypehintCheck.php', 'PHPStan\\Rules\\Missing\\MissingReturnRule' => $baseDir . '/src/Rules/Missing/MissingReturnRule.php', 'PHPStan\\Rules\\Names\\UsedNamesRule' => $baseDir . '/src/Rules/Names/UsedNamesRule.php', 'PHPStan\\Rules\\Namespaces\\ExistingNamesInGroupUseRule' => $baseDir . '/src/Rules/Namespaces/ExistingNamesInGroupUseRule.php', 'PHPStan\\Rules\\Namespaces\\ExistingNamesInUseRule' => $baseDir . '/src/Rules/Namespaces/ExistingNamesInUseRule.php', 'PHPStan\\Rules\\NonIgnorableRuleError' => $baseDir . '/src/Rules/NonIgnorableRuleError.php', 'PHPStan\\Rules\\NullsafeCheck' => $baseDir . '/src/Rules/NullsafeCheck.php', 'PHPStan\\Rules\\Operators\\BacktickRule' => $baseDir . '/src/Rules/Operators/BacktickRule.php', 'PHPStan\\Rules\\Operators\\InvalidAssignVarRule' => $baseDir . '/src/Rules/Operators/InvalidAssignVarRule.php', 'PHPStan\\Rules\\Operators\\InvalidBinaryOperationRule' => $baseDir . '/src/Rules/Operators/InvalidBinaryOperationRule.php', 'PHPStan\\Rules\\Operators\\InvalidComparisonOperationRule' => $baseDir . '/src/Rules/Operators/InvalidComparisonOperationRule.php', 'PHPStan\\Rules\\Operators\\InvalidIncDecOperationRule' => $baseDir . '/src/Rules/Operators/InvalidIncDecOperationRule.php', 'PHPStan\\Rules\\Operators\\InvalidUnaryOperationRule' => $baseDir . '/src/Rules/Operators/InvalidUnaryOperationRule.php', 'PHPStan\\Rules\\Operators\\PipeOperatorRule' => $baseDir . '/src/Rules/Operators/PipeOperatorRule.php', 'PHPStan\\Rules\\ParameterCastableToStringCheck' => $baseDir . '/src/Rules/ParameterCastableToStringCheck.php', 'PHPStan\\Rules\\PhpDoc\\AssertRuleHelper' => $baseDir . '/src/Rules/PhpDoc/AssertRuleHelper.php', 'PHPStan\\Rules\\PhpDoc\\ConditionalReturnTypeRuleHelper' => $baseDir . '/src/Rules/PhpDoc/ConditionalReturnTypeRuleHelper.php', 'PHPStan\\Rules\\PhpDoc\\FunctionAssertRule' => $baseDir . '/src/Rules/PhpDoc/FunctionAssertRule.php', 'PHPStan\\Rules\\PhpDoc\\FunctionConditionalReturnTypeRule' => $baseDir . '/src/Rules/PhpDoc/FunctionConditionalReturnTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\GenericCallableRuleHelper' => $baseDir . '/src/Rules/PhpDoc/GenericCallableRuleHelper.php', 'PHPStan\\Rules\\PhpDoc\\IncompatibleClassConstantPhpDocTypeRule' => $baseDir . '/src/Rules/PhpDoc/IncompatibleClassConstantPhpDocTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\IncompatibleParamImmediatelyInvokedCallableRule' => $baseDir . '/src/Rules/PhpDoc/IncompatibleParamImmediatelyInvokedCallableRule.php', 'PHPStan\\Rules\\PhpDoc\\IncompatiblePhpDocTypeCheck' => $baseDir . '/src/Rules/PhpDoc/IncompatiblePhpDocTypeCheck.php', 'PHPStan\\Rules\\PhpDoc\\IncompatiblePhpDocTypeRule' => $baseDir . '/src/Rules/PhpDoc/IncompatiblePhpDocTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\IncompatiblePropertyHookPhpDocTypeRule' => $baseDir . '/src/Rules/PhpDoc/IncompatiblePropertyHookPhpDocTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\IncompatiblePropertyPhpDocTypeRule' => $baseDir . '/src/Rules/PhpDoc/IncompatiblePropertyPhpDocTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\IncompatibleSelfOutTypeRule' => $baseDir . '/src/Rules/PhpDoc/IncompatibleSelfOutTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\InvalidPHPStanDocTagRule' => $baseDir . '/src/Rules/PhpDoc/InvalidPHPStanDocTagRule.php', 'PHPStan\\Rules\\PhpDoc\\InvalidPhpDocTagValueRule' => $baseDir . '/src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php', 'PHPStan\\Rules\\PhpDoc\\InvalidPhpDocVarTagTypeRule' => $baseDir . '/src/Rules/PhpDoc/InvalidPhpDocVarTagTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\InvalidThrowsPhpDocValueRule' => $baseDir . '/src/Rules/PhpDoc/InvalidThrowsPhpDocValueRule.php', 'PHPStan\\Rules\\PhpDoc\\MethodAssertRule' => $baseDir . '/src/Rules/PhpDoc/MethodAssertRule.php', 'PHPStan\\Rules\\PhpDoc\\MethodConditionalReturnTypeRule' => $baseDir . '/src/Rules/PhpDoc/MethodConditionalReturnTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\PhpDocLineHelper' => $baseDir . '/src/Rules/PhpDoc/PhpDocLineHelper.php', 'PHPStan\\Rules\\PhpDoc\\RequireExtendsCheck' => $baseDir . '/src/Rules/PhpDoc/RequireExtendsCheck.php', 'PHPStan\\Rules\\PhpDoc\\RequireExtendsDefinitionClassRule' => $baseDir . '/src/Rules/PhpDoc/RequireExtendsDefinitionClassRule.php', 'PHPStan\\Rules\\PhpDoc\\RequireExtendsDefinitionTraitRule' => $baseDir . '/src/Rules/PhpDoc/RequireExtendsDefinitionTraitRule.php', 'PHPStan\\Rules\\PhpDoc\\RequireImplementsDefinitionClassRule' => $baseDir . '/src/Rules/PhpDoc/RequireImplementsDefinitionClassRule.php', 'PHPStan\\Rules\\PhpDoc\\RequireImplementsDefinitionTraitRule' => $baseDir . '/src/Rules/PhpDoc/RequireImplementsDefinitionTraitRule.php', 'PHPStan\\Rules\\PhpDoc\\SealedDefinitionClassRule' => $baseDir . '/src/Rules/PhpDoc/SealedDefinitionClassRule.php', 'PHPStan\\Rules\\PhpDoc\\SealedDefinitionTraitRule' => $baseDir . '/src/Rules/PhpDoc/SealedDefinitionTraitRule.php', 'PHPStan\\Rules\\PhpDoc\\UnresolvableTypeHelper' => $baseDir . '/src/Rules/PhpDoc/UnresolvableTypeHelper.php', 'PHPStan\\Rules\\PhpDoc\\VarTagChangedExpressionTypeRule' => $baseDir . '/src/Rules/PhpDoc/VarTagChangedExpressionTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\VarTagTypeRuleHelper' => $baseDir . '/src/Rules/PhpDoc/VarTagTypeRuleHelper.php', 'PHPStan\\Rules\\PhpDoc\\WrongVariableNameInVarTagRule' => $baseDir . '/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php', 'PHPStan\\Rules\\Playground\\FunctionNeverRule' => $baseDir . '/src/Rules/Playground/FunctionNeverRule.php', 'PHPStan\\Rules\\Playground\\MethodNeverRule' => $baseDir . '/src/Rules/Playground/MethodNeverRule.php', 'PHPStan\\Rules\\Playground\\NeverRuleHelper' => $baseDir . '/src/Rules/Playground/NeverRuleHelper.php', 'PHPStan\\Rules\\Playground\\NoPhpCodeRule' => $baseDir . '/src/Rules/Playground/NoPhpCodeRule.php', 'PHPStan\\Rules\\Playground\\NotAnalysedTraitRule' => $baseDir . '/src/Rules/Playground/NotAnalysedTraitRule.php', 'PHPStan\\Rules\\Playground\\PhpdocCommentRule' => $baseDir . '/src/Rules/Playground/PhpdocCommentRule.php', 'PHPStan\\Rules\\Playground\\PromoteParameterRule' => $baseDir . '/src/Rules/Playground/PromoteParameterRule.php', 'PHPStan\\Rules\\Playground\\StaticVarWithoutTypeRule' => $baseDir . '/src/Rules/Playground/StaticVarWithoutTypeRule.php', 'PHPStan\\Rules\\Properties\\AccessPrivatePropertyThroughStaticRule' => $baseDir . '/src/Rules/Properties/AccessPrivatePropertyThroughStaticRule.php', 'PHPStan\\Rules\\Properties\\AccessPropertiesCheck' => $baseDir . '/src/Rules/Properties/AccessPropertiesCheck.php', 'PHPStan\\Rules\\Properties\\AccessPropertiesInAssignRule' => $baseDir . '/src/Rules/Properties/AccessPropertiesInAssignRule.php', 'PHPStan\\Rules\\Properties\\AccessPropertiesRule' => $baseDir . '/src/Rules/Properties/AccessPropertiesRule.php', 'PHPStan\\Rules\\Properties\\AccessStaticPropertiesCheck' => $baseDir . '/src/Rules/Properties/AccessStaticPropertiesCheck.php', 'PHPStan\\Rules\\Properties\\AccessStaticPropertiesInAssignRule' => $baseDir . '/src/Rules/Properties/AccessStaticPropertiesInAssignRule.php', 'PHPStan\\Rules\\Properties\\AccessStaticPropertiesRule' => $baseDir . '/src/Rules/Properties/AccessStaticPropertiesRule.php', 'PHPStan\\Rules\\Properties\\DefaultValueTypesAssignedToPropertiesRule' => $baseDir . '/src/Rules/Properties/DefaultValueTypesAssignedToPropertiesRule.php', 'PHPStan\\Rules\\Properties\\DirectReadWritePropertiesExtensionProvider' => $baseDir . '/src/Rules/Properties/DirectReadWritePropertiesExtensionProvider.php', 'PHPStan\\Rules\\Properties\\ExistingClassesInPropertiesRule' => $baseDir . '/src/Rules/Properties/ExistingClassesInPropertiesRule.php', 'PHPStan\\Rules\\Properties\\ExistingClassesInPropertyHookTypehintsRule' => $baseDir . '/src/Rules/Properties/ExistingClassesInPropertyHookTypehintsRule.php', 'PHPStan\\Rules\\Properties\\FoundPropertyReflection' => $baseDir . '/src/Rules/Properties/FoundPropertyReflection.php', 'PHPStan\\Rules\\Properties\\GetNonVirtualPropertyHookReadRule' => $baseDir . '/src/Rules/Properties/GetNonVirtualPropertyHookReadRule.php', 'PHPStan\\Rules\\Properties\\InvalidCallablePropertyTypeRule' => $baseDir . '/src/Rules/Properties/InvalidCallablePropertyTypeRule.php', 'PHPStan\\Rules\\Properties\\LazyReadWritePropertiesExtensionProvider' => $baseDir . '/src/Rules/Properties/LazyReadWritePropertiesExtensionProvider.php', 'PHPStan\\Rules\\Properties\\MissingPropertyTypehintRule' => $baseDir . '/src/Rules/Properties/MissingPropertyTypehintRule.php', 'PHPStan\\Rules\\Properties\\MissingReadOnlyByPhpDocPropertyAssignRule' => $baseDir . '/src/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRule.php', 'PHPStan\\Rules\\Properties\\MissingReadOnlyPropertyAssignRule' => $baseDir . '/src/Rules/Properties/MissingReadOnlyPropertyAssignRule.php', 'PHPStan\\Rules\\Properties\\NullsafePropertyFetchRule' => $baseDir . '/src/Rules/Properties/NullsafePropertyFetchRule.php', 'PHPStan\\Rules\\Properties\\OverridingPropertyRule' => $baseDir . '/src/Rules/Properties/OverridingPropertyRule.php', 'PHPStan\\Rules\\Properties\\PropertiesInInterfaceRule' => $baseDir . '/src/Rules/Properties/PropertiesInInterfaceRule.php', 'PHPStan\\Rules\\Properties\\PropertyAssignRefRule' => $baseDir . '/src/Rules/Properties/PropertyAssignRefRule.php', 'PHPStan\\Rules\\Properties\\PropertyAttributesRule' => $baseDir . '/src/Rules/Properties/PropertyAttributesRule.php', 'PHPStan\\Rules\\Properties\\PropertyDescriptor' => $baseDir . '/src/Rules/Properties/PropertyDescriptor.php', 'PHPStan\\Rules\\Properties\\PropertyHookAttributesRule' => $baseDir . '/src/Rules/Properties/PropertyHookAttributesRule.php', 'PHPStan\\Rules\\Properties\\PropertyInClassRule' => $baseDir . '/src/Rules/Properties/PropertyInClassRule.php', 'PHPStan\\Rules\\Properties\\PropertyReflectionFinder' => $baseDir . '/src/Rules/Properties/PropertyReflectionFinder.php', 'PHPStan\\Rules\\Properties\\ReadOnlyByPhpDocPropertyAssignRefRule' => $baseDir . '/src/Rules/Properties/ReadOnlyByPhpDocPropertyAssignRefRule.php', 'PHPStan\\Rules\\Properties\\ReadOnlyByPhpDocPropertyAssignRule' => $baseDir . '/src/Rules/Properties/ReadOnlyByPhpDocPropertyAssignRule.php', 'PHPStan\\Rules\\Properties\\ReadOnlyByPhpDocPropertyRule' => $baseDir . '/src/Rules/Properties/ReadOnlyByPhpDocPropertyRule.php', 'PHPStan\\Rules\\Properties\\ReadOnlyPropertyAssignRefRule' => $baseDir . '/src/Rules/Properties/ReadOnlyPropertyAssignRefRule.php', 'PHPStan\\Rules\\Properties\\ReadOnlyPropertyAssignRule' => $baseDir . '/src/Rules/Properties/ReadOnlyPropertyAssignRule.php', 'PHPStan\\Rules\\Properties\\ReadOnlyPropertyRule' => $baseDir . '/src/Rules/Properties/ReadOnlyPropertyRule.php', 'PHPStan\\Rules\\Properties\\ReadWritePropertiesExtension' => $baseDir . '/src/Rules/Properties/ReadWritePropertiesExtension.php', 'PHPStan\\Rules\\Properties\\ReadWritePropertiesExtensionProvider' => $baseDir . '/src/Rules/Properties/ReadWritePropertiesExtensionProvider.php', 'PHPStan\\Rules\\Properties\\ReadingWriteOnlyPropertiesRule' => $baseDir . '/src/Rules/Properties/ReadingWriteOnlyPropertiesRule.php', 'PHPStan\\Rules\\Properties\\SetNonVirtualPropertyHookAssignRule' => $baseDir . '/src/Rules/Properties/SetNonVirtualPropertyHookAssignRule.php', 'PHPStan\\Rules\\Properties\\SetPropertyHookParameterRule' => $baseDir . '/src/Rules/Properties/SetPropertyHookParameterRule.php', 'PHPStan\\Rules\\Properties\\TypesAssignedToPropertiesRule' => $baseDir . '/src/Rules/Properties/TypesAssignedToPropertiesRule.php', 'PHPStan\\Rules\\Properties\\UninitializedPropertyRule' => $baseDir . '/src/Rules/Properties/UninitializedPropertyRule.php', 'PHPStan\\Rules\\Properties\\WritingToReadOnlyPropertiesRule' => $baseDir . '/src/Rules/Properties/WritingToReadOnlyPropertiesRule.php', 'PHPStan\\Rules\\Pure\\FunctionPurityCheck' => $baseDir . '/src/Rules/Pure/FunctionPurityCheck.php', 'PHPStan\\Rules\\Pure\\PureFunctionRule' => $baseDir . '/src/Rules/Pure/PureFunctionRule.php', 'PHPStan\\Rules\\Pure\\PureMethodRule' => $baseDir . '/src/Rules/Pure/PureMethodRule.php', 'PHPStan\\Rules\\Regexp\\RegularExpressionPatternRule' => $baseDir . '/src/Rules/Regexp/RegularExpressionPatternRule.php', 'PHPStan\\Rules\\Regexp\\RegularExpressionQuotingRule' => $baseDir . '/src/Rules/Regexp/RegularExpressionQuotingRule.php', 'PHPStan\\Rules\\Registry' => $baseDir . '/src/Rules/Registry.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedClassConstantUsageExtension' => $baseDir . '/src/Rules/RestrictedUsage/RestrictedClassConstantUsageExtension.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedClassConstantUsageRule' => $baseDir . '/src/Rules/RestrictedUsage/RestrictedClassConstantUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedClassNameUsageExtension' => $baseDir . '/src/Rules/RestrictedUsage/RestrictedClassNameUsageExtension.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedFunctionCallableUsageRule' => $baseDir . '/src/Rules/RestrictedUsage/RestrictedFunctionCallableUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedFunctionUsageExtension' => $baseDir . '/src/Rules/RestrictedUsage/RestrictedFunctionUsageExtension.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedFunctionUsageRule' => $baseDir . '/src/Rules/RestrictedUsage/RestrictedFunctionUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedMethodCallableUsageRule' => $baseDir . '/src/Rules/RestrictedUsage/RestrictedMethodCallableUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedMethodUsageExtension' => $baseDir . '/src/Rules/RestrictedUsage/RestrictedMethodUsageExtension.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedMethodUsageRule' => $baseDir . '/src/Rules/RestrictedUsage/RestrictedMethodUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedPropertyUsageExtension' => $baseDir . '/src/Rules/RestrictedUsage/RestrictedPropertyUsageExtension.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedPropertyUsageRule' => $baseDir . '/src/Rules/RestrictedUsage/RestrictedPropertyUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedStaticMethodCallableUsageRule' => $baseDir . '/src/Rules/RestrictedUsage/RestrictedStaticMethodCallableUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedStaticMethodUsageRule' => $baseDir . '/src/Rules/RestrictedUsage/RestrictedStaticMethodUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedStaticPropertyUsageRule' => $baseDir . '/src/Rules/RestrictedUsage/RestrictedStaticPropertyUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedUsage' => $baseDir . '/src/Rules/RestrictedUsage/RestrictedUsage.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedUsageOfDeprecatedStringCastRule' => $baseDir . '/src/Rules/RestrictedUsage/RestrictedUsageOfDeprecatedStringCastRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RewrittenDeclaringClassClassConstantReflection' => $baseDir . '/src/Rules/RestrictedUsage/RewrittenDeclaringClassClassConstantReflection.php', 'PHPStan\\Rules\\RestrictedUsage\\RewrittenDeclaringClassMethodReflection' => $baseDir . '/src/Rules/RestrictedUsage/RewrittenDeclaringClassMethodReflection.php', 'PHPStan\\Rules\\RestrictedUsage\\RewrittenDeclaringClassPropertyReflection' => $baseDir . '/src/Rules/RestrictedUsage/RewrittenDeclaringClassPropertyReflection.php', 'PHPStan\\Rules\\Rule' => $baseDir . '/src/Rules/Rule.php', 'PHPStan\\Rules\\RuleError' => $baseDir . '/src/Rules/RuleError.php', 'PHPStan\\Rules\\RuleErrorBuilder' => $baseDir . '/src/Rules/RuleErrorBuilder.php', 'PHPStan\\Rules\\RuleErrors\\RuleError1' => $baseDir . '/src/Rules/RuleErrors/RuleError1.php', 'PHPStan\\Rules\\RuleErrors\\RuleError101' => $baseDir . '/src/Rules/RuleErrors/RuleError101.php', 'PHPStan\\Rules\\RuleErrors\\RuleError103' => $baseDir . '/src/Rules/RuleErrors/RuleError103.php', 'PHPStan\\Rules\\RuleErrors\\RuleError105' => $baseDir . '/src/Rules/RuleErrors/RuleError105.php', 'PHPStan\\Rules\\RuleErrors\\RuleError107' => $baseDir . '/src/Rules/RuleErrors/RuleError107.php', 'PHPStan\\Rules\\RuleErrors\\RuleError109' => $baseDir . '/src/Rules/RuleErrors/RuleError109.php', 'PHPStan\\Rules\\RuleErrors\\RuleError11' => $baseDir . '/src/Rules/RuleErrors/RuleError11.php', 'PHPStan\\Rules\\RuleErrors\\RuleError111' => $baseDir . '/src/Rules/RuleErrors/RuleError111.php', 'PHPStan\\Rules\\RuleErrors\\RuleError113' => $baseDir . '/src/Rules/RuleErrors/RuleError113.php', 'PHPStan\\Rules\\RuleErrors\\RuleError115' => $baseDir . '/src/Rules/RuleErrors/RuleError115.php', 'PHPStan\\Rules\\RuleErrors\\RuleError117' => $baseDir . '/src/Rules/RuleErrors/RuleError117.php', 'PHPStan\\Rules\\RuleErrors\\RuleError119' => $baseDir . '/src/Rules/RuleErrors/RuleError119.php', 'PHPStan\\Rules\\RuleErrors\\RuleError121' => $baseDir . '/src/Rules/RuleErrors/RuleError121.php', 'PHPStan\\Rules\\RuleErrors\\RuleError123' => $baseDir . '/src/Rules/RuleErrors/RuleError123.php', 'PHPStan\\Rules\\RuleErrors\\RuleError125' => $baseDir . '/src/Rules/RuleErrors/RuleError125.php', 'PHPStan\\Rules\\RuleErrors\\RuleError127' => $baseDir . '/src/Rules/RuleErrors/RuleError127.php', 'PHPStan\\Rules\\RuleErrors\\RuleError129' => $baseDir . '/src/Rules/RuleErrors/RuleError129.php', 'PHPStan\\Rules\\RuleErrors\\RuleError13' => $baseDir . '/src/Rules/RuleErrors/RuleError13.php', 'PHPStan\\Rules\\RuleErrors\\RuleError131' => $baseDir . '/src/Rules/RuleErrors/RuleError131.php', 'PHPStan\\Rules\\RuleErrors\\RuleError133' => $baseDir . '/src/Rules/RuleErrors/RuleError133.php', 'PHPStan\\Rules\\RuleErrors\\RuleError135' => $baseDir . '/src/Rules/RuleErrors/RuleError135.php', 'PHPStan\\Rules\\RuleErrors\\RuleError137' => $baseDir . '/src/Rules/RuleErrors/RuleError137.php', 'PHPStan\\Rules\\RuleErrors\\RuleError139' => $baseDir . '/src/Rules/RuleErrors/RuleError139.php', 'PHPStan\\Rules\\RuleErrors\\RuleError141' => $baseDir . '/src/Rules/RuleErrors/RuleError141.php', 'PHPStan\\Rules\\RuleErrors\\RuleError143' => $baseDir . '/src/Rules/RuleErrors/RuleError143.php', 'PHPStan\\Rules\\RuleErrors\\RuleError145' => $baseDir . '/src/Rules/RuleErrors/RuleError145.php', 'PHPStan\\Rules\\RuleErrors\\RuleError147' => $baseDir . '/src/Rules/RuleErrors/RuleError147.php', 'PHPStan\\Rules\\RuleErrors\\RuleError149' => $baseDir . '/src/Rules/RuleErrors/RuleError149.php', 'PHPStan\\Rules\\RuleErrors\\RuleError15' => $baseDir . '/src/Rules/RuleErrors/RuleError15.php', 'PHPStan\\Rules\\RuleErrors\\RuleError151' => $baseDir . '/src/Rules/RuleErrors/RuleError151.php', 'PHPStan\\Rules\\RuleErrors\\RuleError153' => $baseDir . '/src/Rules/RuleErrors/RuleError153.php', 'PHPStan\\Rules\\RuleErrors\\RuleError155' => $baseDir . '/src/Rules/RuleErrors/RuleError155.php', 'PHPStan\\Rules\\RuleErrors\\RuleError157' => $baseDir . '/src/Rules/RuleErrors/RuleError157.php', 'PHPStan\\Rules\\RuleErrors\\RuleError159' => $baseDir . '/src/Rules/RuleErrors/RuleError159.php', 'PHPStan\\Rules\\RuleErrors\\RuleError161' => $baseDir . '/src/Rules/RuleErrors/RuleError161.php', 'PHPStan\\Rules\\RuleErrors\\RuleError163' => $baseDir . '/src/Rules/RuleErrors/RuleError163.php', 'PHPStan\\Rules\\RuleErrors\\RuleError165' => $baseDir . '/src/Rules/RuleErrors/RuleError165.php', 'PHPStan\\Rules\\RuleErrors\\RuleError167' => $baseDir . '/src/Rules/RuleErrors/RuleError167.php', 'PHPStan\\Rules\\RuleErrors\\RuleError169' => $baseDir . '/src/Rules/RuleErrors/RuleError169.php', 'PHPStan\\Rules\\RuleErrors\\RuleError17' => $baseDir . '/src/Rules/RuleErrors/RuleError17.php', 'PHPStan\\Rules\\RuleErrors\\RuleError171' => $baseDir . '/src/Rules/RuleErrors/RuleError171.php', 'PHPStan\\Rules\\RuleErrors\\RuleError173' => $baseDir . '/src/Rules/RuleErrors/RuleError173.php', 'PHPStan\\Rules\\RuleErrors\\RuleError175' => $baseDir . '/src/Rules/RuleErrors/RuleError175.php', 'PHPStan\\Rules\\RuleErrors\\RuleError177' => $baseDir . '/src/Rules/RuleErrors/RuleError177.php', 'PHPStan\\Rules\\RuleErrors\\RuleError179' => $baseDir . '/src/Rules/RuleErrors/RuleError179.php', 'PHPStan\\Rules\\RuleErrors\\RuleError181' => $baseDir . '/src/Rules/RuleErrors/RuleError181.php', 'PHPStan\\Rules\\RuleErrors\\RuleError183' => $baseDir . '/src/Rules/RuleErrors/RuleError183.php', 'PHPStan\\Rules\\RuleErrors\\RuleError185' => $baseDir . '/src/Rules/RuleErrors/RuleError185.php', 'PHPStan\\Rules\\RuleErrors\\RuleError187' => $baseDir . '/src/Rules/RuleErrors/RuleError187.php', 'PHPStan\\Rules\\RuleErrors\\RuleError189' => $baseDir . '/src/Rules/RuleErrors/RuleError189.php', 'PHPStan\\Rules\\RuleErrors\\RuleError19' => $baseDir . '/src/Rules/RuleErrors/RuleError19.php', 'PHPStan\\Rules\\RuleErrors\\RuleError191' => $baseDir . '/src/Rules/RuleErrors/RuleError191.php', 'PHPStan\\Rules\\RuleErrors\\RuleError193' => $baseDir . '/src/Rules/RuleErrors/RuleError193.php', 'PHPStan\\Rules\\RuleErrors\\RuleError195' => $baseDir . '/src/Rules/RuleErrors/RuleError195.php', 'PHPStan\\Rules\\RuleErrors\\RuleError197' => $baseDir . '/src/Rules/RuleErrors/RuleError197.php', 'PHPStan\\Rules\\RuleErrors\\RuleError199' => $baseDir . '/src/Rules/RuleErrors/RuleError199.php', 'PHPStan\\Rules\\RuleErrors\\RuleError201' => $baseDir . '/src/Rules/RuleErrors/RuleError201.php', 'PHPStan\\Rules\\RuleErrors\\RuleError203' => $baseDir . '/src/Rules/RuleErrors/RuleError203.php', 'PHPStan\\Rules\\RuleErrors\\RuleError205' => $baseDir . '/src/Rules/RuleErrors/RuleError205.php', 'PHPStan\\Rules\\RuleErrors\\RuleError207' => $baseDir . '/src/Rules/RuleErrors/RuleError207.php', 'PHPStan\\Rules\\RuleErrors\\RuleError209' => $baseDir . '/src/Rules/RuleErrors/RuleError209.php', 'PHPStan\\Rules\\RuleErrors\\RuleError21' => $baseDir . '/src/Rules/RuleErrors/RuleError21.php', 'PHPStan\\Rules\\RuleErrors\\RuleError211' => $baseDir . '/src/Rules/RuleErrors/RuleError211.php', 'PHPStan\\Rules\\RuleErrors\\RuleError213' => $baseDir . '/src/Rules/RuleErrors/RuleError213.php', 'PHPStan\\Rules\\RuleErrors\\RuleError215' => $baseDir . '/src/Rules/RuleErrors/RuleError215.php', 'PHPStan\\Rules\\RuleErrors\\RuleError217' => $baseDir . '/src/Rules/RuleErrors/RuleError217.php', 'PHPStan\\Rules\\RuleErrors\\RuleError219' => $baseDir . '/src/Rules/RuleErrors/RuleError219.php', 'PHPStan\\Rules\\RuleErrors\\RuleError221' => $baseDir . '/src/Rules/RuleErrors/RuleError221.php', 'PHPStan\\Rules\\RuleErrors\\RuleError223' => $baseDir . '/src/Rules/RuleErrors/RuleError223.php', 'PHPStan\\Rules\\RuleErrors\\RuleError225' => $baseDir . '/src/Rules/RuleErrors/RuleError225.php', 'PHPStan\\Rules\\RuleErrors\\RuleError227' => $baseDir . '/src/Rules/RuleErrors/RuleError227.php', 'PHPStan\\Rules\\RuleErrors\\RuleError229' => $baseDir . '/src/Rules/RuleErrors/RuleError229.php', 'PHPStan\\Rules\\RuleErrors\\RuleError23' => $baseDir . '/src/Rules/RuleErrors/RuleError23.php', 'PHPStan\\Rules\\RuleErrors\\RuleError231' => $baseDir . '/src/Rules/RuleErrors/RuleError231.php', 'PHPStan\\Rules\\RuleErrors\\RuleError233' => $baseDir . '/src/Rules/RuleErrors/RuleError233.php', 'PHPStan\\Rules\\RuleErrors\\RuleError235' => $baseDir . '/src/Rules/RuleErrors/RuleError235.php', 'PHPStan\\Rules\\RuleErrors\\RuleError237' => $baseDir . '/src/Rules/RuleErrors/RuleError237.php', 'PHPStan\\Rules\\RuleErrors\\RuleError239' => $baseDir . '/src/Rules/RuleErrors/RuleError239.php', 'PHPStan\\Rules\\RuleErrors\\RuleError241' => $baseDir . '/src/Rules/RuleErrors/RuleError241.php', 'PHPStan\\Rules\\RuleErrors\\RuleError243' => $baseDir . '/src/Rules/RuleErrors/RuleError243.php', 'PHPStan\\Rules\\RuleErrors\\RuleError245' => $baseDir . '/src/Rules/RuleErrors/RuleError245.php', 'PHPStan\\Rules\\RuleErrors\\RuleError247' => $baseDir . '/src/Rules/RuleErrors/RuleError247.php', 'PHPStan\\Rules\\RuleErrors\\RuleError249' => $baseDir . '/src/Rules/RuleErrors/RuleError249.php', 'PHPStan\\Rules\\RuleErrors\\RuleError25' => $baseDir . '/src/Rules/RuleErrors/RuleError25.php', 'PHPStan\\Rules\\RuleErrors\\RuleError251' => $baseDir . '/src/Rules/RuleErrors/RuleError251.php', 'PHPStan\\Rules\\RuleErrors\\RuleError253' => $baseDir . '/src/Rules/RuleErrors/RuleError253.php', 'PHPStan\\Rules\\RuleErrors\\RuleError255' => $baseDir . '/src/Rules/RuleErrors/RuleError255.php', 'PHPStan\\Rules\\RuleErrors\\RuleError27' => $baseDir . '/src/Rules/RuleErrors/RuleError27.php', 'PHPStan\\Rules\\RuleErrors\\RuleError29' => $baseDir . '/src/Rules/RuleErrors/RuleError29.php', 'PHPStan\\Rules\\RuleErrors\\RuleError3' => $baseDir . '/src/Rules/RuleErrors/RuleError3.php', 'PHPStan\\Rules\\RuleErrors\\RuleError31' => $baseDir . '/src/Rules/RuleErrors/RuleError31.php', 'PHPStan\\Rules\\RuleErrors\\RuleError33' => $baseDir . '/src/Rules/RuleErrors/RuleError33.php', 'PHPStan\\Rules\\RuleErrors\\RuleError35' => $baseDir . '/src/Rules/RuleErrors/RuleError35.php', 'PHPStan\\Rules\\RuleErrors\\RuleError37' => $baseDir . '/src/Rules/RuleErrors/RuleError37.php', 'PHPStan\\Rules\\RuleErrors\\RuleError39' => $baseDir . '/src/Rules/RuleErrors/RuleError39.php', 'PHPStan\\Rules\\RuleErrors\\RuleError41' => $baseDir . '/src/Rules/RuleErrors/RuleError41.php', 'PHPStan\\Rules\\RuleErrors\\RuleError43' => $baseDir . '/src/Rules/RuleErrors/RuleError43.php', 'PHPStan\\Rules\\RuleErrors\\RuleError45' => $baseDir . '/src/Rules/RuleErrors/RuleError45.php', 'PHPStan\\Rules\\RuleErrors\\RuleError47' => $baseDir . '/src/Rules/RuleErrors/RuleError47.php', 'PHPStan\\Rules\\RuleErrors\\RuleError49' => $baseDir . '/src/Rules/RuleErrors/RuleError49.php', 'PHPStan\\Rules\\RuleErrors\\RuleError5' => $baseDir . '/src/Rules/RuleErrors/RuleError5.php', 'PHPStan\\Rules\\RuleErrors\\RuleError51' => $baseDir . '/src/Rules/RuleErrors/RuleError51.php', 'PHPStan\\Rules\\RuleErrors\\RuleError53' => $baseDir . '/src/Rules/RuleErrors/RuleError53.php', 'PHPStan\\Rules\\RuleErrors\\RuleError55' => $baseDir . '/src/Rules/RuleErrors/RuleError55.php', 'PHPStan\\Rules\\RuleErrors\\RuleError57' => $baseDir . '/src/Rules/RuleErrors/RuleError57.php', 'PHPStan\\Rules\\RuleErrors\\RuleError59' => $baseDir . '/src/Rules/RuleErrors/RuleError59.php', 'PHPStan\\Rules\\RuleErrors\\RuleError61' => $baseDir . '/src/Rules/RuleErrors/RuleError61.php', 'PHPStan\\Rules\\RuleErrors\\RuleError63' => $baseDir . '/src/Rules/RuleErrors/RuleError63.php', 'PHPStan\\Rules\\RuleErrors\\RuleError65' => $baseDir . '/src/Rules/RuleErrors/RuleError65.php', 'PHPStan\\Rules\\RuleErrors\\RuleError67' => $baseDir . '/src/Rules/RuleErrors/RuleError67.php', 'PHPStan\\Rules\\RuleErrors\\RuleError69' => $baseDir . '/src/Rules/RuleErrors/RuleError69.php', 'PHPStan\\Rules\\RuleErrors\\RuleError7' => $baseDir . '/src/Rules/RuleErrors/RuleError7.php', 'PHPStan\\Rules\\RuleErrors\\RuleError71' => $baseDir . '/src/Rules/RuleErrors/RuleError71.php', 'PHPStan\\Rules\\RuleErrors\\RuleError73' => $baseDir . '/src/Rules/RuleErrors/RuleError73.php', 'PHPStan\\Rules\\RuleErrors\\RuleError75' => $baseDir . '/src/Rules/RuleErrors/RuleError75.php', 'PHPStan\\Rules\\RuleErrors\\RuleError77' => $baseDir . '/src/Rules/RuleErrors/RuleError77.php', 'PHPStan\\Rules\\RuleErrors\\RuleError79' => $baseDir . '/src/Rules/RuleErrors/RuleError79.php', 'PHPStan\\Rules\\RuleErrors\\RuleError81' => $baseDir . '/src/Rules/RuleErrors/RuleError81.php', 'PHPStan\\Rules\\RuleErrors\\RuleError83' => $baseDir . '/src/Rules/RuleErrors/RuleError83.php', 'PHPStan\\Rules\\RuleErrors\\RuleError85' => $baseDir . '/src/Rules/RuleErrors/RuleError85.php', 'PHPStan\\Rules\\RuleErrors\\RuleError87' => $baseDir . '/src/Rules/RuleErrors/RuleError87.php', 'PHPStan\\Rules\\RuleErrors\\RuleError89' => $baseDir . '/src/Rules/RuleErrors/RuleError89.php', 'PHPStan\\Rules\\RuleErrors\\RuleError9' => $baseDir . '/src/Rules/RuleErrors/RuleError9.php', 'PHPStan\\Rules\\RuleErrors\\RuleError91' => $baseDir . '/src/Rules/RuleErrors/RuleError91.php', 'PHPStan\\Rules\\RuleErrors\\RuleError93' => $baseDir . '/src/Rules/RuleErrors/RuleError93.php', 'PHPStan\\Rules\\RuleErrors\\RuleError95' => $baseDir . '/src/Rules/RuleErrors/RuleError95.php', 'PHPStan\\Rules\\RuleErrors\\RuleError97' => $baseDir . '/src/Rules/RuleErrors/RuleError97.php', 'PHPStan\\Rules\\RuleErrors\\RuleError99' => $baseDir . '/src/Rules/RuleErrors/RuleError99.php', 'PHPStan\\Rules\\RuleLevelHelper' => $baseDir . '/src/Rules/RuleLevelHelper.php', 'PHPStan\\Rules\\RuleLevelHelperAcceptsResult' => $baseDir . '/src/Rules/RuleLevelHelperAcceptsResult.php', 'PHPStan\\Rules\\TipRuleError' => $baseDir . '/src/Rules/TipRuleError.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWideArrowFunctionReturnTypehintRule' => $baseDir . '/src/Rules/TooWideTypehints/TooWideArrowFunctionReturnTypehintRule.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWideClosureReturnTypehintRule' => $baseDir . '/src/Rules/TooWideTypehints/TooWideClosureReturnTypehintRule.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWideFunctionParameterOutTypeRule' => $baseDir . '/src/Rules/TooWideTypehints/TooWideFunctionParameterOutTypeRule.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWideFunctionReturnTypehintRule' => $baseDir . '/src/Rules/TooWideTypehints/TooWideFunctionReturnTypehintRule.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWideMethodParameterOutTypeRule' => $baseDir . '/src/Rules/TooWideTypehints/TooWideMethodParameterOutTypeRule.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWideMethodReturnTypehintRule' => $baseDir . '/src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWideParameterOutTypeCheck' => $baseDir . '/src/Rules/TooWideTypehints/TooWideParameterOutTypeCheck.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWidePropertyTypeRule' => $baseDir . '/src/Rules/TooWideTypehints/TooWidePropertyTypeRule.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWideTypeCheck' => $baseDir . '/src/Rules/TooWideTypehints/TooWideTypeCheck.php', 'PHPStan\\Rules\\Traits\\ConflictingTraitConstantsRule' => $baseDir . '/src/Rules/Traits/ConflictingTraitConstantsRule.php', 'PHPStan\\Rules\\Traits\\ConstantsInTraitsRule' => $baseDir . '/src/Rules/Traits/ConstantsInTraitsRule.php', 'PHPStan\\Rules\\Traits\\NotAnalysedTraitRule' => $baseDir . '/src/Rules/Traits/NotAnalysedTraitRule.php', 'PHPStan\\Rules\\Traits\\TraitAttributesRule' => $baseDir . '/src/Rules/Traits/TraitAttributesRule.php', 'PHPStan\\Rules\\Traits\\TraitDeclarationCollector' => $baseDir . '/src/Rules/Traits/TraitDeclarationCollector.php', 'PHPStan\\Rules\\Traits\\TraitUseCollector' => $baseDir . '/src/Rules/Traits/TraitUseCollector.php', 'PHPStan\\Rules\\Types\\InvalidTypesInUnionRule' => $baseDir . '/src/Rules/Types/InvalidTypesInUnionRule.php', 'PHPStan\\Rules\\UnusedFunctionParametersCheck' => $baseDir . '/src/Rules/UnusedFunctionParametersCheck.php', 'PHPStan\\Rules\\Variables\\AssignToByRefExprFromForeachRule' => $baseDir . '/src/Rules/Variables/AssignToByRefExprFromForeachRule.php', 'PHPStan\\Rules\\Variables\\CompactVariablesRule' => $baseDir . '/src/Rules/Variables/CompactVariablesRule.php', 'PHPStan\\Rules\\Variables\\DefinedVariableRule' => $baseDir . '/src/Rules/Variables/DefinedVariableRule.php', 'PHPStan\\Rules\\Variables\\EmptyRule' => $baseDir . '/src/Rules/Variables/EmptyRule.php', 'PHPStan\\Rules\\Variables\\InvalidVariableAssignRule' => $baseDir . '/src/Rules/Variables/InvalidVariableAssignRule.php', 'PHPStan\\Rules\\Variables\\IssetRule' => $baseDir . '/src/Rules/Variables/IssetRule.php', 'PHPStan\\Rules\\Variables\\NullCoalesceRule' => $baseDir . '/src/Rules/Variables/NullCoalesceRule.php', 'PHPStan\\Rules\\Variables\\ParameterOutAssignedTypeRule' => $baseDir . '/src/Rules/Variables/ParameterOutAssignedTypeRule.php', 'PHPStan\\Rules\\Variables\\ParameterOutExecutionEndTypeRule' => $baseDir . '/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php', 'PHPStan\\Rules\\Variables\\ThisInGlobalStatementRule' => $baseDir . '/src/Rules/Variables/ThisInGlobalStatementRule.php', 'PHPStan\\Rules\\Variables\\ThisInStaticStatementRule' => $baseDir . '/src/Rules/Variables/ThisInStaticStatementRule.php', 'PHPStan\\Rules\\Variables\\UnsetRule' => $baseDir . '/src/Rules/Variables/UnsetRule.php', 'PHPStan\\Rules\\Variables\\VariableCloningRule' => $baseDir . '/src/Rules/Variables/VariableCloningRule.php', 'PHPStan\\Rules\\Whitespace\\FileWhitespaceRule' => $baseDir . '/src/Rules/Whitespace/FileWhitespaceRule.php', 'PHPStan\\ShouldNotHappenException' => $baseDir . '/src/ShouldNotHappenException.php', 'PHPStan\\Testing\\CompositeRule' => $baseDir . '/src/Testing/CompositeRule.php', 'PHPStan\\Testing\\DelayedRule' => $baseDir . '/src/Testing/DelayedRule.php', 'PHPStan\\Testing\\ErrorFormatterTestCase' => $baseDir . '/src/Testing/ErrorFormatterTestCase.php', 'PHPStan\\Testing\\LevelsTestCase' => $baseDir . '/src/Testing/LevelsTestCase.php', 'PHPStan\\Testing\\NonexistentAnalysedClassRule' => $baseDir . '/src/Testing/NonexistentAnalysedClassRule.php', 'PHPStan\\Testing\\NonexistentAnalysedTraitRule' => $baseDir . '/src/Testing/NonexistentAnalysedTraitRule.php', 'PHPStan\\Testing\\PHPStanTestCase' => $baseDir . '/src/Testing/PHPStanTestCase.php', 'PHPStan\\Testing\\PHPStanTestCaseTrait' => $baseDir . '/src/Testing/PHPStanTestCaseTrait.php', 'PHPStan\\Testing\\PHPUnit\\ContainerInitializer' => $baseDir . '/src/Testing/PHPUnit/ContainerInitializer.php', 'PHPStan\\Testing\\PHPUnit\\InitContainerBeforeDataProviderSubscriber' => $baseDir . '/src/Testing/PHPUnit/InitContainerBeforeDataProviderSubscriber.php', 'PHPStan\\Testing\\PHPUnit\\InitContainerBeforeTestSubscriber' => $baseDir . '/src/Testing/PHPUnit/InitContainerBeforeTestSubscriber.php', 'PHPStan\\Testing\\PHPUnit\\PHPStanPHPUnitExtension' => $baseDir . '/src/Testing/PHPUnit/PHPStanPHPUnitExtension.php', 'PHPStan\\Testing\\RuleTestCase' => $baseDir . '/src/Testing/RuleTestCase.php', 'PHPStan\\Testing\\TestCaseSourceLocatorFactory' => $baseDir . '/src/Testing/TestCaseSourceLocatorFactory.php', 'PHPStan\\Testing\\TypeInferenceTestCase' => $baseDir . '/src/Testing/TypeInferenceTestCase.php', 'PHPStan\\TrinaryLogic' => $baseDir . '/src/TrinaryLogic.php', 'PHPStan\\Turbo\\TurboExtensionEnabler' => $baseDir . '/src/Turbo/TurboExtensionEnabler.php', 'PHPStan\\Type\\AcceptsResult' => $baseDir . '/src/Type/AcceptsResult.php', 'PHPStan\\Type\\Accessory\\AccessoryArrayListType' => $baseDir . '/src/Type/Accessory/AccessoryArrayListType.php', 'PHPStan\\Type\\Accessory\\AccessoryLiteralStringType' => $baseDir . '/src/Type/Accessory/AccessoryLiteralStringType.php', 'PHPStan\\Type\\Accessory\\AccessoryLowercaseStringType' => $baseDir . '/src/Type/Accessory/AccessoryLowercaseStringType.php', 'PHPStan\\Type\\Accessory\\AccessoryNonEmptyStringType' => $baseDir . '/src/Type/Accessory/AccessoryNonEmptyStringType.php', 'PHPStan\\Type\\Accessory\\AccessoryNonFalsyStringType' => $baseDir . '/src/Type/Accessory/AccessoryNonFalsyStringType.php', 'PHPStan\\Type\\Accessory\\AccessoryNumericStringType' => $baseDir . '/src/Type/Accessory/AccessoryNumericStringType.php', 'PHPStan\\Type\\Accessory\\AccessoryType' => $baseDir . '/src/Type/Accessory/AccessoryType.php', 'PHPStan\\Type\\Accessory\\AccessoryUppercaseStringType' => $baseDir . '/src/Type/Accessory/AccessoryUppercaseStringType.php', 'PHPStan\\Type\\Accessory\\HasMethodType' => $baseDir . '/src/Type/Accessory/HasMethodType.php', 'PHPStan\\Type\\Accessory\\HasOffsetType' => $baseDir . '/src/Type/Accessory/HasOffsetType.php', 'PHPStan\\Type\\Accessory\\HasOffsetValueType' => $baseDir . '/src/Type/Accessory/HasOffsetValueType.php', 'PHPStan\\Type\\Accessory\\HasPropertyType' => $baseDir . '/src/Type/Accessory/HasPropertyType.php', 'PHPStan\\Type\\Accessory\\NonEmptyArrayType' => $baseDir . '/src/Type/Accessory/NonEmptyArrayType.php', 'PHPStan\\Type\\Accessory\\OversizedArrayType' => $baseDir . '/src/Type/Accessory/OversizedArrayType.php', 'PHPStan\\Type\\ArrayType' => $baseDir . '/src/Type/ArrayType.php', 'PHPStan\\Type\\BenevolentUnionType' => $baseDir . '/src/Type/BenevolentUnionType.php', 'PHPStan\\Type\\BitwiseFlagHelper' => $baseDir . '/src/Type/BitwiseFlagHelper.php', 'PHPStan\\Type\\BooleanType' => $baseDir . '/src/Type/BooleanType.php', 'PHPStan\\Type\\CallableType' => $baseDir . '/src/Type/CallableType.php', 'PHPStan\\Type\\CallableTypeHelper' => $baseDir . '/src/Type/CallableTypeHelper.php', 'PHPStan\\Type\\CircularTypeAliasDefinitionException' => $baseDir . '/src/Type/CircularTypeAliasDefinitionException.php', 'PHPStan\\Type\\CircularTypeAliasErrorType' => $baseDir . '/src/Type/CircularTypeAliasErrorType.php', 'PHPStan\\Type\\ClassConstantAccessType' => $baseDir . '/src/Type/ClassConstantAccessType.php', 'PHPStan\\Type\\ClassNameToObjectTypeResult' => $baseDir . '/src/Type/ClassNameToObjectTypeResult.php', 'PHPStan\\Type\\ClassStringType' => $baseDir . '/src/Type/ClassStringType.php', 'PHPStan\\Type\\ClosureType' => $baseDir . '/src/Type/ClosureType.php', 'PHPStan\\Type\\ClosureTypeFactory' => $baseDir . '/src/Type/ClosureTypeFactory.php', 'PHPStan\\Type\\CompoundType' => $baseDir . '/src/Type/CompoundType.php', 'PHPStan\\Type\\ConditionalType' => $baseDir . '/src/Type/ConditionalType.php', 'PHPStan\\Type\\ConditionalTypeForParameter' => $baseDir . '/src/Type/ConditionalTypeForParameter.php', 'PHPStan\\Type\\ConstantScalarType' => $baseDir . '/src/Type/ConstantScalarType.php', 'PHPStan\\Type\\ConstantTypeHelper' => $baseDir . '/src/Type/ConstantTypeHelper.php', 'PHPStan\\Type\\Constant\\ConstantArrayType' => $baseDir . '/src/Type/Constant/ConstantArrayType.php', 'PHPStan\\Type\\Constant\\ConstantArrayTypeAndMethod' => $baseDir . '/src/Type/Constant/ConstantArrayTypeAndMethod.php', 'PHPStan\\Type\\Constant\\ConstantArrayTypeBuilder' => $baseDir . '/src/Type/Constant/ConstantArrayTypeBuilder.php', 'PHPStan\\Type\\Constant\\ConstantBooleanType' => $baseDir . '/src/Type/Constant/ConstantBooleanType.php', 'PHPStan\\Type\\Constant\\ConstantFloatType' => $baseDir . '/src/Type/Constant/ConstantFloatType.php', 'PHPStan\\Type\\Constant\\ConstantIntegerType' => $baseDir . '/src/Type/Constant/ConstantIntegerType.php', 'PHPStan\\Type\\Constant\\ConstantScalarToBooleanTrait' => $baseDir . '/src/Type/Constant/ConstantScalarToBooleanTrait.php', 'PHPStan\\Type\\Constant\\ConstantStringType' => $baseDir . '/src/Type/Constant/ConstantStringType.php', 'PHPStan\\Type\\Constant\\OversizedArrayBuilder' => $baseDir . '/src/Type/Constant/OversizedArrayBuilder.php', 'PHPStan\\Type\\DirectTypeAliasResolverProvider' => $baseDir . '/src/Type/DirectTypeAliasResolverProvider.php', 'PHPStan\\Type\\DynamicFunctionReturnTypeExtension' => $baseDir . '/src/Type/DynamicFunctionReturnTypeExtension.php', 'PHPStan\\Type\\DynamicFunctionThrowTypeExtension' => $baseDir . '/src/Type/DynamicFunctionThrowTypeExtension.php', 'PHPStan\\Type\\DynamicMethodReturnTypeExtension' => $baseDir . '/src/Type/DynamicMethodReturnTypeExtension.php', 'PHPStan\\Type\\DynamicMethodThrowTypeExtension' => $baseDir . '/src/Type/DynamicMethodThrowTypeExtension.php', 'PHPStan\\Type\\DynamicReturnTypeExtensionRegistry' => $baseDir . '/src/Type/DynamicReturnTypeExtensionRegistry.php', 'PHPStan\\Type\\DynamicStaticMethodReturnTypeExtension' => $baseDir . '/src/Type/DynamicStaticMethodReturnTypeExtension.php', 'PHPStan\\Type\\DynamicStaticMethodThrowTypeExtension' => $baseDir . '/src/Type/DynamicStaticMethodThrowTypeExtension.php', 'PHPStan\\Type\\Enum\\EnumCaseObjectType' => $baseDir . '/src/Type/Enum/EnumCaseObjectType.php', 'PHPStan\\Type\\ErrorType' => $baseDir . '/src/Type/ErrorType.php', 'PHPStan\\Type\\ExponentiateHelper' => $baseDir . '/src/Type/ExponentiateHelper.php', 'PHPStan\\Type\\ExpressionTypeResolverExtension' => $baseDir . '/src/Type/ExpressionTypeResolverExtension.php', 'PHPStan\\Type\\ExpressionTypeResolverExtensionRegistry' => $baseDir . '/src/Type/ExpressionTypeResolverExtensionRegistry.php', 'PHPStan\\Type\\FileTypeMapper' => $baseDir . '/src/Type/FileTypeMapper.php', 'PHPStan\\Type\\FloatType' => $baseDir . '/src/Type/FloatType.php', 'PHPStan\\Type\\FunctionParameterClosureThisExtension' => $baseDir . '/src/Type/FunctionParameterClosureThisExtension.php', 'PHPStan\\Type\\FunctionParameterClosureTypeExtension' => $baseDir . '/src/Type/FunctionParameterClosureTypeExtension.php', 'PHPStan\\Type\\FunctionParameterOutTypeExtension' => $baseDir . '/src/Type/FunctionParameterOutTypeExtension.php', 'PHPStan\\Type\\FunctionTypeSpecifyingExtension' => $baseDir . '/src/Type/FunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\GeneralizePrecision' => $baseDir . '/src/Type/GeneralizePrecision.php', 'PHPStan\\Type\\Generic\\GenericClassStringType' => $baseDir . '/src/Type/Generic/GenericClassStringType.php', 'PHPStan\\Type\\Generic\\GenericObjectType' => $baseDir . '/src/Type/Generic/GenericObjectType.php', 'PHPStan\\Type\\Generic\\GenericStaticType' => $baseDir . '/src/Type/Generic/GenericStaticType.php', 'PHPStan\\Type\\Generic\\TemplateArrayType' => $baseDir . '/src/Type/Generic/TemplateArrayType.php', 'PHPStan\\Type\\Generic\\TemplateBenevolentUnionType' => $baseDir . '/src/Type/Generic/TemplateBenevolentUnionType.php', 'PHPStan\\Type\\Generic\\TemplateBooleanType' => $baseDir . '/src/Type/Generic/TemplateBooleanType.php', 'PHPStan\\Type\\Generic\\TemplateConstantArrayType' => $baseDir . '/src/Type/Generic/TemplateConstantArrayType.php', 'PHPStan\\Type\\Generic\\TemplateConstantIntegerType' => $baseDir . '/src/Type/Generic/TemplateConstantIntegerType.php', 'PHPStan\\Type\\Generic\\TemplateConstantStringType' => $baseDir . '/src/Type/Generic/TemplateConstantStringType.php', 'PHPStan\\Type\\Generic\\TemplateFloatType' => $baseDir . '/src/Type/Generic/TemplateFloatType.php', 'PHPStan\\Type\\Generic\\TemplateGenericObjectType' => $baseDir . '/src/Type/Generic/TemplateGenericObjectType.php', 'PHPStan\\Type\\Generic\\TemplateIntegerType' => $baseDir . '/src/Type/Generic/TemplateIntegerType.php', 'PHPStan\\Type\\Generic\\TemplateIntersectionType' => $baseDir . '/src/Type/Generic/TemplateIntersectionType.php', 'PHPStan\\Type\\Generic\\TemplateIterableType' => $baseDir . '/src/Type/Generic/TemplateIterableType.php', 'PHPStan\\Type\\Generic\\TemplateKeyOfType' => $baseDir . '/src/Type/Generic/TemplateKeyOfType.php', 'PHPStan\\Type\\Generic\\TemplateMixedType' => $baseDir . '/src/Type/Generic/TemplateMixedType.php', 'PHPStan\\Type\\Generic\\TemplateNullType' => $baseDir . '/src/Type/Generic/TemplateNullType.php', 'PHPStan\\Type\\Generic\\TemplateObjectShapeType' => $baseDir . '/src/Type/Generic/TemplateObjectShapeType.php', 'PHPStan\\Type\\Generic\\TemplateObjectType' => $baseDir . '/src/Type/Generic/TemplateObjectType.php', 'PHPStan\\Type\\Generic\\TemplateObjectWithoutClassType' => $baseDir . '/src/Type/Generic/TemplateObjectWithoutClassType.php', 'PHPStan\\Type\\Generic\\TemplateStrictMixedType' => $baseDir . '/src/Type/Generic/TemplateStrictMixedType.php', 'PHPStan\\Type\\Generic\\TemplateStringType' => $baseDir . '/src/Type/Generic/TemplateStringType.php', 'PHPStan\\Type\\Generic\\TemplateType' => $baseDir . '/src/Type/Generic/TemplateType.php', 'PHPStan\\Type\\Generic\\TemplateTypeArgumentStrategy' => $baseDir . '/src/Type/Generic/TemplateTypeArgumentStrategy.php', 'PHPStan\\Type\\Generic\\TemplateTypeFactory' => $baseDir . '/src/Type/Generic/TemplateTypeFactory.php', 'PHPStan\\Type\\Generic\\TemplateTypeHelper' => $baseDir . '/src/Type/Generic/TemplateTypeHelper.php', 'PHPStan\\Type\\Generic\\TemplateTypeMap' => $baseDir . '/src/Type/Generic/TemplateTypeMap.php', 'PHPStan\\Type\\Generic\\TemplateTypeParameterStrategy' => $baseDir . '/src/Type/Generic/TemplateTypeParameterStrategy.php', 'PHPStan\\Type\\Generic\\TemplateTypeReference' => $baseDir . '/src/Type/Generic/TemplateTypeReference.php', 'PHPStan\\Type\\Generic\\TemplateTypeScope' => $baseDir . '/src/Type/Generic/TemplateTypeScope.php', 'PHPStan\\Type\\Generic\\TemplateTypeStrategy' => $baseDir . '/src/Type/Generic/TemplateTypeStrategy.php', 'PHPStan\\Type\\Generic\\TemplateTypeTrait' => $baseDir . '/src/Type/Generic/TemplateTypeTrait.php', 'PHPStan\\Type\\Generic\\TemplateTypeVariance' => $baseDir . '/src/Type/Generic/TemplateTypeVariance.php', 'PHPStan\\Type\\Generic\\TemplateTypeVarianceMap' => $baseDir . '/src/Type/Generic/TemplateTypeVarianceMap.php', 'PHPStan\\Type\\Generic\\TemplateUnionType' => $baseDir . '/src/Type/Generic/TemplateUnionType.php', 'PHPStan\\Type\\Generic\\TypeProjectionHelper' => $baseDir . '/src/Type/Generic/TypeProjectionHelper.php', 'PHPStan\\Type\\Helper\\GetTemplateTypeType' => $baseDir . '/src/Type/Helper/GetTemplateTypeType.php', 'PHPStan\\Type\\IntegerRangeType' => $baseDir . '/src/Type/IntegerRangeType.php', 'PHPStan\\Type\\IntegerType' => $baseDir . '/src/Type/IntegerType.php', 'PHPStan\\Type\\IntersectionType' => $baseDir . '/src/Type/IntersectionType.php', 'PHPStan\\Type\\IsSuperTypeOfResult' => $baseDir . '/src/Type/IsSuperTypeOfResult.php', 'PHPStan\\Type\\IterableType' => $baseDir . '/src/Type/IterableType.php', 'PHPStan\\Type\\JustNullableTypeTrait' => $baseDir . '/src/Type/JustNullableTypeTrait.php', 'PHPStan\\Type\\KeyOfType' => $baseDir . '/src/Type/KeyOfType.php', 'PHPStan\\Type\\LateResolvableType' => $baseDir . '/src/Type/LateResolvableType.php', 'PHPStan\\Type\\LazyTypeAliasResolverProvider' => $baseDir . '/src/Type/LazyTypeAliasResolverProvider.php', 'PHPStan\\Type\\LooseComparisonHelper' => $baseDir . '/src/Type/LooseComparisonHelper.php', 'PHPStan\\Type\\MethodParameterClosureThisExtension' => $baseDir . '/src/Type/MethodParameterClosureThisExtension.php', 'PHPStan\\Type\\MethodParameterClosureTypeExtension' => $baseDir . '/src/Type/MethodParameterClosureTypeExtension.php', 'PHPStan\\Type\\MethodParameterOutTypeExtension' => $baseDir . '/src/Type/MethodParameterOutTypeExtension.php', 'PHPStan\\Type\\MethodTypeSpecifyingExtension' => $baseDir . '/src/Type/MethodTypeSpecifyingExtension.php', 'PHPStan\\Type\\MixedType' => $baseDir . '/src/Type/MixedType.php', 'PHPStan\\Type\\NeverType' => $baseDir . '/src/Type/NeverType.php', 'PHPStan\\Type\\NewObjectType' => $baseDir . '/src/Type/NewObjectType.php', 'PHPStan\\Type\\NonAcceptingNeverType' => $baseDir . '/src/Type/NonAcceptingNeverType.php', 'PHPStan\\Type\\NonexistentParentClassType' => $baseDir . '/src/Type/NonexistentParentClassType.php', 'PHPStan\\Type\\NullType' => $baseDir . '/src/Type/NullType.php', 'PHPStan\\Type\\ObjectShapePropertyReflection' => $baseDir . '/src/Type/ObjectShapePropertyReflection.php', 'PHPStan\\Type\\ObjectShapeType' => $baseDir . '/src/Type/ObjectShapeType.php', 'PHPStan\\Type\\ObjectType' => $baseDir . '/src/Type/ObjectType.php', 'PHPStan\\Type\\ObjectWithoutClassType' => $baseDir . '/src/Type/ObjectWithoutClassType.php', 'PHPStan\\Type\\OffsetAccessType' => $baseDir . '/src/Type/OffsetAccessType.php', 'PHPStan\\Type\\OperatorTypeSpecifyingExtension' => $baseDir . '/src/Type/OperatorTypeSpecifyingExtension.php', 'PHPStan\\Type\\OperatorTypeSpecifyingExtensionRegistry' => $baseDir . '/src/Type/OperatorTypeSpecifyingExtensionRegistry.php', 'PHPStan\\Type\\PHPStan\\ClassNameUsageLocationCreateIdentifierDynamicReturnTypeExtension' => $baseDir . '/src/Type/PHPStan/ClassNameUsageLocationCreateIdentifierDynamicReturnTypeExtension.php', 'PHPStan\\Type\\ParserNodeTypeToPHPStanType' => $baseDir . '/src/Type/ParserNodeTypeToPHPStanType.php', 'PHPStan\\Type\\Php\\AbsFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/AbsFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArgumentBasedFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArgumentBasedFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayChangeKeyCaseFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayChangeKeyCaseFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayChunkFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayChunkFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayColumnFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayColumnFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayColumnHelper' => $baseDir . '/src/Type/Php/ArrayColumnHelper.php', 'PHPStan\\Type\\Php\\ArrayCombineFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayCombineFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayCombineFunctionThrowTypeExtension' => $baseDir . '/src/Type/Php/ArrayCombineFunctionThrowTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayCombineHelper' => $baseDir . '/src/Type/Php/ArrayCombineHelper.php', 'PHPStan\\Type\\Php\\ArrayCountValuesDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayCountValuesDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayCurrentDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayCurrentDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayFillFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayFillFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayFillKeysFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayFillKeysFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayFilterFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayFilterFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayFilterFunctionReturnTypeHelper' => $baseDir . '/src/Type/Php/ArrayFilterFunctionReturnTypeHelper.php', 'PHPStan\\Type\\Php\\ArrayFindFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayFindFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayFindKeyFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayFindKeyFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayFirstLastDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayFirstLastDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayFlipFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayFlipFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayIntersectKeyFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayIntersectKeyFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayKeyDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayKeyDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayKeyExistsFunctionTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\ArrayKeysFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayKeysFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayMapFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayMapFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayMergeFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayNextDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayNextDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayPadDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayPadDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayPointerFunctionsDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayPointerFunctionsDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayPopFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayPopFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayRandFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayRandFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayReduceFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayReduceFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayReplaceFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayReplaceFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayReverseFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayReverseFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArraySearchFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ArraySearchFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArraySearchFunctionTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/ArraySearchFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\ArrayShiftFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayShiftFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArraySliceFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArraySliceFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArraySpliceFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArraySpliceFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArraySumFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ArraySumFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayValuesFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayValuesFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\AssertFunctionTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/AssertFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\AssertThrowTypeExtension' => $baseDir . '/src/Type/Php/AssertThrowTypeExtension.php', 'PHPStan\\Type\\Php\\BackedEnumFromMethodDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/BackedEnumFromMethodDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\Base64DecodeDynamicFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/Base64DecodeDynamicFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\BcMathNumberOperatorTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/BcMathNumberOperatorTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\BcMathStringOrNullReturnTypeExtension' => $baseDir . '/src/Type/Php/BcMathStringOrNullReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ClassExistsFunctionTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/ClassExistsFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\ClassImplementsFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ClassImplementsFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ClosureBindDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ClosureBindDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ClosureBindToDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ClosureBindToDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ClosureFromCallableDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ClosureFromCallableDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ClosureGetCurrentDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ClosureGetCurrentDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\CompactFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/CompactFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ConstantFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ConstantFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ConstantHelper' => $baseDir . '/src/Type/Php/ConstantHelper.php', 'PHPStan\\Type\\Php\\CountCharsFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/CountCharsFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\CountFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/CountFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\CountFunctionTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/CountFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\CtypeDigitFunctionTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/CtypeDigitFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\CurlGetinfoFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/CurlGetinfoFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateFormatFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/DateFormatFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateFormatMethodReturnTypeExtension' => $baseDir . '/src/Type/Php/DateFormatMethodReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/DateFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateFunctionReturnTypeHelper' => $baseDir . '/src/Type/Php/DateFunctionReturnTypeHelper.php', 'PHPStan\\Type\\Php\\DateIntervalConstructorThrowTypeExtension' => $baseDir . '/src/Type/Php/DateIntervalConstructorThrowTypeExtension.php', 'PHPStan\\Type\\Php\\DateIntervalCreateFromDateStringThrowTypeExtension' => $baseDir . '/src/Type/Php/DateIntervalCreateFromDateStringThrowTypeExtension.php', 'PHPStan\\Type\\Php\\DateIntervalDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/DateIntervalDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateIntervalFormatDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/DateIntervalFormatDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateIntervalFormatFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/DateIntervalFormatFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateIntervalFormatReturnTypeHelper' => $baseDir . '/src/Type/Php/DateIntervalFormatReturnTypeHelper.php', 'PHPStan\\Type\\Php\\DatePeriodConstructorReturnTypeExtension' => $baseDir . '/src/Type/Php/DatePeriodConstructorReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateTimeConstructorThrowTypeExtension' => $baseDir . '/src/Type/Php/DateTimeConstructorThrowTypeExtension.php', 'PHPStan\\Type\\Php\\DateTimeCreateDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/DateTimeCreateDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateTimeDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/DateTimeDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateTimeModifyMethodThrowTypeExtension' => $baseDir . '/src/Type/Php/DateTimeModifyMethodThrowTypeExtension.php', 'PHPStan\\Type\\Php\\DateTimeModifyReturnTypeExtension' => $baseDir . '/src/Type/Php/DateTimeModifyReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateTimeSubMethodThrowTypeExtension' => $baseDir . '/src/Type/Php/DateTimeSubMethodThrowTypeExtension.php', 'PHPStan\\Type\\Php\\DateTimeZoneConstructorThrowTypeExtension' => $baseDir . '/src/Type/Php/DateTimeZoneConstructorThrowTypeExtension.php', 'PHPStan\\Type\\Php\\DefineConstantTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/DefineConstantTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\DefinedConstantTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/DefinedConstantTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\DioStatDynamicFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/DioStatDynamicFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DomDocumentCreateElementDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/DomDocumentCreateElementDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DomDocumentCreateElementDynamicThrowTypeExtension' => $baseDir . '/src/Type/Php/DomDocumentCreateElementDynamicThrowTypeExtension.php', 'PHPStan\\Type\\Php\\DsMapDynamicMethodThrowTypeExtension' => $baseDir . '/src/Type/Php/DsMapDynamicMethodThrowTypeExtension.php', 'PHPStan\\Type\\Php\\DsMapDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/DsMapDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ExplodeFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ExplodeFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\FilterFunctionReturnTypeHelper' => $baseDir . '/src/Type/Php/FilterFunctionReturnTypeHelper.php', 'PHPStan\\Type\\Php\\FilterInputDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/FilterInputDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\FilterVarArrayDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/FilterVarArrayDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\FilterVarDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/FilterVarDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\FilterVarThrowTypeExtension' => $baseDir . '/src/Type/Php/FilterVarThrowTypeExtension.php', 'PHPStan\\Type\\Php\\FunctionExistsFunctionTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/FunctionExistsFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\GetCalledClassDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/GetCalledClassDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\GetClassDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/GetClassDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\GetDebugTypeFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/GetDebugTypeFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\GetDefinedVarsFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/GetDefinedVarsFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\GetParentClassDynamicFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/GetParentClassDynamicFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\GettimeofdayDynamicFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/GettimeofdayDynamicFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\GettypeFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/GettypeFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\GmpOperatorTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/GmpOperatorTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\GmpUnaryOperatorTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/GmpUnaryOperatorTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\HashFunctionsReturnTypeExtension' => $baseDir . '/src/Type/Php/HashFunctionsReturnTypeExtension.php', 'PHPStan\\Type\\Php\\HighlightStringDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/HighlightStringDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\HrtimeFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/HrtimeFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\IdateFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/IdateFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\IdateFunctionReturnTypeHelper' => $baseDir . '/src/Type/Php/IdateFunctionReturnTypeHelper.php', 'PHPStan\\Type\\Php\\ImplodeFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ImplodeFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\InArrayFunctionTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\IniGetReturnTypeExtension' => $baseDir . '/src/Type/Php/IniGetReturnTypeExtension.php', 'PHPStan\\Type\\Php\\IntdivThrowTypeExtension' => $baseDir . '/src/Type/Php/IntdivThrowTypeExtension.php', 'PHPStan\\Type\\Php\\IsAFunctionTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/IsAFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\IsAFunctionTypeSpecifyingHelper' => $baseDir . '/src/Type/Php/IsAFunctionTypeSpecifyingHelper.php', 'PHPStan\\Type\\Php\\IsArrayFunctionTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/IsArrayFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\IsCallableFunctionTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/IsCallableFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\IsIterableFunctionTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/IsIterableFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\IsSubclassOfFunctionTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\IteratorToArrayFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/IteratorToArrayFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\JsonThrowOnErrorDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/JsonThrowOnErrorDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\JsonThrowTypeExtension' => $baseDir . '/src/Type/Php/JsonThrowTypeExtension.php', 'PHPStan\\Type\\Php\\LtrimFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/LtrimFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\MbConvertEncodingFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/MbConvertEncodingFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\MbFunctionsReturnTypeExtension' => $baseDir . '/src/Type/Php/MbFunctionsReturnTypeExtension.php', 'PHPStan\\Type\\Php\\MbFunctionsReturnTypeExtensionTrait' => $baseDir . '/src/Type/Php/MbFunctionsReturnTypeExtensionTrait.php', 'PHPStan\\Type\\Php\\MbStrlenFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/MbStrlenFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\MbSubstituteCharacterDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/MbSubstituteCharacterDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\MethodExistsTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/MethodExistsTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\MicrotimeFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/MicrotimeFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\MinMaxFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/MinMaxFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\NonEmptyStringFunctionsReturnTypeExtension' => $baseDir . '/src/Type/Php/NonEmptyStringFunctionsReturnTypeExtension.php', 'PHPStan\\Type\\Php\\NumberFormatFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/NumberFormatFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\OpenSslCipherMethodsProvider' => $baseDir . '/src/Type/Php/OpenSslCipherMethodsProvider.php', 'PHPStan\\Type\\Php\\OpenSslEncryptParameterOutTypeExtension' => $baseDir . '/src/Type/Php/OpenSslEncryptParameterOutTypeExtension.php', 'PHPStan\\Type\\Php\\OpensslCipherFunctionsReturnTypeExtension' => $baseDir . '/src/Type/Php/OpensslCipherFunctionsReturnTypeExtension.php', 'PHPStan\\Type\\Php\\PDOConnectReturnTypeExtension' => $baseDir . '/src/Type/Php/PDOConnectReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ParseStrParameterOutTypeExtension' => $baseDir . '/src/Type/Php/ParseStrParameterOutTypeExtension.php', 'PHPStan\\Type\\Php\\ParseUrlFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ParseUrlFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\PathinfoFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/PathinfoFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\PdoStatementFetchAllReturnTypeExtension' => $baseDir . '/src/Type/Php/PdoStatementFetchAllReturnTypeExtension.php', 'PHPStan\\Type\\Php\\PowFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/PowFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\PregFilterFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/PregFilterFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\PregMatchParameterOutTypeExtension' => $baseDir . '/src/Type/Php/PregMatchParameterOutTypeExtension.php', 'PHPStan\\Type\\Php\\PregMatchTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/PregMatchTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\PregReplaceCallbackClosureTypeExtension' => $baseDir . '/src/Type/Php/PregReplaceCallbackClosureTypeExtension.php', 'PHPStan\\Type\\Php\\PregSplitDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/PregSplitDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\PropertyExistsTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/PropertyExistsTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\RandomIntFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/RandomIntFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\RangeFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/RangeFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ReflectionClassConstructorThrowTypeExtension' => $baseDir . '/src/Type/Php/ReflectionClassConstructorThrowTypeExtension.php', 'PHPStan\\Type\\Php\\ReflectionClassIsSubclassOfTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/ReflectionClassIsSubclassOfTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\ReflectionFunctionConstructorThrowTypeExtension' => $baseDir . '/src/Type/Php/ReflectionFunctionConstructorThrowTypeExtension.php', 'PHPStan\\Type\\Php\\ReflectionGetAttributesMethodReturnTypeExtension' => $baseDir . '/src/Type/Php/ReflectionGetAttributesMethodReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ReflectionMethodConstructorThrowTypeExtension' => $baseDir . '/src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php', 'PHPStan\\Type\\Php\\ReflectionPropertyConstructorThrowTypeExtension' => $baseDir . '/src/Type/Php/ReflectionPropertyConstructorThrowTypeExtension.php', 'PHPStan\\Type\\Php\\RegexArrayShapeMatcher' => $baseDir . '/src/Type/Php/RegexArrayShapeMatcher.php', 'PHPStan\\Type\\Php\\ReplaceFunctionsDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/ReplaceFunctionsDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\RoundFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/RoundFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\SetTypeFunctionTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/SetTypeFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\SimpleXMLElementAsXMLMethodReturnTypeExtension' => $baseDir . '/src/Type/Php/SimpleXMLElementAsXMLMethodReturnTypeExtension.php', 'PHPStan\\Type\\Php\\SimpleXMLElementClassPropertyReflectionExtension' => $baseDir . '/src/Type/Php/SimpleXMLElementClassPropertyReflectionExtension.php', 'PHPStan\\Type\\Php\\SimpleXMLElementConstructorThrowTypeExtension' => $baseDir . '/src/Type/Php/SimpleXMLElementConstructorThrowTypeExtension.php', 'PHPStan\\Type\\Php\\SimpleXMLElementXpathMethodReturnTypeExtension' => $baseDir . '/src/Type/Php/SimpleXMLElementXpathMethodReturnTypeExtension.php', 'PHPStan\\Type\\Php\\SprintfFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/SprintfFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\SscanfFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/SscanfFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StatDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/StatDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrCaseFunctionsReturnTypeExtension' => $baseDir . '/src/Type/Php/StrCaseFunctionsReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrContainingTypeSpecifyingExtension' => $baseDir . '/src/Type/Php/StrContainingTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\StrIncrementDecrementFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/StrIncrementDecrementFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrPadFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/StrPadFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrRepeatFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/StrRepeatFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrSplitFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/StrSplitFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrTokFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/StrTokFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrWordCountFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/StrWordCountFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrlenFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/StrlenFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrrevFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/StrrevFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrtotimeFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/StrtotimeFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrvalFamilyFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/StrvalFamilyFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\SubstrDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/SubstrDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ThrowableReturnTypeExtension' => $baseDir . '/src/Type/Php/ThrowableReturnTypeExtension.php', 'PHPStan\\Type\\Php\\TriggerErrorDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/TriggerErrorDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\TrimFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/TrimFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\TypeSpecifyingFunctionsDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/TypeSpecifyingFunctionsDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\VersionCompareFunctionDynamicReturnTypeExtension' => $baseDir . '/src/Type/Php/VersionCompareFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\VersionCompareFunctionDynamicThrowTypeExtension' => $baseDir . '/src/Type/Php/VersionCompareFunctionDynamicThrowTypeExtension.php', 'PHPStan\\Type\\Php\\XMLReaderOpenReturnTypeExtension' => $baseDir . '/src/Type/Php/XMLReaderOpenReturnTypeExtension.php', 'PHPStan\\Type\\RecursionGuard' => $baseDir . '/src/Type/RecursionGuard.php', 'PHPStan\\Type\\Regex\\RegexAlternation' => $baseDir . '/src/Type/Regex/RegexAlternation.php', 'PHPStan\\Type\\Regex\\RegexAstWalkResult' => $baseDir . '/src/Type/Regex/RegexAstWalkResult.php', 'PHPStan\\Type\\Regex\\RegexCapturingGroup' => $baseDir . '/src/Type/Regex/RegexCapturingGroup.php', 'PHPStan\\Type\\Regex\\RegexExpressionHelper' => $baseDir . '/src/Type/Regex/RegexExpressionHelper.php', 'PHPStan\\Type\\Regex\\RegexGroupList' => $baseDir . '/src/Type/Regex/RegexGroupList.php', 'PHPStan\\Type\\Regex\\RegexGroupParser' => $baseDir . '/src/Type/Regex/RegexGroupParser.php', 'PHPStan\\Type\\Regex\\RegexGroupWalkResult' => $baseDir . '/src/Type/Regex/RegexGroupWalkResult.php', 'PHPStan\\Type\\Regex\\RegexNonCapturingGroup' => $baseDir . '/src/Type/Regex/RegexNonCapturingGroup.php', 'PHPStan\\Type\\ResourceType' => $baseDir . '/src/Type/ResourceType.php', 'PHPStan\\Type\\SimultaneousTypeTraverser' => $baseDir . '/src/Type/SimultaneousTypeTraverser.php', 'PHPStan\\Type\\StaticMethodParameterClosureThisExtension' => $baseDir . '/src/Type/StaticMethodParameterClosureThisExtension.php', 'PHPStan\\Type\\StaticMethodParameterClosureTypeExtension' => $baseDir . '/src/Type/StaticMethodParameterClosureTypeExtension.php', 'PHPStan\\Type\\StaticMethodParameterOutTypeExtension' => $baseDir . '/src/Type/StaticMethodParameterOutTypeExtension.php', 'PHPStan\\Type\\StaticMethodTypeSpecifyingExtension' => $baseDir . '/src/Type/StaticMethodTypeSpecifyingExtension.php', 'PHPStan\\Type\\StaticType' => $baseDir . '/src/Type/StaticType.php', 'PHPStan\\Type\\StaticTypeFactory' => $baseDir . '/src/Type/StaticTypeFactory.php', 'PHPStan\\Type\\StrictMixedType' => $baseDir . '/src/Type/StrictMixedType.php', 'PHPStan\\Type\\StringAlwaysAcceptingObjectWithToStringType' => $baseDir . '/src/Type/StringAlwaysAcceptingObjectWithToStringType.php', 'PHPStan\\Type\\StringNeverAcceptingObjectWithToStringType' => $baseDir . '/src/Type/StringNeverAcceptingObjectWithToStringType.php', 'PHPStan\\Type\\StringType' => $baseDir . '/src/Type/StringType.php', 'PHPStan\\Type\\SubtractableType' => $baseDir . '/src/Type/SubtractableType.php', 'PHPStan\\Type\\ThisType' => $baseDir . '/src/Type/ThisType.php', 'PHPStan\\Type\\Traits\\ArrayTypeTrait' => $baseDir . '/src/Type/Traits/ArrayTypeTrait.php', 'PHPStan\\Type\\Traits\\ConstantNumericComparisonTypeTrait' => $baseDir . '/src/Type/Traits/ConstantNumericComparisonTypeTrait.php', 'PHPStan\\Type\\Traits\\ConstantScalarTypeTrait' => $baseDir . '/src/Type/Traits/ConstantScalarTypeTrait.php', 'PHPStan\\Type\\Traits\\FalseyBooleanTypeTrait' => $baseDir . '/src/Type/Traits/FalseyBooleanTypeTrait.php', 'PHPStan\\Type\\Traits\\LateResolvableTypeTrait' => $baseDir . '/src/Type/Traits/LateResolvableTypeTrait.php', 'PHPStan\\Type\\Traits\\MaybeArrayTypeTrait' => $baseDir . '/src/Type/Traits/MaybeArrayTypeTrait.php', 'PHPStan\\Type\\Traits\\MaybeCallableTypeTrait' => $baseDir . '/src/Type/Traits/MaybeCallableTypeTrait.php', 'PHPStan\\Type\\Traits\\MaybeIterableTypeTrait' => $baseDir . '/src/Type/Traits/MaybeIterableTypeTrait.php', 'PHPStan\\Type\\Traits\\MaybeObjectTypeTrait' => $baseDir . '/src/Type/Traits/MaybeObjectTypeTrait.php', 'PHPStan\\Type\\Traits\\MaybeOffsetAccessibleTypeTrait' => $baseDir . '/src/Type/Traits/MaybeOffsetAccessibleTypeTrait.php', 'PHPStan\\Type\\Traits\\MaybeStringTypeTrait' => $baseDir . '/src/Type/Traits/MaybeStringTypeTrait.php', 'PHPStan\\Type\\Traits\\NonArrayTypeTrait' => $baseDir . '/src/Type/Traits/NonArrayTypeTrait.php', 'PHPStan\\Type\\Traits\\NonCallableTypeTrait' => $baseDir . '/src/Type/Traits/NonCallableTypeTrait.php', 'PHPStan\\Type\\Traits\\NonGeneralizableTypeTrait' => $baseDir . '/src/Type/Traits/NonGeneralizableTypeTrait.php', 'PHPStan\\Type\\Traits\\NonGenericTypeTrait' => $baseDir . '/src/Type/Traits/NonGenericTypeTrait.php', 'PHPStan\\Type\\Traits\\NonIterableTypeTrait' => $baseDir . '/src/Type/Traits/NonIterableTypeTrait.php', 'PHPStan\\Type\\Traits\\NonObjectTypeTrait' => $baseDir . '/src/Type/Traits/NonObjectTypeTrait.php', 'PHPStan\\Type\\Traits\\NonOffsetAccessibleTypeTrait' => $baseDir . '/src/Type/Traits/NonOffsetAccessibleTypeTrait.php', 'PHPStan\\Type\\Traits\\NonRemoveableTypeTrait' => $baseDir . '/src/Type/Traits/NonRemoveableTypeTrait.php', 'PHPStan\\Type\\Traits\\ObjectTypeTrait' => $baseDir . '/src/Type/Traits/ObjectTypeTrait.php', 'PHPStan\\Type\\Traits\\SubstractableTypeTrait' => $baseDir . '/src/Type/Traits/SubstractableTypeTrait.php', 'PHPStan\\Type\\Traits\\TruthyBooleanTypeTrait' => $baseDir . '/src/Type/Traits/TruthyBooleanTypeTrait.php', 'PHPStan\\Type\\Traits\\UndecidedBooleanTypeTrait' => $baseDir . '/src/Type/Traits/UndecidedBooleanTypeTrait.php', 'PHPStan\\Type\\Traits\\UndecidedComparisonCompoundTypeTrait' => $baseDir . '/src/Type/Traits/UndecidedComparisonCompoundTypeTrait.php', 'PHPStan\\Type\\Traits\\UndecidedComparisonTypeTrait' => $baseDir . '/src/Type/Traits/UndecidedComparisonTypeTrait.php', 'PHPStan\\Type\\Traverser\\LateResolvableTraverser' => $baseDir . '/src/Type/Traverser/LateResolvableTraverser.php', 'PHPStan\\Type\\Type' => $baseDir . '/src/Type/Type.php', 'PHPStan\\Type\\TypeAlias' => $baseDir . '/src/Type/TypeAlias.php', 'PHPStan\\Type\\TypeAliasResolver' => $baseDir . '/src/Type/TypeAliasResolver.php', 'PHPStan\\Type\\TypeAliasResolverProvider' => $baseDir . '/src/Type/TypeAliasResolverProvider.php', 'PHPStan\\Type\\TypeCombinator' => $baseDir . '/src/Type/TypeCombinator.php', 'PHPStan\\Type\\TypeResult' => $baseDir . '/src/Type/TypeResult.php', 'PHPStan\\Type\\TypeTraverser' => $baseDir . '/src/Type/TypeTraverser.php', 'PHPStan\\Type\\TypeTraverserCallable' => $baseDir . '/src/Type/TypeTraverserCallable.php', 'PHPStan\\Type\\TypeUtils' => $baseDir . '/src/Type/TypeUtils.php', 'PHPStan\\Type\\TypeWithClassName' => $baseDir . '/src/Type/TypeWithClassName.php', 'PHPStan\\Type\\TypehintHelper' => $baseDir . '/src/Type/TypehintHelper.php', 'PHPStan\\Type\\UnaryOperatorTypeSpecifyingExtension' => $baseDir . '/src/Type/UnaryOperatorTypeSpecifyingExtension.php', 'PHPStan\\Type\\UnaryOperatorTypeSpecifyingExtensionRegistry' => $baseDir . '/src/Type/UnaryOperatorTypeSpecifyingExtensionRegistry.php', 'PHPStan\\Type\\UnionType' => $baseDir . '/src/Type/UnionType.php', 'PHPStan\\Type\\UnionTypeHelper' => $baseDir . '/src/Type/UnionTypeHelper.php', 'PHPStan\\Type\\UsefulTypeAliasResolver' => $baseDir . '/src/Type/UsefulTypeAliasResolver.php', 'PHPStan\\Type\\ValueOfType' => $baseDir . '/src/Type/ValueOfType.php', 'PHPStan\\Type\\VerbosityLevel' => $baseDir . '/src/Type/VerbosityLevel.php', 'PHPStan\\Type\\VoidType' => $baseDir . '/src/Type/VoidType.php', 'Pdo\\Dblib' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Dblib.php', 'Pdo\\Firebird' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Firebird.php', 'Pdo\\Mysql' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Mysql.php', 'Pdo\\Odbc' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Odbc.php', 'Pdo\\Pgsql' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Pgsql.php', 'Pdo\\Sqlite' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Sqlite.php', 'PhpParser\\Builder' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder.php', 'PhpParser\\BuilderFactory' => $vendorDir . '/nikic/php-parser/lib/PhpParser/BuilderFactory.php', 'PhpParser\\BuilderHelpers' => $vendorDir . '/nikic/php-parser/lib/PhpParser/BuilderHelpers.php', 'PhpParser\\Builder\\ClassConst' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/ClassConst.php', 'PhpParser\\Builder\\Class_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Class_.php', 'PhpParser\\Builder\\Declaration' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Declaration.php', 'PhpParser\\Builder\\EnumCase' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php', 'PhpParser\\Builder\\Enum_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Enum_.php', 'PhpParser\\Builder\\FunctionLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php', 'PhpParser\\Builder\\Function_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Function_.php', 'PhpParser\\Builder\\Interface_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Interface_.php', 'PhpParser\\Builder\\Method' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Method.php', 'PhpParser\\Builder\\Namespace_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php', 'PhpParser\\Builder\\Param' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Param.php', 'PhpParser\\Builder\\Property' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Property.php', 'PhpParser\\Builder\\TraitUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php', 'PhpParser\\Builder\\TraitUseAdaptation' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php', 'PhpParser\\Builder\\Trait_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Trait_.php', 'PhpParser\\Builder\\Use_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Use_.php', 'PhpParser\\Comment' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Comment.php', 'PhpParser\\Comment\\Doc' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Comment/Doc.php', 'PhpParser\\ConstExprEvaluationException' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.php', 'PhpParser\\ConstExprEvaluator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php', 'PhpParser\\Error' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Error.php', 'PhpParser\\ErrorHandler' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ErrorHandler.php', 'PhpParser\\ErrorHandler\\Collecting' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php', 'PhpParser\\ErrorHandler\\Throwing' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php', 'PhpParser\\Internal\\DiffElem' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Internal/DiffElem.php', 'PhpParser\\Internal\\Differ' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Internal/Differ.php', 'PhpParser\\Internal\\PrintableNewAnonClassNode' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php', 'PhpParser\\Internal\\TokenPolyfill' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Internal/TokenPolyfill.php', 'PhpParser\\Internal\\TokenStream' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php', 'PhpParser\\JsonDecoder' => $vendorDir . '/nikic/php-parser/lib/PhpParser/JsonDecoder.php', 'PhpParser\\Lexer' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer.php', 'PhpParser\\Lexer\\Emulative' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php', 'PhpParser\\Lexer\\TokenEmulator\\AsymmetricVisibilityTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AsymmetricVisibilityTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\AttributeEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\EnumTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\ExplicitOctalEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\KeywordEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\MatchTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\NullsafeTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\PipeOperatorEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/PipeOperatorEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\PropertyTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/PropertyTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\ReadonlyFunctionTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyFunctionTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\ReadonlyTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\ReverseEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\TokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\VoidCastEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/VoidCastEmulator.php', 'PhpParser\\Modifiers' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Modifiers.php', 'PhpParser\\NameContext' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NameContext.php', 'PhpParser\\Node' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node.php', 'PhpParser\\NodeAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeAbstract.php', 'PhpParser\\NodeDumper' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeDumper.php', 'PhpParser\\NodeFinder' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeFinder.php', 'PhpParser\\NodeTraverser' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeTraverser.php', 'PhpParser\\NodeTraverserInterface' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php', 'PhpParser\\NodeVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor.php', 'PhpParser\\NodeVisitorAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php', 'PhpParser\\NodeVisitor\\CloningVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php', 'PhpParser\\NodeVisitor\\CommentAnnotatingVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/CommentAnnotatingVisitor.php', 'PhpParser\\NodeVisitor\\FindingVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php', 'PhpParser\\NodeVisitor\\FirstFindingVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php', 'PhpParser\\NodeVisitor\\NameResolver' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php', 'PhpParser\\NodeVisitor\\NodeConnectingVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php', 'PhpParser\\NodeVisitor\\ParentConnectingVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php', 'PhpParser\\Node\\Arg' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Arg.php', 'PhpParser\\Node\\ArrayItem' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/ArrayItem.php', 'PhpParser\\Node\\Attribute' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Attribute.php', 'PhpParser\\Node\\AttributeGroup' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php', 'PhpParser\\Node\\ClosureUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/ClosureUse.php', 'PhpParser\\Node\\ComplexType' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/ComplexType.php', 'PhpParser\\Node\\Const_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Const_.php', 'PhpParser\\Node\\DeclareItem' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/DeclareItem.php', 'PhpParser\\Node\\Expr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr.php', 'PhpParser\\Node\\Expr\\ArrayDimFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php', 'PhpParser\\Node\\Expr\\ArrayItem' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php', 'PhpParser\\Node\\Expr\\Array_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php', 'PhpParser\\Node\\Expr\\ArrowFunction' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php', 'PhpParser\\Node\\Expr\\Assign' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php', 'PhpParser\\Node\\Expr\\AssignOp' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php', 'PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', 'PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', 'PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', 'PhpParser\\Node\\Expr\\AssignOp\\Coalesce' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php', 'PhpParser\\Node\\Expr\\AssignOp\\Concat' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php', 'PhpParser\\Node\\Expr\\AssignOp\\Div' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php', 'PhpParser\\Node\\Expr\\AssignOp\\Minus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php', 'PhpParser\\Node\\Expr\\AssignOp\\Mod' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php', 'PhpParser\\Node\\Expr\\AssignOp\\Mul' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php', 'PhpParser\\Node\\Expr\\AssignOp\\Plus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php', 'PhpParser\\Node\\Expr\\AssignOp\\Pow' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php', 'PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', 'PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', 'PhpParser\\Node\\Expr\\AssignRef' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php', 'PhpParser\\Node\\Expr\\BinaryOp' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php', 'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', 'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', 'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', 'PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', 'PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Coalesce' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Concat' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Div' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Equal' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Greater' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php', 'PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Identical' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php', 'PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', 'PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', 'PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Minus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Mod' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Mul' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php', 'PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', 'PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Pipe' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pipe.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Plus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Pow' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php', 'PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', 'PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', 'PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Spaceship' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', 'PhpParser\\Node\\Expr\\BitwiseNot' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php', 'PhpParser\\Node\\Expr\\BooleanNot' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php', 'PhpParser\\Node\\Expr\\CallLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php', 'PhpParser\\Node\\Expr\\Cast' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php', 'PhpParser\\Node\\Expr\\Cast\\Array_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php', 'PhpParser\\Node\\Expr\\Cast\\Bool_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php', 'PhpParser\\Node\\Expr\\Cast\\Double' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php', 'PhpParser\\Node\\Expr\\Cast\\Int_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php', 'PhpParser\\Node\\Expr\\Cast\\Object_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php', 'PhpParser\\Node\\Expr\\Cast\\String_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php', 'PhpParser\\Node\\Expr\\Cast\\Unset_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php', 'PhpParser\\Node\\Expr\\Cast\\Void_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Void_.php', 'PhpParser\\Node\\Expr\\ClassConstFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php', 'PhpParser\\Node\\Expr\\Clone_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php', 'PhpParser\\Node\\Expr\\Closure' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php', 'PhpParser\\Node\\Expr\\ClosureUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php', 'PhpParser\\Node\\Expr\\ConstFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php', 'PhpParser\\Node\\Expr\\Empty_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php', 'PhpParser\\Node\\Expr\\Error' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php', 'PhpParser\\Node\\Expr\\ErrorSuppress' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php', 'PhpParser\\Node\\Expr\\Eval_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php', 'PhpParser\\Node\\Expr\\Exit_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php', 'PhpParser\\Node\\Expr\\FuncCall' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php', 'PhpParser\\Node\\Expr\\Include_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php', 'PhpParser\\Node\\Expr\\Instanceof_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php', 'PhpParser\\Node\\Expr\\Isset_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php', 'PhpParser\\Node\\Expr\\List_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php', 'PhpParser\\Node\\Expr\\Match_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php', 'PhpParser\\Node\\Expr\\MethodCall' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php', 'PhpParser\\Node\\Expr\\New_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php', 'PhpParser\\Node\\Expr\\NullsafeMethodCall' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php', 'PhpParser\\Node\\Expr\\NullsafePropertyFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php', 'PhpParser\\Node\\Expr\\PostDec' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php', 'PhpParser\\Node\\Expr\\PostInc' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php', 'PhpParser\\Node\\Expr\\PreDec' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php', 'PhpParser\\Node\\Expr\\PreInc' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php', 'PhpParser\\Node\\Expr\\Print_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php', 'PhpParser\\Node\\Expr\\PropertyFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php', 'PhpParser\\Node\\Expr\\ShellExec' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php', 'PhpParser\\Node\\Expr\\StaticCall' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php', 'PhpParser\\Node\\Expr\\StaticPropertyFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php', 'PhpParser\\Node\\Expr\\Ternary' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php', 'PhpParser\\Node\\Expr\\Throw_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php', 'PhpParser\\Node\\Expr\\UnaryMinus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php', 'PhpParser\\Node\\Expr\\UnaryPlus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php', 'PhpParser\\Node\\Expr\\Variable' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php', 'PhpParser\\Node\\Expr\\YieldFrom' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php', 'PhpParser\\Node\\Expr\\Yield_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php', 'PhpParser\\Node\\FunctionLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php', 'PhpParser\\Node\\Identifier' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Identifier.php', 'PhpParser\\Node\\InterpolatedStringPart' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/InterpolatedStringPart.php', 'PhpParser\\Node\\IntersectionType' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php', 'PhpParser\\Node\\MatchArm' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/MatchArm.php', 'PhpParser\\Node\\Name' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Name.php', 'PhpParser\\Node\\Name\\FullyQualified' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php', 'PhpParser\\Node\\Name\\Relative' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php', 'PhpParser\\Node\\NullableType' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/NullableType.php', 'PhpParser\\Node\\Param' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Param.php', 'PhpParser\\Node\\PropertyHook' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/PropertyHook.php', 'PhpParser\\Node\\PropertyItem' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/PropertyItem.php', 'PhpParser\\Node\\Scalar' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar.php', 'PhpParser\\Node\\Scalar\\DNumber' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php', 'PhpParser\\Node\\Scalar\\Encapsed' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php', 'PhpParser\\Node\\Scalar\\EncapsedStringPart' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php', 'PhpParser\\Node\\Scalar\\Float_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/Float_.php', 'PhpParser\\Node\\Scalar\\Int_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/Int_.php', 'PhpParser\\Node\\Scalar\\InterpolatedString' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/InterpolatedString.php', 'PhpParser\\Node\\Scalar\\LNumber' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php', 'PhpParser\\Node\\Scalar\\MagicConst' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php', 'PhpParser\\Node\\Scalar\\MagicConst\\Class_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php', 'PhpParser\\Node\\Scalar\\MagicConst\\Dir' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php', 'PhpParser\\Node\\Scalar\\MagicConst\\File' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php', 'PhpParser\\Node\\Scalar\\MagicConst\\Function_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php', 'PhpParser\\Node\\Scalar\\MagicConst\\Line' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php', 'PhpParser\\Node\\Scalar\\MagicConst\\Method' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php', 'PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', 'PhpParser\\Node\\Scalar\\MagicConst\\Property' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Property.php', 'PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', 'PhpParser\\Node\\Scalar\\String_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php', 'PhpParser\\Node\\StaticVar' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/StaticVar.php', 'PhpParser\\Node\\Stmt' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt.php', 'PhpParser\\Node\\Stmt\\Block' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Block.php', 'PhpParser\\Node\\Stmt\\Break_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php', 'PhpParser\\Node\\Stmt\\Case_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php', 'PhpParser\\Node\\Stmt\\Catch_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php', 'PhpParser\\Node\\Stmt\\ClassConst' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php', 'PhpParser\\Node\\Stmt\\ClassLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php', 'PhpParser\\Node\\Stmt\\ClassMethod' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php', 'PhpParser\\Node\\Stmt\\Class_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php', 'PhpParser\\Node\\Stmt\\Const_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php', 'PhpParser\\Node\\Stmt\\Continue_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php', 'PhpParser\\Node\\Stmt\\DeclareDeclare' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php', 'PhpParser\\Node\\Stmt\\Declare_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php', 'PhpParser\\Node\\Stmt\\Do_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php', 'PhpParser\\Node\\Stmt\\Echo_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php', 'PhpParser\\Node\\Stmt\\ElseIf_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php', 'PhpParser\\Node\\Stmt\\Else_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php', 'PhpParser\\Node\\Stmt\\EnumCase' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php', 'PhpParser\\Node\\Stmt\\Enum_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php', 'PhpParser\\Node\\Stmt\\Expression' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php', 'PhpParser\\Node\\Stmt\\Finally_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php', 'PhpParser\\Node\\Stmt\\For_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php', 'PhpParser\\Node\\Stmt\\Foreach_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php', 'PhpParser\\Node\\Stmt\\Function_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php', 'PhpParser\\Node\\Stmt\\Global_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php', 'PhpParser\\Node\\Stmt\\Goto_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php', 'PhpParser\\Node\\Stmt\\GroupUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php', 'PhpParser\\Node\\Stmt\\HaltCompiler' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php', 'PhpParser\\Node\\Stmt\\If_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php', 'PhpParser\\Node\\Stmt\\InlineHTML' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php', 'PhpParser\\Node\\Stmt\\Interface_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php', 'PhpParser\\Node\\Stmt\\Label' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php', 'PhpParser\\Node\\Stmt\\Namespace_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php', 'PhpParser\\Node\\Stmt\\Nop' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php', 'PhpParser\\Node\\Stmt\\Property' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php', 'PhpParser\\Node\\Stmt\\PropertyProperty' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php', 'PhpParser\\Node\\Stmt\\Return_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php', 'PhpParser\\Node\\Stmt\\StaticVar' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php', 'PhpParser\\Node\\Stmt\\Static_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php', 'PhpParser\\Node\\Stmt\\Switch_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php', 'PhpParser\\Node\\Stmt\\TraitUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php', 'PhpParser\\Node\\Stmt\\TraitUseAdaptation' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', 'PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Alias' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', 'PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Precedence' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', 'PhpParser\\Node\\Stmt\\Trait_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php', 'PhpParser\\Node\\Stmt\\TryCatch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php', 'PhpParser\\Node\\Stmt\\Unset_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php', 'PhpParser\\Node\\Stmt\\UseUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php', 'PhpParser\\Node\\Stmt\\Use_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php', 'PhpParser\\Node\\Stmt\\While_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php', 'PhpParser\\Node\\UnionType' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/UnionType.php', 'PhpParser\\Node\\UseItem' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/UseItem.php', 'PhpParser\\Node\\VarLikeIdentifier' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php', 'PhpParser\\Node\\VariadicPlaceholder' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php', 'PhpParser\\Parser' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser.php', 'PhpParser\\ParserAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ParserAbstract.php', 'PhpParser\\ParserFactory' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ParserFactory.php', 'PhpParser\\Parser\\Php7' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser/Php7.php', 'PhpParser\\Parser\\Php8' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser/Php8.php', 'PhpParser\\PhpVersion' => $vendorDir . '/nikic/php-parser/lib/PhpParser/PhpVersion.php', 'PhpParser\\PrettyPrinter' => $vendorDir . '/nikic/php-parser/lib/PhpParser/PrettyPrinter.php', 'PhpParser\\PrettyPrinterAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php', 'PhpParser\\PrettyPrinter\\Standard' => $vendorDir . '/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php', 'PhpParser\\Token' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Token.php', 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 'ReflectionConstant' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php', 'ReturnTypeWillChange' => $vendorDir . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php', 'RoundingMode' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/RoundingMode.php', 'SQLite3Exception' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php', 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'Symfony\\Polyfill\\Intl\\Grapheme\\Grapheme' => $vendorDir . '/symfony/polyfill-intl-grapheme/Grapheme.php', 'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Normalizer.php', 'Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/symfony/polyfill-mbstring/Mbstring.php', 'Symfony\\Polyfill\\Php80\\Php80' => $vendorDir . '/symfony/polyfill-php80/Php80.php', 'Symfony\\Polyfill\\Php80\\PhpToken' => $vendorDir . '/symfony/polyfill-php80/PhpToken.php', 'Symfony\\Polyfill\\Php81\\Php81' => $vendorDir . '/symfony/polyfill-php81/Php81.php', 'Symfony\\Polyfill\\Php83\\Php83' => $vendorDir . '/symfony/polyfill-php83/Php83.php', 'Symfony\\Polyfill\\Php84\\Php84' => $vendorDir . '/symfony/polyfill-php84/Php84.php', 'Symfony\\Polyfill\\Php85\\Php85' => $vendorDir . '/symfony/polyfill-php85/Php85.php', 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', '_PHPStan_33c983f26\\Clue\\React\\NDJson\\Decoder' => $vendorDir . '/clue/ndjson-react/src/Decoder.php', '_PHPStan_33c983f26\\Clue\\React\\NDJson\\Encoder' => $vendorDir . '/clue/ndjson-react/src/Encoder.php', '_PHPStan_33c983f26\\Composer\\Pcre\\MatchAllResult' => $vendorDir . '/composer/pcre/src/MatchAllResult.php', '_PHPStan_33c983f26\\Composer\\Pcre\\MatchAllStrictGroupsResult' => $vendorDir . '/composer/pcre/src/MatchAllStrictGroupsResult.php', '_PHPStan_33c983f26\\Composer\\Pcre\\MatchAllWithOffsetsResult' => $vendorDir . '/composer/pcre/src/MatchAllWithOffsetsResult.php', '_PHPStan_33c983f26\\Composer\\Pcre\\MatchResult' => $vendorDir . '/composer/pcre/src/MatchResult.php', '_PHPStan_33c983f26\\Composer\\Pcre\\MatchStrictGroupsResult' => $vendorDir . '/composer/pcre/src/MatchStrictGroupsResult.php', '_PHPStan_33c983f26\\Composer\\Pcre\\MatchWithOffsetsResult' => $vendorDir . '/composer/pcre/src/MatchWithOffsetsResult.php', '_PHPStan_33c983f26\\Composer\\Pcre\\PcreException' => $vendorDir . '/composer/pcre/src/PcreException.php', '_PHPStan_33c983f26\\Composer\\Pcre\\Preg' => $vendorDir . '/composer/pcre/src/Preg.php', '_PHPStan_33c983f26\\Composer\\Pcre\\Regex' => $vendorDir . '/composer/pcre/src/Regex.php', '_PHPStan_33c983f26\\Composer\\Pcre\\ReplaceResult' => $vendorDir . '/composer/pcre/src/ReplaceResult.php', '_PHPStan_33c983f26\\Composer\\Pcre\\UnexpectedNullMatchException' => $vendorDir . '/composer/pcre/src/UnexpectedNullMatchException.php', '_PHPStan_33c983f26\\Composer\\Semver\\Comparator' => $vendorDir . '/composer/semver/src/Comparator.php', '_PHPStan_33c983f26\\Composer\\Semver\\CompilingMatcher' => $vendorDir . '/composer/semver/src/CompilingMatcher.php', '_PHPStan_33c983f26\\Composer\\Semver\\Constraint\\Bound' => $vendorDir . '/composer/semver/src/Constraint/Bound.php', '_PHPStan_33c983f26\\Composer\\Semver\\Constraint\\Constraint' => $vendorDir . '/composer/semver/src/Constraint/Constraint.php', '_PHPStan_33c983f26\\Composer\\Semver\\Constraint\\ConstraintInterface' => $vendorDir . '/composer/semver/src/Constraint/ConstraintInterface.php', '_PHPStan_33c983f26\\Composer\\Semver\\Constraint\\MatchAllConstraint' => $vendorDir . '/composer/semver/src/Constraint/MatchAllConstraint.php', '_PHPStan_33c983f26\\Composer\\Semver\\Constraint\\MatchNoneConstraint' => $vendorDir . '/composer/semver/src/Constraint/MatchNoneConstraint.php', '_PHPStan_33c983f26\\Composer\\Semver\\Constraint\\MultiConstraint' => $vendorDir . '/composer/semver/src/Constraint/MultiConstraint.php', '_PHPStan_33c983f26\\Composer\\Semver\\Interval' => $vendorDir . '/composer/semver/src/Interval.php', '_PHPStan_33c983f26\\Composer\\Semver\\Intervals' => $vendorDir . '/composer/semver/src/Intervals.php', '_PHPStan_33c983f26\\Composer\\Semver\\Semver' => $vendorDir . '/composer/semver/src/Semver.php', '_PHPStan_33c983f26\\Composer\\Semver\\VersionParser' => $vendorDir . '/composer/semver/src/VersionParser.php', '_PHPStan_33c983f26\\Composer\\XdebugHandler\\PhpConfig' => $vendorDir . '/composer/xdebug-handler/src/PhpConfig.php', '_PHPStan_33c983f26\\Composer\\XdebugHandler\\Process' => $vendorDir . '/composer/xdebug-handler/src/Process.php', '_PHPStan_33c983f26\\Composer\\XdebugHandler\\Status' => $vendorDir . '/composer/xdebug-handler/src/Status.php', '_PHPStan_33c983f26\\Composer\\XdebugHandler\\XdebugHandler' => $vendorDir . '/composer/xdebug-handler/src/XdebugHandler.php', '_PHPStan_33c983f26\\Evenement\\EventEmitter' => $vendorDir . '/evenement/evenement/src/EventEmitter.php', '_PHPStan_33c983f26\\Evenement\\EventEmitterInterface' => $vendorDir . '/evenement/evenement/src/EventEmitterInterface.php', '_PHPStan_33c983f26\\Evenement\\EventEmitterTrait' => $vendorDir . '/evenement/evenement/src/EventEmitterTrait.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\CpuCoreCounter' => $vendorDir . '/fidry/cpu-core-counter/src/CpuCoreCounter.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Diagnoser' => $vendorDir . '/fidry/cpu-core-counter/src/Diagnoser.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Executor\\ProcOpenExecutor' => $vendorDir . '/fidry/cpu-core-counter/src/Executor/ProcOpenExecutor.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Executor\\ProcessExecutor' => $vendorDir . '/fidry/cpu-core-counter/src/Executor/ProcessExecutor.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\CmiCmdletLogicalFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/CmiCmdletLogicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\CmiCmdletPhysicalFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/CmiCmdletPhysicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\CpuCoreFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/CpuCoreFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\CpuInfoFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/CpuInfoFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\DummyCpuCoreFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/DummyCpuCoreFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\EnvVariableFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/EnvVariableFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\FinderRegistry' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/FinderRegistry.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\HwLogicalFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/HwLogicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\HwPhysicalFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/HwPhysicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\LscpuLogicalFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/LscpuLogicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\LscpuPhysicalFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/LscpuPhysicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\NProcFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/NProcFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\NProcessorFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/NProcessorFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\NullCpuCoreFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/NullCpuCoreFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\OnlyInPowerShellFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/OnlyInPowerShellFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\OnlyOnOSFamilyFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/OnlyOnOSFamilyFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\ProcOpenBasedFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/ProcOpenBasedFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\SkipOnOSFamilyFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/SkipOnOSFamilyFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\WindowsRegistryLogicalFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/WindowsRegistryLogicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\WmicLogicalFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/WmicLogicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\WmicPhysicalFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/WmicPhysicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\_NProcessorFinder' => $vendorDir . '/fidry/cpu-core-counter/src/Finder/_NProcessorFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\NumberOfCpuCoreNotFound' => $vendorDir . '/fidry/cpu-core-counter/src/NumberOfCpuCoreNotFound.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\ParallelisationResult' => $vendorDir . '/fidry/cpu-core-counter/src/ParallelisationResult.php', '_PHPStan_33c983f26\\GuzzleHttp\\BodySummarizer' => $vendorDir . '/guzzlehttp/guzzle/src/BodySummarizer.php', '_PHPStan_33c983f26\\GuzzleHttp\\BodySummarizerInterface' => $vendorDir . '/guzzlehttp/guzzle/src/BodySummarizerInterface.php', '_PHPStan_33c983f26\\GuzzleHttp\\Client' => $vendorDir . '/guzzlehttp/guzzle/src/Client.php', '_PHPStan_33c983f26\\GuzzleHttp\\ClientInterface' => $vendorDir . '/guzzlehttp/guzzle/src/ClientInterface.php', '_PHPStan_33c983f26\\GuzzleHttp\\ClientTrait' => $vendorDir . '/guzzlehttp/guzzle/src/ClientTrait.php', '_PHPStan_33c983f26\\GuzzleHttp\\Cookie\\CookieJar' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/CookieJar.php', '_PHPStan_33c983f26\\GuzzleHttp\\Cookie\\CookieJarInterface' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php', '_PHPStan_33c983f26\\GuzzleHttp\\Cookie\\FileCookieJar' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php', '_PHPStan_33c983f26\\GuzzleHttp\\Cookie\\SessionCookieJar' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php', '_PHPStan_33c983f26\\GuzzleHttp\\Cookie\\SetCookie' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/SetCookie.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\BadResponseException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/BadResponseException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\ClientException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/ClientException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\ConnectException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/ConnectException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\GuzzleException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/GuzzleException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\InvalidArgumentException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\RequestException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/RequestException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\ServerException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/ServerException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\TooManyRedirectsException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\TransferException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/TransferException.php', '_PHPStan_33c983f26\\GuzzleHttp\\HandlerStack' => $vendorDir . '/guzzlehttp/guzzle/src/HandlerStack.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\CurlFactory' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/CurlFactory.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\CurlFactoryInterface' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\CurlHandler' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/CurlHandler.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\CurlMultiHandler' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\EasyHandle' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/EasyHandle.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\HeaderProcessor' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\MockHandler' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/MockHandler.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\Proxy' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/Proxy.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\StreamHandler' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/StreamHandler.php', '_PHPStan_33c983f26\\GuzzleHttp\\MessageFormatter' => $vendorDir . '/guzzlehttp/guzzle/src/MessageFormatter.php', '_PHPStan_33c983f26\\GuzzleHttp\\MessageFormatterInterface' => $vendorDir . '/guzzlehttp/guzzle/src/MessageFormatterInterface.php', '_PHPStan_33c983f26\\GuzzleHttp\\Middleware' => $vendorDir . '/guzzlehttp/guzzle/src/Middleware.php', '_PHPStan_33c983f26\\GuzzleHttp\\Pool' => $vendorDir . '/guzzlehttp/guzzle/src/Pool.php', '_PHPStan_33c983f26\\GuzzleHttp\\PrepareBodyMiddleware' => $vendorDir . '/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\AggregateException' => $vendorDir . '/guzzlehttp/promises/src/AggregateException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\CancellationException' => $vendorDir . '/guzzlehttp/promises/src/CancellationException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\Coroutine' => $vendorDir . '/guzzlehttp/promises/src/Coroutine.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\Create' => $vendorDir . '/guzzlehttp/promises/src/Create.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\Each' => $vendorDir . '/guzzlehttp/promises/src/Each.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\EachPromise' => $vendorDir . '/guzzlehttp/promises/src/EachPromise.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\FulfilledPromise' => $vendorDir . '/guzzlehttp/promises/src/FulfilledPromise.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\Is' => $vendorDir . '/guzzlehttp/promises/src/Is.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\Promise' => $vendorDir . '/guzzlehttp/promises/src/Promise.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\PromiseInterface' => $vendorDir . '/guzzlehttp/promises/src/PromiseInterface.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\PromisorInterface' => $vendorDir . '/guzzlehttp/promises/src/PromisorInterface.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\RejectedPromise' => $vendorDir . '/guzzlehttp/promises/src/RejectedPromise.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\RejectionException' => $vendorDir . '/guzzlehttp/promises/src/RejectionException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\TaskQueue' => $vendorDir . '/guzzlehttp/promises/src/TaskQueue.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\TaskQueueInterface' => $vendorDir . '/guzzlehttp/promises/src/TaskQueueInterface.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\Utils' => $vendorDir . '/guzzlehttp/promises/src/Utils.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\AppendStream' => $vendorDir . '/guzzlehttp/psr7/src/AppendStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\BufferStream' => $vendorDir . '/guzzlehttp/psr7/src/BufferStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\CachingStream' => $vendorDir . '/guzzlehttp/psr7/src/CachingStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\DroppingStream' => $vendorDir . '/guzzlehttp/psr7/src/DroppingStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Exception\\MalformedUriException' => $vendorDir . '/guzzlehttp/psr7/src/Exception/MalformedUriException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\FnStream' => $vendorDir . '/guzzlehttp/psr7/src/FnStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Header' => $vendorDir . '/guzzlehttp/psr7/src/Header.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\HttpFactory' => $vendorDir . '/guzzlehttp/psr7/src/HttpFactory.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\InflateStream' => $vendorDir . '/guzzlehttp/psr7/src/InflateStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\LazyOpenStream' => $vendorDir . '/guzzlehttp/psr7/src/LazyOpenStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\LimitStream' => $vendorDir . '/guzzlehttp/psr7/src/LimitStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Message' => $vendorDir . '/guzzlehttp/psr7/src/Message.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\MessageTrait' => $vendorDir . '/guzzlehttp/psr7/src/MessageTrait.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\MimeType' => $vendorDir . '/guzzlehttp/psr7/src/MimeType.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\MultipartStream' => $vendorDir . '/guzzlehttp/psr7/src/MultipartStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\NoSeekStream' => $vendorDir . '/guzzlehttp/psr7/src/NoSeekStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\PumpStream' => $vendorDir . '/guzzlehttp/psr7/src/PumpStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Query' => $vendorDir . '/guzzlehttp/psr7/src/Query.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Request' => $vendorDir . '/guzzlehttp/psr7/src/Request.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Response' => $vendorDir . '/guzzlehttp/psr7/src/Response.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Rfc7230' => $vendorDir . '/guzzlehttp/psr7/src/Rfc7230.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\ServerRequest' => $vendorDir . '/guzzlehttp/psr7/src/ServerRequest.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Stream' => $vendorDir . '/guzzlehttp/psr7/src/Stream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\StreamDecoratorTrait' => $vendorDir . '/guzzlehttp/psr7/src/StreamDecoratorTrait.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\StreamWrapper' => $vendorDir . '/guzzlehttp/psr7/src/StreamWrapper.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\UploadedFile' => $vendorDir . '/guzzlehttp/psr7/src/UploadedFile.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Uri' => $vendorDir . '/guzzlehttp/psr7/src/Uri.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\UriComparator' => $vendorDir . '/guzzlehttp/psr7/src/UriComparator.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\UriNormalizer' => $vendorDir . '/guzzlehttp/psr7/src/UriNormalizer.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\UriResolver' => $vendorDir . '/guzzlehttp/psr7/src/UriResolver.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Utils' => $vendorDir . '/guzzlehttp/psr7/src/Utils.php', '_PHPStan_33c983f26\\GuzzleHttp\\RedirectMiddleware' => $vendorDir . '/guzzlehttp/guzzle/src/RedirectMiddleware.php', '_PHPStan_33c983f26\\GuzzleHttp\\RequestOptions' => $vendorDir . '/guzzlehttp/guzzle/src/RequestOptions.php', '_PHPStan_33c983f26\\GuzzleHttp\\RetryMiddleware' => $vendorDir . '/guzzlehttp/guzzle/src/RetryMiddleware.php', '_PHPStan_33c983f26\\GuzzleHttp\\TransferStats' => $vendorDir . '/guzzlehttp/guzzle/src/TransferStats.php', '_PHPStan_33c983f26\\GuzzleHttp\\Utils' => $vendorDir . '/guzzlehttp/guzzle/src/Utils.php', '_PHPStan_33c983f26\\Nette\\ArgumentOutOfRangeException' => $vendorDir . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\Bootstrap\\Configurator' => $vendorDir . '/nette/bootstrap/src/Bootstrap/Configurator.php', '_PHPStan_33c983f26\\Nette\\Bootstrap\\Extensions\\ConstantsExtension' => $vendorDir . '/nette/bootstrap/src/Bootstrap/Extensions/ConstantsExtension.php', '_PHPStan_33c983f26\\Nette\\Bootstrap\\Extensions\\PhpExtension' => $vendorDir . '/nette/bootstrap/src/Bootstrap/Extensions/PhpExtension.php', '_PHPStan_33c983f26\\Nette\\Bridges\\DITracy\\ContainerPanel' => $vendorDir . '/nette/di/src/Bridges/DITracy/ContainerPanel.php', '_PHPStan_33c983f26\\Nette\\Configurator' => $vendorDir . '/nette/bootstrap/src/Configurator.php', '_PHPStan_33c983f26\\Nette\\DI\\Attributes\\Inject' => $vendorDir . '/nette/di/src/DI/Attributes/Inject.php', '_PHPStan_33c983f26\\Nette\\DI\\Autowiring' => $vendorDir . '/nette/di/src/DI/Autowiring.php', '_PHPStan_33c983f26\\Nette\\DI\\Compiler' => $vendorDir . '/nette/di/src/DI/Compiler.php', '_PHPStan_33c983f26\\Nette\\DI\\CompilerExtension' => $vendorDir . '/nette/di/src/DI/CompilerExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Config\\Adapter' => $vendorDir . '/nette/di/src/DI/Config/Adapter.php', '_PHPStan_33c983f26\\Nette\\DI\\Config\\Adapters\\NeonAdapter' => $vendorDir . '/nette/di/src/DI/Config/Adapters/NeonAdapter.php', '_PHPStan_33c983f26\\Nette\\DI\\Config\\Adapters\\PhpAdapter' => $vendorDir . '/nette/di/src/DI/Config/Adapters/PhpAdapter.php', '_PHPStan_33c983f26\\Nette\\DI\\Config\\Helpers' => $vendorDir . '/nette/di/src/DI/Config/Helpers.php', '_PHPStan_33c983f26\\Nette\\DI\\Config\\IAdapter' => $vendorDir . '/nette/di/src/compatibility.php', '_PHPStan_33c983f26\\Nette\\DI\\Config\\Loader' => $vendorDir . '/nette/di/src/DI/Config/Loader.php', '_PHPStan_33c983f26\\Nette\\DI\\Container' => $vendorDir . '/nette/di/src/DI/Container.php', '_PHPStan_33c983f26\\Nette\\DI\\ContainerBuilder' => $vendorDir . '/nette/di/src/DI/ContainerBuilder.php', '_PHPStan_33c983f26\\Nette\\DI\\ContainerLoader' => $vendorDir . '/nette/di/src/DI/ContainerLoader.php', '_PHPStan_33c983f26\\Nette\\DI\\Definitions\\AccessorDefinition' => $vendorDir . '/nette/di/src/DI/Definitions/AccessorDefinition.php', '_PHPStan_33c983f26\\Nette\\DI\\Definitions\\Definition' => $vendorDir . '/nette/di/src/DI/Definitions/Definition.php', '_PHPStan_33c983f26\\Nette\\DI\\Definitions\\FactoryDefinition' => $vendorDir . '/nette/di/src/DI/Definitions/FactoryDefinition.php', '_PHPStan_33c983f26\\Nette\\DI\\Definitions\\ImportedDefinition' => $vendorDir . '/nette/di/src/DI/Definitions/ImportedDefinition.php', '_PHPStan_33c983f26\\Nette\\DI\\Definitions\\LocatorDefinition' => $vendorDir . '/nette/di/src/DI/Definitions/LocatorDefinition.php', '_PHPStan_33c983f26\\Nette\\DI\\Definitions\\Reference' => $vendorDir . '/nette/di/src/DI/Definitions/Reference.php', '_PHPStan_33c983f26\\Nette\\DI\\Definitions\\ServiceDefinition' => $vendorDir . '/nette/di/src/DI/Definitions/ServiceDefinition.php', '_PHPStan_33c983f26\\Nette\\DI\\Definitions\\Statement' => $vendorDir . '/nette/di/src/DI/Definitions/Statement.php', '_PHPStan_33c983f26\\Nette\\DI\\DependencyChecker' => $vendorDir . '/nette/di/src/DI/DependencyChecker.php', '_PHPStan_33c983f26\\Nette\\DI\\DynamicParameter' => $vendorDir . '/nette/di/src/DI/DynamicParameter.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\ConstantsExtension' => $vendorDir . '/nette/di/src/DI/Extensions/ConstantsExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\DIExtension' => $vendorDir . '/nette/di/src/DI/Extensions/DIExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\DecoratorExtension' => $vendorDir . '/nette/di/src/DI/Extensions/DecoratorExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\DefinitionSchema' => $vendorDir . '/nette/di/src/DI/Extensions/DefinitionSchema.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\ExtensionsExtension' => $vendorDir . '/nette/di/src/DI/Extensions/ExtensionsExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\InjectExtension' => $vendorDir . '/nette/di/src/DI/Extensions/InjectExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\ParametersExtension' => $vendorDir . '/nette/di/src/DI/Extensions/ParametersExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\PhpExtension' => $vendorDir . '/nette/di/src/DI/Extensions/PhpExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\SearchExtension' => $vendorDir . '/nette/di/src/DI/Extensions/SearchExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\ServicesExtension' => $vendorDir . '/nette/di/src/DI/Extensions/ServicesExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Helpers' => $vendorDir . '/nette/di/src/DI/Helpers.php', '_PHPStan_33c983f26\\Nette\\DI\\InvalidConfigurationException' => $vendorDir . '/nette/di/src/DI/exceptions.php', '_PHPStan_33c983f26\\Nette\\DI\\MissingServiceException' => $vendorDir . '/nette/di/src/DI/exceptions.php', '_PHPStan_33c983f26\\Nette\\DI\\NotAllowedDuringResolvingException' => $vendorDir . '/nette/di/src/DI/exceptions.php', '_PHPStan_33c983f26\\Nette\\DI\\PhpGenerator' => $vendorDir . '/nette/di/src/DI/PhpGenerator.php', '_PHPStan_33c983f26\\Nette\\DI\\Resolver' => $vendorDir . '/nette/di/src/DI/Resolver.php', '_PHPStan_33c983f26\\Nette\\DI\\ServiceCreationException' => $vendorDir . '/nette/di/src/DI/exceptions.php', '_PHPStan_33c983f26\\Nette\\DI\\ServiceDefinition' => $vendorDir . '/nette/di/src/compatibility.php', '_PHPStan_33c983f26\\Nette\\DI\\Statement' => $vendorDir . '/nette/di/src/compatibility.php', '_PHPStan_33c983f26\\Nette\\DeprecatedException' => $vendorDir . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\DirectoryNotFoundException' => $vendorDir . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\FileNotFoundException' => $vendorDir . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\HtmlStringable' => $vendorDir . '/nette/utils/src/HtmlStringable.php', '_PHPStan_33c983f26\\Nette\\IOException' => $vendorDir . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\InvalidArgumentException' => $vendorDir . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\InvalidStateException' => $vendorDir . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\Iterators\\CachingIterator' => $vendorDir . '/nette/utils/src/Iterators/CachingIterator.php', '_PHPStan_33c983f26\\Nette\\Iterators\\Mapper' => $vendorDir . '/nette/utils/src/Iterators/Mapper.php', '_PHPStan_33c983f26\\Nette\\Loaders\\RobotLoader' => $vendorDir . '/nette/robot-loader/src/RobotLoader/RobotLoader.php', '_PHPStan_33c983f26\\Nette\\Localization\\ITranslator' => $vendorDir . '/nette/utils/src/compatibility.php', '_PHPStan_33c983f26\\Nette\\Localization\\Translator' => $vendorDir . '/nette/utils/src/Translator.php', '_PHPStan_33c983f26\\Nette\\MemberAccessException' => $vendorDir . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\Neon\\Decoder' => $vendorDir . '/nette/neon/src/Neon/Decoder.php', '_PHPStan_33c983f26\\Nette\\Neon\\Encoder' => $vendorDir . '/nette/neon/src/Neon/Encoder.php', '_PHPStan_33c983f26\\Nette\\Neon\\Entity' => $vendorDir . '/nette/neon/src/Neon/Entity.php', '_PHPStan_33c983f26\\Nette\\Neon\\Exception' => $vendorDir . '/nette/neon/src/Neon/Exception.php', '_PHPStan_33c983f26\\Nette\\Neon\\Lexer' => $vendorDir . '/nette/neon/src/Neon/Lexer.php', '_PHPStan_33c983f26\\Nette\\Neon\\Neon' => $vendorDir . '/nette/neon/src/Neon/Neon.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node' => $vendorDir . '/nette/neon/src/Neon/Node.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node\\ArrayItemNode' => $vendorDir . '/nette/neon/src/Neon/Node/ArrayItemNode.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node\\ArrayNode' => $vendorDir . '/nette/neon/src/Neon/Node/ArrayNode.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node\\BlockArrayNode' => $vendorDir . '/nette/neon/src/Neon/Node/BlockArrayNode.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node\\EntityChainNode' => $vendorDir . '/nette/neon/src/Neon/Node/EntityChainNode.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node\\EntityNode' => $vendorDir . '/nette/neon/src/Neon/Node/EntityNode.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node\\InlineArrayNode' => $vendorDir . '/nette/neon/src/Neon/Node/InlineArrayNode.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node\\LiteralNode' => $vendorDir . '/nette/neon/src/Neon/Node/LiteralNode.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node\\StringNode' => $vendorDir . '/nette/neon/src/Neon/Node/StringNode.php', '_PHPStan_33c983f26\\Nette\\Neon\\Parser' => $vendorDir . '/nette/neon/src/Neon/Parser.php', '_PHPStan_33c983f26\\Nette\\Neon\\Token' => $vendorDir . '/nette/neon/src/Neon/Token.php', '_PHPStan_33c983f26\\Nette\\Neon\\TokenStream' => $vendorDir . '/nette/neon/src/Neon/TokenStream.php', '_PHPStan_33c983f26\\Nette\\Neon\\Traverser' => $vendorDir . '/nette/neon/src/Neon/Traverser.php', '_PHPStan_33c983f26\\Nette\\NotImplementedException' => $vendorDir . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\NotSupportedException' => $vendorDir . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\OutOfRangeException' => $vendorDir . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Attribute' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Attribute.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\ClassType' => $vendorDir . '/nette/php-generator/src/PhpGenerator/ClassType.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Closure' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Closure.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Constant' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Constant.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Dumper' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Dumper.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\EnumCase' => $vendorDir . '/nette/php-generator/src/PhpGenerator/EnumCase.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Extractor' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Extractor.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Factory' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Factory.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\GlobalFunction' => $vendorDir . '/nette/php-generator/src/PhpGenerator/GlobalFunction.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Helpers' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Helpers.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Literal' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Literal.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Method' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Method.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Parameter' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Parameter.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\PhpFile' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PhpFile.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\PhpLiteral' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PhpLiteral.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\PhpNamespace' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PhpNamespace.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Printer' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Printer.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\PromotedParameter' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PromotedParameter.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Property' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Property.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\PsrPrinter' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PsrPrinter.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\TraitUse' => $vendorDir . '/nette/php-generator/src/PhpGenerator/TraitUse.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Traits\\AttributeAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/AttributeAware.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Traits\\CommentAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/CommentAware.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Traits\\FunctionLike' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/FunctionLike.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Traits\\NameAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/NameAware.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Traits\\VisibilityAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/VisibilityAware.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Type' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Type.php', '_PHPStan_33c983f26\\Nette\\Schema\\Context' => $vendorDir . '/nette/schema/src/Schema/Context.php', '_PHPStan_33c983f26\\Nette\\Schema\\DynamicParameter' => $vendorDir . '/nette/schema/src/Schema/DynamicParameter.php', '_PHPStan_33c983f26\\Nette\\Schema\\Elements\\AnyOf' => $vendorDir . '/nette/schema/src/Schema/Elements/AnyOf.php', '_PHPStan_33c983f26\\Nette\\Schema\\Elements\\Base' => $vendorDir . '/nette/schema/src/Schema/Elements/Base.php', '_PHPStan_33c983f26\\Nette\\Schema\\Elements\\Structure' => $vendorDir . '/nette/schema/src/Schema/Elements/Structure.php', '_PHPStan_33c983f26\\Nette\\Schema\\Elements\\Type' => $vendorDir . '/nette/schema/src/Schema/Elements/Type.php', '_PHPStan_33c983f26\\Nette\\Schema\\Expect' => $vendorDir . '/nette/schema/src/Schema/Expect.php', '_PHPStan_33c983f26\\Nette\\Schema\\Helpers' => $vendorDir . '/nette/schema/src/Schema/Helpers.php', '_PHPStan_33c983f26\\Nette\\Schema\\Message' => $vendorDir . '/nette/schema/src/Schema/Message.php', '_PHPStan_33c983f26\\Nette\\Schema\\Processor' => $vendorDir . '/nette/schema/src/Schema/Processor.php', '_PHPStan_33c983f26\\Nette\\Schema\\Schema' => $vendorDir . '/nette/schema/src/Schema/Schema.php', '_PHPStan_33c983f26\\Nette\\Schema\\ValidationException' => $vendorDir . '/nette/schema/src/Schema/ValidationException.php', '_PHPStan_33c983f26\\Nette\\SmartObject' => $vendorDir . '/nette/utils/src/SmartObject.php', '_PHPStan_33c983f26\\Nette\\StaticClass' => $vendorDir . '/nette/utils/src/StaticClass.php', '_PHPStan_33c983f26\\Nette\\UnexpectedValueException' => $vendorDir . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\Utils\\ArrayHash' => $vendorDir . '/nette/utils/src/Utils/ArrayHash.php', '_PHPStan_33c983f26\\Nette\\Utils\\ArrayList' => $vendorDir . '/nette/utils/src/Utils/ArrayList.php', '_PHPStan_33c983f26\\Nette\\Utils\\Arrays' => $vendorDir . '/nette/utils/src/Utils/Arrays.php', '_PHPStan_33c983f26\\Nette\\Utils\\AssertionException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', '_PHPStan_33c983f26\\Nette\\Utils\\Callback' => $vendorDir . '/nette/utils/src/Utils/Callback.php', '_PHPStan_33c983f26\\Nette\\Utils\\DateTime' => $vendorDir . '/nette/utils/src/Utils/DateTime.php', '_PHPStan_33c983f26\\Nette\\Utils\\FileSystem' => $vendorDir . '/nette/utils/src/Utils/FileSystem.php', '_PHPStan_33c983f26\\Nette\\Utils\\Finder' => $vendorDir . '/nette/finder/src/Utils/Finder.php', '_PHPStan_33c983f26\\Nette\\Utils\\Floats' => $vendorDir . '/nette/utils/src/Utils/Floats.php', '_PHPStan_33c983f26\\Nette\\Utils\\Helpers' => $vendorDir . '/nette/utils/src/Utils/Helpers.php', '_PHPStan_33c983f26\\Nette\\Utils\\Html' => $vendorDir . '/nette/utils/src/Utils/Html.php', '_PHPStan_33c983f26\\Nette\\Utils\\IHtmlString' => $vendorDir . '/nette/utils/src/compatibility.php', '_PHPStan_33c983f26\\Nette\\Utils\\Image' => $vendorDir . '/nette/utils/src/Utils/Image.php', '_PHPStan_33c983f26\\Nette\\Utils\\ImageException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', '_PHPStan_33c983f26\\Nette\\Utils\\Json' => $vendorDir . '/nette/utils/src/Utils/Json.php', '_PHPStan_33c983f26\\Nette\\Utils\\JsonException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', '_PHPStan_33c983f26\\Nette\\Utils\\ObjectHelpers' => $vendorDir . '/nette/utils/src/Utils/ObjectHelpers.php', '_PHPStan_33c983f26\\Nette\\Utils\\ObjectMixin' => $vendorDir . '/nette/utils/src/Utils/ObjectMixin.php', '_PHPStan_33c983f26\\Nette\\Utils\\Paginator' => $vendorDir . '/nette/utils/src/Utils/Paginator.php', '_PHPStan_33c983f26\\Nette\\Utils\\Random' => $vendorDir . '/nette/utils/src/Utils/Random.php', '_PHPStan_33c983f26\\Nette\\Utils\\Reflection' => $vendorDir . '/nette/utils/src/Utils/Reflection.php', '_PHPStan_33c983f26\\Nette\\Utils\\RegexpException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', '_PHPStan_33c983f26\\Nette\\Utils\\Strings' => $vendorDir . '/nette/utils/src/Utils/Strings.php', '_PHPStan_33c983f26\\Nette\\Utils\\Type' => $vendorDir . '/nette/utils/src/Utils/Type.php', '_PHPStan_33c983f26\\Nette\\Utils\\UnknownImageFileException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', '_PHPStan_33c983f26\\Nette\\Utils\\Validators' => $vendorDir . '/nette/utils/src/Utils/Validators.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\CiDetector' => $vendorDir . '/ondram/ci-detector/src/CiDetector.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\CiDetectorInterface' => $vendorDir . '/ondram/ci-detector/src/CiDetectorInterface.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\AbstractCi' => $vendorDir . '/ondram/ci-detector/src/Ci/AbstractCi.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\AppVeyor' => $vendorDir . '/ondram/ci-detector/src/Ci/AppVeyor.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\AwsCodeBuild' => $vendorDir . '/ondram/ci-detector/src/Ci/AwsCodeBuild.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\AzurePipelines' => $vendorDir . '/ondram/ci-detector/src/Ci/AzurePipelines.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Bamboo' => $vendorDir . '/ondram/ci-detector/src/Ci/Bamboo.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\BitbucketPipelines' => $vendorDir . '/ondram/ci-detector/src/Ci/BitbucketPipelines.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Buddy' => $vendorDir . '/ondram/ci-detector/src/Ci/Buddy.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\CiInterface' => $vendorDir . '/ondram/ci-detector/src/Ci/CiInterface.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Circle' => $vendorDir . '/ondram/ci-detector/src/Ci/Circle.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Codeship' => $vendorDir . '/ondram/ci-detector/src/Ci/Codeship.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Continuousphp' => $vendorDir . '/ondram/ci-detector/src/Ci/Continuousphp.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Drone' => $vendorDir . '/ondram/ci-detector/src/Ci/Drone.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\GitHubActions' => $vendorDir . '/ondram/ci-detector/src/Ci/GitHubActions.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\GitLab' => $vendorDir . '/ondram/ci-detector/src/Ci/GitLab.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Jenkins' => $vendorDir . '/ondram/ci-detector/src/Ci/Jenkins.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\SourceHut' => $vendorDir . '/ondram/ci-detector/src/Ci/SourceHut.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\TeamCity' => $vendorDir . '/ondram/ci-detector/src/Ci/TeamCity.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Travis' => $vendorDir . '/ondram/ci-detector/src/Ci/Travis.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Wercker' => $vendorDir . '/ondram/ci-detector/src/Ci/Wercker.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Env' => $vendorDir . '/ondram/ci-detector/src/Env.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Exception\\CiNotDetectedException' => $vendorDir . '/ondram/ci-detector/src/Exception/CiNotDetectedException.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\TrinaryLogic' => $vendorDir . '/ondram/ci-detector/src/TrinaryLogic.php', '_PHPStan_33c983f26\\PhpMerge\\GitMerge' => $vendorDir . '/ondrejmirtes/php-merge/src/PhpMerge/GitMerge.php', '_PHPStan_33c983f26\\PhpMerge\\MergeConflict' => $vendorDir . '/ondrejmirtes/php-merge/src/PhpMerge/MergeConflict.php', '_PHPStan_33c983f26\\PhpMerge\\MergeException' => $vendorDir . '/ondrejmirtes/php-merge/src/PhpMerge/MergeException.php', '_PHPStan_33c983f26\\PhpMerge\\PhpMerge' => $vendorDir . '/ondrejmirtes/php-merge/src/PhpMerge/PhpMerge.php', '_PHPStan_33c983f26\\PhpMerge\\PhpMergeInterface' => $vendorDir . '/ondrejmirtes/php-merge/src/PhpMerge/PhpMergeInterface.php', '_PHPStan_33c983f26\\PhpMerge\\internal\\AbstractMergeBase' => $vendorDir . '/ondrejmirtes/php-merge/src/PhpMerge/internal/AbstractMergeBase.php', '_PHPStan_33c983f26\\PhpMerge\\internal\\Hunk' => $vendorDir . '/ondrejmirtes/php-merge/src/PhpMerge/internal/Hunk.php', '_PHPStan_33c983f26\\PhpMerge\\internal\\Line' => $vendorDir . '/ondrejmirtes/php-merge/src/PhpMerge/internal/Line.php', '_PHPStan_33c983f26\\Psr\\Container\\ContainerExceptionInterface' => $vendorDir . '/psr/container/src/ContainerExceptionInterface.php', '_PHPStan_33c983f26\\Psr\\Container\\ContainerInterface' => $vendorDir . '/psr/container/src/ContainerInterface.php', '_PHPStan_33c983f26\\Psr\\Container\\NotFoundExceptionInterface' => $vendorDir . '/psr/container/src/NotFoundExceptionInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Client\\ClientExceptionInterface' => $vendorDir . '/psr/http-client/src/ClientExceptionInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Client\\ClientInterface' => $vendorDir . '/psr/http-client/src/ClientInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Client\\NetworkExceptionInterface' => $vendorDir . '/psr/http-client/src/NetworkExceptionInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Client\\RequestExceptionInterface' => $vendorDir . '/psr/http-client/src/RequestExceptionInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\MessageInterface' => $vendorDir . '/psr/http-message/src/MessageInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\RequestFactoryInterface' => $vendorDir . '/psr/http-factory/src/RequestFactoryInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\RequestInterface' => $vendorDir . '/psr/http-message/src/RequestInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\ResponseFactoryInterface' => $vendorDir . '/psr/http-factory/src/ResponseFactoryInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\ResponseInterface' => $vendorDir . '/psr/http-message/src/ResponseInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\ServerRequestFactoryInterface' => $vendorDir . '/psr/http-factory/src/ServerRequestFactoryInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\ServerRequestInterface' => $vendorDir . '/psr/http-message/src/ServerRequestInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\StreamFactoryInterface' => $vendorDir . '/psr/http-factory/src/StreamFactoryInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\StreamInterface' => $vendorDir . '/psr/http-message/src/StreamInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\UploadedFileFactoryInterface' => $vendorDir . '/psr/http-factory/src/UploadedFileFactoryInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\UploadedFileInterface' => $vendorDir . '/psr/http-message/src/UploadedFileInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\UriFactoryInterface' => $vendorDir . '/psr/http-factory/src/UriFactoryInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\UriInterface' => $vendorDir . '/psr/http-message/src/UriInterface.php', '_PHPStan_33c983f26\\Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/src/AbstractLogger.php', '_PHPStan_33c983f26\\Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/src/InvalidArgumentException.php', '_PHPStan_33c983f26\\Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/src/LogLevel.php', '_PHPStan_33c983f26\\Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/psr/log/src/LoggerAwareInterface.php', '_PHPStan_33c983f26\\Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/psr/log/src/LoggerAwareTrait.php', '_PHPStan_33c983f26\\Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/src/LoggerInterface.php', '_PHPStan_33c983f26\\Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/src/LoggerTrait.php', '_PHPStan_33c983f26\\Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/src/NullLogger.php', '_PHPStan_33c983f26\\React\\Cache\\ArrayCache' => $vendorDir . '/react/cache/src/ArrayCache.php', '_PHPStan_33c983f26\\React\\Cache\\CacheInterface' => $vendorDir . '/react/cache/src/CacheInterface.php', '_PHPStan_33c983f26\\React\\ChildProcess\\Process' => $vendorDir . '/react/child-process/src/Process.php', '_PHPStan_33c983f26\\React\\Dns\\BadServerException' => $vendorDir . '/react/dns/src/BadServerException.php', '_PHPStan_33c983f26\\React\\Dns\\Config\\Config' => $vendorDir . '/react/dns/src/Config/Config.php', '_PHPStan_33c983f26\\React\\Dns\\Config\\HostsFile' => $vendorDir . '/react/dns/src/Config/HostsFile.php', '_PHPStan_33c983f26\\React\\Dns\\Model\\Message' => $vendorDir . '/react/dns/src/Model/Message.php', '_PHPStan_33c983f26\\React\\Dns\\Model\\Record' => $vendorDir . '/react/dns/src/Model/Record.php', '_PHPStan_33c983f26\\React\\Dns\\Protocol\\BinaryDumper' => $vendorDir . '/react/dns/src/Protocol/BinaryDumper.php', '_PHPStan_33c983f26\\React\\Dns\\Protocol\\Parser' => $vendorDir . '/react/dns/src/Protocol/Parser.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\CachingExecutor' => $vendorDir . '/react/dns/src/Query/CachingExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\CancellationException' => $vendorDir . '/react/dns/src/Query/CancellationException.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\CoopExecutor' => $vendorDir . '/react/dns/src/Query/CoopExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\ExecutorInterface' => $vendorDir . '/react/dns/src/Query/ExecutorInterface.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\FallbackExecutor' => $vendorDir . '/react/dns/src/Query/FallbackExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\HostsFileExecutor' => $vendorDir . '/react/dns/src/Query/HostsFileExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\Query' => $vendorDir . '/react/dns/src/Query/Query.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\RetryExecutor' => $vendorDir . '/react/dns/src/Query/RetryExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\SelectiveTransportExecutor' => $vendorDir . '/react/dns/src/Query/SelectiveTransportExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\TcpTransportExecutor' => $vendorDir . '/react/dns/src/Query/TcpTransportExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\TimeoutException' => $vendorDir . '/react/dns/src/Query/TimeoutException.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\TimeoutExecutor' => $vendorDir . '/react/dns/src/Query/TimeoutExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\UdpTransportExecutor' => $vendorDir . '/react/dns/src/Query/UdpTransportExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\RecordNotFoundException' => $vendorDir . '/react/dns/src/RecordNotFoundException.php', '_PHPStan_33c983f26\\React\\Dns\\Resolver\\Factory' => $vendorDir . '/react/dns/src/Resolver/Factory.php', '_PHPStan_33c983f26\\React\\Dns\\Resolver\\Resolver' => $vendorDir . '/react/dns/src/Resolver/Resolver.php', '_PHPStan_33c983f26\\React\\Dns\\Resolver\\ResolverInterface' => $vendorDir . '/react/dns/src/Resolver/ResolverInterface.php', '_PHPStan_33c983f26\\React\\EventLoop\\ExtEvLoop' => $vendorDir . '/react/event-loop/src/ExtEvLoop.php', '_PHPStan_33c983f26\\React\\EventLoop\\ExtEventLoop' => $vendorDir . '/react/event-loop/src/ExtEventLoop.php', '_PHPStan_33c983f26\\React\\EventLoop\\ExtLibevLoop' => $vendorDir . '/react/event-loop/src/ExtLibevLoop.php', '_PHPStan_33c983f26\\React\\EventLoop\\ExtLibeventLoop' => $vendorDir . '/react/event-loop/src/ExtLibeventLoop.php', '_PHPStan_33c983f26\\React\\EventLoop\\ExtUvLoop' => $vendorDir . '/react/event-loop/src/ExtUvLoop.php', '_PHPStan_33c983f26\\React\\EventLoop\\Factory' => $vendorDir . '/react/event-loop/src/Factory.php', '_PHPStan_33c983f26\\React\\EventLoop\\Loop' => $vendorDir . '/react/event-loop/src/Loop.php', '_PHPStan_33c983f26\\React\\EventLoop\\LoopInterface' => $vendorDir . '/react/event-loop/src/LoopInterface.php', '_PHPStan_33c983f26\\React\\EventLoop\\SignalsHandler' => $vendorDir . '/react/event-loop/src/SignalsHandler.php', '_PHPStan_33c983f26\\React\\EventLoop\\StreamSelectLoop' => $vendorDir . '/react/event-loop/src/StreamSelectLoop.php', '_PHPStan_33c983f26\\React\\EventLoop\\Tick\\FutureTickQueue' => $vendorDir . '/react/event-loop/src/Tick/FutureTickQueue.php', '_PHPStan_33c983f26\\React\\EventLoop\\TimerInterface' => $vendorDir . '/react/event-loop/src/TimerInterface.php', '_PHPStan_33c983f26\\React\\EventLoop\\Timer\\Timer' => $vendorDir . '/react/event-loop/src/Timer/Timer.php', '_PHPStan_33c983f26\\React\\EventLoop\\Timer\\Timers' => $vendorDir . '/react/event-loop/src/Timer/Timers.php', '_PHPStan_33c983f26\\React\\Promise\\Deferred' => $vendorDir . '/react/promise/src/Deferred.php', '_PHPStan_33c983f26\\React\\Promise\\Exception\\CompositeException' => $vendorDir . '/react/promise/src/Exception/CompositeException.php', '_PHPStan_33c983f26\\React\\Promise\\Exception\\LengthException' => $vendorDir . '/react/promise/src/Exception/LengthException.php', '_PHPStan_33c983f26\\React\\Promise\\Internal\\CancellationQueue' => $vendorDir . '/react/promise/src/Internal/CancellationQueue.php', '_PHPStan_33c983f26\\React\\Promise\\Internal\\FulfilledPromise' => $vendorDir . '/react/promise/src/Internal/FulfilledPromise.php', '_PHPStan_33c983f26\\React\\Promise\\Internal\\RejectedPromise' => $vendorDir . '/react/promise/src/Internal/RejectedPromise.php', '_PHPStan_33c983f26\\React\\Promise\\Promise' => $vendorDir . '/react/promise/src/Promise.php', '_PHPStan_33c983f26\\React\\Promise\\PromiseInterface' => $vendorDir . '/react/promise/src/PromiseInterface.php', '_PHPStan_33c983f26\\React\\Socket\\Connection' => $vendorDir . '/react/socket/src/Connection.php', '_PHPStan_33c983f26\\React\\Socket\\ConnectionInterface' => $vendorDir . '/react/socket/src/ConnectionInterface.php', '_PHPStan_33c983f26\\React\\Socket\\Connector' => $vendorDir . '/react/socket/src/Connector.php', '_PHPStan_33c983f26\\React\\Socket\\ConnectorInterface' => $vendorDir . '/react/socket/src/ConnectorInterface.php', '_PHPStan_33c983f26\\React\\Socket\\DnsConnector' => $vendorDir . '/react/socket/src/DnsConnector.php', '_PHPStan_33c983f26\\React\\Socket\\FdServer' => $vendorDir . '/react/socket/src/FdServer.php', '_PHPStan_33c983f26\\React\\Socket\\FixedUriConnector' => $vendorDir . '/react/socket/src/FixedUriConnector.php', '_PHPStan_33c983f26\\React\\Socket\\HappyEyeBallsConnectionBuilder' => $vendorDir . '/react/socket/src/HappyEyeBallsConnectionBuilder.php', '_PHPStan_33c983f26\\React\\Socket\\HappyEyeBallsConnector' => $vendorDir . '/react/socket/src/HappyEyeBallsConnector.php', '_PHPStan_33c983f26\\React\\Socket\\LimitingServer' => $vendorDir . '/react/socket/src/LimitingServer.php', '_PHPStan_33c983f26\\React\\Socket\\SecureConnector' => $vendorDir . '/react/socket/src/SecureConnector.php', '_PHPStan_33c983f26\\React\\Socket\\SecureServer' => $vendorDir . '/react/socket/src/SecureServer.php', '_PHPStan_33c983f26\\React\\Socket\\Server' => $vendorDir . '/react/socket/src/Server.php', '_PHPStan_33c983f26\\React\\Socket\\ServerInterface' => $vendorDir . '/react/socket/src/ServerInterface.php', '_PHPStan_33c983f26\\React\\Socket\\SocketServer' => $vendorDir . '/react/socket/src/SocketServer.php', '_PHPStan_33c983f26\\React\\Socket\\StreamEncryption' => $vendorDir . '/react/socket/src/StreamEncryption.php', '_PHPStan_33c983f26\\React\\Socket\\TcpConnector' => $vendorDir . '/react/socket/src/TcpConnector.php', '_PHPStan_33c983f26\\React\\Socket\\TcpServer' => $vendorDir . '/react/socket/src/TcpServer.php', '_PHPStan_33c983f26\\React\\Socket\\TimeoutConnector' => $vendorDir . '/react/socket/src/TimeoutConnector.php', '_PHPStan_33c983f26\\React\\Socket\\UnixConnector' => $vendorDir . '/react/socket/src/UnixConnector.php', '_PHPStan_33c983f26\\React\\Socket\\UnixServer' => $vendorDir . '/react/socket/src/UnixServer.php', '_PHPStan_33c983f26\\React\\Stream\\CompositeStream' => $vendorDir . '/react/stream/src/CompositeStream.php', '_PHPStan_33c983f26\\React\\Stream\\DuplexResourceStream' => $vendorDir . '/react/stream/src/DuplexResourceStream.php', '_PHPStan_33c983f26\\React\\Stream\\DuplexStreamInterface' => $vendorDir . '/react/stream/src/DuplexStreamInterface.php', '_PHPStan_33c983f26\\React\\Stream\\ReadableResourceStream' => $vendorDir . '/react/stream/src/ReadableResourceStream.php', '_PHPStan_33c983f26\\React\\Stream\\ReadableStreamInterface' => $vendorDir . '/react/stream/src/ReadableStreamInterface.php', '_PHPStan_33c983f26\\React\\Stream\\ThroughStream' => $vendorDir . '/react/stream/src/ThroughStream.php', '_PHPStan_33c983f26\\React\\Stream\\Util' => $vendorDir . '/react/stream/src/Util.php', '_PHPStan_33c983f26\\React\\Stream\\WritableResourceStream' => $vendorDir . '/react/stream/src/WritableResourceStream.php', '_PHPStan_33c983f26\\React\\Stream\\WritableStreamInterface' => $vendorDir . '/react/stream/src/WritableStreamInterface.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Chunk' => $vendorDir . '/sebastian/diff/src/Chunk.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\ConfigurationException' => $vendorDir . '/sebastian/diff/src/Exception/ConfigurationException.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Diff' => $vendorDir . '/sebastian/diff/src/Diff.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Differ' => $vendorDir . '/sebastian/diff/src/Differ.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Exception' => $vendorDir . '/sebastian/diff/src/Exception/Exception.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\InvalidArgumentException' => $vendorDir . '/sebastian/diff/src/Exception/InvalidArgumentException.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Line' => $vendorDir . '/sebastian/diff/src/Line.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\LongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/LongestCommonSubsequenceCalculator.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\MemoryEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Output\\AbstractChunkOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Output\\DiffOnlyOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Output\\DiffOutputBuilderInterface' => $vendorDir . '/sebastian/diff/src/Output/DiffOutputBuilderInterface.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Output\\StrictUnifiedDiffOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Output\\UnifiedDiffOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Parser' => $vendorDir . '/sebastian/diff/src/Parser.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\TimeEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Application' => $vendorDir . '/symfony/console/Application.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Attribute\\AsCommand' => $vendorDir . '/symfony/console/Attribute/AsCommand.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\CI\\GithubActionReporter' => $vendorDir . '/symfony/console/CI/GithubActionReporter.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Color' => $vendorDir . '/symfony/console/Color.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => $vendorDir . '/symfony/console/CommandLoader/CommandLoaderInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/ContainerCommandLoader.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/FactoryCommandLoader.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Command\\Command' => $vendorDir . '/symfony/console/Command/Command.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Command\\CompleteCommand' => $vendorDir . '/symfony/console/Command/CompleteCommand.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Command\\DumpCompletionCommand' => $vendorDir . '/symfony/console/Command/DumpCompletionCommand.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Command\\HelpCommand' => $vendorDir . '/symfony/console/Command/HelpCommand.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Command\\LazyCommand' => $vendorDir . '/symfony/console/Command/LazyCommand.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Command\\ListCommand' => $vendorDir . '/symfony/console/Command/ListCommand.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Command\\LockableTrait' => $vendorDir . '/symfony/console/Command/LockableTrait.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Command\\SignalableCommandInterface' => $vendorDir . '/symfony/console/Command/SignalableCommandInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Completion\\CompletionInput' => $vendorDir . '/symfony/console/Completion/CompletionInput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Completion\\CompletionSuggestions' => $vendorDir . '/symfony/console/Completion/CompletionSuggestions.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Completion\\Output\\BashCompletionOutput' => $vendorDir . '/symfony/console/Completion/Output/BashCompletionOutput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Completion\\Output\\CompletionOutputInterface' => $vendorDir . '/symfony/console/Completion/Output/CompletionOutputInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Completion\\Suggestion' => $vendorDir . '/symfony/console/Completion/Suggestion.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\ConsoleEvents' => $vendorDir . '/symfony/console/ConsoleEvents.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Cursor' => $vendorDir . '/symfony/console/Cursor.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => $vendorDir . '/symfony/console/DependencyInjection/AddConsoleCommandPass.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => $vendorDir . '/symfony/console/Descriptor/ApplicationDescription.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Descriptor\\Descriptor' => $vendorDir . '/symfony/console/Descriptor/Descriptor.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => $vendorDir . '/symfony/console/Descriptor/DescriptorInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => $vendorDir . '/symfony/console/Descriptor/JsonDescriptor.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => $vendorDir . '/symfony/console/Descriptor/MarkdownDescriptor.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => $vendorDir . '/symfony/console/Descriptor/TextDescriptor.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => $vendorDir . '/symfony/console/Descriptor/XmlDescriptor.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\EventListener\\ErrorListener' => $vendorDir . '/symfony/console/EventListener/ErrorListener.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => $vendorDir . '/symfony/console/Event/ConsoleCommandEvent.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => $vendorDir . '/symfony/console/Event/ConsoleErrorEvent.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Event\\ConsoleEvent' => $vendorDir . '/symfony/console/Event/ConsoleEvent.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Event\\ConsoleSignalEvent' => $vendorDir . '/symfony/console/Event/ConsoleSignalEvent.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => $vendorDir . '/symfony/console/Event/ConsoleTerminateEvent.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => $vendorDir . '/symfony/console/Exception/CommandNotFoundException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/console/Exception/ExceptionInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/console/Exception/InvalidArgumentException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Exception\\InvalidOptionException' => $vendorDir . '/symfony/console/Exception/InvalidOptionException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Exception\\LogicException' => $vendorDir . '/symfony/console/Exception/LogicException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Exception\\MissingInputException' => $vendorDir . '/symfony/console/Exception/MissingInputException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Exception\\NamespaceNotFoundException' => $vendorDir . '/symfony/console/Exception/NamespaceNotFoundException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Exception\\RuntimeException' => $vendorDir . '/symfony/console/Exception/RuntimeException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatter' => $vendorDir . '/symfony/console/Formatter/NullOutputFormatter.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatterStyle' => $vendorDir . '/symfony/console/Formatter/NullOutputFormatterStyle.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Formatter\\OutputFormatter' => $vendorDir . '/symfony/console/Formatter/OutputFormatter.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => $vendorDir . '/symfony/console/Formatter/OutputFormatterInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyle.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleStack.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Formatter\\WrappableOutputFormatterInterface' => $vendorDir . '/symfony/console/Formatter/WrappableOutputFormatterInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => $vendorDir . '/symfony/console/Helper/DebugFormatterHelper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/symfony/console/Helper/DescriptorHelper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\Dumper' => $vendorDir . '/symfony/console/Helper/Dumper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\FormatterHelper' => $vendorDir . '/symfony/console/Helper/FormatterHelper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\Helper' => $vendorDir . '/symfony/console/Helper/Helper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\HelperInterface' => $vendorDir . '/symfony/console/Helper/HelperInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\HelperSet' => $vendorDir . '/symfony/console/Helper/HelperSet.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\InputAwareHelper' => $vendorDir . '/symfony/console/Helper/InputAwareHelper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\ProcessHelper' => $vendorDir . '/symfony/console/Helper/ProcessHelper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\ProgressBar' => $vendorDir . '/symfony/console/Helper/ProgressBar.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\ProgressIndicator' => $vendorDir . '/symfony/console/Helper/ProgressIndicator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\QuestionHelper' => $vendorDir . '/symfony/console/Helper/QuestionHelper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => $vendorDir . '/symfony/console/Helper/SymfonyQuestionHelper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\Table' => $vendorDir . '/symfony/console/Helper/Table.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\TableCell' => $vendorDir . '/symfony/console/Helper/TableCell.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\TableCellStyle' => $vendorDir . '/symfony/console/Helper/TableCellStyle.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\TableRows' => $vendorDir . '/symfony/console/Helper/TableRows.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\TableSeparator' => $vendorDir . '/symfony/console/Helper/TableSeparator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\TableStyle' => $vendorDir . '/symfony/console/Helper/TableStyle.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\ArgvInput' => $vendorDir . '/symfony/console/Input/ArgvInput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\ArrayInput' => $vendorDir . '/symfony/console/Input/ArrayInput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\Input' => $vendorDir . '/symfony/console/Input/Input.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\InputArgument' => $vendorDir . '/symfony/console/Input/InputArgument.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\InputAwareInterface' => $vendorDir . '/symfony/console/Input/InputAwareInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\InputDefinition' => $vendorDir . '/symfony/console/Input/InputDefinition.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\InputInterface' => $vendorDir . '/symfony/console/Input/InputInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\InputOption' => $vendorDir . '/symfony/console/Input/InputOption.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\StreamableInputInterface' => $vendorDir . '/symfony/console/Input/StreamableInputInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\StringInput' => $vendorDir . '/symfony/console/Input/StringInput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Logger\\ConsoleLogger' => $vendorDir . '/symfony/console/Logger/ConsoleLogger.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\BufferedOutput' => $vendorDir . '/symfony/console/Output/BufferedOutput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\ConsoleOutput' => $vendorDir . '/symfony/console/Output/ConsoleOutput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => $vendorDir . '/symfony/console/Output/ConsoleOutputInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\ConsoleSectionOutput' => $vendorDir . '/symfony/console/Output/ConsoleSectionOutput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\NullOutput' => $vendorDir . '/symfony/console/Output/NullOutput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\Output' => $vendorDir . '/symfony/console/Output/Output.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\OutputInterface' => $vendorDir . '/symfony/console/Output/OutputInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\StreamOutput' => $vendorDir . '/symfony/console/Output/StreamOutput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\TrimmedBufferOutput' => $vendorDir . '/symfony/console/Output/TrimmedBufferOutput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Question\\ChoiceQuestion' => $vendorDir . '/symfony/console/Question/ChoiceQuestion.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => $vendorDir . '/symfony/console/Question/ConfirmationQuestion.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Question\\Question' => $vendorDir . '/symfony/console/Question/Question.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\SignalRegistry\\SignalRegistry' => $vendorDir . '/symfony/console/SignalRegistry/SignalRegistry.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\SingleCommandApplication' => $vendorDir . '/symfony/console/SingleCommandApplication.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Style\\OutputStyle' => $vendorDir . '/symfony/console/Style/OutputStyle.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Style\\StyleInterface' => $vendorDir . '/symfony/console/Style/StyleInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Style\\SymfonyStyle' => $vendorDir . '/symfony/console/Style/SymfonyStyle.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Terminal' => $vendorDir . '/symfony/console/Terminal.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Tester\\ApplicationTester' => $vendorDir . '/symfony/console/Tester/ApplicationTester.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Tester\\CommandCompletionTester' => $vendorDir . '/symfony/console/Tester/CommandCompletionTester.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Tester\\CommandTester' => $vendorDir . '/symfony/console/Tester/CommandTester.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Tester\\Constraint\\CommandIsSuccessful' => $vendorDir . '/symfony/console/Tester/Constraint/CommandIsSuccessful.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Tester\\TesterTrait' => $vendorDir . '/symfony/console/Tester/TesterTrait.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Comparator\\Comparator' => $vendorDir . '/symfony/finder/Comparator/Comparator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Comparator\\DateComparator' => $vendorDir . '/symfony/finder/Comparator/DateComparator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Comparator\\NumberComparator' => $vendorDir . '/symfony/finder/Comparator/NumberComparator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Exception\\AccessDeniedException' => $vendorDir . '/symfony/finder/Exception/AccessDeniedException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Exception\\DirectoryNotFoundException' => $vendorDir . '/symfony/finder/Exception/DirectoryNotFoundException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Finder' => $vendorDir . '/symfony/finder/Finder.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Gitignore' => $vendorDir . '/symfony/finder/Gitignore.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Glob' => $vendorDir . '/symfony/finder/Glob.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\CustomFilterIterator' => $vendorDir . '/symfony/finder/Iterator/CustomFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\DateRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/DateRangeFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\DepthRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/DepthRangeFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\ExcludeDirectoryFilterIterator' => $vendorDir . '/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FileTypeFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilecontentFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilenameFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\LazyIterator' => $vendorDir . '/symfony/finder/Iterator/LazyIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => $vendorDir . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => $vendorDir . '/symfony/finder/Iterator/PathFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => $vendorDir . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/SizeRangeFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\SortableIterator' => $vendorDir . '/symfony/finder/Iterator/SortableIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\VcsIgnoredFilterIterator' => $vendorDir . '/symfony/finder/Iterator/VcsIgnoredFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\SplFileInfo' => $vendorDir . '/symfony/finder/SplFileInfo.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/process/Exception/ExceptionInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/process/Exception/InvalidArgumentException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Exception\\LogicException' => $vendorDir . '/symfony/process/Exception/LogicException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Exception\\ProcessFailedException' => $vendorDir . '/symfony/process/Exception/ProcessFailedException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Exception\\ProcessSignaledException' => $vendorDir . '/symfony/process/Exception/ProcessSignaledException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => $vendorDir . '/symfony/process/Exception/ProcessTimedOutException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Exception\\RuntimeException' => $vendorDir . '/symfony/process/Exception/RuntimeException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\ExecutableFinder' => $vendorDir . '/symfony/process/ExecutableFinder.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\InputStream' => $vendorDir . '/symfony/process/InputStream.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\PhpExecutableFinder' => $vendorDir . '/symfony/process/PhpExecutableFinder.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\PhpProcess' => $vendorDir . '/symfony/process/PhpProcess.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Pipes\\AbstractPipes' => $vendorDir . '/symfony/process/Pipes/AbstractPipes.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Pipes\\PipesInterface' => $vendorDir . '/symfony/process/Pipes/PipesInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Pipes\\UnixPipes' => $vendorDir . '/symfony/process/Pipes/UnixPipes.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Pipes\\WindowsPipes' => $vendorDir . '/symfony/process/Pipes/WindowsPipes.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Process' => $vendorDir . '/symfony/process/Process.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\ProcessUtils' => $vendorDir . '/symfony/process/ProcessUtils.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\AbstractString' => $vendorDir . '/symfony/string/AbstractString.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\AbstractUnicodeString' => $vendorDir . '/symfony/string/AbstractUnicodeString.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\ByteString' => $vendorDir . '/symfony/string/ByteString.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\CodePointString' => $vendorDir . '/symfony/string/CodePointString.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/string/Exception/ExceptionInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/string/Exception/InvalidArgumentException.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\Exception\\RuntimeException' => $vendorDir . '/symfony/string/Exception/RuntimeException.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\Inflector\\EnglishInflector' => $vendorDir . '/symfony/string/Inflector/EnglishInflector.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\Inflector\\FrenchInflector' => $vendorDir . '/symfony/string/Inflector/FrenchInflector.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\Inflector\\InflectorInterface' => $vendorDir . '/symfony/string/Inflector/InflectorInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\LazyString' => $vendorDir . '/symfony/string/LazyString.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\Slugger\\AsciiSlugger' => $vendorDir . '/symfony/string/Slugger/AsciiSlugger.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\Slugger\\SluggerInterface' => $vendorDir . '/symfony/string/Slugger/SluggerInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\UnicodeString' => $vendorDir . '/symfony/string/UnicodeString.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\Attribute\\Required' => $vendorDir . '/symfony/service-contracts/Attribute/Required.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => $vendorDir . '/symfony/service-contracts/Attribute/SubscribedService.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\ResetInterface' => $vendorDir . '/symfony/service-contracts/ResetInterface.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\ServiceLocatorTrait' => $vendorDir . '/symfony/service-contracts/ServiceLocatorTrait.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\ServiceProviderInterface' => $vendorDir . '/symfony/service-contracts/ServiceProviderInterface.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberInterface.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberTrait.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\Test\\ServiceLocatorTest' => $vendorDir . '/symfony/service-contracts/Test/ServiceLocatorTest.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\Test\\ServiceLocatorTestCase' => $vendorDir . '/symfony/service-contracts/Test/ServiceLocatorTestCase.php', '_PHPStan_33c983f26\\Symfony\\Polyfill\\Ctype\\Ctype' => $vendorDir . '/symfony/polyfill-ctype/Ctype.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\AttributeGroupsReflector' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/AttributeGroupsReflector.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Attributes' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/Attributes.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\CachedParser' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/CachedParser.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\ClassAttributeCollector' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/ClassAttributeCollector.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Collection' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/Collection.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Config' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/Config.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Datastore' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/Datastore.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Datastore\\FileDatastore' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/Datastore/FileDatastore.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Datastore\\RuntimeDatastore' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/Datastore/RuntimeDatastore.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\FakeAttribute' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/FakeAttribute.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Filter' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/Filter.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Filter\\Chain' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/Filter/Chain.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Filter\\ContentFilter' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/Filter/ContentFilter.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\ForClass' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/ForClass.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\MemoizeAttributeCollector' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/MemoizeAttributeCollector.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\MemoizeClassMapFilter' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/MemoizeClassMapFilter.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\MemoizeClassMapGenerator' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/MemoizeClassMapGenerator.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\ParameterAttributeCollector' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/ParameterAttributeCollector.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Plugin' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/Plugin.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TargetClass' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/TargetClass.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TargetMethod' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/TargetMethod.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TargetMethodParameter' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/TargetMethodParameter.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TargetProperty' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/TargetProperty.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TransientCollection' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/TransientCollection.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TransientCollectionRenderer' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/TransientCollectionRenderer.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TransientTargetClass' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/TransientTargetClass.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TransientTargetMethod' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/TransientTargetMethod.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TransientTargetMethodParameter' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/TransientTargetMethodParameter.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TransientTargetProperty' => $vendorDir . '/ondrejmirtes/composer-attribute-collector/src/TransientTargetProperty.php', ); $vendorDir . '/hoa/consistency/Prelude.php', '3e76f7f02b41af8cea96018933f6b7e3' => $vendorDir . '/hoa/protocol/Wrapper.php', 'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php', '6e3fae29631ef280660b3cdad06f25a8' => $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', 'fe1d4898277c26748a003292f432cd3b' => $vendorDir . '/jetbrains/phpstorm-stubs/PhpStormStubsMap.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', '23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php', '662a729f963d39afe703c9d9b7ab4a8c' => $vendorDir . '/symfony/polyfill-php83/bootstrap.php', '9d2b9fc6db0f153a0a149fefb182415e' => $vendorDir . '/symfony/polyfill-php84/bootstrap.php', '606a39d89246991a373564698c2d8383' => $vendorDir . '/symfony/polyfill-php85/bootstrap.php', '23e1affdf407e3538a1f32c140fb0401' => $baseDir . '/src/debugScope.php', '8b3b25e11e82753923d43e298a70dcd0' => $baseDir . '/src/dumpType.php', '9662279e3e75f737d93030252673bf2d' => $baseDir . '/src/autoloadFunctions.php', '1a2eab53065eff9692bac238d15cc8cb' => $baseDir . '/src/Testing/functions.php', ); array($vendorDir . '/ondrejmirtes/composer-attribute-collector/src'), '_PHPStan_33c983f26\\Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'), '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'), '_PHPStan_33c983f26\\Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'), '_PHPStan_33c983f26\\Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'), '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'), '_PHPStan_33c983f26\\Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), '_PHPStan_33c983f26\\React\\Stream\\' => array($vendorDir . '/react/stream/src'), '_PHPStan_33c983f26\\React\\Socket\\' => array($vendorDir . '/react/socket/src'), '_PHPStan_33c983f26\\React\\Promise\\' => array($vendorDir . '/react/promise/src'), '_PHPStan_33c983f26\\React\\EventLoop\\' => array($vendorDir . '/react/event-loop/src'), '_PHPStan_33c983f26\\React\\Dns\\' => array($vendorDir . '/react/dns/src'), '_PHPStan_33c983f26\\React\\ChildProcess\\' => array($vendorDir . '/react/child-process/src'), '_PHPStan_33c983f26\\React\\Cache\\' => array($vendorDir . '/react/cache/src'), '_PHPStan_33c983f26\\Psr\\Log\\' => array($vendorDir . '/psr/log/src'), '_PHPStan_33c983f26\\Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'), '_PHPStan_33c983f26\\Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'), '_PHPStan_33c983f26\\Psr\\Container\\' => array($vendorDir . '/psr/container/src'), '_PHPStan_33c983f26\\PhpMerge\\' => array($vendorDir . '/ondrejmirtes/php-merge/src/PhpMerge'), '_PHPStan_33c983f26\\OndraM\\CiDetector\\' => array($vendorDir . '/ondram/ci-detector/src'), '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'), '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'), '_PHPStan_33c983f26\\GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'), '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\' => array($vendorDir . '/fidry/cpu-core-counter/src'), '_PHPStan_33c983f26\\Evenement\\' => array($vendorDir . '/evenement/evenement/src'), '_PHPStan_33c983f26\\Composer\\XdebugHandler\\' => array($vendorDir . '/composer/xdebug-handler/src'), '_PHPStan_33c983f26\\Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'), '_PHPStan_33c983f26\\Composer\\Pcre\\' => array($vendorDir . '/composer/pcre/src'), '_PHPStan_33c983f26\\Clue\\React\\NDJson\\' => array($vendorDir . '/clue/ndjson-react/src'), 'Symfony\\Polyfill\\Php85\\' => array($vendorDir . '/symfony/polyfill-php85'), 'Symfony\\Polyfill\\Php84\\' => array($vendorDir . '/symfony/polyfill-php84'), 'Symfony\\Polyfill\\Php83\\' => array($vendorDir . '/symfony/polyfill-php83'), 'Symfony\\Polyfill\\Php81\\' => array($vendorDir . '/symfony/polyfill-php81'), 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), 'Symfony\\Polyfill\\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'), 'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'), 'PHPStan\\PhpDocParser\\' => array($vendorDir . '/phpstan/phpdoc-parser/src'), 'PHPStan\\BetterReflection\\' => array($vendorDir . '/ondrejmirtes/better-reflection/src'), 'PHPStan\\' => array($baseDir . '/src'), 'Hoa\\Zformat\\' => array($vendorDir . '/hoa/zformat'), 'Hoa\\Visitor\\' => array($vendorDir . '/hoa/visitor'), 'Hoa\\Ustring\\' => array($vendorDir . '/hoa/ustring'), 'Hoa\\Stream\\' => array($vendorDir . '/hoa/stream'), 'Hoa\\Regex\\' => array($vendorDir . '/hoa/regex'), 'Hoa\\Protocol\\' => array($vendorDir . '/hoa/protocol'), 'Hoa\\Math\\' => array($vendorDir . '/hoa/math'), 'Hoa\\Iterator\\' => array($vendorDir . '/hoa/iterator'), 'Hoa\\File\\' => array($vendorDir . '/hoa/file'), 'Hoa\\Exception\\' => array($vendorDir . '/hoa/exception'), 'Hoa\\Event\\' => array($vendorDir . '/hoa/event'), 'Hoa\\Consistency\\' => array($vendorDir . '/hoa/consistency'), 'Hoa\\Compiler\\' => array($vendorDir . '/hoa/compiler'), ); setClassMapAuthoritative(true); $loader->register(true); $filesToLoad = \Composer\Autoload\ComposerStaticInitcd1bbf15618bee29b84872b5979c9478::$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__ . '/..' . '/hoa/consistency/Prelude.php', '3e76f7f02b41af8cea96018933f6b7e3' => __DIR__ . '/..' . '/hoa/protocol/Wrapper.php', 'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php', '6e3fae29631ef280660b3cdad06f25a8' => __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', 'fe1d4898277c26748a003292f432cd3b' => __DIR__ . '/..' . '/jetbrains/phpstorm-stubs/PhpStormStubsMap.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php', '23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php', '662a729f963d39afe703c9d9b7ab4a8c' => __DIR__ . '/..' . '/symfony/polyfill-php83/bootstrap.php', '9d2b9fc6db0f153a0a149fefb182415e' => __DIR__ . '/..' . '/symfony/polyfill-php84/bootstrap.php', '606a39d89246991a373564698c2d8383' => __DIR__ . '/..' . '/symfony/polyfill-php85/bootstrap.php', '23e1affdf407e3538a1f32c140fb0401' => __DIR__ . '/../..' . '/src/debugScope.php', '8b3b25e11e82753923d43e298a70dcd0' => __DIR__ . '/../..' . '/src/dumpType.php', '9662279e3e75f737d93030252673bf2d' => __DIR__ . '/../..' . '/src/autoloadFunctions.php', '1a2eab53065eff9692bac238d15cc8cb' => __DIR__ . '/../..' . '/src/Testing/functions.php', ); public static $prefixLengthsPsr4 = array ( '_' => array ( '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\' => 53, '_PHPStan_33c983f26\\Symfony\\Polyfill\\Ctype\\' => 42, '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\' => 45, '_PHPStan_33c983f26\\Symfony\\Component\\String\\' => 44, '_PHPStan_33c983f26\\Symfony\\Component\\Process\\' => 45, '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\' => 44, '_PHPStan_33c983f26\\Symfony\\Component\\Console\\' => 45, '_PHPStan_33c983f26\\React\\Stream\\' => 32, '_PHPStan_33c983f26\\React\\Socket\\' => 32, '_PHPStan_33c983f26\\React\\Promise\\' => 33, '_PHPStan_33c983f26\\React\\EventLoop\\' => 35, '_PHPStan_33c983f26\\React\\Dns\\' => 29, '_PHPStan_33c983f26\\React\\ChildProcess\\' => 38, '_PHPStan_33c983f26\\React\\Cache\\' => 31, '_PHPStan_33c983f26\\Psr\\Log\\' => 27, '_PHPStan_33c983f26\\Psr\\Http\\Message\\' => 36, '_PHPStan_33c983f26\\Psr\\Http\\Client\\' => 35, '_PHPStan_33c983f26\\Psr\\Container\\' => 33, '_PHPStan_33c983f26\\PhpMerge\\' => 28, '_PHPStan_33c983f26\\OndraM\\CiDetector\\' => 37, '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\' => 35, '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\' => 38, '_PHPStan_33c983f26\\GuzzleHttp\\' => 30, '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\' => 40, '_PHPStan_33c983f26\\Evenement\\' => 29, '_PHPStan_33c983f26\\Composer\\XdebugHandler\\' => 42, '_PHPStan_33c983f26\\Composer\\Semver\\' => 35, '_PHPStan_33c983f26\\Composer\\Pcre\\' => 33, '_PHPStan_33c983f26\\Clue\\React\\NDJson\\' => 37, ), 'S' => array ( 'Symfony\\Polyfill\\Php85\\' => 23, 'Symfony\\Polyfill\\Php84\\' => 23, 'Symfony\\Polyfill\\Php83\\' => 23, 'Symfony\\Polyfill\\Php81\\' => 23, 'Symfony\\Polyfill\\Php80\\' => 23, 'Symfony\\Polyfill\\Mbstring\\' => 26, 'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33, 'Symfony\\Polyfill\\Intl\\Grapheme\\' => 31, ), 'P' => array ( 'PhpParser\\' => 10, 'PHPStan\\PhpDocParser\\' => 21, 'PHPStan\\BetterReflection\\' => 25, 'PHPStan\\' => 8, ), 'H' => array ( 'Hoa\\Zformat\\' => 12, 'Hoa\\Visitor\\' => 12, 'Hoa\\Ustring\\' => 12, 'Hoa\\Stream\\' => 11, 'Hoa\\Regex\\' => 10, 'Hoa\\Protocol\\' => 13, 'Hoa\\Math\\' => 9, 'Hoa\\Iterator\\' => 13, 'Hoa\\File\\' => 9, 'Hoa\\Exception\\' => 14, 'Hoa\\Event\\' => 10, 'Hoa\\Consistency\\' => 16, 'Hoa\\Compiler\\' => 13, ), ); public static $prefixDirsPsr4 = array ( '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\' => array ( 0 => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src', ), '_PHPStan_33c983f26\\Symfony\\Polyfill\\Ctype\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype', ), '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\' => array ( 0 => __DIR__ . '/..' . '/symfony/service-contracts', ), '_PHPStan_33c983f26\\Symfony\\Component\\String\\' => array ( 0 => __DIR__ . '/..' . '/symfony/string', ), '_PHPStan_33c983f26\\Symfony\\Component\\Process\\' => array ( 0 => __DIR__ . '/..' . '/symfony/process', ), '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\' => array ( 0 => __DIR__ . '/..' . '/symfony/finder', ), '_PHPStan_33c983f26\\Symfony\\Component\\Console\\' => array ( 0 => __DIR__ . '/..' . '/symfony/console', ), '_PHPStan_33c983f26\\React\\Stream\\' => array ( 0 => __DIR__ . '/..' . '/react/stream/src', ), '_PHPStan_33c983f26\\React\\Socket\\' => array ( 0 => __DIR__ . '/..' . '/react/socket/src', ), '_PHPStan_33c983f26\\React\\Promise\\' => array ( 0 => __DIR__ . '/..' . '/react/promise/src', ), '_PHPStan_33c983f26\\React\\EventLoop\\' => array ( 0 => __DIR__ . '/..' . '/react/event-loop/src', ), '_PHPStan_33c983f26\\React\\Dns\\' => array ( 0 => __DIR__ . '/..' . '/react/dns/src', ), '_PHPStan_33c983f26\\React\\ChildProcess\\' => array ( 0 => __DIR__ . '/..' . '/react/child-process/src', ), '_PHPStan_33c983f26\\React\\Cache\\' => array ( 0 => __DIR__ . '/..' . '/react/cache/src', ), '_PHPStan_33c983f26\\Psr\\Log\\' => array ( 0 => __DIR__ . '/..' . '/psr/log/src', ), '_PHPStan_33c983f26\\Psr\\Http\\Message\\' => array ( 0 => __DIR__ . '/..' . '/psr/http-factory/src', 1 => __DIR__ . '/..' . '/psr/http-message/src', ), '_PHPStan_33c983f26\\Psr\\Http\\Client\\' => array ( 0 => __DIR__ . '/..' . '/psr/http-client/src', ), '_PHPStan_33c983f26\\Psr\\Container\\' => array ( 0 => __DIR__ . '/..' . '/psr/container/src', ), '_PHPStan_33c983f26\\PhpMerge\\' => array ( 0 => __DIR__ . '/..' . '/ondrejmirtes/php-merge/src/PhpMerge', ), '_PHPStan_33c983f26\\OndraM\\CiDetector\\' => array ( 0 => __DIR__ . '/..' . '/ondram/ci-detector/src', ), '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\' => array ( 0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src', ), '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\' => array ( 0 => __DIR__ . '/..' . '/guzzlehttp/promises/src', ), '_PHPStan_33c983f26\\GuzzleHttp\\' => array ( 0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src', ), '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\' => array ( 0 => __DIR__ . '/..' . '/fidry/cpu-core-counter/src', ), '_PHPStan_33c983f26\\Evenement\\' => array ( 0 => __DIR__ . '/..' . '/evenement/evenement/src', ), '_PHPStan_33c983f26\\Composer\\XdebugHandler\\' => array ( 0 => __DIR__ . '/..' . '/composer/xdebug-handler/src', ), '_PHPStan_33c983f26\\Composer\\Semver\\' => array ( 0 => __DIR__ . '/..' . '/composer/semver/src', ), '_PHPStan_33c983f26\\Composer\\Pcre\\' => array ( 0 => __DIR__ . '/..' . '/composer/pcre/src', ), '_PHPStan_33c983f26\\Clue\\React\\NDJson\\' => array ( 0 => __DIR__ . '/..' . '/clue/ndjson-react/src', ), 'Symfony\\Polyfill\\Php85\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php85', ), 'Symfony\\Polyfill\\Php84\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php84', ), 'Symfony\\Polyfill\\Php83\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php83', ), 'Symfony\\Polyfill\\Php81\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php81', ), 'Symfony\\Polyfill\\Php80\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php80', ), 'Symfony\\Polyfill\\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', ), 'PhpParser\\' => array ( 0 => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser', ), 'PHPStan\\PhpDocParser\\' => array ( 0 => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src', ), 'PHPStan\\BetterReflection\\' => array ( 0 => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src', ), 'PHPStan\\' => array ( 0 => __DIR__ . '/../..' . '/src', ), 'Hoa\\Zformat\\' => array ( 0 => __DIR__ . '/..' . '/hoa/zformat', ), 'Hoa\\Visitor\\' => array ( 0 => __DIR__ . '/..' . '/hoa/visitor', ), 'Hoa\\Ustring\\' => array ( 0 => __DIR__ . '/..' . '/hoa/ustring', ), 'Hoa\\Stream\\' => array ( 0 => __DIR__ . '/..' . '/hoa/stream', ), 'Hoa\\Regex\\' => array ( 0 => __DIR__ . '/..' . '/hoa/regex', ), 'Hoa\\Protocol\\' => array ( 0 => __DIR__ . '/..' . '/hoa/protocol', ), 'Hoa\\Math\\' => array ( 0 => __DIR__ . '/..' . '/hoa/math', ), 'Hoa\\Iterator\\' => array ( 0 => __DIR__ . '/..' . '/hoa/iterator', ), 'Hoa\\File\\' => array ( 0 => __DIR__ . '/..' . '/hoa/file', ), 'Hoa\\Exception\\' => array ( 0 => __DIR__ . '/..' . '/hoa/exception', ), 'Hoa\\Event\\' => array ( 0 => __DIR__ . '/..' . '/hoa/event', ), 'Hoa\\Consistency\\' => array ( 0 => __DIR__ . '/..' . '/hoa/consistency', ), 'Hoa\\Compiler\\' => array ( 0 => __DIR__ . '/..' . '/hoa/compiler', ), ); public static $classMap = array ( 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'CURLStringFile' => __DIR__ . '/..' . '/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php', 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'DateError' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateError.php', 'DateException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateException.php', 'DateInvalidOperationException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateInvalidOperationException.php', 'DateInvalidTimeZoneException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateInvalidTimeZoneException.php', 'DateMalformedIntervalStringException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateMalformedIntervalStringException.php', 'DateMalformedPeriodStringException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateMalformedPeriodStringException.php', 'DateMalformedStringException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateMalformedStringException.php', 'DateObjectError' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateObjectError.php', 'DateRangeError' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateRangeError.php', 'DelayedTargetValidation' => __DIR__ . '/..' . '/symfony/polyfill-php85/Resources/stubs/DelayedTargetValidation.php', 'Deprecated' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php', 'Filter\\FilterException' => __DIR__ . '/..' . '/symfony/polyfill-php85/Resources/stubs/Filter/FilterException.php', 'Filter\\FilterFailedException' => __DIR__ . '/..' . '/symfony/polyfill-php85/Resources/stubs/Filter/FilterFailedException.php', 'Hoa\\Compiler\\Bin\\Pp' => __DIR__ . '/..' . '/hoa/compiler/Bin/Pp.php', 'Hoa\\Compiler\\Exception\\Exception' => __DIR__ . '/..' . '/hoa/compiler/Exception/Exception.php', 'Hoa\\Compiler\\Exception\\FinalStateHasNotBeenReached' => __DIR__ . '/..' . '/hoa/compiler/Exception/FinalStateHasNotBeenReached.php', 'Hoa\\Compiler\\Exception\\IllegalToken' => __DIR__ . '/..' . '/hoa/compiler/Exception/IllegalToken.php', 'Hoa\\Compiler\\Exception\\Lexer' => __DIR__ . '/..' . '/hoa/compiler/Exception/Lexer.php', 'Hoa\\Compiler\\Exception\\Rule' => __DIR__ . '/..' . '/hoa/compiler/Exception/Rule.php', 'Hoa\\Compiler\\Exception\\UnexpectedToken' => __DIR__ . '/..' . '/hoa/compiler/Exception/UnexpectedToken.php', 'Hoa\\Compiler\\Exception\\UnrecognizedToken' => __DIR__ . '/..' . '/hoa/compiler/Exception/UnrecognizedToken.php', 'Hoa\\Compiler\\Ll1' => __DIR__ . '/..' . '/hoa/compiler/Ll1.php', 'Hoa\\Compiler\\Llk\\Lexer' => __DIR__ . '/..' . '/hoa/compiler/Llk/Lexer.php', 'Hoa\\Compiler\\Llk\\Llk' => __DIR__ . '/..' . '/hoa/compiler/Llk/Llk.php', 'Hoa\\Compiler\\Llk\\Parser' => __DIR__ . '/..' . '/hoa/compiler/Llk/Parser.php', 'Hoa\\Compiler\\Llk\\Rule\\Analyzer' => __DIR__ . '/..' . '/hoa/compiler/Llk/Rule/Analyzer.php', 'Hoa\\Compiler\\Llk\\Rule\\Choice' => __DIR__ . '/..' . '/hoa/compiler/Llk/Rule/Choice.php', 'Hoa\\Compiler\\Llk\\Rule\\Concatenation' => __DIR__ . '/..' . '/hoa/compiler/Llk/Rule/Concatenation.php', 'Hoa\\Compiler\\Llk\\Rule\\Ekzit' => __DIR__ . '/..' . '/hoa/compiler/Llk/Rule/Ekzit.php', 'Hoa\\Compiler\\Llk\\Rule\\Entry' => __DIR__ . '/..' . '/hoa/compiler/Llk/Rule/Entry.php', 'Hoa\\Compiler\\Llk\\Rule\\Invocation' => __DIR__ . '/..' . '/hoa/compiler/Llk/Rule/Invocation.php', 'Hoa\\Compiler\\Llk\\Rule\\Repetition' => __DIR__ . '/..' . '/hoa/compiler/Llk/Rule/Repetition.php', 'Hoa\\Compiler\\Llk\\Rule\\Rule' => __DIR__ . '/..' . '/hoa/compiler/Llk/Rule/Rule.php', 'Hoa\\Compiler\\Llk\\Rule\\Token' => __DIR__ . '/..' . '/hoa/compiler/Llk/Rule/Token.php', 'Hoa\\Compiler\\Llk\\Sampler\\BoundedExhaustive' => __DIR__ . '/..' . '/hoa/compiler/Llk/Sampler/BoundedExhaustive.php', 'Hoa\\Compiler\\Llk\\Sampler\\Coverage' => __DIR__ . '/..' . '/hoa/compiler/Llk/Sampler/Coverage.php', 'Hoa\\Compiler\\Llk\\Sampler\\Exception' => __DIR__ . '/..' . '/hoa/compiler/Llk/Sampler/Exception.php', 'Hoa\\Compiler\\Llk\\Sampler\\Sampler' => __DIR__ . '/..' . '/hoa/compiler/Llk/Sampler/Sampler.php', 'Hoa\\Compiler\\Llk\\Sampler\\Uniform' => __DIR__ . '/..' . '/hoa/compiler/Llk/Sampler/Uniform.php', 'Hoa\\Compiler\\Llk\\TreeNode' => __DIR__ . '/..' . '/hoa/compiler/Llk/TreeNode.php', 'Hoa\\Compiler\\Test\\Integration\\Documentation' => __DIR__ . '/..' . '/hoa/compiler/Test/Integration/Documentation.php', 'Hoa\\Compiler\\Test\\Integration\\Llk\\Documentation' => __DIR__ . '/..' . '/hoa/compiler/Test/Integration/Llk/Documentation.php', 'Hoa\\Compiler\\Test\\Integration\\Llk\\Rule\\Analyzer' => __DIR__ . '/..' . '/hoa/compiler/Test/Integration/Llk/Rule/Analyzer.php', 'Hoa\\Compiler\\Test\\Integration\\Llk\\Soundness' => __DIR__ . '/..' . '/hoa/compiler/Test/Integration/Llk/Soundness.php', 'Hoa\\Compiler\\Test\\Unit\\Exception\\Exception' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Exception/Exception.php', 'Hoa\\Compiler\\Test\\Unit\\Exception\\FinalStateHasNotBeenReached' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Exception/FinalStateHasNotBeenReached.php', 'Hoa\\Compiler\\Test\\Unit\\Exception\\IllegalToken' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Exception/IllegalToken.php', 'Hoa\\Compiler\\Test\\Unit\\Exception\\Lexer' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Exception/Lexer.php', 'Hoa\\Compiler\\Test\\Unit\\Exception\\Rule' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Exception/Rule.php', 'Hoa\\Compiler\\Test\\Unit\\Exception\\UnexpectedToken' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Exception/UnexpectedToken.php', 'Hoa\\Compiler\\Test\\Unit\\Exception\\UnrecognizedToken' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Exception/UnrecognizedToken.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Lexer' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Llk/Lexer.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Llk' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Llk/Llk.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Rule\\Choice' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Llk/Rule/Choice.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Rule\\Concatenation' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Llk/Rule/Concatenation.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Rule\\Ekzit' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Llk/Rule/Ekzit.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Rule\\Entry' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Llk/Rule/Entry.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Rule\\Invocation' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Llk/Rule/Invocation.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Rule\\Repetition' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Llk/Rule/Repetition.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Rule\\Rule' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Llk/Rule/Rule.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Rule\\Token' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Llk/Rule/Token.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\Sampler\\Exception' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Llk/Sampler/Exception.php', 'Hoa\\Compiler\\Test\\Unit\\Llk\\TreeNode' => __DIR__ . '/..' . '/hoa/compiler/Test/Unit/Llk/TreeNode.php', 'Hoa\\Compiler\\Visitor\\Dump' => __DIR__ . '/..' . '/hoa/compiler/Visitor/Dump.php', 'Hoa\\Consistency\\Autoloader' => __DIR__ . '/..' . '/hoa/consistency/Autoloader.php', 'Hoa\\Consistency\\Consistency' => __DIR__ . '/..' . '/hoa/consistency/Consistency.php', 'Hoa\\Consistency\\Exception' => __DIR__ . '/..' . '/hoa/consistency/Exception.php', 'Hoa\\Consistency\\Test\\Unit\\Autoloader' => __DIR__ . '/..' . '/hoa/consistency/Test/Unit/Autoloader.php', 'Hoa\\Consistency\\Test\\Unit\\Consistency' => __DIR__ . '/..' . '/hoa/consistency/Test/Unit/Consistency.php', 'Hoa\\Consistency\\Test\\Unit\\Exception' => __DIR__ . '/..' . '/hoa/consistency/Test/Unit/Exception.php', 'Hoa\\Consistency\\Test\\Unit\\Xcallable' => __DIR__ . '/..' . '/hoa/consistency/Test/Unit/Xcallable.php', 'Hoa\\Consistency\\Xcallable' => __DIR__ . '/..' . '/hoa/consistency/Xcallable.php', 'Hoa\\Event\\Bucket' => __DIR__ . '/..' . '/hoa/event/Bucket.php', 'Hoa\\Event\\Event' => __DIR__ . '/..' . '/hoa/event/Event.php', 'Hoa\\Event\\Exception' => __DIR__ . '/..' . '/hoa/event/Exception.php', 'Hoa\\Event\\Listenable' => __DIR__ . '/..' . '/hoa/event/Listenable.php', 'Hoa\\Event\\Listener' => __DIR__ . '/..' . '/hoa/event/Listener.php', 'Hoa\\Event\\Listens' => __DIR__ . '/..' . '/hoa/event/Listens.php', 'Hoa\\Event\\Source' => __DIR__ . '/..' . '/hoa/event/Source.php', 'Hoa\\Event\\Test\\Unit\\Bucket' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Bucket.php', 'Hoa\\Event\\Test\\Unit\\Event' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Event.php', 'Hoa\\Event\\Test\\Unit\\Exception' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Exception.php', 'Hoa\\Event\\Test\\Unit\\Listenable' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Listenable.php', 'Hoa\\Event\\Test\\Unit\\Listener' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Listener.php', 'Hoa\\Event\\Test\\Unit\\Listens' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Listens.php', 'Hoa\\Event\\Test\\Unit\\Source' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Source.php', 'Hoa\\Exception\\Error' => __DIR__ . '/..' . '/hoa/exception/Error.php', 'Hoa\\Exception\\Exception' => __DIR__ . '/..' . '/hoa/exception/Exception.php', 'Hoa\\Exception\\Group' => __DIR__ . '/..' . '/hoa/exception/Group.php', 'Hoa\\Exception\\Idle' => __DIR__ . '/..' . '/hoa/exception/Idle.php', 'Hoa\\Exception\\Test\\Unit\\Error' => __DIR__ . '/..' . '/hoa/exception/Test/Unit/Error.php', 'Hoa\\Exception\\Test\\Unit\\Exception' => __DIR__ . '/..' . '/hoa/exception/Test/Unit/Exception.php', 'Hoa\\Exception\\Test\\Unit\\Group' => __DIR__ . '/..' . '/hoa/exception/Test/Unit/Group.php', 'Hoa\\Exception\\Test\\Unit\\Idle' => __DIR__ . '/..' . '/hoa/exception/Test/Unit/Idle.php', 'Hoa\\File\\Directory' => __DIR__ . '/..' . '/hoa/file/Directory.php', 'Hoa\\File\\Exception\\Exception' => __DIR__ . '/..' . '/hoa/file/Exception/Exception.php', 'Hoa\\File\\Exception\\FileDoesNotExist' => __DIR__ . '/..' . '/hoa/file/Exception/FileDoesNotExist.php', 'Hoa\\File\\File' => __DIR__ . '/..' . '/hoa/file/File.php', 'Hoa\\File\\Finder' => __DIR__ . '/..' . '/hoa/file/Finder.php', 'Hoa\\File\\Generic' => __DIR__ . '/..' . '/hoa/file/Generic.php', 'Hoa\\File\\Link\\Link' => __DIR__ . '/..' . '/hoa/file/Link/Link.php', 'Hoa\\File\\Link\\Read' => __DIR__ . '/..' . '/hoa/file/Link/Read.php', 'Hoa\\File\\Link\\ReadWrite' => __DIR__ . '/..' . '/hoa/file/Link/ReadWrite.php', 'Hoa\\File\\Link\\Write' => __DIR__ . '/..' . '/hoa/file/Link/Write.php', 'Hoa\\File\\Read' => __DIR__ . '/..' . '/hoa/file/Read.php', 'Hoa\\File\\ReadWrite' => __DIR__ . '/..' . '/hoa/file/ReadWrite.php', 'Hoa\\File\\SplFileInfo' => __DIR__ . '/..' . '/hoa/file/SplFileInfo.php', 'Hoa\\File\\Temporary\\Read' => __DIR__ . '/..' . '/hoa/file/Temporary/Read.php', 'Hoa\\File\\Temporary\\ReadWrite' => __DIR__ . '/..' . '/hoa/file/Temporary/ReadWrite.php', 'Hoa\\File\\Temporary\\Temporary' => __DIR__ . '/..' . '/hoa/file/Temporary/Temporary.php', 'Hoa\\File\\Temporary\\Write' => __DIR__ . '/..' . '/hoa/file/Temporary/Write.php', 'Hoa\\File\\Watcher' => __DIR__ . '/..' . '/hoa/file/Watcher.php', 'Hoa\\File\\Write' => __DIR__ . '/..' . '/hoa/file/Write.php', 'Hoa\\Iterator\\Aggregate' => __DIR__ . '/..' . '/hoa/iterator/Aggregate.php', 'Hoa\\Iterator\\Append' => __DIR__ . '/..' . '/hoa/iterator/Append.php', 'Hoa\\Iterator\\Buffer' => __DIR__ . '/..' . '/hoa/iterator/Buffer.php', 'Hoa\\Iterator\\CallbackFilter' => __DIR__ . '/..' . '/hoa/iterator/CallbackFilter.php', 'Hoa\\Iterator\\CallbackGenerator' => __DIR__ . '/..' . '/hoa/iterator/CallbackGenerator.php', 'Hoa\\Iterator\\Counter' => __DIR__ . '/..' . '/hoa/iterator/Counter.php', 'Hoa\\Iterator\\Demultiplexer' => __DIR__ . '/..' . '/hoa/iterator/Demultiplexer.php', 'Hoa\\Iterator\\Directory' => __DIR__ . '/..' . '/hoa/iterator/Directory.php', 'Hoa\\Iterator\\Exception' => __DIR__ . '/..' . '/hoa/iterator/Exception.php', 'Hoa\\Iterator\\FileSystem' => __DIR__ . '/..' . '/hoa/iterator/FileSystem.php', 'Hoa\\Iterator\\Filter' => __DIR__ . '/..' . '/hoa/iterator/Filter.php', 'Hoa\\Iterator\\Glob' => __DIR__ . '/..' . '/hoa/iterator/Glob.php', 'Hoa\\Iterator\\Infinite' => __DIR__ . '/..' . '/hoa/iterator/Infinite.php', 'Hoa\\Iterator\\Iterator' => __DIR__ . '/..' . '/hoa/iterator/Iterator.php', 'Hoa\\Iterator\\IteratorIterator' => __DIR__ . '/..' . '/hoa/iterator/IteratorIterator.php', 'Hoa\\Iterator\\Limit' => __DIR__ . '/..' . '/hoa/iterator/Limit.php', 'Hoa\\Iterator\\Lookahead' => __DIR__ . '/..' . '/hoa/iterator/Lookahead.php', 'Hoa\\Iterator\\Lookbehind' => __DIR__ . '/..' . '/hoa/iterator/Lookbehind.php', 'Hoa\\Iterator\\Map' => __DIR__ . '/..' . '/hoa/iterator/Map.php', 'Hoa\\Iterator\\Mock' => __DIR__ . '/..' . '/hoa/iterator/Mock.php', 'Hoa\\Iterator\\Multiple' => __DIR__ . '/..' . '/hoa/iterator/Multiple.php', 'Hoa\\Iterator\\NoRewind' => __DIR__ . '/..' . '/hoa/iterator/NoRewind.php', 'Hoa\\Iterator\\Outer' => __DIR__ . '/..' . '/hoa/iterator/Outer.php', 'Hoa\\Iterator\\Recursive\\CallbackFilter' => __DIR__ . '/..' . '/hoa/iterator/Recursive/CallbackFilter.php', 'Hoa\\Iterator\\Recursive\\Directory' => __DIR__ . '/..' . '/hoa/iterator/Recursive/Directory.php', 'Hoa\\Iterator\\Recursive\\Filter' => __DIR__ . '/..' . '/hoa/iterator/Recursive/Filter.php', 'Hoa\\Iterator\\Recursive\\Iterator' => __DIR__ . '/..' . '/hoa/iterator/Recursive/Iterator.php', 'Hoa\\Iterator\\Recursive\\Map' => __DIR__ . '/..' . '/hoa/iterator/Recursive/Map.php', 'Hoa\\Iterator\\Recursive\\Mock' => __DIR__ . '/..' . '/hoa/iterator/Recursive/Mock.php', 'Hoa\\Iterator\\Recursive\\Recursive' => __DIR__ . '/..' . '/hoa/iterator/Recursive/Recursive.php', 'Hoa\\Iterator\\Recursive\\RegularExpression' => __DIR__ . '/..' . '/hoa/iterator/Recursive/RegularExpression.php', 'Hoa\\Iterator\\RegularExpression' => __DIR__ . '/..' . '/hoa/iterator/RegularExpression.php', 'Hoa\\Iterator\\Repeater' => __DIR__ . '/..' . '/hoa/iterator/Repeater.php', 'Hoa\\Iterator\\Seekable' => __DIR__ . '/..' . '/hoa/iterator/Seekable.php', 'Hoa\\Iterator\\SplFileInfo' => __DIR__ . '/..' . '/hoa/iterator/SplFileInfo.php', 'Hoa\\Iterator\\Test\\Unit\\Append' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/Append.php', 'Hoa\\Iterator\\Test\\Unit\\Buffer' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/Buffer.php', 'Hoa\\Iterator\\Test\\Unit\\CallbackFilter' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/CallbackFilter.php', 'Hoa\\Iterator\\Test\\Unit\\CallbackGenerator' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/CallbackGenerator.php', 'Hoa\\Iterator\\Test\\Unit\\Counter' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/Counter.php', 'Hoa\\Iterator\\Test\\Unit\\Demultiplexer' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/Demultiplexer.php', 'Hoa\\Iterator\\Test\\Unit\\Directory' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/Directory.php', 'Hoa\\Iterator\\Test\\Unit\\FileSystem' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/FileSystem.php', 'Hoa\\Iterator\\Test\\Unit\\Filter' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/Filter.php', 'Hoa\\Iterator\\Test\\Unit\\Infinite' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/Infinite.php', 'Hoa\\Iterator\\Test\\Unit\\IteratorIterator' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/IteratorIterator.php', 'Hoa\\Iterator\\Test\\Unit\\Limit' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/Limit.php', 'Hoa\\Iterator\\Test\\Unit\\Lookahead' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/Lookahead.php', 'Hoa\\Iterator\\Test\\Unit\\Lookbehind' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/Lookbehind.php', 'Hoa\\Iterator\\Test\\Unit\\Map' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/Map.php', 'Hoa\\Iterator\\Test\\Unit\\Mock' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/Mock.php', 'Hoa\\Iterator\\Test\\Unit\\Multiple' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/Multiple.php', 'Hoa\\Iterator\\Test\\Unit\\NoRewind' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/NoRewind.php', 'Hoa\\Iterator\\Test\\Unit\\RegularExpression' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/RegularExpression.php', 'Hoa\\Iterator\\Test\\Unit\\Repeater' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/Repeater.php', 'Hoa\\Iterator\\Test\\Unit\\SplFileInfo' => __DIR__ . '/..' . '/hoa/iterator/Test/Unit/SplFileInfo.php', 'Hoa\\Math\\Bin\\Calc' => __DIR__ . '/..' . '/hoa/math/Bin/Calc.php', 'Hoa\\Math\\Combinatorics\\Combination\\CartesianProduct' => __DIR__ . '/..' . '/hoa/math/Combinatorics/Combination/CartesianProduct.php', 'Hoa\\Math\\Combinatorics\\Combination\\Combination' => __DIR__ . '/..' . '/hoa/math/Combinatorics/Combination/Combination.php', 'Hoa\\Math\\Combinatorics\\Combination\\Gamma' => __DIR__ . '/..' . '/hoa/math/Combinatorics/Combination/Gamma.php', 'Hoa\\Math\\Context' => __DIR__ . '/..' . '/hoa/math/Context.php', 'Hoa\\Math\\Exception\\AlreadyDefinedConstant' => __DIR__ . '/..' . '/hoa/math/Exception/AlreadyDefinedConstant.php', 'Hoa\\Math\\Exception\\Exception' => __DIR__ . '/..' . '/hoa/math/Exception/Exception.php', 'Hoa\\Math\\Exception\\UnknownConstant' => __DIR__ . '/..' . '/hoa/math/Exception/UnknownConstant.php', 'Hoa\\Math\\Exception\\UnknownFunction' => __DIR__ . '/..' . '/hoa/math/Exception/UnknownFunction.php', 'Hoa\\Math\\Exception\\UnknownVariable' => __DIR__ . '/..' . '/hoa/math/Exception/UnknownVariable.php', 'Hoa\\Math\\Sampler\\Random' => __DIR__ . '/..' . '/hoa/math/Sampler/Random.php', 'Hoa\\Math\\Sampler\\Sampler' => __DIR__ . '/..' . '/hoa/math/Sampler/Sampler.php', 'Hoa\\Math\\Test\\Unit\\Combinatorics\\Combination\\CartesianProduct' => __DIR__ . '/..' . '/hoa/math/Test/Unit/Combinatorics/Combination/CartesianProduct.php', 'Hoa\\Math\\Test\\Unit\\Combinatorics\\Combination\\Combination' => __DIR__ . '/..' . '/hoa/math/Test/Unit/Combinatorics/Combination/Combination.php', 'Hoa\\Math\\Test\\Unit\\Combinatorics\\Combination\\Gamma' => __DIR__ . '/..' . '/hoa/math/Test/Unit/Combinatorics/Combination/Gamma.php', 'Hoa\\Math\\Test\\Unit\\Context' => __DIR__ . '/..' . '/hoa/math/Test/Unit/Context.php', 'Hoa\\Math\\Test\\Unit\\Issue' => __DIR__ . '/..' . '/hoa/math/Test/Unit/Issue.php', 'Hoa\\Math\\Test\\Unit\\Sampler\\Random' => __DIR__ . '/..' . '/hoa/math/Test/Unit/Sampler/Random.php', 'Hoa\\Math\\Test\\Unit\\Visitor\\Arithmetic' => __DIR__ . '/..' . '/hoa/math/Test/Unit/Visitor/Arithmetic.php', 'Hoa\\Math\\Util' => __DIR__ . '/..' . '/hoa/math/Util.php', 'Hoa\\Math\\Visitor\\Arithmetic' => __DIR__ . '/..' . '/hoa/math/Visitor/Arithmetic.php', 'Hoa\\Protocol\\Bin\\Resolve' => __DIR__ . '/..' . '/hoa/protocol/Bin/Resolve.php', 'Hoa\\Protocol\\Exception' => __DIR__ . '/..' . '/hoa/protocol/Exception.php', 'Hoa\\Protocol\\Node\\Library' => __DIR__ . '/..' . '/hoa/protocol/Node/Library.php', 'Hoa\\Protocol\\Node\\Node' => __DIR__ . '/..' . '/hoa/protocol/Node/Node.php', 'Hoa\\Protocol\\Protocol' => __DIR__ . '/..' . '/hoa/protocol/Protocol.php', 'Hoa\\Protocol\\Test\\Unit\\Exception' => __DIR__ . '/..' . '/hoa/protocol/Test/Unit/Exception.php', 'Hoa\\Protocol\\Test\\Unit\\Node\\Library' => __DIR__ . '/..' . '/hoa/protocol/Test/Unit/Node/Library.php', 'Hoa\\Protocol\\Test\\Unit\\Node\\Node' => __DIR__ . '/..' . '/hoa/protocol/Test/Unit/Node/Node.php', 'Hoa\\Protocol\\Test\\Unit\\Protocol' => __DIR__ . '/..' . '/hoa/protocol/Test/Unit/Protocol.php', 'Hoa\\Protocol\\Test\\Unit\\Wrapper' => __DIR__ . '/..' . '/hoa/protocol/Test/Unit/Wrapper.php', 'Hoa\\Protocol\\Wrapper' => __DIR__ . '/..' . '/hoa/protocol/Wrapper.php', 'Hoa\\Regex\\Exception' => __DIR__ . '/..' . '/hoa/regex/Exception.php', 'Hoa\\Regex\\Visitor\\Isotropic' => __DIR__ . '/..' . '/hoa/regex/Visitor/Isotropic.php', 'Hoa\\Stream\\Bucket' => __DIR__ . '/..' . '/hoa/stream/Bucket.php', 'Hoa\\Stream\\Composite' => __DIR__ . '/..' . '/hoa/stream/Composite.php', 'Hoa\\Stream\\Context' => __DIR__ . '/..' . '/hoa/stream/Context.php', 'Hoa\\Stream\\Exception' => __DIR__ . '/..' . '/hoa/stream/Exception.php', 'Hoa\\Stream\\Filter\\Basic' => __DIR__ . '/..' . '/hoa/stream/Filter/Basic.php', 'Hoa\\Stream\\Filter\\Exception' => __DIR__ . '/..' . '/hoa/stream/Filter/Exception.php', 'Hoa\\Stream\\Filter\\Filter' => __DIR__ . '/..' . '/hoa/stream/Filter/Filter.php', 'Hoa\\Stream\\Filter\\LateComputed' => __DIR__ . '/..' . '/hoa/stream/Filter/LateComputed.php', 'Hoa\\Stream\\IStream\\Bufferable' => __DIR__ . '/..' . '/hoa/stream/IStream/Bufferable.php', 'Hoa\\Stream\\IStream\\In' => __DIR__ . '/..' . '/hoa/stream/IStream/In.php', 'Hoa\\Stream\\IStream\\Lockable' => __DIR__ . '/..' . '/hoa/stream/IStream/Lockable.php', 'Hoa\\Stream\\IStream\\Out' => __DIR__ . '/..' . '/hoa/stream/IStream/Out.php', 'Hoa\\Stream\\IStream\\Pathable' => __DIR__ . '/..' . '/hoa/stream/IStream/Pathable.php', 'Hoa\\Stream\\IStream\\Pointable' => __DIR__ . '/..' . '/hoa/stream/IStream/Pointable.php', 'Hoa\\Stream\\IStream\\Statable' => __DIR__ . '/..' . '/hoa/stream/IStream/Statable.php', 'Hoa\\Stream\\IStream\\Stream' => __DIR__ . '/..' . '/hoa/stream/IStream/Stream.php', 'Hoa\\Stream\\IStream\\Structural' => __DIR__ . '/..' . '/hoa/stream/IStream/Structural.php', 'Hoa\\Stream\\IStream\\Touchable' => __DIR__ . '/..' . '/hoa/stream/IStream/Touchable.php', 'Hoa\\Stream\\Stream' => __DIR__ . '/..' . '/hoa/stream/Stream.php', 'Hoa\\Stream\\Test\\Integration\\Filter\\Filter' => __DIR__ . '/..' . '/hoa/stream/Test/Integration/Filter/Filter.php', 'Hoa\\Stream\\Test\\Integration\\Filter\\LateComputed' => __DIR__ . '/..' . '/hoa/stream/Test/Integration/Filter/LateComputed.php', 'Hoa\\Stream\\Test\\Integration\\Stream' => __DIR__ . '/..' . '/hoa/stream/Test/Integration/Stream.php', 'Hoa\\Stream\\Test\\Unit\\Bucket' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/Bucket.php', 'Hoa\\Stream\\Test\\Unit\\Composite' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/Composite.php', 'Hoa\\Stream\\Test\\Unit\\Context' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/Context.php', 'Hoa\\Stream\\Test\\Unit\\Exception' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/Exception.php', 'Hoa\\Stream\\Test\\Unit\\Filter\\Basic' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/Filter/Basic.php', 'Hoa\\Stream\\Test\\Unit\\Filter\\Exception' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/Filter/Exception.php', 'Hoa\\Stream\\Test\\Unit\\Filter\\Filter' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/Filter/Filter.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Bufferable' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/IStream/Bufferable.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\In' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/IStream/In.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Lockable' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/IStream/Lockable.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Out' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/IStream/Out.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Pathable' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/IStream/Pathable.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Pointable' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/IStream/Pointable.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Statable' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/IStream/Statable.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Stream' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/IStream/Stream.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Structural' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/IStream/Structural.php', 'Hoa\\Stream\\Test\\Unit\\IStream\\Touchable' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/IStream/Touchable.php', 'Hoa\\Stream\\Test\\Unit\\Stream' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/Stream.php', 'Hoa\\Stream\\Test\\Unit\\Wrapper\\Exception' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/Wrapper/Exception.php', 'Hoa\\Stream\\Test\\Unit\\Wrapper\\IWrapper\\File' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/Wrapper/IWrapper/File.php', 'Hoa\\Stream\\Test\\Unit\\Wrapper\\IWrapper\\IWrapper' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/Wrapper/IWrapper/IWrapper.php', 'Hoa\\Stream\\Test\\Unit\\Wrapper\\IWrapper\\Stream' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/Wrapper/IWrapper/Stream.php', 'Hoa\\Stream\\Test\\Unit\\Wrapper\\Wrapper' => __DIR__ . '/..' . '/hoa/stream/Test/Unit/Wrapper/Wrapper.php', 'Hoa\\Stream\\Wrapper\\Exception' => __DIR__ . '/..' . '/hoa/stream/Wrapper/Exception.php', 'Hoa\\Stream\\Wrapper\\IWrapper\\File' => __DIR__ . '/..' . '/hoa/stream/Wrapper/IWrapper/File.php', 'Hoa\\Stream\\Wrapper\\IWrapper\\IWrapper' => __DIR__ . '/..' . '/hoa/stream/Wrapper/IWrapper/IWrapper.php', 'Hoa\\Stream\\Wrapper\\IWrapper\\Stream' => __DIR__ . '/..' . '/hoa/stream/Wrapper/IWrapper/Stream.php', 'Hoa\\Stream\\Wrapper\\Wrapper' => __DIR__ . '/..' . '/hoa/stream/Wrapper/Wrapper.php', 'Hoa\\Ustring\\Bin\\Fromcode' => __DIR__ . '/..' . '/hoa/ustring/Bin/Fromcode.php', 'Hoa\\Ustring\\Bin\\Tocode' => __DIR__ . '/..' . '/hoa/ustring/Bin/Tocode.php', 'Hoa\\Ustring\\Exception' => __DIR__ . '/..' . '/hoa/ustring/Exception.php', 'Hoa\\Ustring\\Search' => __DIR__ . '/..' . '/hoa/ustring/Search.php', 'Hoa\\Ustring\\Test\\Unit\\Issue' => __DIR__ . '/..' . '/hoa/ustring/Test/Unit/Issue.php', 'Hoa\\Ustring\\Test\\Unit\\Search' => __DIR__ . '/..' . '/hoa/ustring/Test/Unit/Search.php', 'Hoa\\Ustring\\Test\\Unit\\Ustring' => __DIR__ . '/..' . '/hoa/ustring/Test/Unit/Ustring.php', 'Hoa\\Ustring\\Ustring' => __DIR__ . '/..' . '/hoa/ustring/Ustring.php', 'Hoa\\Visitor\\Element' => __DIR__ . '/..' . '/hoa/visitor/Element.php', 'Hoa\\Visitor\\Test\\Unit\\Element' => __DIR__ . '/..' . '/hoa/visitor/Test/Unit/Element.php', 'Hoa\\Visitor\\Test\\Unit\\Visit' => __DIR__ . '/..' . '/hoa/visitor/Test/Unit/Visit.php', 'Hoa\\Visitor\\Visit' => __DIR__ . '/..' . '/hoa/visitor/Visit.php', 'Hoa\\Zformat\\Exception' => __DIR__ . '/..' . '/hoa/zformat/Exception.php', 'Hoa\\Zformat\\Parameter' => __DIR__ . '/..' . '/hoa/zformat/Parameter.php', 'Hoa\\Zformat\\Parameterizable' => __DIR__ . '/..' . '/hoa/zformat/Parameterizable.php', 'NoDiscard' => __DIR__ . '/..' . '/symfony/polyfill-php85/Resources/stubs/NoDiscard.php', 'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', 'Override' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/Override.php', 'PHPStan\\AnalysedCodeException' => __DIR__ . '/../..' . '/src/AnalysedCodeException.php', 'PHPStan\\Analyser\\Analyser' => __DIR__ . '/../..' . '/src/Analyser/Analyser.php', 'PHPStan\\Analyser\\AnalyserResult' => __DIR__ . '/../..' . '/src/Analyser/AnalyserResult.php', 'PHPStan\\Analyser\\AnalyserResultFinalizer' => __DIR__ . '/../..' . '/src/Analyser/AnalyserResultFinalizer.php', 'PHPStan\\Analyser\\ArgumentsNormalizer' => __DIR__ . '/../..' . '/src/Analyser/ArgumentsNormalizer.php', 'PHPStan\\Analyser\\ConditionalExpressionHolder' => __DIR__ . '/../..' . '/src/Analyser/ConditionalExpressionHolder.php', 'PHPStan\\Analyser\\ConstantResolver' => __DIR__ . '/../..' . '/src/Analyser/ConstantResolver.php', 'PHPStan\\Analyser\\ConstantResolverFactory' => __DIR__ . '/../..' . '/src/Analyser/ConstantResolverFactory.php', 'PHPStan\\Analyser\\DirectInternalScopeFactory' => __DIR__ . '/../..' . '/src/Analyser/DirectInternalScopeFactory.php', 'PHPStan\\Analyser\\DirectInternalScopeFactoryFactory' => __DIR__ . '/../..' . '/src/Analyser/DirectInternalScopeFactoryFactory.php', 'PHPStan\\Analyser\\EndStatementResult' => __DIR__ . '/../..' . '/src/Analyser/EndStatementResult.php', 'PHPStan\\Analyser\\EnsuredNonNullabilityResult' => __DIR__ . '/../..' . '/src/Analyser/EnsuredNonNullabilityResult.php', 'PHPStan\\Analyser\\EnsuredNonNullabilityResultExpression' => __DIR__ . '/../..' . '/src/Analyser/EnsuredNonNullabilityResultExpression.php', 'PHPStan\\Analyser\\Error' => __DIR__ . '/../..' . '/src/Analyser/Error.php', 'PHPStan\\Analyser\\ExprHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ArrayDimFetchHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/ArrayDimFetchHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ArrayHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/ArrayHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ArrowFunctionHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/ArrowFunctionHandler.php', 'PHPStan\\Analyser\\ExprHandler\\AssignHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/AssignHandler.php', 'PHPStan\\Analyser\\ExprHandler\\AssignOpHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/AssignOpHandler.php', 'PHPStan\\Analyser\\ExprHandler\\BinaryOpHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/BinaryOpHandler.php', 'PHPStan\\Analyser\\ExprHandler\\BitwiseNotHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/BitwiseNotHandler.php', 'PHPStan\\Analyser\\ExprHandler\\BooleanAndHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/BooleanAndHandler.php', 'PHPStan\\Analyser\\ExprHandler\\BooleanNotHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/BooleanNotHandler.php', 'PHPStan\\Analyser\\ExprHandler\\BooleanOrHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/BooleanOrHandler.php', 'PHPStan\\Analyser\\ExprHandler\\CastHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/CastHandler.php', 'PHPStan\\Analyser\\ExprHandler\\CastStringHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/CastStringHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ClassConstFetchHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/ClassConstFetchHandler.php', 'PHPStan\\Analyser\\ExprHandler\\CloneHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/CloneHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ClosureHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/ClosureHandler.php', 'PHPStan\\Analyser\\ExprHandler\\CoalesceHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/CoalesceHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ConstFetchHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/ConstFetchHandler.php', 'PHPStan\\Analyser\\ExprHandler\\EmptyHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/EmptyHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ErrorSuppressHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/ErrorSuppressHandler.php', 'PHPStan\\Analyser\\ExprHandler\\EvalHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/EvalHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ExitHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/ExitHandler.php', 'PHPStan\\Analyser\\ExprHandler\\FirstClassCallableFuncCallHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/FirstClassCallableFuncCallHandler.php', 'PHPStan\\Analyser\\ExprHandler\\FirstClassCallableMethodCallHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/FirstClassCallableMethodCallHandler.php', 'PHPStan\\Analyser\\ExprHandler\\FirstClassCallableNewHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/FirstClassCallableNewHandler.php', 'PHPStan\\Analyser\\ExprHandler\\FirstClassCallableStaticCallHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/FirstClassCallableStaticCallHandler.php', 'PHPStan\\Analyser\\ExprHandler\\FuncCallHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/FuncCallHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Helper\\ClosureTypeResolver' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Helper/ClosureTypeResolver.php', 'PHPStan\\Analyser\\ExprHandler\\Helper\\ImplicitToStringCallHelper' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Helper/ImplicitToStringCallHelper.php', 'PHPStan\\Analyser\\ExprHandler\\Helper\\MethodCallReturnTypeHelper' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Helper/MethodCallReturnTypeHelper.php', 'PHPStan\\Analyser\\ExprHandler\\Helper\\MethodThrowPointHelper' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Helper/MethodThrowPointHelper.php', 'PHPStan\\Analyser\\ExprHandler\\Helper\\NonNullabilityHelper' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Helper/NonNullabilityHelper.php', 'PHPStan\\Analyser\\ExprHandler\\Helper\\NullsafeShortCircuitingHelper' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Helper/NullsafeShortCircuitingHelper.php', 'PHPStan\\Analyser\\ExprHandler\\Helper\\VoidToNullTypeTransformer' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Helper/VoidToNullTypeTransformer.php', 'PHPStan\\Analyser\\ExprHandler\\IncludeHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/IncludeHandler.php', 'PHPStan\\Analyser\\ExprHandler\\InstanceofHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/InstanceofHandler.php', 'PHPStan\\Analyser\\ExprHandler\\InterpolatedStringHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/InterpolatedStringHandler.php', 'PHPStan\\Analyser\\ExprHandler\\IssetHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/IssetHandler.php', 'PHPStan\\Analyser\\ExprHandler\\MatchHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/MatchHandler.php', 'PHPStan\\Analyser\\ExprHandler\\MethodCallHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/MethodCallHandler.php', 'PHPStan\\Analyser\\ExprHandler\\NewHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/NewHandler.php', 'PHPStan\\Analyser\\ExprHandler\\NullsafeMethodCallHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/NullsafeMethodCallHandler.php', 'PHPStan\\Analyser\\ExprHandler\\NullsafePropertyFetchHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/NullsafePropertyFetchHandler.php', 'PHPStan\\Analyser\\ExprHandler\\PipeHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/PipeHandler.php', 'PHPStan\\Analyser\\ExprHandler\\PostDecHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/PostDecHandler.php', 'PHPStan\\Analyser\\ExprHandler\\PostIncHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/PostIncHandler.php', 'PHPStan\\Analyser\\ExprHandler\\PreDecHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/PreDecHandler.php', 'PHPStan\\Analyser\\ExprHandler\\PreIncHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/PreIncHandler.php', 'PHPStan\\Analyser\\ExprHandler\\PrintHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/PrintHandler.php', 'PHPStan\\Analyser\\ExprHandler\\PropertyFetchHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/PropertyFetchHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ScalarHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/ScalarHandler.php', 'PHPStan\\Analyser\\ExprHandler\\StaticCallHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/StaticCallHandler.php', 'PHPStan\\Analyser\\ExprHandler\\StaticPropertyFetchHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/StaticPropertyFetchHandler.php', 'PHPStan\\Analyser\\ExprHandler\\TernaryHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/TernaryHandler.php', 'PHPStan\\Analyser\\ExprHandler\\ThrowHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/ThrowHandler.php', 'PHPStan\\Analyser\\ExprHandler\\UnaryMinusHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/UnaryMinusHandler.php', 'PHPStan\\Analyser\\ExprHandler\\UnaryPlusHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/UnaryPlusHandler.php', 'PHPStan\\Analyser\\ExprHandler\\VariableHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/VariableHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\AlwaysRememberedExprHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Virtual/AlwaysRememberedExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\ExistingArrayDimFetchHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Virtual/ExistingArrayDimFetchHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\FunctionCallableNodeHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Virtual/FunctionCallableNodeHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\GetIterableKeyTypeExprHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Virtual/GetIterableKeyTypeExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\GetIterableValueTypeExprHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Virtual/GetIterableValueTypeExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\GetOffsetValueTypeExprHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Virtual/GetOffsetValueTypeExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\InstantiationCallableNodeHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Virtual/InstantiationCallableNodeHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\MethodCallableNodeHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Virtual/MethodCallableNodeHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\NativeTypeExprHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Virtual/NativeTypeExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\OriginalPropertyTypeExprHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Virtual/OriginalPropertyTypeExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\SetExistingOffsetValueTypeExprHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Virtual/SetExistingOffsetValueTypeExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\SetOffsetValueTypeExprHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Virtual/SetOffsetValueTypeExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\StaticMethodCallableNodeHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Virtual/StaticMethodCallableNodeHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\TypeExprHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Virtual/TypeExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\Virtual\\UnsetOffsetExprHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/Virtual/UnsetOffsetExprHandler.php', 'PHPStan\\Analyser\\ExprHandler\\YieldFromHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/YieldFromHandler.php', 'PHPStan\\Analyser\\ExprHandler\\YieldHandler' => __DIR__ . '/../..' . '/src/Analyser/ExprHandler/YieldHandler.php', 'PHPStan\\Analyser\\ExpressionContext' => __DIR__ . '/../..' . '/src/Analyser/ExpressionContext.php', 'PHPStan\\Analyser\\ExpressionResult' => __DIR__ . '/../..' . '/src/Analyser/ExpressionResult.php', 'PHPStan\\Analyser\\ExpressionResultStorage' => __DIR__ . '/../..' . '/src/Analyser/ExpressionResultStorage.php', 'PHPStan\\Analyser\\ExpressionTypeHolder' => __DIR__ . '/../..' . '/src/Analyser/ExpressionTypeHolder.php', 'PHPStan\\Analyser\\Fiber\\BeforeScopeForExprRequest' => __DIR__ . '/../..' . '/src/Analyser/Fiber/BeforeScopeForExprRequest.php', 'PHPStan\\Analyser\\Fiber\\FiberNodeScopeResolver' => __DIR__ . '/../..' . '/src/Analyser/Fiber/FiberNodeScopeResolver.php', 'PHPStan\\Analyser\\Fiber\\FiberScope' => __DIR__ . '/../..' . '/src/Analyser/Fiber/FiberScope.php', 'PHPStan\\Analyser\\Fiber\\ParkFiberRequest' => __DIR__ . '/../..' . '/src/Analyser/Fiber/ParkFiberRequest.php', 'PHPStan\\Analyser\\FileAnalyser' => __DIR__ . '/../..' . '/src/Analyser/FileAnalyser.php', 'PHPStan\\Analyser\\FileAnalyserCallback' => __DIR__ . '/../..' . '/src/Analyser/FileAnalyserCallback.php', 'PHPStan\\Analyser\\FileAnalyserResult' => __DIR__ . '/../..' . '/src/Analyser/FileAnalyserResult.php', 'PHPStan\\Analyser\\FinalizerResult' => __DIR__ . '/../..' . '/src/Analyser/FinalizerResult.php', 'PHPStan\\Analyser\\FixedErrorDiff' => __DIR__ . '/../..' . '/src/Analyser/FixedErrorDiff.php', 'PHPStan\\Analyser\\IgnoreErrorExtension' => __DIR__ . '/../..' . '/src/Analyser/IgnoreErrorExtension.php', 'PHPStan\\Analyser\\IgnoreErrorExtensionProvider' => __DIR__ . '/../..' . '/src/Analyser/IgnoreErrorExtensionProvider.php', 'PHPStan\\Analyser\\Ignore\\IgnoreLexer' => __DIR__ . '/../..' . '/src/Analyser/Ignore/IgnoreLexer.php', 'PHPStan\\Analyser\\Ignore\\IgnoreParseException' => __DIR__ . '/../..' . '/src/Analyser/Ignore/IgnoreParseException.php', 'PHPStan\\Analyser\\Ignore\\IgnoredError' => __DIR__ . '/../..' . '/src/Analyser/Ignore/IgnoredError.php', 'PHPStan\\Analyser\\Ignore\\IgnoredErrorHelper' => __DIR__ . '/../..' . '/src/Analyser/Ignore/IgnoredErrorHelper.php', 'PHPStan\\Analyser\\Ignore\\IgnoredErrorHelperProcessedResult' => __DIR__ . '/../..' . '/src/Analyser/Ignore/IgnoredErrorHelperProcessedResult.php', 'PHPStan\\Analyser\\Ignore\\IgnoredErrorHelperResult' => __DIR__ . '/../..' . '/src/Analyser/Ignore/IgnoredErrorHelperResult.php', 'PHPStan\\Analyser\\ImpurePoint' => __DIR__ . '/../..' . '/src/Analyser/ImpurePoint.php', 'PHPStan\\Analyser\\IntermediaryNameScope' => __DIR__ . '/../..' . '/src/Analyser/IntermediaryNameScope.php', 'PHPStan\\Analyser\\InternalEndStatementResult' => __DIR__ . '/../..' . '/src/Analyser/InternalEndStatementResult.php', 'PHPStan\\Analyser\\InternalError' => __DIR__ . '/../..' . '/src/Analyser/InternalError.php', 'PHPStan\\Analyser\\InternalScopeFactory' => __DIR__ . '/../..' . '/src/Analyser/InternalScopeFactory.php', 'PHPStan\\Analyser\\InternalScopeFactoryFactory' => __DIR__ . '/../..' . '/src/Analyser/InternalScopeFactoryFactory.php', 'PHPStan\\Analyser\\InternalStatementExitPoint' => __DIR__ . '/../..' . '/src/Analyser/InternalStatementExitPoint.php', 'PHPStan\\Analyser\\InternalStatementResult' => __DIR__ . '/../..' . '/src/Analyser/InternalStatementResult.php', 'PHPStan\\Analyser\\InternalThrowPoint' => __DIR__ . '/../..' . '/src/Analyser/InternalThrowPoint.php', 'PHPStan\\Analyser\\LazyInternalScopeFactory' => __DIR__ . '/../..' . '/src/Analyser/LazyInternalScopeFactory.php', 'PHPStan\\Analyser\\LocalIgnoresProcessor' => __DIR__ . '/../..' . '/src/Analyser/LocalIgnoresProcessor.php', 'PHPStan\\Analyser\\LocalIgnoresProcessorResult' => __DIR__ . '/../..' . '/src/Analyser/LocalIgnoresProcessorResult.php', 'PHPStan\\Analyser\\MutatingScope' => __DIR__ . '/../..' . '/src/Analyser/MutatingScope.php', 'PHPStan\\Analyser\\NameScope' => __DIR__ . '/../..' . '/src/Analyser/NameScope.php', 'PHPStan\\Analyser\\NodeCallbackInvoker' => __DIR__ . '/../..' . '/src/Analyser/NodeCallbackInvoker.php', 'PHPStan\\Analyser\\NodeScopeResolver' => __DIR__ . '/../..' . '/src/Analyser/NodeScopeResolver.php', 'PHPStan\\Analyser\\NoopNodeCallback' => __DIR__ . '/../..' . '/src/Analyser/NoopNodeCallback.php', 'PHPStan\\Analyser\\NullsafeOperatorHelper' => __DIR__ . '/../..' . '/src/Analyser/NullsafeOperatorHelper.php', 'PHPStan\\Analyser\\OutOfClassScope' => __DIR__ . '/../..' . '/src/Analyser/OutOfClassScope.php', 'PHPStan\\Analyser\\ProcessClosureResult' => __DIR__ . '/../..' . '/src/Analyser/ProcessClosureResult.php', 'PHPStan\\Analyser\\ResultCache\\ResultCache' => __DIR__ . '/../..' . '/src/Analyser/ResultCache/ResultCache.php', 'PHPStan\\Analyser\\ResultCache\\ResultCacheClearer' => __DIR__ . '/../..' . '/src/Analyser/ResultCache/ResultCacheClearer.php', 'PHPStan\\Analyser\\ResultCache\\ResultCacheManager' => __DIR__ . '/../..' . '/src/Analyser/ResultCache/ResultCacheManager.php', 'PHPStan\\Analyser\\ResultCache\\ResultCacheManagerFactory' => __DIR__ . '/../..' . '/src/Analyser/ResultCache/ResultCacheManagerFactory.php', 'PHPStan\\Analyser\\ResultCache\\ResultCacheMetaExtension' => __DIR__ . '/../..' . '/src/Analyser/ResultCache/ResultCacheMetaExtension.php', 'PHPStan\\Analyser\\ResultCache\\ResultCacheProcessResult' => __DIR__ . '/../..' . '/src/Analyser/ResultCache/ResultCacheProcessResult.php', 'PHPStan\\Analyser\\RicherScopeGetTypeHelper' => __DIR__ . '/../..' . '/src/Analyser/RicherScopeGetTypeHelper.php', 'PHPStan\\Analyser\\RuleErrorTransformer' => __DIR__ . '/../..' . '/src/Analyser/RuleErrorTransformer.php', 'PHPStan\\Analyser\\Scope' => __DIR__ . '/../..' . '/src/Analyser/Scope.php', 'PHPStan\\Analyser\\ScopeContext' => __DIR__ . '/../..' . '/src/Analyser/ScopeContext.php', 'PHPStan\\Analyser\\ScopeFactory' => __DIR__ . '/../..' . '/src/Analyser/ScopeFactory.php', 'PHPStan\\Analyser\\ShallowNodeCallback' => __DIR__ . '/../..' . '/src/Analyser/ShallowNodeCallback.php', 'PHPStan\\Analyser\\SpecifiedTypes' => __DIR__ . '/../..' . '/src/Analyser/SpecifiedTypes.php', 'PHPStan\\Analyser\\StatementContext' => __DIR__ . '/../..' . '/src/Analyser/StatementContext.php', 'PHPStan\\Analyser\\StatementExitPoint' => __DIR__ . '/../..' . '/src/Analyser/StatementExitPoint.php', 'PHPStan\\Analyser\\StatementResult' => __DIR__ . '/../..' . '/src/Analyser/StatementResult.php', 'PHPStan\\Analyser\\ThrowPoint' => __DIR__ . '/../..' . '/src/Analyser/ThrowPoint.php', 'PHPStan\\Analyser\\Traverser\\CloneTypeTraverser' => __DIR__ . '/../..' . '/src/Analyser/Traverser/CloneTypeTraverser.php', 'PHPStan\\Analyser\\Traverser\\ConstructorClassTemplateTraverser' => __DIR__ . '/../..' . '/src/Analyser/Traverser/ConstructorClassTemplateTraverser.php', 'PHPStan\\Analyser\\Traverser\\GenericTypeTemplateTraverser' => __DIR__ . '/../..' . '/src/Analyser/Traverser/GenericTypeTemplateTraverser.php', 'PHPStan\\Analyser\\Traverser\\TransformStaticTypeTraverser' => __DIR__ . '/../..' . '/src/Analyser/Traverser/TransformStaticTypeTraverser.php', 'PHPStan\\Analyser\\Traverser\\VoidToNullTraverser' => __DIR__ . '/../..' . '/src/Analyser/Traverser/VoidToNullTraverser.php', 'PHPStan\\Analyser\\TypeSpecifier' => __DIR__ . '/../..' . '/src/Analyser/TypeSpecifier.php', 'PHPStan\\Analyser\\TypeSpecifierAwareExtension' => __DIR__ . '/../..' . '/src/Analyser/TypeSpecifierAwareExtension.php', 'PHPStan\\Analyser\\TypeSpecifierContext' => __DIR__ . '/../..' . '/src/Analyser/TypeSpecifierContext.php', 'PHPStan\\Analyser\\TypeSpecifierFactory' => __DIR__ . '/../..' . '/src/Analyser/TypeSpecifierFactory.php', 'PHPStan\\Analyser\\UndefinedVariableException' => __DIR__ . '/../..' . '/src/Analyser/UndefinedVariableException.php', 'PHPStan\\Analyser\\VirtualAssignNodeCallback' => __DIR__ . '/../..' . '/src/Analyser/VirtualAssignNodeCallback.php', 'PHPStan\\BetterReflection\\BetterReflection' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/BetterReflection.php', 'PHPStan\\BetterReflection\\Identifier\\Exception\\InvalidIdentifierName' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Identifier/Exception/InvalidIdentifierName.php', 'PHPStan\\BetterReflection\\Identifier\\Identifier' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Identifier/Identifier.php', 'PHPStan\\BetterReflection\\Identifier\\IdentifierType' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Identifier/IdentifierType.php', 'PHPStan\\BetterReflection\\NodeCompiler\\CompileNodeToValue' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/NodeCompiler/CompileNodeToValue.php', 'PHPStan\\BetterReflection\\NodeCompiler\\CompiledValue' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/NodeCompiler/CompiledValue.php', 'PHPStan\\BetterReflection\\NodeCompiler\\CompilerContext' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/NodeCompiler/CompilerContext.php', 'PHPStan\\BetterReflection\\NodeCompiler\\Exception\\UnableToCompileNode' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/NodeCompiler/Exception/UnableToCompileNode.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\Exception\\NotImplemented' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/Exception/NotImplemented.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\Exception\\NotImplementedBecauseItTriggersAutoloading' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/Exception/NotImplementedBecauseItTriggersAutoloading.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\FakeReflectionAttribute' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/FakeReflectionAttribute.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionAttribute' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionAttribute.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionAttributeFactory' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionAttributeFactory.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionClass' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionClass.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionClassConstant' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionClassConstant.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionEnum' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionEnum.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionEnumBackedCase' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionEnumBackedCase.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionEnumUnitCase' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionEnumUnitCase.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionFunction' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionFunction.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionIntersectionType' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionIntersectionType.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionMethod' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionMethod.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionNamedType' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionNamedType.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionObject' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionObject.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionParameter' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionParameter.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionProperty' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionProperty.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionType' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionType.php', 'PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionUnionType' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionUnionType.php', 'PHPStan\\BetterReflection\\Reflection\\Annotation\\AnnotationHelper' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Annotation/AnnotationHelper.php', 'PHPStan\\BetterReflection\\Reflection\\Attribute\\ReflectionAttributeHelper' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Attribute/ReflectionAttributeHelper.php', 'PHPStan\\BetterReflection\\Reflection\\Deprecated\\DeprecatedHelper' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Deprecated/DeprecatedHelper.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\CircularReference' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Exception/CircularReference.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\ClassDoesNotExist' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Exception/ClassDoesNotExist.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\CodeLocationMissing' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Exception/CodeLocationMissing.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\FunctionDoesNotExist' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Exception/FunctionDoesNotExist.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\InvalidArrowFunctionBodyNode' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Exception/InvalidArrowFunctionBodyNode.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\InvalidConstantNode' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Exception/InvalidConstantNode.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\InvalidDefaultValueType' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Exception/InvalidDefaultValueType.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\MethodPrototypeNotFound' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Exception/MethodPrototypeNotFound.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\NoObjectProvided' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Exception/NoObjectProvided.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\NoParent' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Exception/NoParent.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\NotAnObject' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Exception/NotAnObject.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\ObjectNotInstanceOfClass' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Exception/ObjectNotInstanceOfClass.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\PropertyDoesNotExist' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Exception/PropertyDoesNotExist.php', 'PHPStan\\BetterReflection\\Reflection\\Exception\\PropertyIsNotStatic' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Exception/PropertyIsNotStatic.php', 'PHPStan\\BetterReflection\\Reflection\\ExprCacheHelper' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ExprCacheHelper.php', 'PHPStan\\BetterReflection\\Reflection\\Reflection' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Reflection.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionAttribute' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionAttribute.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionClass' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionClass.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionClassConstant' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionClassConstant.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionConstant' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionConstant.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionEnum' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionEnum.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionEnumCase' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionEnumCase.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionFunction' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionFunction.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionFunctionAbstract' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionFunctionAbstract.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionIntersectionType' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionIntersectionType.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionMethod' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionMethod.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionNamedType' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionNamedType.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionObject' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionObject.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionParameter' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionParameter.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionProperty' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionProperty.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionPropertyHookType' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionPropertyHookType.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionType' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionType.php', 'PHPStan\\BetterReflection\\Reflection\\ReflectionUnionType' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/ReflectionUnionType.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionAttributeStringCast' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionAttributeStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionClassConstantStringCast' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionClassConstantStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionClassStringCast' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionClassStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionConstantStringCast' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionConstantStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionEnumCaseStringCast' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionEnumCaseStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionFunctionStringCast' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionFunctionStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionMethodStringCast' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionMethodStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionParameterStringCast' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionParameterStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionPropertyStringCast' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionPropertyStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionStringCastHelper' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionStringCastHelper.php', 'PHPStan\\BetterReflection\\Reflection\\StringCast\\ReflectionTypeStringCast' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionTypeStringCast.php', 'PHPStan\\BetterReflection\\Reflection\\Support\\AlreadyVisitedClasses' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflection/Support/AlreadyVisitedClasses.php', 'PHPStan\\BetterReflection\\Reflector\\DefaultReflector' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflector/DefaultReflector.php', 'PHPStan\\BetterReflection\\Reflector\\Exception\\IdentifierNotFound' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflector/Exception/IdentifierNotFound.php', 'PHPStan\\BetterReflection\\Reflector\\Reflector' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Reflector/Reflector.php', 'PHPStan\\BetterReflection\\SourceLocator\\Ast\\Exception\\ParseToAstFailure' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Exception/ParseToAstFailure.php', 'PHPStan\\BetterReflection\\SourceLocator\\Ast\\FindReflectionsInTree' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Ast/FindReflectionsInTree.php', 'PHPStan\\BetterReflection\\SourceLocator\\Ast\\Locator' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Locator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Ast\\Parser\\MemoizingParser' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Parser/MemoizingParser.php', 'PHPStan\\BetterReflection\\SourceLocator\\Ast\\Strategy\\AstConversionStrategy' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Strategy/AstConversionStrategy.php', 'PHPStan\\BetterReflection\\SourceLocator\\Ast\\Strategy\\NodeToReflection' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Strategy/NodeToReflection.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\EvaledAnonymousClassCannotBeLocated' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/EvaledAnonymousClassCannotBeLocated.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\EvaledClosureCannotBeLocated' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/EvaledClosureCannotBeLocated.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\InvalidDirectory' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/InvalidDirectory.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\InvalidFileInfo' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/InvalidFileInfo.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\InvalidFileLocation' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/InvalidFileLocation.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\NoAnonymousClassOnLine' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/NoAnonymousClassOnLine.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\NoClosureOnLine' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/NoClosureOnLine.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\NotInternalClass' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/NotInternalClass.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\TwoAnonymousClassesOnSameLine' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/TwoAnonymousClassesOnSameLine.php', 'PHPStan\\BetterReflection\\SourceLocator\\Exception\\TwoClosuresOnSameLine' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Exception/TwoClosuresOnSameLine.php', 'PHPStan\\BetterReflection\\SourceLocator\\FileChecker' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/FileChecker.php', 'PHPStan\\BetterReflection\\SourceLocator\\Located\\AliasLocatedSource' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Located/AliasLocatedSource.php', 'PHPStan\\BetterReflection\\SourceLocator\\Located\\AnonymousLocatedSource' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Located/AnonymousLocatedSource.php', 'PHPStan\\BetterReflection\\SourceLocator\\Located\\EvaledLocatedSource' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Located/EvaledLocatedSource.php', 'PHPStan\\BetterReflection\\SourceLocator\\Located\\InternalLocatedSource' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Located/InternalLocatedSource.php', 'PHPStan\\BetterReflection\\SourceLocator\\Located\\LocatedSource' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Located/LocatedSource.php', 'PHPStan\\BetterReflection\\SourceLocator\\SourceStubber\\AggregateSourceStubber' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/AggregateSourceStubber.php', 'PHPStan\\BetterReflection\\SourceLocator\\SourceStubber\\Exception\\CouldNotFindPhpStormStubs' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/Exception/CouldNotFindPhpStormStubs.php', 'PHPStan\\BetterReflection\\SourceLocator\\SourceStubber\\PhpStormStubsSourceStubber' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/PhpStormStubsSourceStubber.php', 'PHPStan\\BetterReflection\\SourceLocator\\SourceStubber\\PhpStormStubs\\CachingVisitor' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/PhpStormStubs/CachingVisitor.php', 'PHPStan\\BetterReflection\\SourceLocator\\SourceStubber\\ReflectionSourceStubber' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/ReflectionSourceStubber.php', 'PHPStan\\BetterReflection\\SourceLocator\\SourceStubber\\SourceStubber' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/SourceStubber.php', 'PHPStan\\BetterReflection\\SourceLocator\\SourceStubber\\StubData' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/StubData.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\AbstractSourceLocator' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/AbstractSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\AggregateSourceLocator' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/AggregateSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\AnonymousClassObjectSourceLocator' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/AnonymousClassObjectSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\AutoloadSourceLocator' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/AutoloadSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\AutoloadSourceLocator\\FileReadTrapStreamWrapper' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/AutoloadSourceLocator/FileReadTrapStreamWrapper.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\ClosureSourceLocator' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/ClosureSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\ComposerSourceLocator' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/ComposerSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Factory\\Exception\\Exception' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/Exception.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Factory\\Exception\\FailedToParseJson' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/FailedToParseJson.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Factory\\Exception\\InvalidProjectDirectory' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/InvalidProjectDirectory.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Factory\\Exception\\MissingComposerJson' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/MissingComposerJson.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Factory\\Exception\\MissingInstalledJson' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/MissingInstalledJson.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Factory\\MakeLocatorForComposerJson' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/MakeLocatorForComposerJson.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Factory\\MakeLocatorForComposerJsonAndInstalledJson' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/MakeLocatorForComposerJsonAndInstalledJson.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Factory\\MakeLocatorForInstalledJson' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/MakeLocatorForInstalledJson.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\PsrAutoloaderLocator' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/PsrAutoloaderLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Psr\\Exception\\Exception' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/Exception/Exception.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Psr\\Exception\\InvalidPrefixMapping' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/Exception/InvalidPrefixMapping.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Psr\\Psr0Mapping' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/Psr0Mapping.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Psr\\Psr4Mapping' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/Psr4Mapping.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\Composer\\Psr\\PsrAutoloaderMapping' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/PsrAutoloaderMapping.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\DirectoriesSourceLocator' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/DirectoriesSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\EvaledCodeSourceLocator' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/EvaledCodeSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\FileIteratorSourceLocator' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/FileIteratorSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\MemoizingSourceLocator' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/MemoizingSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\PhpInternalSourceLocator' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/PhpInternalSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\SingleFileSourceLocator' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/SingleFileSourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\SourceLocator' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/SourceLocator.php', 'PHPStan\\BetterReflection\\SourceLocator\\Type\\StringSourceLocator' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/SourceLocator/Type/StringSourceLocator.php', 'PHPStan\\BetterReflection\\Util\\CalculateReflectionColumn' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Util/CalculateReflectionColumn.php', 'PHPStan\\BetterReflection\\Util\\ClassExistenceChecker' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Util/ClassExistenceChecker.php', 'PHPStan\\BetterReflection\\Util\\ConstantNodeChecker' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Util/ConstantNodeChecker.php', 'PHPStan\\BetterReflection\\Util\\Exception\\InvalidNodePosition' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Util/Exception/InvalidNodePosition.php', 'PHPStan\\BetterReflection\\Util\\Exception\\NoNodePosition' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Util/Exception/NoNodePosition.php', 'PHPStan\\BetterReflection\\Util\\FileHelper' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Util/FileHelper.php', 'PHPStan\\BetterReflection\\Util\\FindReflectionOnLine' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Util/FindReflectionOnLine.php', 'PHPStan\\BetterReflection\\Util\\GetLastDocComment' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Util/GetLastDocComment.php', 'PHPStan\\BetterReflection\\Util\\Memoize' => __DIR__ . '/..' . '/ondrejmirtes/better-reflection/src/Util/Memoize.php', 'PHPStan\\Broker\\AnonymousClassNameHelper' => __DIR__ . '/../..' . '/src/Broker/AnonymousClassNameHelper.php', 'PHPStan\\Broker\\BrokerFactory' => __DIR__ . '/../..' . '/src/Broker/BrokerFactory.php', 'PHPStan\\Broker\\ClassNotFoundException' => __DIR__ . '/../..' . '/src/Broker/ClassNotFoundException.php', 'PHPStan\\Broker\\ConstantNotFoundException' => __DIR__ . '/../..' . '/src/Broker/ConstantNotFoundException.php', 'PHPStan\\Broker\\FunctionNotFoundException' => __DIR__ . '/../..' . '/src/Broker/FunctionNotFoundException.php', 'PHPStan\\Cache\\Cache' => __DIR__ . '/../..' . '/src/Cache/Cache.php', 'PHPStan\\Cache\\CacheItem' => __DIR__ . '/../..' . '/src/Cache/CacheItem.php', 'PHPStan\\Cache\\CacheStorage' => __DIR__ . '/../..' . '/src/Cache/CacheStorage.php', 'PHPStan\\Cache\\FileCacheStorage' => __DIR__ . '/../..' . '/src/Cache/FileCacheStorage.php', 'PHPStan\\Cache\\MemoryCacheStorage' => __DIR__ . '/../..' . '/src/Cache/MemoryCacheStorage.php', 'PHPStan\\Classes\\ForbiddenClassNameExtension' => __DIR__ . '/../..' . '/src/Classes/ForbiddenClassNameExtension.php', 'PHPStan\\Collectors\\CollectedData' => __DIR__ . '/../..' . '/src/Collectors/CollectedData.php', 'PHPStan\\Collectors\\Collector' => __DIR__ . '/../..' . '/src/Collectors/Collector.php', 'PHPStan\\Collectors\\Registry' => __DIR__ . '/../..' . '/src/Collectors/Registry.php', 'PHPStan\\Collectors\\RegistryFactory' => __DIR__ . '/../..' . '/src/Collectors/RegistryFactory.php', 'PHPStan\\Command\\AnalyseApplication' => __DIR__ . '/../..' . '/src/Command/AnalyseApplication.php', 'PHPStan\\Command\\AnalyseCommand' => __DIR__ . '/../..' . '/src/Command/AnalyseCommand.php', 'PHPStan\\Command\\AnalyserRunner' => __DIR__ . '/../..' . '/src/Command/AnalyserRunner.php', 'PHPStan\\Command\\AnalysisResult' => __DIR__ . '/../..' . '/src/Command/AnalysisResult.php', 'PHPStan\\Command\\BisectCommand' => __DIR__ . '/../..' . '/src/Command/BisectCommand.php', 'PHPStan\\Command\\Bisect\\BinarySearch' => __DIR__ . '/../..' . '/src/Command/Bisect/BinarySearch.php', 'PHPStan\\Command\\Bisect\\BinarySearchStep' => __DIR__ . '/../..' . '/src/Command/Bisect/BinarySearchStep.php', 'PHPStan\\Command\\ClearResultCacheCommand' => __DIR__ . '/../..' . '/src/Command/ClearResultCacheCommand.php', 'PHPStan\\Command\\CommandHelper' => __DIR__ . '/../..' . '/src/Command/CommandHelper.php', 'PHPStan\\Command\\DiagnoseCommand' => __DIR__ . '/../..' . '/src/Command/DiagnoseCommand.php', 'PHPStan\\Command\\DumpParametersCommand' => __DIR__ . '/../..' . '/src/Command/DumpParametersCommand.php', 'PHPStan\\Command\\ErrorFormatter\\BaselineNeonErrorFormatter' => __DIR__ . '/../..' . '/src/Command/ErrorFormatter/BaselineNeonErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\BaselinePhpErrorFormatter' => __DIR__ . '/../..' . '/src/Command/ErrorFormatter/BaselinePhpErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\CheckstyleErrorFormatter' => __DIR__ . '/../..' . '/src/Command/ErrorFormatter/CheckstyleErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\CiDetectedErrorFormatter' => __DIR__ . '/../..' . '/src/Command/ErrorFormatter/CiDetectedErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\ErrorFormatter' => __DIR__ . '/../..' . '/src/Command/ErrorFormatter/ErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\GithubErrorFormatter' => __DIR__ . '/../..' . '/src/Command/ErrorFormatter/GithubErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\GitlabErrorFormatter' => __DIR__ . '/../..' . '/src/Command/ErrorFormatter/GitlabErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\JsonErrorFormatter' => __DIR__ . '/../..' . '/src/Command/ErrorFormatter/JsonErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\JunitErrorFormatter' => __DIR__ . '/../..' . '/src/Command/ErrorFormatter/JunitErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\RawErrorFormatter' => __DIR__ . '/../..' . '/src/Command/ErrorFormatter/RawErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\TableErrorFormatter' => __DIR__ . '/../..' . '/src/Command/ErrorFormatter/TableErrorFormatter.php', 'PHPStan\\Command\\ErrorFormatter\\TeamcityErrorFormatter' => __DIR__ . '/../..' . '/src/Command/ErrorFormatter/TeamcityErrorFormatter.php', 'PHPStan\\Command\\ErrorsConsoleStyle' => __DIR__ . '/../..' . '/src/Command/ErrorsConsoleStyle.php', 'PHPStan\\Command\\FixerApplication' => __DIR__ . '/../..' . '/src/Command/FixerApplication.php', 'PHPStan\\Command\\FixerProcessException' => __DIR__ . '/../..' . '/src/Command/FixerProcessException.php', 'PHPStan\\Command\\FixerWorkerCommand' => __DIR__ . '/../..' . '/src/Command/FixerWorkerCommand.php', 'PHPStan\\Command\\FixerWorkerRunner' => __DIR__ . '/../..' . '/src/Command/FixerWorkerRunner.php', 'PHPStan\\Command\\IgnoredRegexValidator' => __DIR__ . '/../..' . '/src/Command/IgnoredRegexValidator.php', 'PHPStan\\Command\\IgnoredRegexValidatorResult' => __DIR__ . '/../..' . '/src/Command/IgnoredRegexValidatorResult.php', 'PHPStan\\Command\\InceptionNotSuccessfulException' => __DIR__ . '/../..' . '/src/Command/InceptionNotSuccessfulException.php', 'PHPStan\\Command\\InceptionResult' => __DIR__ . '/../..' . '/src/Command/InceptionResult.php', 'PHPStan\\Command\\Output' => __DIR__ . '/../..' . '/src/Command/Output.php', 'PHPStan\\Command\\OutputStyle' => __DIR__ . '/../..' . '/src/Command/OutputStyle.php', 'PHPStan\\Command\\Symfony\\SymfonyOutput' => __DIR__ . '/../..' . '/src/Command/Symfony/SymfonyOutput.php', 'PHPStan\\Command\\Symfony\\SymfonyStyle' => __DIR__ . '/../..' . '/src/Command/Symfony/SymfonyStyle.php', 'PHPStan\\Command\\WorkerCommand' => __DIR__ . '/../..' . '/src/Command/WorkerCommand.php', 'PHPStan\\DependencyInjection\\AutowiredAttributeServicesExtension' => __DIR__ . '/../..' . '/src/DependencyInjection/AutowiredAttributeServicesExtension.php', 'PHPStan\\DependencyInjection\\AutowiredParameter' => __DIR__ . '/../..' . '/src/DependencyInjection/AutowiredParameter.php', 'PHPStan\\DependencyInjection\\AutowiredService' => __DIR__ . '/../..' . '/src/DependencyInjection/AutowiredService.php', 'PHPStan\\DependencyInjection\\BleedingEdgeToggle' => __DIR__ . '/../..' . '/src/DependencyInjection/BleedingEdgeToggle.php', 'PHPStan\\DependencyInjection\\ConditionalTagsExtension' => __DIR__ . '/../..' . '/src/DependencyInjection/ConditionalTagsExtension.php', 'PHPStan\\DependencyInjection\\Configurator' => __DIR__ . '/../..' . '/src/DependencyInjection/Configurator.php', 'PHPStan\\DependencyInjection\\Container' => __DIR__ . '/../..' . '/src/DependencyInjection/Container.php', 'PHPStan\\DependencyInjection\\ContainerFactory' => __DIR__ . '/../..' . '/src/DependencyInjection/ContainerFactory.php', 'PHPStan\\DependencyInjection\\DerivativeContainerFactory' => __DIR__ . '/../..' . '/src/DependencyInjection/DerivativeContainerFactory.php', 'PHPStan\\DependencyInjection\\DuplicateIncludedFilesException' => __DIR__ . '/../..' . '/src/DependencyInjection/DuplicateIncludedFilesException.php', 'PHPStan\\DependencyInjection\\ExpandRelativePathExtension' => __DIR__ . '/../..' . '/src/DependencyInjection/ExpandRelativePathExtension.php', 'PHPStan\\DependencyInjection\\FnsrExtension' => __DIR__ . '/../..' . '/src/DependencyInjection/FnsrExtension.php', 'PHPStan\\DependencyInjection\\GenerateFactory' => __DIR__ . '/../..' . '/src/DependencyInjection/GenerateFactory.php', 'PHPStan\\DependencyInjection\\InvalidExcludePathsException' => __DIR__ . '/../..' . '/src/DependencyInjection/InvalidExcludePathsException.php', 'PHPStan\\DependencyInjection\\InvalidIgnoredErrorException' => __DIR__ . '/../..' . '/src/DependencyInjection/InvalidIgnoredErrorException.php', 'PHPStan\\DependencyInjection\\InvalidIgnoredErrorPatternsException' => __DIR__ . '/../..' . '/src/DependencyInjection/InvalidIgnoredErrorPatternsException.php', 'PHPStan\\DependencyInjection\\InvalidPhpVersionException' => __DIR__ . '/../..' . '/src/DependencyInjection/InvalidPhpVersionException.php', 'PHPStan\\DependencyInjection\\LoaderFactory' => __DIR__ . '/../..' . '/src/DependencyInjection/LoaderFactory.php', 'PHPStan\\DependencyInjection\\MemoizingContainer' => __DIR__ . '/../..' . '/src/DependencyInjection/MemoizingContainer.php', 'PHPStan\\DependencyInjection\\MissingImplementedInterfaceInServiceWithTagException' => __DIR__ . '/../..' . '/src/DependencyInjection/MissingImplementedInterfaceInServiceWithTagException.php', 'PHPStan\\DependencyInjection\\MissingServiceException' => __DIR__ . '/../..' . '/src/DependencyInjection/MissingServiceException.php', 'PHPStan\\DependencyInjection\\NeonAdapter' => __DIR__ . '/../..' . '/src/DependencyInjection/NeonAdapter.php', 'PHPStan\\DependencyInjection\\NeonCachedFileReader' => __DIR__ . '/../..' . '/src/DependencyInjection/NeonCachedFileReader.php', 'PHPStan\\DependencyInjection\\NeonLoader' => __DIR__ . '/../..' . '/src/DependencyInjection/NeonLoader.php', 'PHPStan\\DependencyInjection\\Neon\\OptionalPath' => __DIR__ . '/../..' . '/src/DependencyInjection/Neon/OptionalPath.php', 'PHPStan\\DependencyInjection\\Nette\\NetteContainer' => __DIR__ . '/../..' . '/src/DependencyInjection/Nette/NetteContainer.php', 'PHPStan\\DependencyInjection\\NonAutowiredService' => __DIR__ . '/../..' . '/src/DependencyInjection/NonAutowiredService.php', 'PHPStan\\DependencyInjection\\ParameterNotFoundException' => __DIR__ . '/../..' . '/src/DependencyInjection/ParameterNotFoundException.php', 'PHPStan\\DependencyInjection\\ParametersSchemaExtension' => __DIR__ . '/../..' . '/src/DependencyInjection/ParametersSchemaExtension.php', 'PHPStan\\DependencyInjection\\ProjectConfigHelper' => __DIR__ . '/../..' . '/src/DependencyInjection/ProjectConfigHelper.php', 'PHPStan\\DependencyInjection\\Reflection\\ClassReflectionExtensionRegistryProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Reflection/ClassReflectionExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\Reflection\\LazyClassReflectionExtensionRegistryProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Reflection/LazyClassReflectionExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\RegisteredCollector' => __DIR__ . '/../..' . '/src/DependencyInjection/RegisteredCollector.php', 'PHPStan\\DependencyInjection\\RegisteredRule' => __DIR__ . '/../..' . '/src/DependencyInjection/RegisteredRule.php', 'PHPStan\\DependencyInjection\\RulesExtension' => __DIR__ . '/../..' . '/src/DependencyInjection/RulesExtension.php', 'PHPStan\\DependencyInjection\\StubValidatorRuleServicesExtension' => __DIR__ . '/../..' . '/src/DependencyInjection/StubValidatorRuleServicesExtension.php', 'PHPStan\\DependencyInjection\\Type\\DynamicReturnTypeExtensionRegistryProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Type/DynamicReturnTypeExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\Type\\DynamicThrowTypeExtensionProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Type/DynamicThrowTypeExtensionProvider.php', 'PHPStan\\DependencyInjection\\Type\\ExpressionTypeResolverExtensionRegistryProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Type/ExpressionTypeResolverExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\Type\\LazyDynamicReturnTypeExtensionRegistryProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Type/LazyDynamicReturnTypeExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\Type\\LazyDynamicThrowTypeExtensionProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Type/LazyDynamicThrowTypeExtensionProvider.php', 'PHPStan\\DependencyInjection\\Type\\LazyExpressionTypeResolverExtensionRegistryProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Type/LazyExpressionTypeResolverExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\Type\\LazyOperatorTypeSpecifyingExtensionRegistryProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Type/LazyOperatorTypeSpecifyingExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\Type\\LazyParameterClosureThisExtensionProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Type/LazyParameterClosureThisExtensionProvider.php', 'PHPStan\\DependencyInjection\\Type\\LazyParameterClosureTypeExtensionProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Type/LazyParameterClosureTypeExtensionProvider.php', 'PHPStan\\DependencyInjection\\Type\\LazyParameterOutTypeExtensionProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Type/LazyParameterOutTypeExtensionProvider.php', 'PHPStan\\DependencyInjection\\Type\\LazyUnaryOperatorTypeSpecifyingExtensionRegistryProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Type/LazyUnaryOperatorTypeSpecifyingExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\Type\\OperatorTypeSpecifyingExtensionRegistryProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Type/OperatorTypeSpecifyingExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\Type\\ParameterClosureThisExtensionProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Type/ParameterClosureThisExtensionProvider.php', 'PHPStan\\DependencyInjection\\Type\\ParameterClosureTypeExtensionProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Type/ParameterClosureTypeExtensionProvider.php', 'PHPStan\\DependencyInjection\\Type\\ParameterOutTypeExtensionProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Type/ParameterOutTypeExtensionProvider.php', 'PHPStan\\DependencyInjection\\Type\\UnaryOperatorTypeSpecifyingExtensionRegistryProvider' => __DIR__ . '/../..' . '/src/DependencyInjection/Type/UnaryOperatorTypeSpecifyingExtensionRegistryProvider.php', 'PHPStan\\DependencyInjection\\ValidateExcludePathsExtension' => __DIR__ . '/../..' . '/src/DependencyInjection/ValidateExcludePathsExtension.php', 'PHPStan\\DependencyInjection\\ValidateIgnoredErrorsExtension' => __DIR__ . '/../..' . '/src/DependencyInjection/ValidateIgnoredErrorsExtension.php', 'PHPStan\\DependencyInjection\\ValidateServiceTagsExtension' => __DIR__ . '/../..' . '/src/DependencyInjection/ValidateServiceTagsExtension.php', 'PHPStan\\DependencyInjection\\ValidatesStubFiles' => __DIR__ . '/../..' . '/src/DependencyInjection/ValidatesStubFiles.php', 'PHPStan\\Dependency\\DependencyResolver' => __DIR__ . '/../..' . '/src/Dependency/DependencyResolver.php', 'PHPStan\\Dependency\\ExportedNode' => __DIR__ . '/../..' . '/src/Dependency/ExportedNode.php', 'PHPStan\\Dependency\\ExportedNodeFetcher' => __DIR__ . '/../..' . '/src/Dependency/ExportedNodeFetcher.php', 'PHPStan\\Dependency\\ExportedNodeResolver' => __DIR__ . '/../..' . '/src/Dependency/ExportedNodeResolver.php', 'PHPStan\\Dependency\\ExportedNodeVisitor' => __DIR__ . '/../..' . '/src/Dependency/ExportedNodeVisitor.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedAttributeNode' => __DIR__ . '/../..' . '/src/Dependency/ExportedNode/ExportedAttributeNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedClassConstantNode' => __DIR__ . '/../..' . '/src/Dependency/ExportedNode/ExportedClassConstantNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedClassConstantsNode' => __DIR__ . '/../..' . '/src/Dependency/ExportedNode/ExportedClassConstantsNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedClassNode' => __DIR__ . '/../..' . '/src/Dependency/ExportedNode/ExportedClassNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedEnumCaseNode' => __DIR__ . '/../..' . '/src/Dependency/ExportedNode/ExportedEnumCaseNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedEnumNode' => __DIR__ . '/../..' . '/src/Dependency/ExportedNode/ExportedEnumNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedFunctionNode' => __DIR__ . '/../..' . '/src/Dependency/ExportedNode/ExportedFunctionNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedInterfaceNode' => __DIR__ . '/../..' . '/src/Dependency/ExportedNode/ExportedInterfaceNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedMethodNode' => __DIR__ . '/../..' . '/src/Dependency/ExportedNode/ExportedMethodNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedParameterNode' => __DIR__ . '/../..' . '/src/Dependency/ExportedNode/ExportedParameterNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedPhpDocNode' => __DIR__ . '/../..' . '/src/Dependency/ExportedNode/ExportedPhpDocNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedPropertiesNode' => __DIR__ . '/../..' . '/src/Dependency/ExportedNode/ExportedPropertiesNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedPropertyHookNode' => __DIR__ . '/../..' . '/src/Dependency/ExportedNode/ExportedPropertyHookNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedTraitNode' => __DIR__ . '/../..' . '/src/Dependency/ExportedNode/ExportedTraitNode.php', 'PHPStan\\Dependency\\ExportedNode\\ExportedTraitUseAdaptation' => __DIR__ . '/../..' . '/src/Dependency/ExportedNode/ExportedTraitUseAdaptation.php', 'PHPStan\\Dependency\\NodeDependencies' => __DIR__ . '/../..' . '/src/Dependency/NodeDependencies.php', 'PHPStan\\Dependency\\RootExportedNode' => __DIR__ . '/../..' . '/src/Dependency/RootExportedNode.php', 'PHPStan\\Diagnose\\DiagnoseExtension' => __DIR__ . '/../..' . '/src/Diagnose/DiagnoseExtension.php', 'PHPStan\\Diagnose\\PHPStanDiagnoseExtension' => __DIR__ . '/../..' . '/src/Diagnose/PHPStanDiagnoseExtension.php', 'PHPStan\\File\\CouldNotReadFileException' => __DIR__ . '/../..' . '/src/File/CouldNotReadFileException.php', 'PHPStan\\File\\CouldNotWriteFileException' => __DIR__ . '/../..' . '/src/File/CouldNotWriteFileException.php', 'PHPStan\\File\\FileExcluder' => __DIR__ . '/../..' . '/src/File/FileExcluder.php', 'PHPStan\\File\\FileExcluderFactory' => __DIR__ . '/../..' . '/src/File/FileExcluderFactory.php', 'PHPStan\\File\\FileExcluderRawFactory' => __DIR__ . '/../..' . '/src/File/FileExcluderRawFactory.php', 'PHPStan\\File\\FileFinder' => __DIR__ . '/../..' . '/src/File/FileFinder.php', 'PHPStan\\File\\FileFinderResult' => __DIR__ . '/../..' . '/src/File/FileFinderResult.php', 'PHPStan\\File\\FileHelper' => __DIR__ . '/../..' . '/src/File/FileHelper.php', 'PHPStan\\File\\FileMonitor' => __DIR__ . '/../..' . '/src/File/FileMonitor.php', 'PHPStan\\File\\FileMonitorResult' => __DIR__ . '/../..' . '/src/File/FileMonitorResult.php', 'PHPStan\\File\\FileReader' => __DIR__ . '/../..' . '/src/File/FileReader.php', 'PHPStan\\File\\FileWriter' => __DIR__ . '/../..' . '/src/File/FileWriter.php', 'PHPStan\\File\\FuzzyRelativePathHelper' => __DIR__ . '/../..' . '/src/File/FuzzyRelativePathHelper.php', 'PHPStan\\File\\NullRelativePathHelper' => __DIR__ . '/../..' . '/src/File/NullRelativePathHelper.php', 'PHPStan\\File\\ParentDirectoryRelativePathHelper' => __DIR__ . '/../..' . '/src/File/ParentDirectoryRelativePathHelper.php', 'PHPStan\\File\\PathNotFoundException' => __DIR__ . '/../..' . '/src/File/PathNotFoundException.php', 'PHPStan\\File\\RelativePathHelper' => __DIR__ . '/../..' . '/src/File/RelativePathHelper.php', 'PHPStan\\File\\SimpleRelativePathHelper' => __DIR__ . '/../..' . '/src/File/SimpleRelativePathHelper.php', 'PHPStan\\File\\SystemAgnosticSimpleRelativePathHelper' => __DIR__ . '/../..' . '/src/File/SystemAgnosticSimpleRelativePathHelper.php', 'PHPStan\\Fixable\\FileChangedException' => __DIR__ . '/../..' . '/src/Fixable/FileChangedException.php', 'PHPStan\\Fixable\\MergeConflictException' => __DIR__ . '/../..' . '/src/Fixable/MergeConflictException.php', 'PHPStan\\Fixable\\Patcher' => __DIR__ . '/../..' . '/src/Fixable/Patcher.php', 'PHPStan\\Fixable\\PhpDoc\\CallbackVisitor' => __DIR__ . '/../..' . '/src/Fixable/PhpDoc/CallbackVisitor.php', 'PHPStan\\Fixable\\PhpDoc\\PhpDocEditor' => __DIR__ . '/../..' . '/src/Fixable/PhpDoc/PhpDocEditor.php', 'PHPStan\\Fixable\\PhpPrinter' => __DIR__ . '/../..' . '/src/Fixable/PhpPrinter.php', 'PHPStan\\Fixable\\PhpPrinterIndentationDetectorVisitor' => __DIR__ . '/../..' . '/src/Fixable/PhpPrinterIndentationDetectorVisitor.php', 'PHPStan\\Fixable\\ReplacingNodeVisitor' => __DIR__ . '/../..' . '/src/Fixable/ReplacingNodeVisitor.php', 'PHPStan\\Internal\\AgentDetector' => __DIR__ . '/../..' . '/src/Internal/AgentDetector.php', 'PHPStan\\Internal\\ArrayHelper' => __DIR__ . '/../..' . '/src/Internal/ArrayHelper.php', 'PHPStan\\Internal\\BytesHelper' => __DIR__ . '/../..' . '/src/Internal/BytesHelper.php', 'PHPStan\\Internal\\CombinationsHelper' => __DIR__ . '/../..' . '/src/Internal/CombinationsHelper.php', 'PHPStan\\Internal\\ComposerHelper' => __DIR__ . '/../..' . '/src/Internal/ComposerHelper.php', 'PHPStan\\Internal\\DeprecatedAttributeHelper' => __DIR__ . '/../..' . '/src/Internal/DeprecatedAttributeHelper.php', 'PHPStan\\Internal\\DirectoryCreator' => __DIR__ . '/../..' . '/src/Internal/DirectoryCreator.php', 'PHPStan\\Internal\\DirectoryCreatorException' => __DIR__ . '/../..' . '/src/Internal/DirectoryCreatorException.php', 'PHPStan\\Internal\\HttpClientFactory' => __DIR__ . '/../..' . '/src/Internal/HttpClientFactory.php', 'PHPStan\\Internal\\SprintfHelper' => __DIR__ . '/../..' . '/src/Internal/SprintfHelper.php', 'PHPStan\\NeverException' => __DIR__ . '/../..' . '/src/NeverException.php', 'PHPStan\\Node\\AnonymousClassNode' => __DIR__ . '/../..' . '/src/Node/AnonymousClassNode.php', 'PHPStan\\Node\\BooleanAndNode' => __DIR__ . '/../..' . '/src/Node/BooleanAndNode.php', 'PHPStan\\Node\\BooleanOrNode' => __DIR__ . '/../..' . '/src/Node/BooleanOrNode.php', 'PHPStan\\Node\\BreaklessWhileLoopNode' => __DIR__ . '/../..' . '/src/Node/BreaklessWhileLoopNode.php', 'PHPStan\\Node\\CatchWithUnthrownExceptionNode' => __DIR__ . '/../..' . '/src/Node/CatchWithUnthrownExceptionNode.php', 'PHPStan\\Node\\ClassConstantsNode' => __DIR__ . '/../..' . '/src/Node/ClassConstantsNode.php', 'PHPStan\\Node\\ClassMethod' => __DIR__ . '/../..' . '/src/Node/ClassMethod.php', 'PHPStan\\Node\\ClassMethodsNode' => __DIR__ . '/../..' . '/src/Node/ClassMethodsNode.php', 'PHPStan\\Node\\ClassPropertiesNode' => __DIR__ . '/../..' . '/src/Node/ClassPropertiesNode.php', 'PHPStan\\Node\\ClassPropertyNode' => __DIR__ . '/../..' . '/src/Node/ClassPropertyNode.php', 'PHPStan\\Node\\ClassStatementsGatherer' => __DIR__ . '/../..' . '/src/Node/ClassStatementsGatherer.php', 'PHPStan\\Node\\ClosureReturnStatementsNode' => __DIR__ . '/../..' . '/src/Node/ClosureReturnStatementsNode.php', 'PHPStan\\Node\\CollectedDataNode' => __DIR__ . '/../..' . '/src/Node/CollectedDataNode.php', 'PHPStan\\Node\\Constant\\ClassConstantFetch' => __DIR__ . '/../..' . '/src/Node/Constant/ClassConstantFetch.php', 'PHPStan\\Node\\DeepNodeCloner' => __DIR__ . '/../..' . '/src/Node/DeepNodeCloner.php', 'PHPStan\\Node\\DoWhileLoopConditionNode' => __DIR__ . '/../..' . '/src/Node/DoWhileLoopConditionNode.php', 'PHPStan\\Node\\ExecutionEndNode' => __DIR__ . '/../..' . '/src/Node/ExecutionEndNode.php', 'PHPStan\\Node\\Expr\\AlwaysRememberedExpr' => __DIR__ . '/../..' . '/src/Node/Expr/AlwaysRememberedExpr.php', 'PHPStan\\Node\\Expr\\ExistingArrayDimFetch' => __DIR__ . '/../..' . '/src/Node/Expr/ExistingArrayDimFetch.php', 'PHPStan\\Node\\Expr\\ForeachValueByRefExpr' => __DIR__ . '/../..' . '/src/Node/Expr/ForeachValueByRefExpr.php', 'PHPStan\\Node\\Expr\\GetIterableKeyTypeExpr' => __DIR__ . '/../..' . '/src/Node/Expr/GetIterableKeyTypeExpr.php', 'PHPStan\\Node\\Expr\\GetIterableValueTypeExpr' => __DIR__ . '/../..' . '/src/Node/Expr/GetIterableValueTypeExpr.php', 'PHPStan\\Node\\Expr\\GetOffsetValueTypeExpr' => __DIR__ . '/../..' . '/src/Node/Expr/GetOffsetValueTypeExpr.php', 'PHPStan\\Node\\Expr\\IntertwinedVariableByReferenceWithExpr' => __DIR__ . '/../..' . '/src/Node/Expr/IntertwinedVariableByReferenceWithExpr.php', 'PHPStan\\Node\\Expr\\NativeTypeExpr' => __DIR__ . '/../..' . '/src/Node/Expr/NativeTypeExpr.php', 'PHPStan\\Node\\Expr\\OriginalForeachKeyExpr' => __DIR__ . '/../..' . '/src/Node/Expr/OriginalForeachKeyExpr.php', 'PHPStan\\Node\\Expr\\OriginalForeachValueExpr' => __DIR__ . '/../..' . '/src/Node/Expr/OriginalForeachValueExpr.php', 'PHPStan\\Node\\Expr\\OriginalPropertyTypeExpr' => __DIR__ . '/../..' . '/src/Node/Expr/OriginalPropertyTypeExpr.php', 'PHPStan\\Node\\Expr\\ParameterVariableOriginalValueExpr' => __DIR__ . '/../..' . '/src/Node/Expr/ParameterVariableOriginalValueExpr.php', 'PHPStan\\Node\\Expr\\PossiblyImpureCallExpr' => __DIR__ . '/../..' . '/src/Node/Expr/PossiblyImpureCallExpr.php', 'PHPStan\\Node\\Expr\\PropertyInitializationExpr' => __DIR__ . '/../..' . '/src/Node/Expr/PropertyInitializationExpr.php', 'PHPStan\\Node\\Expr\\SetExistingOffsetValueTypeExpr' => __DIR__ . '/../..' . '/src/Node/Expr/SetExistingOffsetValueTypeExpr.php', 'PHPStan\\Node\\Expr\\SetOffsetValueTypeExpr' => __DIR__ . '/../..' . '/src/Node/Expr/SetOffsetValueTypeExpr.php', 'PHPStan\\Node\\Expr\\TypeExpr' => __DIR__ . '/../..' . '/src/Node/Expr/TypeExpr.php', 'PHPStan\\Node\\Expr\\UnsetOffsetExpr' => __DIR__ . '/../..' . '/src/Node/Expr/UnsetOffsetExpr.php', 'PHPStan\\Node\\FileNode' => __DIR__ . '/../..' . '/src/Node/FileNode.php', 'PHPStan\\Node\\FinallyExitPointsNode' => __DIR__ . '/../..' . '/src/Node/FinallyExitPointsNode.php', 'PHPStan\\Node\\FunctionCallableNode' => __DIR__ . '/../..' . '/src/Node/FunctionCallableNode.php', 'PHPStan\\Node\\FunctionReturnStatementsNode' => __DIR__ . '/../..' . '/src/Node/FunctionReturnStatementsNode.php', 'PHPStan\\Node\\InArrowFunctionNode' => __DIR__ . '/../..' . '/src/Node/InArrowFunctionNode.php', 'PHPStan\\Node\\InClassMethodNode' => __DIR__ . '/../..' . '/src/Node/InClassMethodNode.php', 'PHPStan\\Node\\InClassNode' => __DIR__ . '/../..' . '/src/Node/InClassNode.php', 'PHPStan\\Node\\InClosureNode' => __DIR__ . '/../..' . '/src/Node/InClosureNode.php', 'PHPStan\\Node\\InForeachNode' => __DIR__ . '/../..' . '/src/Node/InForeachNode.php', 'PHPStan\\Node\\InFunctionNode' => __DIR__ . '/../..' . '/src/Node/InFunctionNode.php', 'PHPStan\\Node\\InPropertyHookNode' => __DIR__ . '/../..' . '/src/Node/InPropertyHookNode.php', 'PHPStan\\Node\\InTraitNode' => __DIR__ . '/../..' . '/src/Node/InTraitNode.php', 'PHPStan\\Node\\InstantiationCallableNode' => __DIR__ . '/../..' . '/src/Node/InstantiationCallableNode.php', 'PHPStan\\Node\\InvalidateExprNode' => __DIR__ . '/../..' . '/src/Node/InvalidateExprNode.php', 'PHPStan\\Node\\IssetExpr' => __DIR__ . '/../..' . '/src/Node/IssetExpr.php', 'PHPStan\\Node\\LiteralArrayItem' => __DIR__ . '/../..' . '/src/Node/LiteralArrayItem.php', 'PHPStan\\Node\\LiteralArrayNode' => __DIR__ . '/../..' . '/src/Node/LiteralArrayNode.php', 'PHPStan\\Node\\MatchExpressionArm' => __DIR__ . '/../..' . '/src/Node/MatchExpressionArm.php', 'PHPStan\\Node\\MatchExpressionArmBody' => __DIR__ . '/../..' . '/src/Node/MatchExpressionArmBody.php', 'PHPStan\\Node\\MatchExpressionArmCondition' => __DIR__ . '/../..' . '/src/Node/MatchExpressionArmCondition.php', 'PHPStan\\Node\\MatchExpressionNode' => __DIR__ . '/../..' . '/src/Node/MatchExpressionNode.php', 'PHPStan\\Node\\MethodCallableNode' => __DIR__ . '/../..' . '/src/Node/MethodCallableNode.php', 'PHPStan\\Node\\MethodReturnStatementsNode' => __DIR__ . '/../..' . '/src/Node/MethodReturnStatementsNode.php', 'PHPStan\\Node\\Method\\MethodCall' => __DIR__ . '/../..' . '/src/Node/Method/MethodCall.php', 'PHPStan\\Node\\NoopExpressionNode' => __DIR__ . '/../..' . '/src/Node/NoopExpressionNode.php', 'PHPStan\\Node\\Printer\\ExprPrinter' => __DIR__ . '/../..' . '/src/Node/Printer/ExprPrinter.php', 'PHPStan\\Node\\Printer\\NodeTypePrinter' => __DIR__ . '/../..' . '/src/Node/Printer/NodeTypePrinter.php', 'PHPStan\\Node\\Printer\\Printer' => __DIR__ . '/../..' . '/src/Node/Printer/Printer.php', 'PHPStan\\Node\\PropertyAssignNode' => __DIR__ . '/../..' . '/src/Node/PropertyAssignNode.php', 'PHPStan\\Node\\PropertyHookReturnStatementsNode' => __DIR__ . '/../..' . '/src/Node/PropertyHookReturnStatementsNode.php', 'PHPStan\\Node\\PropertyHookStatementNode' => __DIR__ . '/../..' . '/src/Node/PropertyHookStatementNode.php', 'PHPStan\\Node\\Property\\PropertyAssign' => __DIR__ . '/../..' . '/src/Node/Property/PropertyAssign.php', 'PHPStan\\Node\\Property\\PropertyRead' => __DIR__ . '/../..' . '/src/Node/Property/PropertyRead.php', 'PHPStan\\Node\\Property\\PropertyWrite' => __DIR__ . '/../..' . '/src/Node/Property/PropertyWrite.php', 'PHPStan\\Node\\ReturnStatement' => __DIR__ . '/../..' . '/src/Node/ReturnStatement.php', 'PHPStan\\Node\\ReturnStatementsNode' => __DIR__ . '/../..' . '/src/Node/ReturnStatementsNode.php', 'PHPStan\\Node\\StaticMethodCallableNode' => __DIR__ . '/../..' . '/src/Node/StaticMethodCallableNode.php', 'PHPStan\\Node\\UnreachableStatementNode' => __DIR__ . '/../..' . '/src/Node/UnreachableStatementNode.php', 'PHPStan\\Node\\VarTagChangedExpressionTypeNode' => __DIR__ . '/../..' . '/src/Node/VarTagChangedExpressionTypeNode.php', 'PHPStan\\Node\\VariableAssignNode' => __DIR__ . '/../..' . '/src/Node/VariableAssignNode.php', 'PHPStan\\Node\\VirtualNode' => __DIR__ . '/../..' . '/src/Node/VirtualNode.php', 'PHPStan\\Parallel\\ForkParallelChecker' => __DIR__ . '/../..' . '/src/Parallel/ForkParallelChecker.php', 'PHPStan\\Parallel\\ForkedProcess' => __DIR__ . '/../..' . '/src/Parallel/ForkedProcess.php', 'PHPStan\\Parallel\\ParallelAnalyser' => __DIR__ . '/../..' . '/src/Parallel/ParallelAnalyser.php', 'PHPStan\\Parallel\\Process' => __DIR__ . '/../..' . '/src/Parallel/Process.php', 'PHPStan\\Parallel\\ProcessBase' => __DIR__ . '/../..' . '/src/Parallel/ProcessBase.php', 'PHPStan\\Parallel\\ProcessPool' => __DIR__ . '/../..' . '/src/Parallel/ProcessPool.php', 'PHPStan\\Parallel\\ProcessTimedOutException' => __DIR__ . '/../..' . '/src/Parallel/ProcessTimedOutException.php', 'PHPStan\\Parallel\\Schedule' => __DIR__ . '/../..' . '/src/Parallel/Schedule.php', 'PHPStan\\Parallel\\Scheduler' => __DIR__ . '/../..' . '/src/Parallel/Scheduler.php', 'PHPStan\\Parallel\\SpawnedProcess' => __DIR__ . '/../..' . '/src/Parallel/SpawnedProcess.php', 'PHPStan\\Parallel\\WorkerRunner' => __DIR__ . '/../..' . '/src/Parallel/WorkerRunner.php', 'PHPStan\\Parser\\AnonymousClassVisitor' => __DIR__ . '/../..' . '/src/Parser/AnonymousClassVisitor.php', 'PHPStan\\Parser\\ArrayFilterArgVisitor' => __DIR__ . '/../..' . '/src/Parser/ArrayFilterArgVisitor.php', 'PHPStan\\Parser\\ArrayFindArgVisitor' => __DIR__ . '/../..' . '/src/Parser/ArrayFindArgVisitor.php', 'PHPStan\\Parser\\ArrayMapArgVisitor' => __DIR__ . '/../..' . '/src/Parser/ArrayMapArgVisitor.php', 'PHPStan\\Parser\\ArrayWalkArgVisitor' => __DIR__ . '/../..' . '/src/Parser/ArrayWalkArgVisitor.php', 'PHPStan\\Parser\\ArrowFunctionArgVisitor' => __DIR__ . '/../..' . '/src/Parser/ArrowFunctionArgVisitor.php', 'PHPStan\\Parser\\CachedParser' => __DIR__ . '/../..' . '/src/Parser/CachedParser.php', 'PHPStan\\Parser\\CleaningParser' => __DIR__ . '/../..' . '/src/Parser/CleaningParser.php', 'PHPStan\\Parser\\CleaningVisitor' => __DIR__ . '/../..' . '/src/Parser/CleaningVisitor.php', 'PHPStan\\Parser\\ClosureArgVisitor' => __DIR__ . '/../..' . '/src/Parser/ClosureArgVisitor.php', 'PHPStan\\Parser\\ClosureBindArgVisitor' => __DIR__ . '/../..' . '/src/Parser/ClosureBindArgVisitor.php', 'PHPStan\\Parser\\ClosureBindToVarVisitor' => __DIR__ . '/../..' . '/src/Parser/ClosureBindToVarVisitor.php', 'PHPStan\\Parser\\CurlSetOptArgVisitor' => __DIR__ . '/../..' . '/src/Parser/CurlSetOptArgVisitor.php', 'PHPStan\\Parser\\CurlSetOptArrayArgVisitor' => __DIR__ . '/../..' . '/src/Parser/CurlSetOptArrayArgVisitor.php', 'PHPStan\\Parser\\DeclarePositionVisitor' => __DIR__ . '/../..' . '/src/Parser/DeclarePositionVisitor.php', 'PHPStan\\Parser\\ImmediatelyInvokedClosureVisitor' => __DIR__ . '/../..' . '/src/Parser/ImmediatelyInvokedClosureVisitor.php', 'PHPStan\\Parser\\ImplodeArgVisitor' => __DIR__ . '/../..' . '/src/Parser/ImplodeArgVisitor.php', 'PHPStan\\Parser\\LastConditionVisitor' => __DIR__ . '/../..' . '/src/Parser/LastConditionVisitor.php', 'PHPStan\\Parser\\LexerFactory' => __DIR__ . '/../..' . '/src/Parser/LexerFactory.php', 'PHPStan\\Parser\\LineAttributesVisitor' => __DIR__ . '/../..' . '/src/Parser/LineAttributesVisitor.php', 'PHPStan\\Parser\\MagicConstantParamDefaultVisitor' => __DIR__ . '/../..' . '/src/Parser/MagicConstantParamDefaultVisitor.php', 'PHPStan\\Parser\\NewAssignedToPropertyVisitor' => __DIR__ . '/../..' . '/src/Parser/NewAssignedToPropertyVisitor.php', 'PHPStan\\Parser\\ParentStmtTypesVisitor' => __DIR__ . '/../..' . '/src/Parser/ParentStmtTypesVisitor.php', 'PHPStan\\Parser\\Parser' => __DIR__ . '/../..' . '/src/Parser/Parser.php', 'PHPStan\\Parser\\ParserErrorsException' => __DIR__ . '/../..' . '/src/Parser/ParserErrorsException.php', 'PHPStan\\Parser\\PathRoutingParser' => __DIR__ . '/../..' . '/src/Parser/PathRoutingParser.php', 'PHPStan\\Parser\\PhpParserDecorator' => __DIR__ . '/../..' . '/src/Parser/PhpParserDecorator.php', 'PHPStan\\Parser\\PhpParserFactory' => __DIR__ . '/../..' . '/src/Parser/PhpParserFactory.php', 'PHPStan\\Parser\\PipeTransformerVisitor' => __DIR__ . '/../..' . '/src/Parser/PipeTransformerVisitor.php', 'PHPStan\\Parser\\RemoveUnusedCodeByPhpVersionIdVisitor' => __DIR__ . '/../..' . '/src/Parser/RemoveUnusedCodeByPhpVersionIdVisitor.php', 'PHPStan\\Parser\\ReversePipeTransformerVisitor' => __DIR__ . '/../..' . '/src/Parser/ReversePipeTransformerVisitor.php', 'PHPStan\\Parser\\RichParser' => __DIR__ . '/../..' . '/src/Parser/RichParser.php', 'PHPStan\\Parser\\SimpleParser' => __DIR__ . '/../..' . '/src/Parser/SimpleParser.php', 'PHPStan\\Parser\\StandaloneThrowExprVisitor' => __DIR__ . '/../..' . '/src/Parser/StandaloneThrowExprVisitor.php', 'PHPStan\\Parser\\StubParser' => __DIR__ . '/../..' . '/src/Parser/StubParser.php', 'PHPStan\\Parser\\TraitCollectingVisitor' => __DIR__ . '/../..' . '/src/Parser/TraitCollectingVisitor.php', 'PHPStan\\Parser\\TryCatchTypeVisitor' => __DIR__ . '/../..' . '/src/Parser/TryCatchTypeVisitor.php', 'PHPStan\\Parser\\TypeTraverserInstanceofVisitor' => __DIR__ . '/../..' . '/src/Parser/TypeTraverserInstanceofVisitor.php', 'PHPStan\\Parser\\UseAliasVisitor' => __DIR__ . '/../..' . '/src/Parser/UseAliasVisitor.php', 'PHPStan\\Php8StubsMap' => __DIR__ . '/..' . '/phpstan/php-8-stubs/Php8StubsMap.php', 'PHPStan\\PhpDocParser\\Ast\\AbstractNodeVisitor' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php', 'PHPStan\\PhpDocParser\\Ast\\Attribute' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Attribute.php', 'PHPStan\\PhpDocParser\\Ast\\Comment' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Comment.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayItemNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFalseNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFloatNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprIntegerNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNullNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprStringNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprTrueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstFetchNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php', 'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\DoctrineConstExprStringNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.php', 'PHPStan\\PhpDocParser\\Ast\\Node' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Node.php', 'PHPStan\\PhpDocParser\\Ast\\NodeAttributes' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeAttributes.php', 'PHPStan\\PhpDocParser\\Ast\\NodeTraverser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php', 'PHPStan\\PhpDocParser\\Ast\\NodeVisitor' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php', 'PHPStan\\PhpDocParser\\Ast\\NodeVisitor\\CloningVisitor' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagMethodValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagPropertyValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\DeprecatedTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineAnnotation' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArgument' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArray' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArrayItem' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ExtendsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\GenericTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ImplementsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\InvalidTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueParameterNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MixinTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamClosureThisTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamImmediatelyInvokedCallableTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamLaterInvokedCallableTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamOutTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocChildNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTextNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PropertyTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PureUnlessCallableIsImpureTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\RequireExtendsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\RequireImplementsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ReturnTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\SealedTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/SealedTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\SelfOutTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TemplateTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ThrowsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasImportTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypelessParamTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\UsesTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\VarTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeItemNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeUnsealedTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeParameterNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeForParameterNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ConstTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\GenericTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\IntersectionTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\InvalidTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\NullableTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ObjectShapeItemNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ObjectShapeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\OffsetAccessTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\ThisTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\TypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php', 'PHPStan\\PhpDocParser\\Ast\\Type\\UnionTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php', 'PHPStan\\PhpDocParser\\Lexer\\Lexer' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Lexer/Lexer.php', 'PHPStan\\PhpDocParser\\ParserConfig' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/ParserConfig.php', 'PHPStan\\PhpDocParser\\Parser\\ConstExprParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php', 'PHPStan\\PhpDocParser\\Parser\\ParserException' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/ParserException.php', 'PHPStan\\PhpDocParser\\Parser\\PhpDocParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php', 'PHPStan\\PhpDocParser\\Parser\\StringUnescaper' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php', 'PHPStan\\PhpDocParser\\Parser\\TokenIterator' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/TokenIterator.php', 'PHPStan\\PhpDocParser\\Parser\\TypeParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/TypeParser.php', 'PHPStan\\PhpDocParser\\Printer\\DiffElem' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Printer/DiffElem.php', 'PHPStan\\PhpDocParser\\Printer\\Differ' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Printer/Differ.php', 'PHPStan\\PhpDocParser\\Printer\\Printer' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Printer/Printer.php', 'PHPStan\\PhpDoc\\BcMathNumberStubFilesExtension' => __DIR__ . '/../..' . '/src/PhpDoc/BcMathNumberStubFilesExtension.php', 'PHPStan\\PhpDoc\\ConstExprNodeResolver' => __DIR__ . '/../..' . '/src/PhpDoc/ConstExprNodeResolver.php', 'PHPStan\\PhpDoc\\DefaultStubFilesProvider' => __DIR__ . '/../..' . '/src/PhpDoc/DefaultStubFilesProvider.php', 'PHPStan\\PhpDoc\\DirectTypeNodeResolverExtensionRegistryProvider' => __DIR__ . '/../..' . '/src/PhpDoc/DirectTypeNodeResolverExtensionRegistryProvider.php', 'PHPStan\\PhpDoc\\InheritedPhpDocParameterMapping' => __DIR__ . '/../..' . '/src/PhpDoc/InheritedPhpDocParameterMapping.php', 'PHPStan\\PhpDoc\\JsonValidateStubFilesExtension' => __DIR__ . '/../..' . '/src/PhpDoc/JsonValidateStubFilesExtension.php', 'PHPStan\\PhpDoc\\LazyTypeNodeResolverExtensionRegistryProvider' => __DIR__ . '/../..' . '/src/PhpDoc/LazyTypeNodeResolverExtensionRegistryProvider.php', 'PHPStan\\PhpDoc\\NameScopeAlreadyBeingCreatedException' => __DIR__ . '/../..' . '/src/PhpDoc/NameScopeAlreadyBeingCreatedException.php', 'PHPStan\\PhpDoc\\PhpDocInheritanceResolver' => __DIR__ . '/../..' . '/src/PhpDoc/PhpDocInheritanceResolver.php', 'PHPStan\\PhpDoc\\PhpDocNodeResolver' => __DIR__ . '/../..' . '/src/PhpDoc/PhpDocNodeResolver.php', 'PHPStan\\PhpDoc\\PhpDocStringResolver' => __DIR__ . '/../..' . '/src/PhpDoc/PhpDocStringResolver.php', 'PHPStan\\PhpDoc\\ReflectionClassStubFilesExtension' => __DIR__ . '/../..' . '/src/PhpDoc/ReflectionClassStubFilesExtension.php', 'PHPStan\\PhpDoc\\ReflectionEnumStubFilesExtension' => __DIR__ . '/../..' . '/src/PhpDoc/ReflectionEnumStubFilesExtension.php', 'PHPStan\\PhpDoc\\ResolvedPhpDocBlock' => __DIR__ . '/../..' . '/src/PhpDoc/ResolvedPhpDocBlock.php', 'PHPStan\\PhpDoc\\SocketSelectStubFilesExtension' => __DIR__ . '/../..' . '/src/PhpDoc/SocketSelectStubFilesExtension.php', 'PHPStan\\PhpDoc\\StubFilesExtension' => __DIR__ . '/../..' . '/src/PhpDoc/StubFilesExtension.php', 'PHPStan\\PhpDoc\\StubFilesProvider' => __DIR__ . '/../..' . '/src/PhpDoc/StubFilesProvider.php', 'PHPStan\\PhpDoc\\StubPhpDocProvider' => __DIR__ . '/../..' . '/src/PhpDoc/StubPhpDocProvider.php', 'PHPStan\\PhpDoc\\StubSourceLocatorFactory' => __DIR__ . '/../..' . '/src/PhpDoc/StubSourceLocatorFactory.php', 'PHPStan\\PhpDoc\\StubValidator' => __DIR__ . '/../..' . '/src/PhpDoc/StubValidator.php', 'PHPStan\\PhpDoc\\Tag\\AssertTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/AssertTag.php', 'PHPStan\\PhpDoc\\Tag\\AssertTagParameter' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/AssertTagParameter.php', 'PHPStan\\PhpDoc\\Tag\\DeprecatedTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/DeprecatedTag.php', 'PHPStan\\PhpDoc\\Tag\\ExtendsTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/ExtendsTag.php', 'PHPStan\\PhpDoc\\Tag\\ImplementsTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/ImplementsTag.php', 'PHPStan\\PhpDoc\\Tag\\MethodTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/MethodTag.php', 'PHPStan\\PhpDoc\\Tag\\MethodTagParameter' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/MethodTagParameter.php', 'PHPStan\\PhpDoc\\Tag\\MixinTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/MixinTag.php', 'PHPStan\\PhpDoc\\Tag\\ParamClosureThisTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/ParamClosureThisTag.php', 'PHPStan\\PhpDoc\\Tag\\ParamOutTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/ParamOutTag.php', 'PHPStan\\PhpDoc\\Tag\\ParamTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/ParamTag.php', 'PHPStan\\PhpDoc\\Tag\\PropertyTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/PropertyTag.php', 'PHPStan\\PhpDoc\\Tag\\RequireExtendsTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/RequireExtendsTag.php', 'PHPStan\\PhpDoc\\Tag\\RequireImplementsTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/RequireImplementsTag.php', 'PHPStan\\PhpDoc\\Tag\\ReturnTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/ReturnTag.php', 'PHPStan\\PhpDoc\\Tag\\SealedTypeTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/SealedTypeTag.php', 'PHPStan\\PhpDoc\\Tag\\SelfOutTypeTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/SelfOutTypeTag.php', 'PHPStan\\PhpDoc\\Tag\\TemplateTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/TemplateTag.php', 'PHPStan\\PhpDoc\\Tag\\ThrowsTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/ThrowsTag.php', 'PHPStan\\PhpDoc\\Tag\\TypeAliasImportTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/TypeAliasImportTag.php', 'PHPStan\\PhpDoc\\Tag\\TypeAliasTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/TypeAliasTag.php', 'PHPStan\\PhpDoc\\Tag\\TypedTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/TypedTag.php', 'PHPStan\\PhpDoc\\Tag\\UsesTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/UsesTag.php', 'PHPStan\\PhpDoc\\Tag\\VarTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/VarTag.php', 'PHPStan\\PhpDoc\\TypeNodeResolver' => __DIR__ . '/../..' . '/src/PhpDoc/TypeNodeResolver.php', 'PHPStan\\PhpDoc\\TypeNodeResolverAwareExtension' => __DIR__ . '/../..' . '/src/PhpDoc/TypeNodeResolverAwareExtension.php', 'PHPStan\\PhpDoc\\TypeNodeResolverExtension' => __DIR__ . '/../..' . '/src/PhpDoc/TypeNodeResolverExtension.php', 'PHPStan\\PhpDoc\\TypeNodeResolverExtensionAwareRegistry' => __DIR__ . '/../..' . '/src/PhpDoc/TypeNodeResolverExtensionAwareRegistry.php', 'PHPStan\\PhpDoc\\TypeNodeResolverExtensionRegistry' => __DIR__ . '/../..' . '/src/PhpDoc/TypeNodeResolverExtensionRegistry.php', 'PHPStan\\PhpDoc\\TypeNodeResolverExtensionRegistryProvider' => __DIR__ . '/../..' . '/src/PhpDoc/TypeNodeResolverExtensionRegistryProvider.php', 'PHPStan\\PhpDoc\\TypeStringResolver' => __DIR__ . '/../..' . '/src/PhpDoc/TypeStringResolver.php', 'PHPStan\\Php\\ComposerPhpVersionFactory' => __DIR__ . '/../..' . '/src/Php/ComposerPhpVersionFactory.php', 'PHPStan\\Php\\ComposerPhpVersionParser' => __DIR__ . '/../..' . '/src/Php/ComposerPhpVersionParser.php', 'PHPStan\\Php\\PhpVersion' => __DIR__ . '/../..' . '/src/Php/PhpVersion.php', 'PHPStan\\Php\\PhpVersionFactory' => __DIR__ . '/../..' . '/src/Php/PhpVersionFactory.php', 'PHPStan\\Php\\PhpVersionFactoryFactory' => __DIR__ . '/../..' . '/src/Php/PhpVersionFactoryFactory.php', 'PHPStan\\Php\\PhpVersions' => __DIR__ . '/../..' . '/src/Php/PhpVersions.php', 'PHPStan\\Process\\CpuCoreCounter' => __DIR__ . '/../..' . '/src/Process/CpuCoreCounter.php', 'PHPStan\\Process\\ForkedProcessPromise' => __DIR__ . '/../..' . '/src/Process/ForkedProcessPromise.php', 'PHPStan\\Process\\ProcessCanceledException' => __DIR__ . '/../..' . '/src/Process/ProcessCanceledException.php', 'PHPStan\\Process\\ProcessCrashedException' => __DIR__ . '/../..' . '/src/Process/ProcessCrashedException.php', 'PHPStan\\Process\\ProcessHelper' => __DIR__ . '/../..' . '/src/Process/ProcessHelper.php', 'PHPStan\\Process\\ProcessPromise' => __DIR__ . '/../..' . '/src/Process/ProcessPromise.php', 'PHPStan\\Process\\SpawnedProcessPromise' => __DIR__ . '/../..' . '/src/Process/SpawnedProcessPromise.php', 'PHPStan\\Reflection\\AdditionalConstructorsExtension' => __DIR__ . '/../..' . '/src/Reflection/AdditionalConstructorsExtension.php', 'PHPStan\\Reflection\\AllowedSubTypesClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/AllowedSubTypesClassReflectionExtension.php', 'PHPStan\\Reflection\\Annotations\\AnnotationMethodReflection' => __DIR__ . '/../..' . '/src/Reflection/Annotations/AnnotationMethodReflection.php', 'PHPStan\\Reflection\\Annotations\\AnnotationPropertyReflection' => __DIR__ . '/../..' . '/src/Reflection/Annotations/AnnotationPropertyReflection.php', 'PHPStan\\Reflection\\Annotations\\AnnotationsMethodParameterReflection' => __DIR__ . '/../..' . '/src/Reflection/Annotations/AnnotationsMethodParameterReflection.php', 'PHPStan\\Reflection\\Annotations\\AnnotationsMethodsClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/Annotations/AnnotationsMethodsClassReflectionExtension.php', 'PHPStan\\Reflection\\Annotations\\AnnotationsPropertiesClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/Annotations/AnnotationsPropertiesClassReflectionExtension.php', 'PHPStan\\Reflection\\Assertions' => __DIR__ . '/../..' . '/src/Reflection/Assertions.php', 'PHPStan\\Reflection\\AttributeReflection' => __DIR__ . '/../..' . '/src/Reflection/AttributeReflection.php', 'PHPStan\\Reflection\\AttributeReflectionFactory' => __DIR__ . '/../..' . '/src/Reflection/AttributeReflectionFactory.php', 'PHPStan\\Reflection\\BetterReflection\\BetterReflectionProvider' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/BetterReflectionProvider.php', 'PHPStan\\Reflection\\BetterReflection\\BetterReflectionSourceLocatorFactory' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/BetterReflectionSourceLocatorFactory.php', 'PHPStan\\Reflection\\BetterReflection\\Reflector\\MemoizingReflector' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/Reflector/MemoizingReflector.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\AutoloadFunctionsSourceLocator' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/AutoloadFunctionsSourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\AutoloadSourceLocator' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\CachingVisitor' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/CachingVisitor.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\ComposerJsonAndInstalledJsonSourceLocatorMaker' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/ComposerJsonAndInstalledJsonSourceLocatorMaker.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\FetchedNode' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/FetchedNode.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\FetchedNodesResult' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/FetchedNodesResult.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\FileNodesFetcher' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/FileNodesFetcher.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\FileReadTrapStreamWrapper' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/FileReadTrapStreamWrapper.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\LazySourceLocator' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/LazySourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\OptimizedDirectorySourceLocator' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\OptimizedDirectorySourceLocatorFactory' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorFactory.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\OptimizedDirectorySourceLocatorRepository' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorRepository.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\OptimizedPsrAutoloaderLocator' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/OptimizedPsrAutoloaderLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\OptimizedPsrAutoloaderLocatorFactory' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/OptimizedPsrAutoloaderLocatorFactory.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\OptimizedSingleFileSourceLocator' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\OptimizedSingleFileSourceLocatorFactory' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocatorFactory.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\OptimizedSingleFileSourceLocatorRepository' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocatorRepository.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\PhpFileCleaner' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/PhpFileCleaner.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\PhpVersionBlacklistSourceLocator' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/PhpVersionBlacklistSourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\ReflectionClassSourceLocator' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/ReflectionClassSourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\RewriteClassAliasSourceLocator' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/RewriteClassAliasSourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\SkipClassAliasSourceLocator' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/SkipClassAliasSourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\SkipPolyfillSourceLocator' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/SkipPolyfillSourceLocator.php', 'PHPStan\\Reflection\\BetterReflection\\SourceLocator\\SymbolFinderInFiles' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceLocator/SymbolFinderInFiles.php', 'PHPStan\\Reflection\\BetterReflection\\SourceStubber\\PhpStormStubsSourceStubberFactory' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceStubber/PhpStormStubsSourceStubberFactory.php', 'PHPStan\\Reflection\\BetterReflection\\SourceStubber\\ReflectionSourceStubberFactory' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/SourceStubber/ReflectionSourceStubberFactory.php', 'PHPStan\\Reflection\\BetterReflection\\Type\\AdapterReflectionEnumCaseDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php', 'PHPStan\\Reflection\\BetterReflection\\Type\\AdapterReflectionEnumDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Reflection/BetterReflection/Type/AdapterReflectionEnumDynamicReturnTypeExtension.php', 'PHPStan\\Reflection\\Callables\\CallableParametersAcceptor' => __DIR__ . '/../..' . '/src/Reflection/Callables/CallableParametersAcceptor.php', 'PHPStan\\Reflection\\Callables\\FunctionCallableVariant' => __DIR__ . '/../..' . '/src/Reflection/Callables/FunctionCallableVariant.php', 'PHPStan\\Reflection\\Callables\\SimpleImpurePoint' => __DIR__ . '/../..' . '/src/Reflection/Callables/SimpleImpurePoint.php', 'PHPStan\\Reflection\\Callables\\SimpleThrowPoint' => __DIR__ . '/../..' . '/src/Reflection/Callables/SimpleThrowPoint.php', 'PHPStan\\Reflection\\ClassConstantReflection' => __DIR__ . '/../..' . '/src/Reflection/ClassConstantReflection.php', 'PHPStan\\Reflection\\ClassMemberAccessAnswerer' => __DIR__ . '/../..' . '/src/Reflection/ClassMemberAccessAnswerer.php', 'PHPStan\\Reflection\\ClassMemberReflection' => __DIR__ . '/../..' . '/src/Reflection/ClassMemberReflection.php', 'PHPStan\\Reflection\\ClassNameHelper' => __DIR__ . '/../..' . '/src/Reflection/ClassNameHelper.php', 'PHPStan\\Reflection\\ClassReflection' => __DIR__ . '/../..' . '/src/Reflection/ClassReflection.php', 'PHPStan\\Reflection\\ClassReflectionExtensionRegistry' => __DIR__ . '/../..' . '/src/Reflection/ClassReflectionExtensionRegistry.php', 'PHPStan\\Reflection\\ClassReflectionFactory' => __DIR__ . '/../..' . '/src/Reflection/ClassReflectionFactory.php', 'PHPStan\\Reflection\\ConstantNameHelper' => __DIR__ . '/../..' . '/src/Reflection/ConstantNameHelper.php', 'PHPStan\\Reflection\\ConstantReflection' => __DIR__ . '/../..' . '/src/Reflection/ConstantReflection.php', 'PHPStan\\Reflection\\Constant\\RuntimeConstantReflection' => __DIR__ . '/../..' . '/src/Reflection/Constant/RuntimeConstantReflection.php', 'PHPStan\\Reflection\\ConstructorsHelper' => __DIR__ . '/../..' . '/src/Reflection/ConstructorsHelper.php', 'PHPStan\\Reflection\\Deprecation\\ClassConstantDeprecationExtension' => __DIR__ . '/../..' . '/src/Reflection/Deprecation/ClassConstantDeprecationExtension.php', 'PHPStan\\Reflection\\Deprecation\\ClassDeprecationExtension' => __DIR__ . '/../..' . '/src/Reflection/Deprecation/ClassDeprecationExtension.php', 'PHPStan\\Reflection\\Deprecation\\ConstantDeprecationExtension' => __DIR__ . '/../..' . '/src/Reflection/Deprecation/ConstantDeprecationExtension.php', 'PHPStan\\Reflection\\Deprecation\\Deprecation' => __DIR__ . '/../..' . '/src/Reflection/Deprecation/Deprecation.php', 'PHPStan\\Reflection\\Deprecation\\DeprecationProvider' => __DIR__ . '/../..' . '/src/Reflection/Deprecation/DeprecationProvider.php', 'PHPStan\\Reflection\\Deprecation\\EnumCaseDeprecationExtension' => __DIR__ . '/../..' . '/src/Reflection/Deprecation/EnumCaseDeprecationExtension.php', 'PHPStan\\Reflection\\Deprecation\\FunctionDeprecationExtension' => __DIR__ . '/../..' . '/src/Reflection/Deprecation/FunctionDeprecationExtension.php', 'PHPStan\\Reflection\\Deprecation\\MethodDeprecationExtension' => __DIR__ . '/../..' . '/src/Reflection/Deprecation/MethodDeprecationExtension.php', 'PHPStan\\Reflection\\Deprecation\\PropertyDeprecationExtension' => __DIR__ . '/../..' . '/src/Reflection/Deprecation/PropertyDeprecationExtension.php', 'PHPStan\\Reflection\\Dummy\\ChangedTypeMethodReflection' => __DIR__ . '/../..' . '/src/Reflection/Dummy/ChangedTypeMethodReflection.php', 'PHPStan\\Reflection\\Dummy\\ChangedTypePropertyReflection' => __DIR__ . '/../..' . '/src/Reflection/Dummy/ChangedTypePropertyReflection.php', 'PHPStan\\Reflection\\Dummy\\DummyClassConstantReflection' => __DIR__ . '/../..' . '/src/Reflection/Dummy/DummyClassConstantReflection.php', 'PHPStan\\Reflection\\Dummy\\DummyConstructorReflection' => __DIR__ . '/../..' . '/src/Reflection/Dummy/DummyConstructorReflection.php', 'PHPStan\\Reflection\\Dummy\\DummyMethodReflection' => __DIR__ . '/../..' . '/src/Reflection/Dummy/DummyMethodReflection.php', 'PHPStan\\Reflection\\Dummy\\DummyPropertyReflection' => __DIR__ . '/../..' . '/src/Reflection/Dummy/DummyPropertyReflection.php', 'PHPStan\\Reflection\\EnumCaseReflection' => __DIR__ . '/../..' . '/src/Reflection/EnumCaseReflection.php', 'PHPStan\\Reflection\\ExtendedCallableFunctionVariant' => __DIR__ . '/../..' . '/src/Reflection/ExtendedCallableFunctionVariant.php', 'PHPStan\\Reflection\\ExtendedFunctionVariant' => __DIR__ . '/../..' . '/src/Reflection/ExtendedFunctionVariant.php', 'PHPStan\\Reflection\\ExtendedMethodReflection' => __DIR__ . '/../..' . '/src/Reflection/ExtendedMethodReflection.php', 'PHPStan\\Reflection\\ExtendedParameterReflection' => __DIR__ . '/../..' . '/src/Reflection/ExtendedParameterReflection.php', 'PHPStan\\Reflection\\ExtendedParametersAcceptor' => __DIR__ . '/../..' . '/src/Reflection/ExtendedParametersAcceptor.php', 'PHPStan\\Reflection\\ExtendedPropertyReflection' => __DIR__ . '/../..' . '/src/Reflection/ExtendedPropertyReflection.php', 'PHPStan\\Reflection\\FunctionReflection' => __DIR__ . '/../..' . '/src/Reflection/FunctionReflection.php', 'PHPStan\\Reflection\\FunctionReflectionFactory' => __DIR__ . '/../..' . '/src/Reflection/FunctionReflectionFactory.php', 'PHPStan\\Reflection\\FunctionVariant' => __DIR__ . '/../..' . '/src/Reflection/FunctionVariant.php', 'PHPStan\\Reflection\\GenericParametersAcceptorResolver' => __DIR__ . '/../..' . '/src/Reflection/GenericParametersAcceptorResolver.php', 'PHPStan\\Reflection\\InaccessibleMethod' => __DIR__ . '/../..' . '/src/Reflection/InaccessibleMethod.php', 'PHPStan\\Reflection\\InitializerExprContext' => __DIR__ . '/../..' . '/src/Reflection/InitializerExprContext.php', 'PHPStan\\Reflection\\InitializerExprTypeResolver' => __DIR__ . '/../..' . '/src/Reflection/InitializerExprTypeResolver.php', 'PHPStan\\Reflection\\MethodPrototypeReflection' => __DIR__ . '/../..' . '/src/Reflection/MethodPrototypeReflection.php', 'PHPStan\\Reflection\\MethodReflection' => __DIR__ . '/../..' . '/src/Reflection/MethodReflection.php', 'PHPStan\\Reflection\\MethodsClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/MethodsClassReflectionExtension.php', 'PHPStan\\Reflection\\MissingConstantFromReflectionException' => __DIR__ . '/../..' . '/src/Reflection/MissingConstantFromReflectionException.php', 'PHPStan\\Reflection\\MissingMethodFromReflectionException' => __DIR__ . '/../..' . '/src/Reflection/MissingMethodFromReflectionException.php', 'PHPStan\\Reflection\\MissingPropertyFromReflectionException' => __DIR__ . '/../..' . '/src/Reflection/MissingPropertyFromReflectionException.php', 'PHPStan\\Reflection\\MissingStaticAccessorInstanceException' => __DIR__ . '/../..' . '/src/Reflection/MissingStaticAccessorInstanceException.php', 'PHPStan\\Reflection\\Mixin\\MixinMethodReflection' => __DIR__ . '/../..' . '/src/Reflection/Mixin/MixinMethodReflection.php', 'PHPStan\\Reflection\\Mixin\\MixinMethodsClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/Mixin/MixinMethodsClassReflectionExtension.php', 'PHPStan\\Reflection\\Mixin\\MixinPropertiesClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/Mixin/MixinPropertiesClassReflectionExtension.php', 'PHPStan\\Reflection\\NamespaceAnswerer' => __DIR__ . '/../..' . '/src/Reflection/NamespaceAnswerer.php', 'PHPStan\\Reflection\\Native\\ExtendedNativeParameterReflection' => __DIR__ . '/../..' . '/src/Reflection/Native/ExtendedNativeParameterReflection.php', 'PHPStan\\Reflection\\Native\\NativeFunctionReflection' => __DIR__ . '/../..' . '/src/Reflection/Native/NativeFunctionReflection.php', 'PHPStan\\Reflection\\Native\\NativeMethodReflection' => __DIR__ . '/../..' . '/src/Reflection/Native/NativeMethodReflection.php', 'PHPStan\\Reflection\\Native\\NativeParameterReflection' => __DIR__ . '/../..' . '/src/Reflection/Native/NativeParameterReflection.php', 'PHPStan\\Reflection\\PHPStan\\NativeReflectionEnumReturnDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Reflection/PHPStan/NativeReflectionEnumReturnDynamicReturnTypeExtension.php', 'PHPStan\\Reflection\\ParameterReflection' => __DIR__ . '/../..' . '/src/Reflection/ParameterReflection.php', 'PHPStan\\Reflection\\ParametersAcceptor' => __DIR__ . '/../..' . '/src/Reflection/ParametersAcceptor.php', 'PHPStan\\Reflection\\ParametersAcceptorSelector' => __DIR__ . '/../..' . '/src/Reflection/ParametersAcceptorSelector.php', 'PHPStan\\Reflection\\PassedByReference' => __DIR__ . '/../..' . '/src/Reflection/PassedByReference.php', 'PHPStan\\Reflection\\PhpVersionStaticAccessor' => __DIR__ . '/../..' . '/src/Reflection/PhpVersionStaticAccessor.php', 'PHPStan\\Reflection\\Php\\ClosureCallMethodReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/ClosureCallMethodReflection.php', 'PHPStan\\Reflection\\Php\\ClosureCallUnresolvedMethodPrototypeReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/ClosureCallUnresolvedMethodPrototypeReflection.php', 'PHPStan\\Reflection\\Php\\DummyParameter' => __DIR__ . '/../..' . '/src/Reflection/Php/DummyParameter.php', 'PHPStan\\Reflection\\Php\\EnumAllowedSubTypesClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/Php/EnumAllowedSubTypesClassReflectionExtension.php', 'PHPStan\\Reflection\\Php\\EnumCasesMethodReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/EnumCasesMethodReflection.php', 'PHPStan\\Reflection\\Php\\EnumPropertyReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/EnumPropertyReflection.php', 'PHPStan\\Reflection\\Php\\EnumUnresolvedPropertyPrototypeReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/EnumUnresolvedPropertyPrototypeReflection.php', 'PHPStan\\Reflection\\Php\\ExitFunctionReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/ExitFunctionReflection.php', 'PHPStan\\Reflection\\Php\\ExtendedDummyParameter' => __DIR__ . '/../..' . '/src/Reflection/Php/ExtendedDummyParameter.php', 'PHPStan\\Reflection\\Php\\PhpClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpClassReflectionExtension.php', 'PHPStan\\Reflection\\Php\\PhpFunctionFromParserNodeReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php', 'PHPStan\\Reflection\\Php\\PhpFunctionReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpFunctionReflection.php', 'PHPStan\\Reflection\\Php\\PhpMethodFromParserNodeReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpMethodFromParserNodeReflection.php', 'PHPStan\\Reflection\\Php\\PhpMethodReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpMethodReflection.php', 'PHPStan\\Reflection\\Php\\PhpMethodReflectionFactory' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpMethodReflectionFactory.php', 'PHPStan\\Reflection\\Php\\PhpParameterFromParserNodeReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpParameterFromParserNodeReflection.php', 'PHPStan\\Reflection\\Php\\PhpParameterReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpParameterReflection.php', 'PHPStan\\Reflection\\Php\\PhpPropertyReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpPropertyReflection.php', 'PHPStan\\Reflection\\Php\\SealedAllowedSubTypesClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/Php/SealedAllowedSubTypesClassReflectionExtension.php', 'PHPStan\\Reflection\\Php\\SimpleXMLElementProperty' => __DIR__ . '/../..' . '/src/Reflection/Php/SimpleXMLElementProperty.php', 'PHPStan\\Reflection\\Php\\Soap\\SoapClientMethodReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/Soap/SoapClientMethodReflection.php', 'PHPStan\\Reflection\\Php\\Soap\\SoapClientMethodsClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/Php/Soap/SoapClientMethodsClassReflectionExtension.php', 'PHPStan\\Reflection\\Php\\UniversalObjectCrateProperty' => __DIR__ . '/../..' . '/src/Reflection/Php/UniversalObjectCrateProperty.php', 'PHPStan\\Reflection\\Php\\UniversalObjectCratesClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/Php/UniversalObjectCratesClassReflectionExtension.php', 'PHPStan\\Reflection\\PropertiesClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/PropertiesClassReflectionExtension.php', 'PHPStan\\Reflection\\PropertyReflection' => __DIR__ . '/../..' . '/src/Reflection/PropertyReflection.php', 'PHPStan\\Reflection\\RealClassClassConstantReflection' => __DIR__ . '/../..' . '/src/Reflection/RealClassClassConstantReflection.php', 'PHPStan\\Reflection\\ReflectionProvider' => __DIR__ . '/../..' . '/src/Reflection/ReflectionProvider.php', 'PHPStan\\Reflection\\ReflectionProviderStaticAccessor' => __DIR__ . '/../..' . '/src/Reflection/ReflectionProviderStaticAccessor.php', 'PHPStan\\Reflection\\ReflectionProvider\\DirectReflectionProviderProvider' => __DIR__ . '/../..' . '/src/Reflection/ReflectionProvider/DirectReflectionProviderProvider.php', 'PHPStan\\Reflection\\ReflectionProvider\\DummyReflectionProvider' => __DIR__ . '/../..' . '/src/Reflection/ReflectionProvider/DummyReflectionProvider.php', 'PHPStan\\Reflection\\ReflectionProvider\\LazyReflectionProviderProvider' => __DIR__ . '/../..' . '/src/Reflection/ReflectionProvider/LazyReflectionProviderProvider.php', 'PHPStan\\Reflection\\ReflectionProvider\\MemoizingReflectionProvider' => __DIR__ . '/../..' . '/src/Reflection/ReflectionProvider/MemoizingReflectionProvider.php', 'PHPStan\\Reflection\\ReflectionProvider\\ReflectionProviderFactory' => __DIR__ . '/../..' . '/src/Reflection/ReflectionProvider/ReflectionProviderFactory.php', 'PHPStan\\Reflection\\ReflectionProvider\\ReflectionProviderProvider' => __DIR__ . '/../..' . '/src/Reflection/ReflectionProvider/ReflectionProviderProvider.php', 'PHPStan\\Reflection\\RequireExtension\\RequireExtendsMethodsClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/RequireExtension/RequireExtendsMethodsClassReflectionExtension.php', 'PHPStan\\Reflection\\RequireExtension\\RequireExtendsPropertiesClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/RequireExtension/RequireExtendsPropertiesClassReflectionExtension.php', 'PHPStan\\Reflection\\ResolvedFunctionVariant' => __DIR__ . '/../..' . '/src/Reflection/ResolvedFunctionVariant.php', 'PHPStan\\Reflection\\ResolvedFunctionVariantWithCallable' => __DIR__ . '/../..' . '/src/Reflection/ResolvedFunctionVariantWithCallable.php', 'PHPStan\\Reflection\\ResolvedFunctionVariantWithOriginal' => __DIR__ . '/../..' . '/src/Reflection/ResolvedFunctionVariantWithOriginal.php', 'PHPStan\\Reflection\\ResolvedMethodReflection' => __DIR__ . '/../..' . '/src/Reflection/ResolvedMethodReflection.php', 'PHPStan\\Reflection\\ResolvedPropertyReflection' => __DIR__ . '/../..' . '/src/Reflection/ResolvedPropertyReflection.php', 'PHPStan\\Reflection\\SignatureMap\\FunctionSignature' => __DIR__ . '/../..' . '/src/Reflection/SignatureMap/FunctionSignature.php', 'PHPStan\\Reflection\\SignatureMap\\FunctionSignatureMapProvider' => __DIR__ . '/../..' . '/src/Reflection/SignatureMap/FunctionSignatureMapProvider.php', 'PHPStan\\Reflection\\SignatureMap\\NativeFunctionReflectionProvider' => __DIR__ . '/../..' . '/src/Reflection/SignatureMap/NativeFunctionReflectionProvider.php', 'PHPStan\\Reflection\\SignatureMap\\ParameterSignature' => __DIR__ . '/../..' . '/src/Reflection/SignatureMap/ParameterSignature.php', 'PHPStan\\Reflection\\SignatureMap\\Php8SignatureMapProvider' => __DIR__ . '/../..' . '/src/Reflection/SignatureMap/Php8SignatureMapProvider.php', 'PHPStan\\Reflection\\SignatureMap\\SignatureMapParser' => __DIR__ . '/../..' . '/src/Reflection/SignatureMap/SignatureMapParser.php', 'PHPStan\\Reflection\\SignatureMap\\SignatureMapProvider' => __DIR__ . '/../..' . '/src/Reflection/SignatureMap/SignatureMapProvider.php', 'PHPStan\\Reflection\\SignatureMap\\SignatureMapProviderFactory' => __DIR__ . '/../..' . '/src/Reflection/SignatureMap/SignatureMapProviderFactory.php', 'PHPStan\\Reflection\\TrivialParametersAcceptor' => __DIR__ . '/../..' . '/src/Reflection/TrivialParametersAcceptor.php', 'PHPStan\\Reflection\\Type\\CallbackUnresolvedMethodPrototypeReflection' => __DIR__ . '/../..' . '/src/Reflection/Type/CallbackUnresolvedMethodPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\CallbackUnresolvedPropertyPrototypeReflection' => __DIR__ . '/../..' . '/src/Reflection/Type/CallbackUnresolvedPropertyPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\CalledOnTypeUnresolvedMethodPrototypeReflection' => __DIR__ . '/../..' . '/src/Reflection/Type/CalledOnTypeUnresolvedMethodPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\CalledOnTypeUnresolvedPropertyPrototypeReflection' => __DIR__ . '/../..' . '/src/Reflection/Type/CalledOnTypeUnresolvedPropertyPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\IntersectionTypeMethodReflection' => __DIR__ . '/../..' . '/src/Reflection/Type/IntersectionTypeMethodReflection.php', 'PHPStan\\Reflection\\Type\\IntersectionTypePropertyReflection' => __DIR__ . '/../..' . '/src/Reflection/Type/IntersectionTypePropertyReflection.php', 'PHPStan\\Reflection\\Type\\IntersectionTypeUnresolvedMethodPrototypeReflection' => __DIR__ . '/../..' . '/src/Reflection/Type/IntersectionTypeUnresolvedMethodPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\IntersectionTypeUnresolvedPropertyPrototypeReflection' => __DIR__ . '/../..' . '/src/Reflection/Type/IntersectionTypeUnresolvedPropertyPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\UnionTypeMethodReflection' => __DIR__ . '/../..' . '/src/Reflection/Type/UnionTypeMethodReflection.php', 'PHPStan\\Reflection\\Type\\UnionTypePropertyReflection' => __DIR__ . '/../..' . '/src/Reflection/Type/UnionTypePropertyReflection.php', 'PHPStan\\Reflection\\Type\\UnionTypeUnresolvedMethodPrototypeReflection' => __DIR__ . '/../..' . '/src/Reflection/Type/UnionTypeUnresolvedMethodPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\UnionTypeUnresolvedPropertyPrototypeReflection' => __DIR__ . '/../..' . '/src/Reflection/Type/UnionTypeUnresolvedPropertyPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\UnresolvedMethodPrototypeReflection' => __DIR__ . '/../..' . '/src/Reflection/Type/UnresolvedMethodPrototypeReflection.php', 'PHPStan\\Reflection\\Type\\UnresolvedPropertyPrototypeReflection' => __DIR__ . '/../..' . '/src/Reflection/Type/UnresolvedPropertyPrototypeReflection.php', 'PHPStan\\Reflection\\WrappedExtendedMethodReflection' => __DIR__ . '/../..' . '/src/Reflection/WrappedExtendedMethodReflection.php', 'PHPStan\\Reflection\\WrappedExtendedPropertyReflection' => __DIR__ . '/../..' . '/src/Reflection/WrappedExtendedPropertyReflection.php', 'PHPStan\\Reflection\\WrapperPropertyReflection' => __DIR__ . '/../..' . '/src/Reflection/WrapperPropertyReflection.php', 'PHPStan\\Rules\\Api\\ApiClassConstFetchRule' => __DIR__ . '/../..' . '/src/Rules/Api/ApiClassConstFetchRule.php', 'PHPStan\\Rules\\Api\\ApiClassExtendsRule' => __DIR__ . '/../..' . '/src/Rules/Api/ApiClassExtendsRule.php', 'PHPStan\\Rules\\Api\\ApiClassImplementsRule' => __DIR__ . '/../..' . '/src/Rules/Api/ApiClassImplementsRule.php', 'PHPStan\\Rules\\Api\\ApiInstanceofRule' => __DIR__ . '/../..' . '/src/Rules/Api/ApiInstanceofRule.php', 'PHPStan\\Rules\\Api\\ApiInstanceofTypeRule' => __DIR__ . '/../..' . '/src/Rules/Api/ApiInstanceofTypeRule.php', 'PHPStan\\Rules\\Api\\ApiInstantiationRule' => __DIR__ . '/../..' . '/src/Rules/Api/ApiInstantiationRule.php', 'PHPStan\\Rules\\Api\\ApiInterfaceExtendsRule' => __DIR__ . '/../..' . '/src/Rules/Api/ApiInterfaceExtendsRule.php', 'PHPStan\\Rules\\Api\\ApiMethodCallRule' => __DIR__ . '/../..' . '/src/Rules/Api/ApiMethodCallRule.php', 'PHPStan\\Rules\\Api\\ApiRuleHelper' => __DIR__ . '/../..' . '/src/Rules/Api/ApiRuleHelper.php', 'PHPStan\\Rules\\Api\\ApiStaticCallRule' => __DIR__ . '/../..' . '/src/Rules/Api/ApiStaticCallRule.php', 'PHPStan\\Rules\\Api\\ApiTraitUseRule' => __DIR__ . '/../..' . '/src/Rules/Api/ApiTraitUseRule.php', 'PHPStan\\Rules\\Api\\GetTemplateTypeRule' => __DIR__ . '/../..' . '/src/Rules/Api/GetTemplateTypeRule.php', 'PHPStan\\Rules\\Api\\NodeConnectingVisitorAttributesRule' => __DIR__ . '/../..' . '/src/Rules/Api/NodeConnectingVisitorAttributesRule.php', 'PHPStan\\Rules\\Api\\OldPhpParser4ClassRule' => __DIR__ . '/../..' . '/src/Rules/Api/OldPhpParser4ClassRule.php', 'PHPStan\\Rules\\Api\\PhpStanNamespaceIn3rdPartyPackageRule' => __DIR__ . '/../..' . '/src/Rules/Api/PhpStanNamespaceIn3rdPartyPackageRule.php', 'PHPStan\\Rules\\Api\\RuntimeReflectionFunctionRule' => __DIR__ . '/../..' . '/src/Rules/Api/RuntimeReflectionFunctionRule.php', 'PHPStan\\Rules\\Api\\RuntimeReflectionInstantiationRule' => __DIR__ . '/../..' . '/src/Rules/Api/RuntimeReflectionInstantiationRule.php', 'PHPStan\\Rules\\Arrays\\AllowedArrayKeysTypes' => __DIR__ . '/../..' . '/src/Rules/Arrays/AllowedArrayKeysTypes.php', 'PHPStan\\Rules\\Arrays\\ArrayDestructuringRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/ArrayDestructuringRule.php', 'PHPStan\\Rules\\Arrays\\ArrayUnpackingRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/ArrayUnpackingRule.php', 'PHPStan\\Rules\\Arrays\\DeadForeachRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/DeadForeachRule.php', 'PHPStan\\Rules\\Arrays\\DuplicateKeysInLiteralArraysRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.php', 'PHPStan\\Rules\\Arrays\\InvalidKeyInArrayDimFetchRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/InvalidKeyInArrayDimFetchRule.php', 'PHPStan\\Rules\\Arrays\\InvalidKeyInArrayItemRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/InvalidKeyInArrayItemRule.php', 'PHPStan\\Rules\\Arrays\\IterableInForeachRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/IterableInForeachRule.php', 'PHPStan\\Rules\\Arrays\\NonexistentOffsetInArrayDimFetchCheck' => __DIR__ . '/../..' . '/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php', 'PHPStan\\Rules\\Arrays\\NonexistentOffsetInArrayDimFetchRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchRule.php', 'PHPStan\\Rules\\Arrays\\OffsetAccessAssignOpRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/OffsetAccessAssignOpRule.php', 'PHPStan\\Rules\\Arrays\\OffsetAccessAssignmentRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/OffsetAccessAssignmentRule.php', 'PHPStan\\Rules\\Arrays\\OffsetAccessValueAssignmentRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/OffsetAccessValueAssignmentRule.php', 'PHPStan\\Rules\\Arrays\\OffsetAccessWithoutDimForReadingRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/OffsetAccessWithoutDimForReadingRule.php', 'PHPStan\\Rules\\Arrays\\UnpackIterableInArrayRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/UnpackIterableInArrayRule.php', 'PHPStan\\Rules\\AttributesCheck' => __DIR__ . '/../..' . '/src/Rules/AttributesCheck.php', 'PHPStan\\Rules\\Cast\\DeprecatedCastRule' => __DIR__ . '/../..' . '/src/Rules/Cast/DeprecatedCastRule.php', 'PHPStan\\Rules\\Cast\\EchoRule' => __DIR__ . '/../..' . '/src/Rules/Cast/EchoRule.php', 'PHPStan\\Rules\\Cast\\InvalidCastRule' => __DIR__ . '/../..' . '/src/Rules/Cast/InvalidCastRule.php', 'PHPStan\\Rules\\Cast\\InvalidPartOfEncapsedStringRule' => __DIR__ . '/../..' . '/src/Rules/Cast/InvalidPartOfEncapsedStringRule.php', 'PHPStan\\Rules\\Cast\\PrintRule' => __DIR__ . '/../..' . '/src/Rules/Cast/PrintRule.php', 'PHPStan\\Rules\\Cast\\UnsetCastRule' => __DIR__ . '/../..' . '/src/Rules/Cast/UnsetCastRule.php', 'PHPStan\\Rules\\Cast\\VoidCastRule' => __DIR__ . '/../..' . '/src/Rules/Cast/VoidCastRule.php', 'PHPStan\\Rules\\ClassCaseSensitivityCheck' => __DIR__ . '/../..' . '/src/Rules/ClassCaseSensitivityCheck.php', 'PHPStan\\Rules\\ClassForbiddenNameCheck' => __DIR__ . '/../..' . '/src/Rules/ClassForbiddenNameCheck.php', 'PHPStan\\Rules\\ClassNameCheck' => __DIR__ . '/../..' . '/src/Rules/ClassNameCheck.php', 'PHPStan\\Rules\\ClassNameNodePair' => __DIR__ . '/../..' . '/src/Rules/ClassNameNodePair.php', 'PHPStan\\Rules\\ClassNameUsageLocation' => __DIR__ . '/../..' . '/src/Rules/ClassNameUsageLocation.php', 'PHPStan\\Rules\\Classes\\AccessPrivateConstantThroughStaticRule' => __DIR__ . '/../..' . '/src/Rules/Classes/AccessPrivateConstantThroughStaticRule.php', 'PHPStan\\Rules\\Classes\\AllowedSubTypesRule' => __DIR__ . '/../..' . '/src/Rules/Classes/AllowedSubTypesRule.php', 'PHPStan\\Rules\\Classes\\ClassAttributesRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ClassAttributesRule.php', 'PHPStan\\Rules\\Classes\\ClassConstantAttributesRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ClassConstantAttributesRule.php', 'PHPStan\\Rules\\Classes\\ClassConstantRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ClassConstantRule.php', 'PHPStan\\Rules\\Classes\\ConsistentConstructorHelper' => __DIR__ . '/../..' . '/src/Rules/Classes/ConsistentConstructorHelper.php', 'PHPStan\\Rules\\Classes\\DuplicateClassDeclarationRule' => __DIR__ . '/../..' . '/src/Rules/Classes/DuplicateClassDeclarationRule.php', 'PHPStan\\Rules\\Classes\\DuplicateDeclarationHelper' => __DIR__ . '/../..' . '/src/Rules/Classes/DuplicateDeclarationHelper.php', 'PHPStan\\Rules\\Classes\\DuplicateDeclarationRule' => __DIR__ . '/../..' . '/src/Rules/Classes/DuplicateDeclarationRule.php', 'PHPStan\\Rules\\Classes\\DuplicateTraitDeclarationRule' => __DIR__ . '/../..' . '/src/Rules/Classes/DuplicateTraitDeclarationRule.php', 'PHPStan\\Rules\\Classes\\EnumSanityRule' => __DIR__ . '/../..' . '/src/Rules/Classes/EnumSanityRule.php', 'PHPStan\\Rules\\Classes\\ExistingClassInClassExtendsRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ExistingClassInClassExtendsRule.php', 'PHPStan\\Rules\\Classes\\ExistingClassInInstanceOfRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ExistingClassInInstanceOfRule.php', 'PHPStan\\Rules\\Classes\\ExistingClassInTraitUseRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ExistingClassInTraitUseRule.php', 'PHPStan\\Rules\\Classes\\ExistingClassesInClassImplementsRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ExistingClassesInClassImplementsRule.php', 'PHPStan\\Rules\\Classes\\ExistingClassesInEnumImplementsRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ExistingClassesInEnumImplementsRule.php', 'PHPStan\\Rules\\Classes\\ExistingClassesInInterfaceExtendsRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ExistingClassesInInterfaceExtendsRule.php', 'PHPStan\\Rules\\Classes\\ImpossibleInstanceOfRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ImpossibleInstanceOfRule.php', 'PHPStan\\Rules\\Classes\\InstantiationCallableRule' => __DIR__ . '/../..' . '/src/Rules/Classes/InstantiationCallableRule.php', 'PHPStan\\Rules\\Classes\\InstantiationRule' => __DIR__ . '/../..' . '/src/Rules/Classes/InstantiationRule.php', 'PHPStan\\Rules\\Classes\\InvalidPromotedPropertiesRule' => __DIR__ . '/../..' . '/src/Rules/Classes/InvalidPromotedPropertiesRule.php', 'PHPStan\\Rules\\Classes\\LocalTypeAliasesCheck' => __DIR__ . '/../..' . '/src/Rules/Classes/LocalTypeAliasesCheck.php', 'PHPStan\\Rules\\Classes\\LocalTypeAliasesRule' => __DIR__ . '/../..' . '/src/Rules/Classes/LocalTypeAliasesRule.php', 'PHPStan\\Rules\\Classes\\LocalTypeTraitAliasesRule' => __DIR__ . '/../..' . '/src/Rules/Classes/LocalTypeTraitAliasesRule.php', 'PHPStan\\Rules\\Classes\\LocalTypeTraitUseAliasesRule' => __DIR__ . '/../..' . '/src/Rules/Classes/LocalTypeTraitUseAliasesRule.php', 'PHPStan\\Rules\\Classes\\MethodTagCheck' => __DIR__ . '/../..' . '/src/Rules/Classes/MethodTagCheck.php', 'PHPStan\\Rules\\Classes\\MethodTagRule' => __DIR__ . '/../..' . '/src/Rules/Classes/MethodTagRule.php', 'PHPStan\\Rules\\Classes\\MethodTagTraitRule' => __DIR__ . '/../..' . '/src/Rules/Classes/MethodTagTraitRule.php', 'PHPStan\\Rules\\Classes\\MethodTagTraitUseRule' => __DIR__ . '/../..' . '/src/Rules/Classes/MethodTagTraitUseRule.php', 'PHPStan\\Rules\\Classes\\MixinCheck' => __DIR__ . '/../..' . '/src/Rules/Classes/MixinCheck.php', 'PHPStan\\Rules\\Classes\\MixinRule' => __DIR__ . '/../..' . '/src/Rules/Classes/MixinRule.php', 'PHPStan\\Rules\\Classes\\MixinTraitRule' => __DIR__ . '/../..' . '/src/Rules/Classes/MixinTraitRule.php', 'PHPStan\\Rules\\Classes\\MixinTraitUseRule' => __DIR__ . '/../..' . '/src/Rules/Classes/MixinTraitUseRule.php', 'PHPStan\\Rules\\Classes\\NewStaticInAbstractClassStaticMethodRule' => __DIR__ . '/../..' . '/src/Rules/Classes/NewStaticInAbstractClassStaticMethodRule.php', 'PHPStan\\Rules\\Classes\\NewStaticRule' => __DIR__ . '/../..' . '/src/Rules/Classes/NewStaticRule.php', 'PHPStan\\Rules\\Classes\\NonClassAttributeClassRule' => __DIR__ . '/../..' . '/src/Rules/Classes/NonClassAttributeClassRule.php', 'PHPStan\\Rules\\Classes\\PropertyTagCheck' => __DIR__ . '/../..' . '/src/Rules/Classes/PropertyTagCheck.php', 'PHPStan\\Rules\\Classes\\PropertyTagRule' => __DIR__ . '/../..' . '/src/Rules/Classes/PropertyTagRule.php', 'PHPStan\\Rules\\Classes\\PropertyTagTraitRule' => __DIR__ . '/../..' . '/src/Rules/Classes/PropertyTagTraitRule.php', 'PHPStan\\Rules\\Classes\\PropertyTagTraitUseRule' => __DIR__ . '/../..' . '/src/Rules/Classes/PropertyTagTraitUseRule.php', 'PHPStan\\Rules\\Classes\\ReadOnlyClassRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ReadOnlyClassRule.php', 'PHPStan\\Rules\\Classes\\RequireExtendsRule' => __DIR__ . '/../..' . '/src/Rules/Classes/RequireExtendsRule.php', 'PHPStan\\Rules\\Classes\\RequireImplementsRule' => __DIR__ . '/../..' . '/src/Rules/Classes/RequireImplementsRule.php', 'PHPStan\\Rules\\Classes\\TraitAttributeClassRule' => __DIR__ . '/../..' . '/src/Rules/Classes/TraitAttributeClassRule.php', 'PHPStan\\Rules\\Classes\\UnusedConstructorParametersRule' => __DIR__ . '/../..' . '/src/Rules/Classes/UnusedConstructorParametersRule.php', 'PHPStan\\Rules\\Comparison\\BooleanAndConstantConditionRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/BooleanAndConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\BooleanNotConstantConditionRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/BooleanNotConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\BooleanOrConstantConditionRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/BooleanOrConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\ConstantConditionRuleHelper' => __DIR__ . '/../..' . '/src/Rules/Comparison/ConstantConditionRuleHelper.php', 'PHPStan\\Rules\\Comparison\\ConstantLooseComparisonRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/ConstantLooseComparisonRule.php', 'PHPStan\\Rules\\Comparison\\DoWhileLoopConstantConditionRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/DoWhileLoopConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\ElseIfConstantConditionRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/ElseIfConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\IfConstantConditionRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/IfConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\ImpossibleCheckTypeFunctionCallRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/ImpossibleCheckTypeFunctionCallRule.php', 'PHPStan\\Rules\\Comparison\\ImpossibleCheckTypeHelper' => __DIR__ . '/../..' . '/src/Rules/Comparison/ImpossibleCheckTypeHelper.php', 'PHPStan\\Rules\\Comparison\\ImpossibleCheckTypeMethodCallRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/ImpossibleCheckTypeMethodCallRule.php', 'PHPStan\\Rules\\Comparison\\ImpossibleCheckTypeStaticMethodCallRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRule.php', 'PHPStan\\Rules\\Comparison\\LogicalXorConstantConditionRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/LogicalXorConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\MatchExpressionRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/MatchExpressionRule.php', 'PHPStan\\Rules\\Comparison\\NumberComparisonOperatorsConstantConditionRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/NumberComparisonOperatorsConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\PossiblyImpureTipHelper' => __DIR__ . '/../..' . '/src/Rules/Comparison/PossiblyImpureTipHelper.php', 'PHPStan\\Rules\\Comparison\\StrictComparisonOfDifferentTypesRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/StrictComparisonOfDifferentTypesRule.php', 'PHPStan\\Rules\\Comparison\\TernaryOperatorConstantConditionRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/TernaryOperatorConstantConditionRule.php', 'PHPStan\\Rules\\Comparison\\UsageOfVoidMatchExpressionRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/UsageOfVoidMatchExpressionRule.php', 'PHPStan\\Rules\\Comparison\\WhileLoopAlwaysFalseConditionRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/WhileLoopAlwaysFalseConditionRule.php', 'PHPStan\\Rules\\Comparison\\WhileLoopAlwaysTrueConditionRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php', 'PHPStan\\Rules\\Constants\\AlwaysUsedClassConstantsExtension' => __DIR__ . '/../..' . '/src/Rules/Constants/AlwaysUsedClassConstantsExtension.php', 'PHPStan\\Rules\\Constants\\AlwaysUsedClassConstantsExtensionProvider' => __DIR__ . '/../..' . '/src/Rules/Constants/AlwaysUsedClassConstantsExtensionProvider.php', 'PHPStan\\Rules\\Constants\\ClassAsClassConstantRule' => __DIR__ . '/../..' . '/src/Rules/Constants/ClassAsClassConstantRule.php', 'PHPStan\\Rules\\Constants\\ConstantAttributesRule' => __DIR__ . '/../..' . '/src/Rules/Constants/ConstantAttributesRule.php', 'PHPStan\\Rules\\Constants\\ConstantRule' => __DIR__ . '/../..' . '/src/Rules/Constants/ConstantRule.php', 'PHPStan\\Rules\\Constants\\DynamicClassConstantFetchRule' => __DIR__ . '/../..' . '/src/Rules/Constants/DynamicClassConstantFetchRule.php', 'PHPStan\\Rules\\Constants\\FinalConstantRule' => __DIR__ . '/../..' . '/src/Rules/Constants/FinalConstantRule.php', 'PHPStan\\Rules\\Constants\\FinalPrivateConstantRule' => __DIR__ . '/../..' . '/src/Rules/Constants/FinalPrivateConstantRule.php', 'PHPStan\\Rules\\Constants\\LazyAlwaysUsedClassConstantsExtensionProvider' => __DIR__ . '/../..' . '/src/Rules/Constants/LazyAlwaysUsedClassConstantsExtensionProvider.php', 'PHPStan\\Rules\\Constants\\MagicConstantContextRule' => __DIR__ . '/../..' . '/src/Rules/Constants/MagicConstantContextRule.php', 'PHPStan\\Rules\\Constants\\MissingClassConstantTypehintRule' => __DIR__ . '/../..' . '/src/Rules/Constants/MissingClassConstantTypehintRule.php', 'PHPStan\\Rules\\Constants\\NativeTypedClassConstantRule' => __DIR__ . '/../..' . '/src/Rules/Constants/NativeTypedClassConstantRule.php', 'PHPStan\\Rules\\Constants\\OverridingConstantRule' => __DIR__ . '/../..' . '/src/Rules/Constants/OverridingConstantRule.php', 'PHPStan\\Rules\\Constants\\ValueAssignedToClassConstantRule' => __DIR__ . '/../..' . '/src/Rules/Constants/ValueAssignedToClassConstantRule.php', 'PHPStan\\Rules\\Constants\\ValueAssignedToDefineRule' => __DIR__ . '/../..' . '/src/Rules/Constants/ValueAssignedToDefineRule.php', 'PHPStan\\Rules\\Constants\\ValueAssignedToGlobalConstantRule' => __DIR__ . '/../..' . '/src/Rules/Constants/ValueAssignedToGlobalConstantRule.php', 'PHPStan\\Rules\\DateIntervalInstantiationRule' => __DIR__ . '/../..' . '/src/Rules/DateIntervalInstantiationRule.php', 'PHPStan\\Rules\\DateTimeInstantiationRule' => __DIR__ . '/../..' . '/src/Rules/DateTimeInstantiationRule.php', 'PHPStan\\Rules\\DeadCode\\CallToConstructorStatementWithoutImpurePointsRule' => __DIR__ . '/../..' . '/src/Rules/DeadCode/CallToConstructorStatementWithoutImpurePointsRule.php', 'PHPStan\\Rules\\DeadCode\\CallToFunctionStatementWithoutImpurePointsRule' => __DIR__ . '/../..' . '/src/Rules/DeadCode/CallToFunctionStatementWithoutImpurePointsRule.php', 'PHPStan\\Rules\\DeadCode\\CallToMethodStatementWithoutImpurePointsRule' => __DIR__ . '/../..' . '/src/Rules/DeadCode/CallToMethodStatementWithoutImpurePointsRule.php', 'PHPStan\\Rules\\DeadCode\\CallToStaticMethodStatementWithoutImpurePointsRule' => __DIR__ . '/../..' . '/src/Rules/DeadCode/CallToStaticMethodStatementWithoutImpurePointsRule.php', 'PHPStan\\Rules\\DeadCode\\ConstructorWithoutImpurePointsCollector' => __DIR__ . '/../..' . '/src/Rules/DeadCode/ConstructorWithoutImpurePointsCollector.php', 'PHPStan\\Rules\\DeadCode\\FunctionWithoutImpurePointsCollector' => __DIR__ . '/../..' . '/src/Rules/DeadCode/FunctionWithoutImpurePointsCollector.php', 'PHPStan\\Rules\\DeadCode\\MethodWithoutImpurePointsCollector' => __DIR__ . '/../..' . '/src/Rules/DeadCode/MethodWithoutImpurePointsCollector.php', 'PHPStan\\Rules\\DeadCode\\NoopRule' => __DIR__ . '/../..' . '/src/Rules/DeadCode/NoopRule.php', 'PHPStan\\Rules\\DeadCode\\PossiblyPureFuncCallCollector' => __DIR__ . '/../..' . '/src/Rules/DeadCode/PossiblyPureFuncCallCollector.php', 'PHPStan\\Rules\\DeadCode\\PossiblyPureMethodCallCollector' => __DIR__ . '/../..' . '/src/Rules/DeadCode/PossiblyPureMethodCallCollector.php', 'PHPStan\\Rules\\DeadCode\\PossiblyPureNewCollector' => __DIR__ . '/../..' . '/src/Rules/DeadCode/PossiblyPureNewCollector.php', 'PHPStan\\Rules\\DeadCode\\PossiblyPureStaticCallCollector' => __DIR__ . '/../..' . '/src/Rules/DeadCode/PossiblyPureStaticCallCollector.php', 'PHPStan\\Rules\\DeadCode\\UnreachableStatementRule' => __DIR__ . '/../..' . '/src/Rules/DeadCode/UnreachableStatementRule.php', 'PHPStan\\Rules\\DeadCode\\UnusedPrivateConstantRule' => __DIR__ . '/../..' . '/src/Rules/DeadCode/UnusedPrivateConstantRule.php', 'PHPStan\\Rules\\DeadCode\\UnusedPrivateMethodRule' => __DIR__ . '/../..' . '/src/Rules/DeadCode/UnusedPrivateMethodRule.php', 'PHPStan\\Rules\\DeadCode\\UnusedPrivatePropertyRule' => __DIR__ . '/../..' . '/src/Rules/DeadCode/UnusedPrivatePropertyRule.php', 'PHPStan\\Rules\\Debug\\DebugScopeRule' => __DIR__ . '/../..' . '/src/Rules/Debug/DebugScopeRule.php', 'PHPStan\\Rules\\Debug\\DumpNativeTypeRule' => __DIR__ . '/../..' . '/src/Rules/Debug/DumpNativeTypeRule.php', 'PHPStan\\Rules\\Debug\\DumpPhpDocTypeRule' => __DIR__ . '/../..' . '/src/Rules/Debug/DumpPhpDocTypeRule.php', 'PHPStan\\Rules\\Debug\\DumpTypeRule' => __DIR__ . '/../..' . '/src/Rules/Debug/DumpTypeRule.php', 'PHPStan\\Rules\\Debug\\FileAssertRule' => __DIR__ . '/../..' . '/src/Rules/Debug/FileAssertRule.php', 'PHPStan\\Rules\\DirectRegistry' => __DIR__ . '/../..' . '/src/Rules/DirectRegistry.php', 'PHPStan\\Rules\\EnumCases\\EnumCaseAttributesRule' => __DIR__ . '/../..' . '/src/Rules/EnumCases/EnumCaseAttributesRule.php', 'PHPStan\\Rules\\EnumCases\\EnumCaseOutsideEnumRule' => __DIR__ . '/../..' . '/src/Rules/EnumCases/EnumCaseOutsideEnumRule.php', 'PHPStan\\Rules\\Exceptions\\CatchWithUnthrownExceptionRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/CatchWithUnthrownExceptionRule.php', 'PHPStan\\Rules\\Exceptions\\CaughtExceptionExistenceRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/CaughtExceptionExistenceRule.php', 'PHPStan\\Rules\\Exceptions\\DefaultExceptionTypeResolver' => __DIR__ . '/../..' . '/src/Rules/Exceptions/DefaultExceptionTypeResolver.php', 'PHPStan\\Rules\\Exceptions\\ExceptionTypeResolver' => __DIR__ . '/../..' . '/src/Rules/Exceptions/ExceptionTypeResolver.php', 'PHPStan\\Rules\\Exceptions\\MethodThrowTypeCovarianceRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/MethodThrowTypeCovarianceRule.php', 'PHPStan\\Rules\\Exceptions\\MissingCheckedExceptionInFunctionThrowsRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/MissingCheckedExceptionInFunctionThrowsRule.php', 'PHPStan\\Rules\\Exceptions\\MissingCheckedExceptionInMethodThrowsRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRule.php', 'PHPStan\\Rules\\Exceptions\\MissingCheckedExceptionInPropertyHookThrowsRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/MissingCheckedExceptionInPropertyHookThrowsRule.php', 'PHPStan\\Rules\\Exceptions\\MissingCheckedExceptionInThrowsCheck' => __DIR__ . '/../..' . '/src/Rules/Exceptions/MissingCheckedExceptionInThrowsCheck.php', 'PHPStan\\Rules\\Exceptions\\NoncapturingCatchRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/NoncapturingCatchRule.php', 'PHPStan\\Rules\\Exceptions\\OverwrittenExitPointByFinallyRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/OverwrittenExitPointByFinallyRule.php', 'PHPStan\\Rules\\Exceptions\\ThrowExprTypeRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/ThrowExprTypeRule.php', 'PHPStan\\Rules\\Exceptions\\ThrowExpressionRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/ThrowExpressionRule.php', 'PHPStan\\Rules\\Exceptions\\ThrowsVoidFunctionWithExplicitThrowPointRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/ThrowsVoidFunctionWithExplicitThrowPointRule.php', 'PHPStan\\Rules\\Exceptions\\ThrowsVoidMethodWithExplicitThrowPointRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/ThrowsVoidMethodWithExplicitThrowPointRule.php', 'PHPStan\\Rules\\Exceptions\\ThrowsVoidPropertyHookWithExplicitThrowPointRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/ThrowsVoidPropertyHookWithExplicitThrowPointRule.php', 'PHPStan\\Rules\\Exceptions\\TooWideFunctionThrowTypeRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/TooWideFunctionThrowTypeRule.php', 'PHPStan\\Rules\\Exceptions\\TooWideMethodThrowTypeRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/TooWideMethodThrowTypeRule.php', 'PHPStan\\Rules\\Exceptions\\TooWidePropertyHookThrowTypeRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/TooWidePropertyHookThrowTypeRule.php', 'PHPStan\\Rules\\Exceptions\\TooWideThrowTypeCheck' => __DIR__ . '/../..' . '/src/Rules/Exceptions/TooWideThrowTypeCheck.php', 'PHPStan\\Rules\\FileRuleError' => __DIR__ . '/../..' . '/src/Rules/FileRuleError.php', 'PHPStan\\Rules\\FixableNodeRuleError' => __DIR__ . '/../..' . '/src/Rules/FixableNodeRuleError.php', 'PHPStan\\Rules\\FoundTypeResult' => __DIR__ . '/../..' . '/src/Rules/FoundTypeResult.php', 'PHPStan\\Rules\\FunctionCallParametersCheck' => __DIR__ . '/../..' . '/src/Rules/FunctionCallParametersCheck.php', 'PHPStan\\Rules\\FunctionDefinitionCheck' => __DIR__ . '/../..' . '/src/Rules/FunctionDefinitionCheck.php', 'PHPStan\\Rules\\FunctionReturnTypeCheck' => __DIR__ . '/../..' . '/src/Rules/FunctionReturnTypeCheck.php', 'PHPStan\\Rules\\Functions\\ArrayFilterRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ArrayFilterRule.php', 'PHPStan\\Rules\\Functions\\ArrayValuesRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ArrayValuesRule.php', 'PHPStan\\Rules\\Functions\\ArrowFunctionAttributesRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ArrowFunctionAttributesRule.php', 'PHPStan\\Rules\\Functions\\ArrowFunctionReturnNullsafeByRefRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ArrowFunctionReturnNullsafeByRefRule.php', 'PHPStan\\Rules\\Functions\\ArrowFunctionReturnTypeRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ArrowFunctionReturnTypeRule.php', 'PHPStan\\Rules\\Functions\\CallCallablesRule' => __DIR__ . '/../..' . '/src/Rules/Functions/CallCallablesRule.php', 'PHPStan\\Rules\\Functions\\CallToFunctionParametersRule' => __DIR__ . '/../..' . '/src/Rules/Functions/CallToFunctionParametersRule.php', 'PHPStan\\Rules\\Functions\\CallToFunctionStatementWithNoDiscardRule' => __DIR__ . '/../..' . '/src/Rules/Functions/CallToFunctionStatementWithNoDiscardRule.php', 'PHPStan\\Rules\\Functions\\CallToFunctionStatementWithoutSideEffectsRule' => __DIR__ . '/../..' . '/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php', 'PHPStan\\Rules\\Functions\\CallToNonExistentFunctionRule' => __DIR__ . '/../..' . '/src/Rules/Functions/CallToNonExistentFunctionRule.php', 'PHPStan\\Rules\\Functions\\CallUserFuncRule' => __DIR__ . '/../..' . '/src/Rules/Functions/CallUserFuncRule.php', 'PHPStan\\Rules\\Functions\\ClosureAttributesRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ClosureAttributesRule.php', 'PHPStan\\Rules\\Functions\\ClosureReturnTypeRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ClosureReturnTypeRule.php', 'PHPStan\\Rules\\Functions\\DefineParametersRule' => __DIR__ . '/../..' . '/src/Rules/Functions/DefineParametersRule.php', 'PHPStan\\Rules\\Functions\\DuplicateFunctionDeclarationRule' => __DIR__ . '/../..' . '/src/Rules/Functions/DuplicateFunctionDeclarationRule.php', 'PHPStan\\Rules\\Functions\\ExistingClassesInArrowFunctionTypehintsRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRule.php', 'PHPStan\\Rules\\Functions\\ExistingClassesInClosureTypehintsRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ExistingClassesInClosureTypehintsRule.php', 'PHPStan\\Rules\\Functions\\ExistingClassesInTypehintsRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ExistingClassesInTypehintsRule.php', 'PHPStan\\Rules\\Functions\\FilterVarRule' => __DIR__ . '/../..' . '/src/Rules/Functions/FilterVarRule.php', 'PHPStan\\Rules\\Functions\\FunctionAttributesRule' => __DIR__ . '/../..' . '/src/Rules/Functions/FunctionAttributesRule.php', 'PHPStan\\Rules\\Functions\\FunctionCallableRule' => __DIR__ . '/../..' . '/src/Rules/Functions/FunctionCallableRule.php', 'PHPStan\\Rules\\Functions\\ImplodeParameterCastableToStringRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ImplodeParameterCastableToStringRule.php', 'PHPStan\\Rules\\Functions\\IncompatibleArrowFunctionDefaultParameterTypeRule' => __DIR__ . '/../..' . '/src/Rules/Functions/IncompatibleArrowFunctionDefaultParameterTypeRule.php', 'PHPStan\\Rules\\Functions\\IncompatibleClosureDefaultParameterTypeRule' => __DIR__ . '/../..' . '/src/Rules/Functions/IncompatibleClosureDefaultParameterTypeRule.php', 'PHPStan\\Rules\\Functions\\IncompatibleDefaultParameterTypeRule' => __DIR__ . '/../..' . '/src/Rules/Functions/IncompatibleDefaultParameterTypeRule.php', 'PHPStan\\Rules\\Functions\\InnerFunctionRule' => __DIR__ . '/../..' . '/src/Rules/Functions/InnerFunctionRule.php', 'PHPStan\\Rules\\Functions\\InvalidLexicalVariablesInClosureUseRule' => __DIR__ . '/../..' . '/src/Rules/Functions/InvalidLexicalVariablesInClosureUseRule.php', 'PHPStan\\Rules\\Functions\\InvalidParameterNameRule' => __DIR__ . '/../..' . '/src/Rules/Functions/InvalidParameterNameRule.php', 'PHPStan\\Rules\\Functions\\MissingFunctionParameterTypehintRule' => __DIR__ . '/../..' . '/src/Rules/Functions/MissingFunctionParameterTypehintRule.php', 'PHPStan\\Rules\\Functions\\MissingFunctionReturnTypehintRule' => __DIR__ . '/../..' . '/src/Rules/Functions/MissingFunctionReturnTypehintRule.php', 'PHPStan\\Rules\\Functions\\ParamAttributesRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ParamAttributesRule.php', 'PHPStan\\Rules\\Functions\\ParameterCastableToNumberRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ParameterCastableToNumberRule.php', 'PHPStan\\Rules\\Functions\\ParameterCastableToStringRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ParameterCastableToStringRule.php', 'PHPStan\\Rules\\Functions\\PrintfArrayParametersRule' => __DIR__ . '/../..' . '/src/Rules/Functions/PrintfArrayParametersRule.php', 'PHPStan\\Rules\\Functions\\PrintfHelper' => __DIR__ . '/../..' . '/src/Rules/Functions/PrintfHelper.php', 'PHPStan\\Rules\\Functions\\PrintfParameterTypeRule' => __DIR__ . '/../..' . '/src/Rules/Functions/PrintfParameterTypeRule.php', 'PHPStan\\Rules\\Functions\\PrintfParametersRule' => __DIR__ . '/../..' . '/src/Rules/Functions/PrintfParametersRule.php', 'PHPStan\\Rules\\Functions\\PrintfPlaceholder' => __DIR__ . '/../..' . '/src/Rules/Functions/PrintfPlaceholder.php', 'PHPStan\\Rules\\Functions\\RandomIntParametersRule' => __DIR__ . '/../..' . '/src/Rules/Functions/RandomIntParametersRule.php', 'PHPStan\\Rules\\Functions\\RedefinedParametersRule' => __DIR__ . '/../..' . '/src/Rules/Functions/RedefinedParametersRule.php', 'PHPStan\\Rules\\Functions\\ReturnNullsafeByRefRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ReturnNullsafeByRefRule.php', 'PHPStan\\Rules\\Functions\\ReturnTypeRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ReturnTypeRule.php', 'PHPStan\\Rules\\Functions\\SortParameterCastableToStringRule' => __DIR__ . '/../..' . '/src/Rules/Functions/SortParameterCastableToStringRule.php', 'PHPStan\\Rules\\Functions\\UnusedClosureUsesRule' => __DIR__ . '/../..' . '/src/Rules/Functions/UnusedClosureUsesRule.php', 'PHPStan\\Rules\\Functions\\UselessFunctionReturnValueRule' => __DIR__ . '/../..' . '/src/Rules/Functions/UselessFunctionReturnValueRule.php', 'PHPStan\\Rules\\Functions\\VariadicParametersDeclarationRule' => __DIR__ . '/../..' . '/src/Rules/Functions/VariadicParametersDeclarationRule.php', 'PHPStan\\Rules\\Generators\\YieldFromTypeRule' => __DIR__ . '/../..' . '/src/Rules/Generators/YieldFromTypeRule.php', 'PHPStan\\Rules\\Generators\\YieldInGeneratorRule' => __DIR__ . '/../..' . '/src/Rules/Generators/YieldInGeneratorRule.php', 'PHPStan\\Rules\\Generators\\YieldTypeRule' => __DIR__ . '/../..' . '/src/Rules/Generators/YieldTypeRule.php', 'PHPStan\\Rules\\Generics\\ClassAncestorsRule' => __DIR__ . '/../..' . '/src/Rules/Generics/ClassAncestorsRule.php', 'PHPStan\\Rules\\Generics\\ClassTemplateTypeRule' => __DIR__ . '/../..' . '/src/Rules/Generics/ClassTemplateTypeRule.php', 'PHPStan\\Rules\\Generics\\CrossCheckInterfacesHelper' => __DIR__ . '/../..' . '/src/Rules/Generics/CrossCheckInterfacesHelper.php', 'PHPStan\\Rules\\Generics\\EnumAncestorsRule' => __DIR__ . '/../..' . '/src/Rules/Generics/EnumAncestorsRule.php', 'PHPStan\\Rules\\Generics\\EnumTemplateTypeRule' => __DIR__ . '/../..' . '/src/Rules/Generics/EnumTemplateTypeRule.php', 'PHPStan\\Rules\\Generics\\FunctionSignatureVarianceRule' => __DIR__ . '/../..' . '/src/Rules/Generics/FunctionSignatureVarianceRule.php', 'PHPStan\\Rules\\Generics\\FunctionTemplateTypeRule' => __DIR__ . '/../..' . '/src/Rules/Generics/FunctionTemplateTypeRule.php', 'PHPStan\\Rules\\Generics\\GenericAncestorsCheck' => __DIR__ . '/../..' . '/src/Rules/Generics/GenericAncestorsCheck.php', 'PHPStan\\Rules\\Generics\\GenericObjectTypeCheck' => __DIR__ . '/../..' . '/src/Rules/Generics/GenericObjectTypeCheck.php', 'PHPStan\\Rules\\Generics\\InterfaceAncestorsRule' => __DIR__ . '/../..' . '/src/Rules/Generics/InterfaceAncestorsRule.php', 'PHPStan\\Rules\\Generics\\InterfaceTemplateTypeRule' => __DIR__ . '/../..' . '/src/Rules/Generics/InterfaceTemplateTypeRule.php', 'PHPStan\\Rules\\Generics\\MethodSignatureVarianceRule' => __DIR__ . '/../..' . '/src/Rules/Generics/MethodSignatureVarianceRule.php', 'PHPStan\\Rules\\Generics\\MethodTagTemplateTypeCheck' => __DIR__ . '/../..' . '/src/Rules/Generics/MethodTagTemplateTypeCheck.php', 'PHPStan\\Rules\\Generics\\MethodTagTemplateTypeRule' => __DIR__ . '/../..' . '/src/Rules/Generics/MethodTagTemplateTypeRule.php', 'PHPStan\\Rules\\Generics\\MethodTagTemplateTypeTraitRule' => __DIR__ . '/../..' . '/src/Rules/Generics/MethodTagTemplateTypeTraitRule.php', 'PHPStan\\Rules\\Generics\\MethodTemplateTypeRule' => __DIR__ . '/../..' . '/src/Rules/Generics/MethodTemplateTypeRule.php', 'PHPStan\\Rules\\Generics\\PropertyVarianceRule' => __DIR__ . '/../..' . '/src/Rules/Generics/PropertyVarianceRule.php', 'PHPStan\\Rules\\Generics\\TemplateTypeCheck' => __DIR__ . '/../..' . '/src/Rules/Generics/TemplateTypeCheck.php', 'PHPStan\\Rules\\Generics\\TraitTemplateTypeRule' => __DIR__ . '/../..' . '/src/Rules/Generics/TraitTemplateTypeRule.php', 'PHPStan\\Rules\\Generics\\UsedTraitsRule' => __DIR__ . '/../..' . '/src/Rules/Generics/UsedTraitsRule.php', 'PHPStan\\Rules\\Generics\\VarianceCheck' => __DIR__ . '/../..' . '/src/Rules/Generics/VarianceCheck.php', 'PHPStan\\Rules\\IdentifierRuleError' => __DIR__ . '/../..' . '/src/Rules/IdentifierRuleError.php', 'PHPStan\\Rules\\Ignore\\IgnoreParseErrorRule' => __DIR__ . '/../..' . '/src/Rules/Ignore/IgnoreParseErrorRule.php', 'PHPStan\\Rules\\InternalTag\\RestrictedInternalClassConstantUsageExtension' => __DIR__ . '/../..' . '/src/Rules/InternalTag/RestrictedInternalClassConstantUsageExtension.php', 'PHPStan\\Rules\\InternalTag\\RestrictedInternalClassNameUsageExtension' => __DIR__ . '/../..' . '/src/Rules/InternalTag/RestrictedInternalClassNameUsageExtension.php', 'PHPStan\\Rules\\InternalTag\\RestrictedInternalFunctionUsageExtension' => __DIR__ . '/../..' . '/src/Rules/InternalTag/RestrictedInternalFunctionUsageExtension.php', 'PHPStan\\Rules\\InternalTag\\RestrictedInternalMethodUsageExtension' => __DIR__ . '/../..' . '/src/Rules/InternalTag/RestrictedInternalMethodUsageExtension.php', 'PHPStan\\Rules\\InternalTag\\RestrictedInternalPropertyUsageExtension' => __DIR__ . '/../..' . '/src/Rules/InternalTag/RestrictedInternalPropertyUsageExtension.php', 'PHPStan\\Rules\\InternalTag\\RestrictedInternalUsageHelper' => __DIR__ . '/../..' . '/src/Rules/InternalTag/RestrictedInternalUsageHelper.php', 'PHPStan\\Rules\\IssetCheck' => __DIR__ . '/../..' . '/src/Rules/IssetCheck.php', 'PHPStan\\Rules\\Keywords\\ContinueBreakInLoopRule' => __DIR__ . '/../..' . '/src/Rules/Keywords/ContinueBreakInLoopRule.php', 'PHPStan\\Rules\\Keywords\\DeclareStrictTypesRule' => __DIR__ . '/../..' . '/src/Rules/Keywords/DeclareStrictTypesRule.php', 'PHPStan\\Rules\\Keywords\\RequireFileExistsRule' => __DIR__ . '/../..' . '/src/Rules/Keywords/RequireFileExistsRule.php', 'PHPStan\\Rules\\LazyRegistry' => __DIR__ . '/../..' . '/src/Rules/LazyRegistry.php', 'PHPStan\\Rules\\LineRuleError' => __DIR__ . '/../..' . '/src/Rules/LineRuleError.php', 'PHPStan\\Rules\\MetadataRuleError' => __DIR__ . '/../..' . '/src/Rules/MetadataRuleError.php', 'PHPStan\\Rules\\Methods\\AbstractMethodInNonAbstractClassRule' => __DIR__ . '/../..' . '/src/Rules/Methods/AbstractMethodInNonAbstractClassRule.php', 'PHPStan\\Rules\\Methods\\AbstractPrivateMethodRule' => __DIR__ . '/../..' . '/src/Rules/Methods/AbstractPrivateMethodRule.php', 'PHPStan\\Rules\\Methods\\AlwaysUsedMethodExtension' => __DIR__ . '/../..' . '/src/Rules/Methods/AlwaysUsedMethodExtension.php', 'PHPStan\\Rules\\Methods\\AlwaysUsedMethodExtensionProvider' => __DIR__ . '/../..' . '/src/Rules/Methods/AlwaysUsedMethodExtensionProvider.php', 'PHPStan\\Rules\\Methods\\CallMethodsRule' => __DIR__ . '/../..' . '/src/Rules/Methods/CallMethodsRule.php', 'PHPStan\\Rules\\Methods\\CallPrivateMethodThroughStaticRule' => __DIR__ . '/../..' . '/src/Rules/Methods/CallPrivateMethodThroughStaticRule.php', 'PHPStan\\Rules\\Methods\\CallStaticMethodsRule' => __DIR__ . '/../..' . '/src/Rules/Methods/CallStaticMethodsRule.php', 'PHPStan\\Rules\\Methods\\CallToConstructorStatementWithoutSideEffectsRule' => __DIR__ . '/../..' . '/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php', 'PHPStan\\Rules\\Methods\\CallToMethodStatementWithNoDiscardRule' => __DIR__ . '/../..' . '/src/Rules/Methods/CallToMethodStatementWithNoDiscardRule.php', 'PHPStan\\Rules\\Methods\\CallToMethodStatementWithoutSideEffectsRule' => __DIR__ . '/../..' . '/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php', 'PHPStan\\Rules\\Methods\\CallToStaticMethodStatementWithNoDiscardRule' => __DIR__ . '/../..' . '/src/Rules/Methods/CallToStaticMethodStatementWithNoDiscardRule.php', 'PHPStan\\Rules\\Methods\\CallToStaticMethodStatementWithoutSideEffectsRule' => __DIR__ . '/../..' . '/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php', 'PHPStan\\Rules\\Methods\\ConsistentConstructorDeclarationRule' => __DIR__ . '/../..' . '/src/Rules/Methods/ConsistentConstructorDeclarationRule.php', 'PHPStan\\Rules\\Methods\\ConsistentConstructorRule' => __DIR__ . '/../..' . '/src/Rules/Methods/ConsistentConstructorRule.php', 'PHPStan\\Rules\\Methods\\ConstructorReturnTypeRule' => __DIR__ . '/../..' . '/src/Rules/Methods/ConstructorReturnTypeRule.php', 'PHPStan\\Rules\\Methods\\DirectAlwaysUsedMethodExtensionProvider' => __DIR__ . '/../..' . '/src/Rules/Methods/DirectAlwaysUsedMethodExtensionProvider.php', 'PHPStan\\Rules\\Methods\\ExistingClassesInTypehintsRule' => __DIR__ . '/../..' . '/src/Rules/Methods/ExistingClassesInTypehintsRule.php', 'PHPStan\\Rules\\Methods\\FinalPrivateMethodRule' => __DIR__ . '/../..' . '/src/Rules/Methods/FinalPrivateMethodRule.php', 'PHPStan\\Rules\\Methods\\IncompatibleDefaultParameterTypeRule' => __DIR__ . '/../..' . '/src/Rules/Methods/IncompatibleDefaultParameterTypeRule.php', 'PHPStan\\Rules\\Methods\\LazyAlwaysUsedMethodExtensionProvider' => __DIR__ . '/../..' . '/src/Rules/Methods/LazyAlwaysUsedMethodExtensionProvider.php', 'PHPStan\\Rules\\Methods\\MethodAttributesRule' => __DIR__ . '/../..' . '/src/Rules/Methods/MethodAttributesRule.php', 'PHPStan\\Rules\\Methods\\MethodCallCheck' => __DIR__ . '/../..' . '/src/Rules/Methods/MethodCallCheck.php', 'PHPStan\\Rules\\Methods\\MethodCallableRule' => __DIR__ . '/../..' . '/src/Rules/Methods/MethodCallableRule.php', 'PHPStan\\Rules\\Methods\\MethodParameterComparisonHelper' => __DIR__ . '/../..' . '/src/Rules/Methods/MethodParameterComparisonHelper.php', 'PHPStan\\Rules\\Methods\\MethodPrototypeFinder' => __DIR__ . '/../..' . '/src/Rules/Methods/MethodPrototypeFinder.php', 'PHPStan\\Rules\\Methods\\MethodSignatureRule' => __DIR__ . '/../..' . '/src/Rules/Methods/MethodSignatureRule.php', 'PHPStan\\Rules\\Methods\\MethodVisibilityComparisonHelper' => __DIR__ . '/../..' . '/src/Rules/Methods/MethodVisibilityComparisonHelper.php', 'PHPStan\\Rules\\Methods\\MethodVisibilityInInterfaceRule' => __DIR__ . '/../..' . '/src/Rules/Methods/MethodVisibilityInInterfaceRule.php', 'PHPStan\\Rules\\Methods\\MissingMagicSerializationMethodsRule' => __DIR__ . '/../..' . '/src/Rules/Methods/MissingMagicSerializationMethodsRule.php', 'PHPStan\\Rules\\Methods\\MissingMethodImplementationRule' => __DIR__ . '/../..' . '/src/Rules/Methods/MissingMethodImplementationRule.php', 'PHPStan\\Rules\\Methods\\MissingMethodParameterTypehintRule' => __DIR__ . '/../..' . '/src/Rules/Methods/MissingMethodParameterTypehintRule.php', 'PHPStan\\Rules\\Methods\\MissingMethodReturnTypehintRule' => __DIR__ . '/../..' . '/src/Rules/Methods/MissingMethodReturnTypehintRule.php', 'PHPStan\\Rules\\Methods\\MissingMethodSelfOutTypeRule' => __DIR__ . '/../..' . '/src/Rules/Methods/MissingMethodSelfOutTypeRule.php', 'PHPStan\\Rules\\Methods\\NullsafeMethodCallRule' => __DIR__ . '/../..' . '/src/Rules/Methods/NullsafeMethodCallRule.php', 'PHPStan\\Rules\\Methods\\OverridingMethodRule' => __DIR__ . '/../..' . '/src/Rules/Methods/OverridingMethodRule.php', 'PHPStan\\Rules\\Methods\\ParentMethodHelper' => __DIR__ . '/../..' . '/src/Rules/Methods/ParentMethodHelper.php', 'PHPStan\\Rules\\Methods\\ReturnTypeRule' => __DIR__ . '/../..' . '/src/Rules/Methods/ReturnTypeRule.php', 'PHPStan\\Rules\\Methods\\StaticMethodCallCheck' => __DIR__ . '/../..' . '/src/Rules/Methods/StaticMethodCallCheck.php', 'PHPStan\\Rules\\Methods\\StaticMethodCallableRule' => __DIR__ . '/../..' . '/src/Rules/Methods/StaticMethodCallableRule.php', 'PHPStan\\Rules\\MissingTypehintCheck' => __DIR__ . '/../..' . '/src/Rules/MissingTypehintCheck.php', 'PHPStan\\Rules\\Missing\\MissingReturnRule' => __DIR__ . '/../..' . '/src/Rules/Missing/MissingReturnRule.php', 'PHPStan\\Rules\\Names\\UsedNamesRule' => __DIR__ . '/../..' . '/src/Rules/Names/UsedNamesRule.php', 'PHPStan\\Rules\\Namespaces\\ExistingNamesInGroupUseRule' => __DIR__ . '/../..' . '/src/Rules/Namespaces/ExistingNamesInGroupUseRule.php', 'PHPStan\\Rules\\Namespaces\\ExistingNamesInUseRule' => __DIR__ . '/../..' . '/src/Rules/Namespaces/ExistingNamesInUseRule.php', 'PHPStan\\Rules\\NonIgnorableRuleError' => __DIR__ . '/../..' . '/src/Rules/NonIgnorableRuleError.php', 'PHPStan\\Rules\\NullsafeCheck' => __DIR__ . '/../..' . '/src/Rules/NullsafeCheck.php', 'PHPStan\\Rules\\Operators\\BacktickRule' => __DIR__ . '/../..' . '/src/Rules/Operators/BacktickRule.php', 'PHPStan\\Rules\\Operators\\InvalidAssignVarRule' => __DIR__ . '/../..' . '/src/Rules/Operators/InvalidAssignVarRule.php', 'PHPStan\\Rules\\Operators\\InvalidBinaryOperationRule' => __DIR__ . '/../..' . '/src/Rules/Operators/InvalidBinaryOperationRule.php', 'PHPStan\\Rules\\Operators\\InvalidComparisonOperationRule' => __DIR__ . '/../..' . '/src/Rules/Operators/InvalidComparisonOperationRule.php', 'PHPStan\\Rules\\Operators\\InvalidIncDecOperationRule' => __DIR__ . '/../..' . '/src/Rules/Operators/InvalidIncDecOperationRule.php', 'PHPStan\\Rules\\Operators\\InvalidUnaryOperationRule' => __DIR__ . '/../..' . '/src/Rules/Operators/InvalidUnaryOperationRule.php', 'PHPStan\\Rules\\Operators\\PipeOperatorRule' => __DIR__ . '/../..' . '/src/Rules/Operators/PipeOperatorRule.php', 'PHPStan\\Rules\\ParameterCastableToStringCheck' => __DIR__ . '/../..' . '/src/Rules/ParameterCastableToStringCheck.php', 'PHPStan\\Rules\\PhpDoc\\AssertRuleHelper' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/AssertRuleHelper.php', 'PHPStan\\Rules\\PhpDoc\\ConditionalReturnTypeRuleHelper' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/ConditionalReturnTypeRuleHelper.php', 'PHPStan\\Rules\\PhpDoc\\FunctionAssertRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/FunctionAssertRule.php', 'PHPStan\\Rules\\PhpDoc\\FunctionConditionalReturnTypeRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/FunctionConditionalReturnTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\GenericCallableRuleHelper' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/GenericCallableRuleHelper.php', 'PHPStan\\Rules\\PhpDoc\\IncompatibleClassConstantPhpDocTypeRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/IncompatibleClassConstantPhpDocTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\IncompatibleParamImmediatelyInvokedCallableRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/IncompatibleParamImmediatelyInvokedCallableRule.php', 'PHPStan\\Rules\\PhpDoc\\IncompatiblePhpDocTypeCheck' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/IncompatiblePhpDocTypeCheck.php', 'PHPStan\\Rules\\PhpDoc\\IncompatiblePhpDocTypeRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/IncompatiblePhpDocTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\IncompatiblePropertyHookPhpDocTypeRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/IncompatiblePropertyHookPhpDocTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\IncompatiblePropertyPhpDocTypeRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/IncompatiblePropertyPhpDocTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\IncompatibleSelfOutTypeRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/IncompatibleSelfOutTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\InvalidPHPStanDocTagRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/InvalidPHPStanDocTagRule.php', 'PHPStan\\Rules\\PhpDoc\\InvalidPhpDocTagValueRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php', 'PHPStan\\Rules\\PhpDoc\\InvalidPhpDocVarTagTypeRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/InvalidPhpDocVarTagTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\InvalidThrowsPhpDocValueRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/InvalidThrowsPhpDocValueRule.php', 'PHPStan\\Rules\\PhpDoc\\MethodAssertRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/MethodAssertRule.php', 'PHPStan\\Rules\\PhpDoc\\MethodConditionalReturnTypeRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/MethodConditionalReturnTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\PhpDocLineHelper' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/PhpDocLineHelper.php', 'PHPStan\\Rules\\PhpDoc\\RequireExtendsCheck' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/RequireExtendsCheck.php', 'PHPStan\\Rules\\PhpDoc\\RequireExtendsDefinitionClassRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/RequireExtendsDefinitionClassRule.php', 'PHPStan\\Rules\\PhpDoc\\RequireExtendsDefinitionTraitRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/RequireExtendsDefinitionTraitRule.php', 'PHPStan\\Rules\\PhpDoc\\RequireImplementsDefinitionClassRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/RequireImplementsDefinitionClassRule.php', 'PHPStan\\Rules\\PhpDoc\\RequireImplementsDefinitionTraitRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/RequireImplementsDefinitionTraitRule.php', 'PHPStan\\Rules\\PhpDoc\\SealedDefinitionClassRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/SealedDefinitionClassRule.php', 'PHPStan\\Rules\\PhpDoc\\SealedDefinitionTraitRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/SealedDefinitionTraitRule.php', 'PHPStan\\Rules\\PhpDoc\\UnresolvableTypeHelper' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/UnresolvableTypeHelper.php', 'PHPStan\\Rules\\PhpDoc\\VarTagChangedExpressionTypeRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/VarTagChangedExpressionTypeRule.php', 'PHPStan\\Rules\\PhpDoc\\VarTagTypeRuleHelper' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/VarTagTypeRuleHelper.php', 'PHPStan\\Rules\\PhpDoc\\WrongVariableNameInVarTagRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php', 'PHPStan\\Rules\\Playground\\FunctionNeverRule' => __DIR__ . '/../..' . '/src/Rules/Playground/FunctionNeverRule.php', 'PHPStan\\Rules\\Playground\\MethodNeverRule' => __DIR__ . '/../..' . '/src/Rules/Playground/MethodNeverRule.php', 'PHPStan\\Rules\\Playground\\NeverRuleHelper' => __DIR__ . '/../..' . '/src/Rules/Playground/NeverRuleHelper.php', 'PHPStan\\Rules\\Playground\\NoPhpCodeRule' => __DIR__ . '/../..' . '/src/Rules/Playground/NoPhpCodeRule.php', 'PHPStan\\Rules\\Playground\\NotAnalysedTraitRule' => __DIR__ . '/../..' . '/src/Rules/Playground/NotAnalysedTraitRule.php', 'PHPStan\\Rules\\Playground\\PhpdocCommentRule' => __DIR__ . '/../..' . '/src/Rules/Playground/PhpdocCommentRule.php', 'PHPStan\\Rules\\Playground\\PromoteParameterRule' => __DIR__ . '/../..' . '/src/Rules/Playground/PromoteParameterRule.php', 'PHPStan\\Rules\\Playground\\StaticVarWithoutTypeRule' => __DIR__ . '/../..' . '/src/Rules/Playground/StaticVarWithoutTypeRule.php', 'PHPStan\\Rules\\Properties\\AccessPrivatePropertyThroughStaticRule' => __DIR__ . '/../..' . '/src/Rules/Properties/AccessPrivatePropertyThroughStaticRule.php', 'PHPStan\\Rules\\Properties\\AccessPropertiesCheck' => __DIR__ . '/../..' . '/src/Rules/Properties/AccessPropertiesCheck.php', 'PHPStan\\Rules\\Properties\\AccessPropertiesInAssignRule' => __DIR__ . '/../..' . '/src/Rules/Properties/AccessPropertiesInAssignRule.php', 'PHPStan\\Rules\\Properties\\AccessPropertiesRule' => __DIR__ . '/../..' . '/src/Rules/Properties/AccessPropertiesRule.php', 'PHPStan\\Rules\\Properties\\AccessStaticPropertiesCheck' => __DIR__ . '/../..' . '/src/Rules/Properties/AccessStaticPropertiesCheck.php', 'PHPStan\\Rules\\Properties\\AccessStaticPropertiesInAssignRule' => __DIR__ . '/../..' . '/src/Rules/Properties/AccessStaticPropertiesInAssignRule.php', 'PHPStan\\Rules\\Properties\\AccessStaticPropertiesRule' => __DIR__ . '/../..' . '/src/Rules/Properties/AccessStaticPropertiesRule.php', 'PHPStan\\Rules\\Properties\\DefaultValueTypesAssignedToPropertiesRule' => __DIR__ . '/../..' . '/src/Rules/Properties/DefaultValueTypesAssignedToPropertiesRule.php', 'PHPStan\\Rules\\Properties\\DirectReadWritePropertiesExtensionProvider' => __DIR__ . '/../..' . '/src/Rules/Properties/DirectReadWritePropertiesExtensionProvider.php', 'PHPStan\\Rules\\Properties\\ExistingClassesInPropertiesRule' => __DIR__ . '/../..' . '/src/Rules/Properties/ExistingClassesInPropertiesRule.php', 'PHPStan\\Rules\\Properties\\ExistingClassesInPropertyHookTypehintsRule' => __DIR__ . '/../..' . '/src/Rules/Properties/ExistingClassesInPropertyHookTypehintsRule.php', 'PHPStan\\Rules\\Properties\\FoundPropertyReflection' => __DIR__ . '/../..' . '/src/Rules/Properties/FoundPropertyReflection.php', 'PHPStan\\Rules\\Properties\\GetNonVirtualPropertyHookReadRule' => __DIR__ . '/../..' . '/src/Rules/Properties/GetNonVirtualPropertyHookReadRule.php', 'PHPStan\\Rules\\Properties\\InvalidCallablePropertyTypeRule' => __DIR__ . '/../..' . '/src/Rules/Properties/InvalidCallablePropertyTypeRule.php', 'PHPStan\\Rules\\Properties\\LazyReadWritePropertiesExtensionProvider' => __DIR__ . '/../..' . '/src/Rules/Properties/LazyReadWritePropertiesExtensionProvider.php', 'PHPStan\\Rules\\Properties\\MissingPropertyTypehintRule' => __DIR__ . '/../..' . '/src/Rules/Properties/MissingPropertyTypehintRule.php', 'PHPStan\\Rules\\Properties\\MissingReadOnlyByPhpDocPropertyAssignRule' => __DIR__ . '/../..' . '/src/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRule.php', 'PHPStan\\Rules\\Properties\\MissingReadOnlyPropertyAssignRule' => __DIR__ . '/../..' . '/src/Rules/Properties/MissingReadOnlyPropertyAssignRule.php', 'PHPStan\\Rules\\Properties\\NullsafePropertyFetchRule' => __DIR__ . '/../..' . '/src/Rules/Properties/NullsafePropertyFetchRule.php', 'PHPStan\\Rules\\Properties\\OverridingPropertyRule' => __DIR__ . '/../..' . '/src/Rules/Properties/OverridingPropertyRule.php', 'PHPStan\\Rules\\Properties\\PropertiesInInterfaceRule' => __DIR__ . '/../..' . '/src/Rules/Properties/PropertiesInInterfaceRule.php', 'PHPStan\\Rules\\Properties\\PropertyAssignRefRule' => __DIR__ . '/../..' . '/src/Rules/Properties/PropertyAssignRefRule.php', 'PHPStan\\Rules\\Properties\\PropertyAttributesRule' => __DIR__ . '/../..' . '/src/Rules/Properties/PropertyAttributesRule.php', 'PHPStan\\Rules\\Properties\\PropertyDescriptor' => __DIR__ . '/../..' . '/src/Rules/Properties/PropertyDescriptor.php', 'PHPStan\\Rules\\Properties\\PropertyHookAttributesRule' => __DIR__ . '/../..' . '/src/Rules/Properties/PropertyHookAttributesRule.php', 'PHPStan\\Rules\\Properties\\PropertyInClassRule' => __DIR__ . '/../..' . '/src/Rules/Properties/PropertyInClassRule.php', 'PHPStan\\Rules\\Properties\\PropertyReflectionFinder' => __DIR__ . '/../..' . '/src/Rules/Properties/PropertyReflectionFinder.php', 'PHPStan\\Rules\\Properties\\ReadOnlyByPhpDocPropertyAssignRefRule' => __DIR__ . '/../..' . '/src/Rules/Properties/ReadOnlyByPhpDocPropertyAssignRefRule.php', 'PHPStan\\Rules\\Properties\\ReadOnlyByPhpDocPropertyAssignRule' => __DIR__ . '/../..' . '/src/Rules/Properties/ReadOnlyByPhpDocPropertyAssignRule.php', 'PHPStan\\Rules\\Properties\\ReadOnlyByPhpDocPropertyRule' => __DIR__ . '/../..' . '/src/Rules/Properties/ReadOnlyByPhpDocPropertyRule.php', 'PHPStan\\Rules\\Properties\\ReadOnlyPropertyAssignRefRule' => __DIR__ . '/../..' . '/src/Rules/Properties/ReadOnlyPropertyAssignRefRule.php', 'PHPStan\\Rules\\Properties\\ReadOnlyPropertyAssignRule' => __DIR__ . '/../..' . '/src/Rules/Properties/ReadOnlyPropertyAssignRule.php', 'PHPStan\\Rules\\Properties\\ReadOnlyPropertyRule' => __DIR__ . '/../..' . '/src/Rules/Properties/ReadOnlyPropertyRule.php', 'PHPStan\\Rules\\Properties\\ReadWritePropertiesExtension' => __DIR__ . '/../..' . '/src/Rules/Properties/ReadWritePropertiesExtension.php', 'PHPStan\\Rules\\Properties\\ReadWritePropertiesExtensionProvider' => __DIR__ . '/../..' . '/src/Rules/Properties/ReadWritePropertiesExtensionProvider.php', 'PHPStan\\Rules\\Properties\\ReadingWriteOnlyPropertiesRule' => __DIR__ . '/../..' . '/src/Rules/Properties/ReadingWriteOnlyPropertiesRule.php', 'PHPStan\\Rules\\Properties\\SetNonVirtualPropertyHookAssignRule' => __DIR__ . '/../..' . '/src/Rules/Properties/SetNonVirtualPropertyHookAssignRule.php', 'PHPStan\\Rules\\Properties\\SetPropertyHookParameterRule' => __DIR__ . '/../..' . '/src/Rules/Properties/SetPropertyHookParameterRule.php', 'PHPStan\\Rules\\Properties\\TypesAssignedToPropertiesRule' => __DIR__ . '/../..' . '/src/Rules/Properties/TypesAssignedToPropertiesRule.php', 'PHPStan\\Rules\\Properties\\UninitializedPropertyRule' => __DIR__ . '/../..' . '/src/Rules/Properties/UninitializedPropertyRule.php', 'PHPStan\\Rules\\Properties\\WritingToReadOnlyPropertiesRule' => __DIR__ . '/../..' . '/src/Rules/Properties/WritingToReadOnlyPropertiesRule.php', 'PHPStan\\Rules\\Pure\\FunctionPurityCheck' => __DIR__ . '/../..' . '/src/Rules/Pure/FunctionPurityCheck.php', 'PHPStan\\Rules\\Pure\\PureFunctionRule' => __DIR__ . '/../..' . '/src/Rules/Pure/PureFunctionRule.php', 'PHPStan\\Rules\\Pure\\PureMethodRule' => __DIR__ . '/../..' . '/src/Rules/Pure/PureMethodRule.php', 'PHPStan\\Rules\\Regexp\\RegularExpressionPatternRule' => __DIR__ . '/../..' . '/src/Rules/Regexp/RegularExpressionPatternRule.php', 'PHPStan\\Rules\\Regexp\\RegularExpressionQuotingRule' => __DIR__ . '/../..' . '/src/Rules/Regexp/RegularExpressionQuotingRule.php', 'PHPStan\\Rules\\Registry' => __DIR__ . '/../..' . '/src/Rules/Registry.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedClassConstantUsageExtension' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RestrictedClassConstantUsageExtension.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedClassConstantUsageRule' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RestrictedClassConstantUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedClassNameUsageExtension' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RestrictedClassNameUsageExtension.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedFunctionCallableUsageRule' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RestrictedFunctionCallableUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedFunctionUsageExtension' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RestrictedFunctionUsageExtension.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedFunctionUsageRule' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RestrictedFunctionUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedMethodCallableUsageRule' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RestrictedMethodCallableUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedMethodUsageExtension' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RestrictedMethodUsageExtension.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedMethodUsageRule' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RestrictedMethodUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedPropertyUsageExtension' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RestrictedPropertyUsageExtension.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedPropertyUsageRule' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RestrictedPropertyUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedStaticMethodCallableUsageRule' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RestrictedStaticMethodCallableUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedStaticMethodUsageRule' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RestrictedStaticMethodUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedStaticPropertyUsageRule' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RestrictedStaticPropertyUsageRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedUsage' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RestrictedUsage.php', 'PHPStan\\Rules\\RestrictedUsage\\RestrictedUsageOfDeprecatedStringCastRule' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RestrictedUsageOfDeprecatedStringCastRule.php', 'PHPStan\\Rules\\RestrictedUsage\\RewrittenDeclaringClassClassConstantReflection' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RewrittenDeclaringClassClassConstantReflection.php', 'PHPStan\\Rules\\RestrictedUsage\\RewrittenDeclaringClassMethodReflection' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RewrittenDeclaringClassMethodReflection.php', 'PHPStan\\Rules\\RestrictedUsage\\RewrittenDeclaringClassPropertyReflection' => __DIR__ . '/../..' . '/src/Rules/RestrictedUsage/RewrittenDeclaringClassPropertyReflection.php', 'PHPStan\\Rules\\Rule' => __DIR__ . '/../..' . '/src/Rules/Rule.php', 'PHPStan\\Rules\\RuleError' => __DIR__ . '/../..' . '/src/Rules/RuleError.php', 'PHPStan\\Rules\\RuleErrorBuilder' => __DIR__ . '/../..' . '/src/Rules/RuleErrorBuilder.php', 'PHPStan\\Rules\\RuleErrors\\RuleError1' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError1.php', 'PHPStan\\Rules\\RuleErrors\\RuleError101' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError101.php', 'PHPStan\\Rules\\RuleErrors\\RuleError103' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError103.php', 'PHPStan\\Rules\\RuleErrors\\RuleError105' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError105.php', 'PHPStan\\Rules\\RuleErrors\\RuleError107' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError107.php', 'PHPStan\\Rules\\RuleErrors\\RuleError109' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError109.php', 'PHPStan\\Rules\\RuleErrors\\RuleError11' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError11.php', 'PHPStan\\Rules\\RuleErrors\\RuleError111' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError111.php', 'PHPStan\\Rules\\RuleErrors\\RuleError113' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError113.php', 'PHPStan\\Rules\\RuleErrors\\RuleError115' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError115.php', 'PHPStan\\Rules\\RuleErrors\\RuleError117' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError117.php', 'PHPStan\\Rules\\RuleErrors\\RuleError119' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError119.php', 'PHPStan\\Rules\\RuleErrors\\RuleError121' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError121.php', 'PHPStan\\Rules\\RuleErrors\\RuleError123' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError123.php', 'PHPStan\\Rules\\RuleErrors\\RuleError125' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError125.php', 'PHPStan\\Rules\\RuleErrors\\RuleError127' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError127.php', 'PHPStan\\Rules\\RuleErrors\\RuleError129' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError129.php', 'PHPStan\\Rules\\RuleErrors\\RuleError13' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError13.php', 'PHPStan\\Rules\\RuleErrors\\RuleError131' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError131.php', 'PHPStan\\Rules\\RuleErrors\\RuleError133' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError133.php', 'PHPStan\\Rules\\RuleErrors\\RuleError135' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError135.php', 'PHPStan\\Rules\\RuleErrors\\RuleError137' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError137.php', 'PHPStan\\Rules\\RuleErrors\\RuleError139' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError139.php', 'PHPStan\\Rules\\RuleErrors\\RuleError141' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError141.php', 'PHPStan\\Rules\\RuleErrors\\RuleError143' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError143.php', 'PHPStan\\Rules\\RuleErrors\\RuleError145' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError145.php', 'PHPStan\\Rules\\RuleErrors\\RuleError147' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError147.php', 'PHPStan\\Rules\\RuleErrors\\RuleError149' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError149.php', 'PHPStan\\Rules\\RuleErrors\\RuleError15' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError15.php', 'PHPStan\\Rules\\RuleErrors\\RuleError151' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError151.php', 'PHPStan\\Rules\\RuleErrors\\RuleError153' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError153.php', 'PHPStan\\Rules\\RuleErrors\\RuleError155' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError155.php', 'PHPStan\\Rules\\RuleErrors\\RuleError157' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError157.php', 'PHPStan\\Rules\\RuleErrors\\RuleError159' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError159.php', 'PHPStan\\Rules\\RuleErrors\\RuleError161' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError161.php', 'PHPStan\\Rules\\RuleErrors\\RuleError163' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError163.php', 'PHPStan\\Rules\\RuleErrors\\RuleError165' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError165.php', 'PHPStan\\Rules\\RuleErrors\\RuleError167' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError167.php', 'PHPStan\\Rules\\RuleErrors\\RuleError169' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError169.php', 'PHPStan\\Rules\\RuleErrors\\RuleError17' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError17.php', 'PHPStan\\Rules\\RuleErrors\\RuleError171' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError171.php', 'PHPStan\\Rules\\RuleErrors\\RuleError173' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError173.php', 'PHPStan\\Rules\\RuleErrors\\RuleError175' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError175.php', 'PHPStan\\Rules\\RuleErrors\\RuleError177' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError177.php', 'PHPStan\\Rules\\RuleErrors\\RuleError179' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError179.php', 'PHPStan\\Rules\\RuleErrors\\RuleError181' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError181.php', 'PHPStan\\Rules\\RuleErrors\\RuleError183' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError183.php', 'PHPStan\\Rules\\RuleErrors\\RuleError185' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError185.php', 'PHPStan\\Rules\\RuleErrors\\RuleError187' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError187.php', 'PHPStan\\Rules\\RuleErrors\\RuleError189' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError189.php', 'PHPStan\\Rules\\RuleErrors\\RuleError19' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError19.php', 'PHPStan\\Rules\\RuleErrors\\RuleError191' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError191.php', 'PHPStan\\Rules\\RuleErrors\\RuleError193' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError193.php', 'PHPStan\\Rules\\RuleErrors\\RuleError195' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError195.php', 'PHPStan\\Rules\\RuleErrors\\RuleError197' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError197.php', 'PHPStan\\Rules\\RuleErrors\\RuleError199' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError199.php', 'PHPStan\\Rules\\RuleErrors\\RuleError201' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError201.php', 'PHPStan\\Rules\\RuleErrors\\RuleError203' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError203.php', 'PHPStan\\Rules\\RuleErrors\\RuleError205' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError205.php', 'PHPStan\\Rules\\RuleErrors\\RuleError207' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError207.php', 'PHPStan\\Rules\\RuleErrors\\RuleError209' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError209.php', 'PHPStan\\Rules\\RuleErrors\\RuleError21' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError21.php', 'PHPStan\\Rules\\RuleErrors\\RuleError211' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError211.php', 'PHPStan\\Rules\\RuleErrors\\RuleError213' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError213.php', 'PHPStan\\Rules\\RuleErrors\\RuleError215' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError215.php', 'PHPStan\\Rules\\RuleErrors\\RuleError217' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError217.php', 'PHPStan\\Rules\\RuleErrors\\RuleError219' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError219.php', 'PHPStan\\Rules\\RuleErrors\\RuleError221' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError221.php', 'PHPStan\\Rules\\RuleErrors\\RuleError223' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError223.php', 'PHPStan\\Rules\\RuleErrors\\RuleError225' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError225.php', 'PHPStan\\Rules\\RuleErrors\\RuleError227' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError227.php', 'PHPStan\\Rules\\RuleErrors\\RuleError229' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError229.php', 'PHPStan\\Rules\\RuleErrors\\RuleError23' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError23.php', 'PHPStan\\Rules\\RuleErrors\\RuleError231' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError231.php', 'PHPStan\\Rules\\RuleErrors\\RuleError233' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError233.php', 'PHPStan\\Rules\\RuleErrors\\RuleError235' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError235.php', 'PHPStan\\Rules\\RuleErrors\\RuleError237' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError237.php', 'PHPStan\\Rules\\RuleErrors\\RuleError239' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError239.php', 'PHPStan\\Rules\\RuleErrors\\RuleError241' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError241.php', 'PHPStan\\Rules\\RuleErrors\\RuleError243' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError243.php', 'PHPStan\\Rules\\RuleErrors\\RuleError245' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError245.php', 'PHPStan\\Rules\\RuleErrors\\RuleError247' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError247.php', 'PHPStan\\Rules\\RuleErrors\\RuleError249' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError249.php', 'PHPStan\\Rules\\RuleErrors\\RuleError25' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError25.php', 'PHPStan\\Rules\\RuleErrors\\RuleError251' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError251.php', 'PHPStan\\Rules\\RuleErrors\\RuleError253' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError253.php', 'PHPStan\\Rules\\RuleErrors\\RuleError255' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError255.php', 'PHPStan\\Rules\\RuleErrors\\RuleError27' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError27.php', 'PHPStan\\Rules\\RuleErrors\\RuleError29' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError29.php', 'PHPStan\\Rules\\RuleErrors\\RuleError3' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError3.php', 'PHPStan\\Rules\\RuleErrors\\RuleError31' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError31.php', 'PHPStan\\Rules\\RuleErrors\\RuleError33' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError33.php', 'PHPStan\\Rules\\RuleErrors\\RuleError35' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError35.php', 'PHPStan\\Rules\\RuleErrors\\RuleError37' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError37.php', 'PHPStan\\Rules\\RuleErrors\\RuleError39' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError39.php', 'PHPStan\\Rules\\RuleErrors\\RuleError41' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError41.php', 'PHPStan\\Rules\\RuleErrors\\RuleError43' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError43.php', 'PHPStan\\Rules\\RuleErrors\\RuleError45' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError45.php', 'PHPStan\\Rules\\RuleErrors\\RuleError47' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError47.php', 'PHPStan\\Rules\\RuleErrors\\RuleError49' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError49.php', 'PHPStan\\Rules\\RuleErrors\\RuleError5' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError5.php', 'PHPStan\\Rules\\RuleErrors\\RuleError51' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError51.php', 'PHPStan\\Rules\\RuleErrors\\RuleError53' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError53.php', 'PHPStan\\Rules\\RuleErrors\\RuleError55' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError55.php', 'PHPStan\\Rules\\RuleErrors\\RuleError57' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError57.php', 'PHPStan\\Rules\\RuleErrors\\RuleError59' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError59.php', 'PHPStan\\Rules\\RuleErrors\\RuleError61' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError61.php', 'PHPStan\\Rules\\RuleErrors\\RuleError63' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError63.php', 'PHPStan\\Rules\\RuleErrors\\RuleError65' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError65.php', 'PHPStan\\Rules\\RuleErrors\\RuleError67' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError67.php', 'PHPStan\\Rules\\RuleErrors\\RuleError69' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError69.php', 'PHPStan\\Rules\\RuleErrors\\RuleError7' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError7.php', 'PHPStan\\Rules\\RuleErrors\\RuleError71' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError71.php', 'PHPStan\\Rules\\RuleErrors\\RuleError73' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError73.php', 'PHPStan\\Rules\\RuleErrors\\RuleError75' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError75.php', 'PHPStan\\Rules\\RuleErrors\\RuleError77' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError77.php', 'PHPStan\\Rules\\RuleErrors\\RuleError79' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError79.php', 'PHPStan\\Rules\\RuleErrors\\RuleError81' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError81.php', 'PHPStan\\Rules\\RuleErrors\\RuleError83' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError83.php', 'PHPStan\\Rules\\RuleErrors\\RuleError85' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError85.php', 'PHPStan\\Rules\\RuleErrors\\RuleError87' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError87.php', 'PHPStan\\Rules\\RuleErrors\\RuleError89' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError89.php', 'PHPStan\\Rules\\RuleErrors\\RuleError9' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError9.php', 'PHPStan\\Rules\\RuleErrors\\RuleError91' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError91.php', 'PHPStan\\Rules\\RuleErrors\\RuleError93' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError93.php', 'PHPStan\\Rules\\RuleErrors\\RuleError95' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError95.php', 'PHPStan\\Rules\\RuleErrors\\RuleError97' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError97.php', 'PHPStan\\Rules\\RuleErrors\\RuleError99' => __DIR__ . '/../..' . '/src/Rules/RuleErrors/RuleError99.php', 'PHPStan\\Rules\\RuleLevelHelper' => __DIR__ . '/../..' . '/src/Rules/RuleLevelHelper.php', 'PHPStan\\Rules\\RuleLevelHelperAcceptsResult' => __DIR__ . '/../..' . '/src/Rules/RuleLevelHelperAcceptsResult.php', 'PHPStan\\Rules\\TipRuleError' => __DIR__ . '/../..' . '/src/Rules/TipRuleError.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWideArrowFunctionReturnTypehintRule' => __DIR__ . '/../..' . '/src/Rules/TooWideTypehints/TooWideArrowFunctionReturnTypehintRule.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWideClosureReturnTypehintRule' => __DIR__ . '/../..' . '/src/Rules/TooWideTypehints/TooWideClosureReturnTypehintRule.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWideFunctionParameterOutTypeRule' => __DIR__ . '/../..' . '/src/Rules/TooWideTypehints/TooWideFunctionParameterOutTypeRule.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWideFunctionReturnTypehintRule' => __DIR__ . '/../..' . '/src/Rules/TooWideTypehints/TooWideFunctionReturnTypehintRule.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWideMethodParameterOutTypeRule' => __DIR__ . '/../..' . '/src/Rules/TooWideTypehints/TooWideMethodParameterOutTypeRule.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWideMethodReturnTypehintRule' => __DIR__ . '/../..' . '/src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWideParameterOutTypeCheck' => __DIR__ . '/../..' . '/src/Rules/TooWideTypehints/TooWideParameterOutTypeCheck.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWidePropertyTypeRule' => __DIR__ . '/../..' . '/src/Rules/TooWideTypehints/TooWidePropertyTypeRule.php', 'PHPStan\\Rules\\TooWideTypehints\\TooWideTypeCheck' => __DIR__ . '/../..' . '/src/Rules/TooWideTypehints/TooWideTypeCheck.php', 'PHPStan\\Rules\\Traits\\ConflictingTraitConstantsRule' => __DIR__ . '/../..' . '/src/Rules/Traits/ConflictingTraitConstantsRule.php', 'PHPStan\\Rules\\Traits\\ConstantsInTraitsRule' => __DIR__ . '/../..' . '/src/Rules/Traits/ConstantsInTraitsRule.php', 'PHPStan\\Rules\\Traits\\NotAnalysedTraitRule' => __DIR__ . '/../..' . '/src/Rules/Traits/NotAnalysedTraitRule.php', 'PHPStan\\Rules\\Traits\\TraitAttributesRule' => __DIR__ . '/../..' . '/src/Rules/Traits/TraitAttributesRule.php', 'PHPStan\\Rules\\Traits\\TraitDeclarationCollector' => __DIR__ . '/../..' . '/src/Rules/Traits/TraitDeclarationCollector.php', 'PHPStan\\Rules\\Traits\\TraitUseCollector' => __DIR__ . '/../..' . '/src/Rules/Traits/TraitUseCollector.php', 'PHPStan\\Rules\\Types\\InvalidTypesInUnionRule' => __DIR__ . '/../..' . '/src/Rules/Types/InvalidTypesInUnionRule.php', 'PHPStan\\Rules\\UnusedFunctionParametersCheck' => __DIR__ . '/../..' . '/src/Rules/UnusedFunctionParametersCheck.php', 'PHPStan\\Rules\\Variables\\AssignToByRefExprFromForeachRule' => __DIR__ . '/../..' . '/src/Rules/Variables/AssignToByRefExprFromForeachRule.php', 'PHPStan\\Rules\\Variables\\CompactVariablesRule' => __DIR__ . '/../..' . '/src/Rules/Variables/CompactVariablesRule.php', 'PHPStan\\Rules\\Variables\\DefinedVariableRule' => __DIR__ . '/../..' . '/src/Rules/Variables/DefinedVariableRule.php', 'PHPStan\\Rules\\Variables\\EmptyRule' => __DIR__ . '/../..' . '/src/Rules/Variables/EmptyRule.php', 'PHPStan\\Rules\\Variables\\InvalidVariableAssignRule' => __DIR__ . '/../..' . '/src/Rules/Variables/InvalidVariableAssignRule.php', 'PHPStan\\Rules\\Variables\\IssetRule' => __DIR__ . '/../..' . '/src/Rules/Variables/IssetRule.php', 'PHPStan\\Rules\\Variables\\NullCoalesceRule' => __DIR__ . '/../..' . '/src/Rules/Variables/NullCoalesceRule.php', 'PHPStan\\Rules\\Variables\\ParameterOutAssignedTypeRule' => __DIR__ . '/../..' . '/src/Rules/Variables/ParameterOutAssignedTypeRule.php', 'PHPStan\\Rules\\Variables\\ParameterOutExecutionEndTypeRule' => __DIR__ . '/../..' . '/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php', 'PHPStan\\Rules\\Variables\\ThisInGlobalStatementRule' => __DIR__ . '/../..' . '/src/Rules/Variables/ThisInGlobalStatementRule.php', 'PHPStan\\Rules\\Variables\\ThisInStaticStatementRule' => __DIR__ . '/../..' . '/src/Rules/Variables/ThisInStaticStatementRule.php', 'PHPStan\\Rules\\Variables\\UnsetRule' => __DIR__ . '/../..' . '/src/Rules/Variables/UnsetRule.php', 'PHPStan\\Rules\\Variables\\VariableCloningRule' => __DIR__ . '/../..' . '/src/Rules/Variables/VariableCloningRule.php', 'PHPStan\\Rules\\Whitespace\\FileWhitespaceRule' => __DIR__ . '/../..' . '/src/Rules/Whitespace/FileWhitespaceRule.php', 'PHPStan\\ShouldNotHappenException' => __DIR__ . '/../..' . '/src/ShouldNotHappenException.php', 'PHPStan\\Testing\\CompositeRule' => __DIR__ . '/../..' . '/src/Testing/CompositeRule.php', 'PHPStan\\Testing\\DelayedRule' => __DIR__ . '/../..' . '/src/Testing/DelayedRule.php', 'PHPStan\\Testing\\ErrorFormatterTestCase' => __DIR__ . '/../..' . '/src/Testing/ErrorFormatterTestCase.php', 'PHPStan\\Testing\\LevelsTestCase' => __DIR__ . '/../..' . '/src/Testing/LevelsTestCase.php', 'PHPStan\\Testing\\NonexistentAnalysedClassRule' => __DIR__ . '/../..' . '/src/Testing/NonexistentAnalysedClassRule.php', 'PHPStan\\Testing\\NonexistentAnalysedTraitRule' => __DIR__ . '/../..' . '/src/Testing/NonexistentAnalysedTraitRule.php', 'PHPStan\\Testing\\PHPStanTestCase' => __DIR__ . '/../..' . '/src/Testing/PHPStanTestCase.php', 'PHPStan\\Testing\\PHPStanTestCaseTrait' => __DIR__ . '/../..' . '/src/Testing/PHPStanTestCaseTrait.php', 'PHPStan\\Testing\\PHPUnit\\ContainerInitializer' => __DIR__ . '/../..' . '/src/Testing/PHPUnit/ContainerInitializer.php', 'PHPStan\\Testing\\PHPUnit\\InitContainerBeforeDataProviderSubscriber' => __DIR__ . '/../..' . '/src/Testing/PHPUnit/InitContainerBeforeDataProviderSubscriber.php', 'PHPStan\\Testing\\PHPUnit\\InitContainerBeforeTestSubscriber' => __DIR__ . '/../..' . '/src/Testing/PHPUnit/InitContainerBeforeTestSubscriber.php', 'PHPStan\\Testing\\PHPUnit\\PHPStanPHPUnitExtension' => __DIR__ . '/../..' . '/src/Testing/PHPUnit/PHPStanPHPUnitExtension.php', 'PHPStan\\Testing\\RuleTestCase' => __DIR__ . '/../..' . '/src/Testing/RuleTestCase.php', 'PHPStan\\Testing\\TestCaseSourceLocatorFactory' => __DIR__ . '/../..' . '/src/Testing/TestCaseSourceLocatorFactory.php', 'PHPStan\\Testing\\TypeInferenceTestCase' => __DIR__ . '/../..' . '/src/Testing/TypeInferenceTestCase.php', 'PHPStan\\TrinaryLogic' => __DIR__ . '/../..' . '/src/TrinaryLogic.php', 'PHPStan\\Turbo\\TurboExtensionEnabler' => __DIR__ . '/../..' . '/src/Turbo/TurboExtensionEnabler.php', 'PHPStan\\Type\\AcceptsResult' => __DIR__ . '/../..' . '/src/Type/AcceptsResult.php', 'PHPStan\\Type\\Accessory\\AccessoryArrayListType' => __DIR__ . '/../..' . '/src/Type/Accessory/AccessoryArrayListType.php', 'PHPStan\\Type\\Accessory\\AccessoryLiteralStringType' => __DIR__ . '/../..' . '/src/Type/Accessory/AccessoryLiteralStringType.php', 'PHPStan\\Type\\Accessory\\AccessoryLowercaseStringType' => __DIR__ . '/../..' . '/src/Type/Accessory/AccessoryLowercaseStringType.php', 'PHPStan\\Type\\Accessory\\AccessoryNonEmptyStringType' => __DIR__ . '/../..' . '/src/Type/Accessory/AccessoryNonEmptyStringType.php', 'PHPStan\\Type\\Accessory\\AccessoryNonFalsyStringType' => __DIR__ . '/../..' . '/src/Type/Accessory/AccessoryNonFalsyStringType.php', 'PHPStan\\Type\\Accessory\\AccessoryNumericStringType' => __DIR__ . '/../..' . '/src/Type/Accessory/AccessoryNumericStringType.php', 'PHPStan\\Type\\Accessory\\AccessoryType' => __DIR__ . '/../..' . '/src/Type/Accessory/AccessoryType.php', 'PHPStan\\Type\\Accessory\\AccessoryUppercaseStringType' => __DIR__ . '/../..' . '/src/Type/Accessory/AccessoryUppercaseStringType.php', 'PHPStan\\Type\\Accessory\\HasMethodType' => __DIR__ . '/../..' . '/src/Type/Accessory/HasMethodType.php', 'PHPStan\\Type\\Accessory\\HasOffsetType' => __DIR__ . '/../..' . '/src/Type/Accessory/HasOffsetType.php', 'PHPStan\\Type\\Accessory\\HasOffsetValueType' => __DIR__ . '/../..' . '/src/Type/Accessory/HasOffsetValueType.php', 'PHPStan\\Type\\Accessory\\HasPropertyType' => __DIR__ . '/../..' . '/src/Type/Accessory/HasPropertyType.php', 'PHPStan\\Type\\Accessory\\NonEmptyArrayType' => __DIR__ . '/../..' . '/src/Type/Accessory/NonEmptyArrayType.php', 'PHPStan\\Type\\Accessory\\OversizedArrayType' => __DIR__ . '/../..' . '/src/Type/Accessory/OversizedArrayType.php', 'PHPStan\\Type\\ArrayType' => __DIR__ . '/../..' . '/src/Type/ArrayType.php', 'PHPStan\\Type\\BenevolentUnionType' => __DIR__ . '/../..' . '/src/Type/BenevolentUnionType.php', 'PHPStan\\Type\\BitwiseFlagHelper' => __DIR__ . '/../..' . '/src/Type/BitwiseFlagHelper.php', 'PHPStan\\Type\\BooleanType' => __DIR__ . '/../..' . '/src/Type/BooleanType.php', 'PHPStan\\Type\\CallableType' => __DIR__ . '/../..' . '/src/Type/CallableType.php', 'PHPStan\\Type\\CallableTypeHelper' => __DIR__ . '/../..' . '/src/Type/CallableTypeHelper.php', 'PHPStan\\Type\\CircularTypeAliasDefinitionException' => __DIR__ . '/../..' . '/src/Type/CircularTypeAliasDefinitionException.php', 'PHPStan\\Type\\CircularTypeAliasErrorType' => __DIR__ . '/../..' . '/src/Type/CircularTypeAliasErrorType.php', 'PHPStan\\Type\\ClassConstantAccessType' => __DIR__ . '/../..' . '/src/Type/ClassConstantAccessType.php', 'PHPStan\\Type\\ClassNameToObjectTypeResult' => __DIR__ . '/../..' . '/src/Type/ClassNameToObjectTypeResult.php', 'PHPStan\\Type\\ClassStringType' => __DIR__ . '/../..' . '/src/Type/ClassStringType.php', 'PHPStan\\Type\\ClosureType' => __DIR__ . '/../..' . '/src/Type/ClosureType.php', 'PHPStan\\Type\\ClosureTypeFactory' => __DIR__ . '/../..' . '/src/Type/ClosureTypeFactory.php', 'PHPStan\\Type\\CompoundType' => __DIR__ . '/../..' . '/src/Type/CompoundType.php', 'PHPStan\\Type\\ConditionalType' => __DIR__ . '/../..' . '/src/Type/ConditionalType.php', 'PHPStan\\Type\\ConditionalTypeForParameter' => __DIR__ . '/../..' . '/src/Type/ConditionalTypeForParameter.php', 'PHPStan\\Type\\ConstantScalarType' => __DIR__ . '/../..' . '/src/Type/ConstantScalarType.php', 'PHPStan\\Type\\ConstantTypeHelper' => __DIR__ . '/../..' . '/src/Type/ConstantTypeHelper.php', 'PHPStan\\Type\\Constant\\ConstantArrayType' => __DIR__ . '/../..' . '/src/Type/Constant/ConstantArrayType.php', 'PHPStan\\Type\\Constant\\ConstantArrayTypeAndMethod' => __DIR__ . '/../..' . '/src/Type/Constant/ConstantArrayTypeAndMethod.php', 'PHPStan\\Type\\Constant\\ConstantArrayTypeBuilder' => __DIR__ . '/../..' . '/src/Type/Constant/ConstantArrayTypeBuilder.php', 'PHPStan\\Type\\Constant\\ConstantBooleanType' => __DIR__ . '/../..' . '/src/Type/Constant/ConstantBooleanType.php', 'PHPStan\\Type\\Constant\\ConstantFloatType' => __DIR__ . '/../..' . '/src/Type/Constant/ConstantFloatType.php', 'PHPStan\\Type\\Constant\\ConstantIntegerType' => __DIR__ . '/../..' . '/src/Type/Constant/ConstantIntegerType.php', 'PHPStan\\Type\\Constant\\ConstantScalarToBooleanTrait' => __DIR__ . '/../..' . '/src/Type/Constant/ConstantScalarToBooleanTrait.php', 'PHPStan\\Type\\Constant\\ConstantStringType' => __DIR__ . '/../..' . '/src/Type/Constant/ConstantStringType.php', 'PHPStan\\Type\\Constant\\OversizedArrayBuilder' => __DIR__ . '/../..' . '/src/Type/Constant/OversizedArrayBuilder.php', 'PHPStan\\Type\\DirectTypeAliasResolverProvider' => __DIR__ . '/../..' . '/src/Type/DirectTypeAliasResolverProvider.php', 'PHPStan\\Type\\DynamicFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/DynamicFunctionReturnTypeExtension.php', 'PHPStan\\Type\\DynamicFunctionThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/DynamicFunctionThrowTypeExtension.php', 'PHPStan\\Type\\DynamicMethodReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/DynamicMethodReturnTypeExtension.php', 'PHPStan\\Type\\DynamicMethodThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/DynamicMethodThrowTypeExtension.php', 'PHPStan\\Type\\DynamicReturnTypeExtensionRegistry' => __DIR__ . '/../..' . '/src/Type/DynamicReturnTypeExtensionRegistry.php', 'PHPStan\\Type\\DynamicStaticMethodReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/DynamicStaticMethodReturnTypeExtension.php', 'PHPStan\\Type\\DynamicStaticMethodThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/DynamicStaticMethodThrowTypeExtension.php', 'PHPStan\\Type\\Enum\\EnumCaseObjectType' => __DIR__ . '/../..' . '/src/Type/Enum/EnumCaseObjectType.php', 'PHPStan\\Type\\ErrorType' => __DIR__ . '/../..' . '/src/Type/ErrorType.php', 'PHPStan\\Type\\ExponentiateHelper' => __DIR__ . '/../..' . '/src/Type/ExponentiateHelper.php', 'PHPStan\\Type\\ExpressionTypeResolverExtension' => __DIR__ . '/../..' . '/src/Type/ExpressionTypeResolverExtension.php', 'PHPStan\\Type\\ExpressionTypeResolverExtensionRegistry' => __DIR__ . '/../..' . '/src/Type/ExpressionTypeResolverExtensionRegistry.php', 'PHPStan\\Type\\FileTypeMapper' => __DIR__ . '/../..' . '/src/Type/FileTypeMapper.php', 'PHPStan\\Type\\FloatType' => __DIR__ . '/../..' . '/src/Type/FloatType.php', 'PHPStan\\Type\\FunctionParameterClosureThisExtension' => __DIR__ . '/../..' . '/src/Type/FunctionParameterClosureThisExtension.php', 'PHPStan\\Type\\FunctionParameterClosureTypeExtension' => __DIR__ . '/../..' . '/src/Type/FunctionParameterClosureTypeExtension.php', 'PHPStan\\Type\\FunctionParameterOutTypeExtension' => __DIR__ . '/../..' . '/src/Type/FunctionParameterOutTypeExtension.php', 'PHPStan\\Type\\FunctionTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/FunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\GeneralizePrecision' => __DIR__ . '/../..' . '/src/Type/GeneralizePrecision.php', 'PHPStan\\Type\\Generic\\GenericClassStringType' => __DIR__ . '/../..' . '/src/Type/Generic/GenericClassStringType.php', 'PHPStan\\Type\\Generic\\GenericObjectType' => __DIR__ . '/../..' . '/src/Type/Generic/GenericObjectType.php', 'PHPStan\\Type\\Generic\\GenericStaticType' => __DIR__ . '/../..' . '/src/Type/Generic/GenericStaticType.php', 'PHPStan\\Type\\Generic\\TemplateArrayType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateArrayType.php', 'PHPStan\\Type\\Generic\\TemplateBenevolentUnionType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateBenevolentUnionType.php', 'PHPStan\\Type\\Generic\\TemplateBooleanType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateBooleanType.php', 'PHPStan\\Type\\Generic\\TemplateConstantArrayType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateConstantArrayType.php', 'PHPStan\\Type\\Generic\\TemplateConstantIntegerType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateConstantIntegerType.php', 'PHPStan\\Type\\Generic\\TemplateConstantStringType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateConstantStringType.php', 'PHPStan\\Type\\Generic\\TemplateFloatType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateFloatType.php', 'PHPStan\\Type\\Generic\\TemplateGenericObjectType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateGenericObjectType.php', 'PHPStan\\Type\\Generic\\TemplateIntegerType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateIntegerType.php', 'PHPStan\\Type\\Generic\\TemplateIntersectionType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateIntersectionType.php', 'PHPStan\\Type\\Generic\\TemplateIterableType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateIterableType.php', 'PHPStan\\Type\\Generic\\TemplateKeyOfType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateKeyOfType.php', 'PHPStan\\Type\\Generic\\TemplateMixedType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateMixedType.php', 'PHPStan\\Type\\Generic\\TemplateNullType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateNullType.php', 'PHPStan\\Type\\Generic\\TemplateObjectShapeType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateObjectShapeType.php', 'PHPStan\\Type\\Generic\\TemplateObjectType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateObjectType.php', 'PHPStan\\Type\\Generic\\TemplateObjectWithoutClassType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateObjectWithoutClassType.php', 'PHPStan\\Type\\Generic\\TemplateStrictMixedType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateStrictMixedType.php', 'PHPStan\\Type\\Generic\\TemplateStringType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateStringType.php', 'PHPStan\\Type\\Generic\\TemplateType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateType.php', 'PHPStan\\Type\\Generic\\TemplateTypeArgumentStrategy' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateTypeArgumentStrategy.php', 'PHPStan\\Type\\Generic\\TemplateTypeFactory' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateTypeFactory.php', 'PHPStan\\Type\\Generic\\TemplateTypeHelper' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateTypeHelper.php', 'PHPStan\\Type\\Generic\\TemplateTypeMap' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateTypeMap.php', 'PHPStan\\Type\\Generic\\TemplateTypeParameterStrategy' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateTypeParameterStrategy.php', 'PHPStan\\Type\\Generic\\TemplateTypeReference' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateTypeReference.php', 'PHPStan\\Type\\Generic\\TemplateTypeScope' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateTypeScope.php', 'PHPStan\\Type\\Generic\\TemplateTypeStrategy' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateTypeStrategy.php', 'PHPStan\\Type\\Generic\\TemplateTypeTrait' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateTypeTrait.php', 'PHPStan\\Type\\Generic\\TemplateTypeVariance' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateTypeVariance.php', 'PHPStan\\Type\\Generic\\TemplateTypeVarianceMap' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateTypeVarianceMap.php', 'PHPStan\\Type\\Generic\\TemplateUnionType' => __DIR__ . '/../..' . '/src/Type/Generic/TemplateUnionType.php', 'PHPStan\\Type\\Generic\\TypeProjectionHelper' => __DIR__ . '/../..' . '/src/Type/Generic/TypeProjectionHelper.php', 'PHPStan\\Type\\Helper\\GetTemplateTypeType' => __DIR__ . '/../..' . '/src/Type/Helper/GetTemplateTypeType.php', 'PHPStan\\Type\\IntegerRangeType' => __DIR__ . '/../..' . '/src/Type/IntegerRangeType.php', 'PHPStan\\Type\\IntegerType' => __DIR__ . '/../..' . '/src/Type/IntegerType.php', 'PHPStan\\Type\\IntersectionType' => __DIR__ . '/../..' . '/src/Type/IntersectionType.php', 'PHPStan\\Type\\IsSuperTypeOfResult' => __DIR__ . '/../..' . '/src/Type/IsSuperTypeOfResult.php', 'PHPStan\\Type\\IterableType' => __DIR__ . '/../..' . '/src/Type/IterableType.php', 'PHPStan\\Type\\JustNullableTypeTrait' => __DIR__ . '/../..' . '/src/Type/JustNullableTypeTrait.php', 'PHPStan\\Type\\KeyOfType' => __DIR__ . '/../..' . '/src/Type/KeyOfType.php', 'PHPStan\\Type\\LateResolvableType' => __DIR__ . '/../..' . '/src/Type/LateResolvableType.php', 'PHPStan\\Type\\LazyTypeAliasResolverProvider' => __DIR__ . '/../..' . '/src/Type/LazyTypeAliasResolverProvider.php', 'PHPStan\\Type\\LooseComparisonHelper' => __DIR__ . '/../..' . '/src/Type/LooseComparisonHelper.php', 'PHPStan\\Type\\MethodParameterClosureThisExtension' => __DIR__ . '/../..' . '/src/Type/MethodParameterClosureThisExtension.php', 'PHPStan\\Type\\MethodParameterClosureTypeExtension' => __DIR__ . '/../..' . '/src/Type/MethodParameterClosureTypeExtension.php', 'PHPStan\\Type\\MethodParameterOutTypeExtension' => __DIR__ . '/../..' . '/src/Type/MethodParameterOutTypeExtension.php', 'PHPStan\\Type\\MethodTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/MethodTypeSpecifyingExtension.php', 'PHPStan\\Type\\MixedType' => __DIR__ . '/../..' . '/src/Type/MixedType.php', 'PHPStan\\Type\\NeverType' => __DIR__ . '/../..' . '/src/Type/NeverType.php', 'PHPStan\\Type\\NewObjectType' => __DIR__ . '/../..' . '/src/Type/NewObjectType.php', 'PHPStan\\Type\\NonAcceptingNeverType' => __DIR__ . '/../..' . '/src/Type/NonAcceptingNeverType.php', 'PHPStan\\Type\\NonexistentParentClassType' => __DIR__ . '/../..' . '/src/Type/NonexistentParentClassType.php', 'PHPStan\\Type\\NullType' => __DIR__ . '/../..' . '/src/Type/NullType.php', 'PHPStan\\Type\\ObjectShapePropertyReflection' => __DIR__ . '/../..' . '/src/Type/ObjectShapePropertyReflection.php', 'PHPStan\\Type\\ObjectShapeType' => __DIR__ . '/../..' . '/src/Type/ObjectShapeType.php', 'PHPStan\\Type\\ObjectType' => __DIR__ . '/../..' . '/src/Type/ObjectType.php', 'PHPStan\\Type\\ObjectWithoutClassType' => __DIR__ . '/../..' . '/src/Type/ObjectWithoutClassType.php', 'PHPStan\\Type\\OffsetAccessType' => __DIR__ . '/../..' . '/src/Type/OffsetAccessType.php', 'PHPStan\\Type\\OperatorTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/OperatorTypeSpecifyingExtension.php', 'PHPStan\\Type\\OperatorTypeSpecifyingExtensionRegistry' => __DIR__ . '/../..' . '/src/Type/OperatorTypeSpecifyingExtensionRegistry.php', 'PHPStan\\Type\\PHPStan\\ClassNameUsageLocationCreateIdentifierDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/PHPStan/ClassNameUsageLocationCreateIdentifierDynamicReturnTypeExtension.php', 'PHPStan\\Type\\ParserNodeTypeToPHPStanType' => __DIR__ . '/../..' . '/src/Type/ParserNodeTypeToPHPStanType.php', 'PHPStan\\Type\\Php\\AbsFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/AbsFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArgumentBasedFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArgumentBasedFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayChangeKeyCaseFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayChangeKeyCaseFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayChunkFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayChunkFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayColumnFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayColumnFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayColumnHelper' => __DIR__ . '/../..' . '/src/Type/Php/ArrayColumnHelper.php', 'PHPStan\\Type\\Php\\ArrayCombineFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayCombineFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayCombineFunctionThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayCombineFunctionThrowTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayCombineHelper' => __DIR__ . '/../..' . '/src/Type/Php/ArrayCombineHelper.php', 'PHPStan\\Type\\Php\\ArrayCountValuesDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayCountValuesDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayCurrentDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayCurrentDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayFillFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayFillFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayFillKeysFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayFillKeysFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayFilterFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayFilterFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayFilterFunctionReturnTypeHelper' => __DIR__ . '/../..' . '/src/Type/Php/ArrayFilterFunctionReturnTypeHelper.php', 'PHPStan\\Type\\Php\\ArrayFindFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayFindFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayFindKeyFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayFindKeyFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayFirstLastDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayFirstLastDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayFlipFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayFlipFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayIntersectKeyFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayIntersectKeyFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayKeyDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayKeyDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayKeyExistsFunctionTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\ArrayKeysFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayKeysFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayMapFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayMapFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayMergeFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayNextDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayNextDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayPadDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayPadDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayPointerFunctionsDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayPointerFunctionsDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayPopFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayPopFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayRandFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayRandFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayReduceFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayReduceFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayReplaceFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayReplaceFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayReverseFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayReverseFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArraySearchFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArraySearchFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArraySearchFunctionTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArraySearchFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\ArrayShiftFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayShiftFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArraySliceFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArraySliceFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArraySpliceFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArraySpliceFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArraySumFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArraySumFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ArrayValuesFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayValuesFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\AssertFunctionTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/AssertFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\AssertThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/AssertThrowTypeExtension.php', 'PHPStan\\Type\\Php\\BackedEnumFromMethodDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/BackedEnumFromMethodDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\Base64DecodeDynamicFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/Base64DecodeDynamicFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\BcMathNumberOperatorTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/BcMathNumberOperatorTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\BcMathStringOrNullReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/BcMathStringOrNullReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ClassExistsFunctionTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/ClassExistsFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\ClassImplementsFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ClassImplementsFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ClosureBindDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ClosureBindDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ClosureBindToDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ClosureBindToDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ClosureFromCallableDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ClosureFromCallableDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ClosureGetCurrentDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ClosureGetCurrentDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\CompactFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/CompactFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ConstantFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ConstantFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ConstantHelper' => __DIR__ . '/../..' . '/src/Type/Php/ConstantHelper.php', 'PHPStan\\Type\\Php\\CountCharsFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/CountCharsFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\CountFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/CountFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\CountFunctionTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/CountFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\CtypeDigitFunctionTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/CtypeDigitFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\CurlGetinfoFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/CurlGetinfoFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateFormatFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DateFormatFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateFormatMethodReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DateFormatMethodReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DateFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateFunctionReturnTypeHelper' => __DIR__ . '/../..' . '/src/Type/Php/DateFunctionReturnTypeHelper.php', 'PHPStan\\Type\\Php\\DateIntervalConstructorThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DateIntervalConstructorThrowTypeExtension.php', 'PHPStan\\Type\\Php\\DateIntervalCreateFromDateStringThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DateIntervalCreateFromDateStringThrowTypeExtension.php', 'PHPStan\\Type\\Php\\DateIntervalDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DateIntervalDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateIntervalFormatDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DateIntervalFormatDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateIntervalFormatFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DateIntervalFormatFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateIntervalFormatReturnTypeHelper' => __DIR__ . '/../..' . '/src/Type/Php/DateIntervalFormatReturnTypeHelper.php', 'PHPStan\\Type\\Php\\DatePeriodConstructorReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DatePeriodConstructorReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateTimeConstructorThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DateTimeConstructorThrowTypeExtension.php', 'PHPStan\\Type\\Php\\DateTimeCreateDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DateTimeCreateDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateTimeDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DateTimeDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateTimeModifyMethodThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DateTimeModifyMethodThrowTypeExtension.php', 'PHPStan\\Type\\Php\\DateTimeModifyReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DateTimeModifyReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DateTimeSubMethodThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DateTimeSubMethodThrowTypeExtension.php', 'PHPStan\\Type\\Php\\DateTimeZoneConstructorThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DateTimeZoneConstructorThrowTypeExtension.php', 'PHPStan\\Type\\Php\\DefineConstantTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/DefineConstantTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\DefinedConstantTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/DefinedConstantTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\DioStatDynamicFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DioStatDynamicFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DomDocumentCreateElementDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DomDocumentCreateElementDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\DomDocumentCreateElementDynamicThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DomDocumentCreateElementDynamicThrowTypeExtension.php', 'PHPStan\\Type\\Php\\DsMapDynamicMethodThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DsMapDynamicMethodThrowTypeExtension.php', 'PHPStan\\Type\\Php\\DsMapDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/DsMapDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ExplodeFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ExplodeFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\FilterFunctionReturnTypeHelper' => __DIR__ . '/../..' . '/src/Type/Php/FilterFunctionReturnTypeHelper.php', 'PHPStan\\Type\\Php\\FilterInputDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/FilterInputDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\FilterVarArrayDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/FilterVarArrayDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\FilterVarDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/FilterVarDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\FilterVarThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/FilterVarThrowTypeExtension.php', 'PHPStan\\Type\\Php\\FunctionExistsFunctionTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/FunctionExistsFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\GetCalledClassDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/GetCalledClassDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\GetClassDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/GetClassDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\GetDebugTypeFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/GetDebugTypeFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\GetDefinedVarsFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/GetDefinedVarsFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\GetParentClassDynamicFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/GetParentClassDynamicFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\GettimeofdayDynamicFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/GettimeofdayDynamicFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\GettypeFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/GettypeFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\GmpOperatorTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/GmpOperatorTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\GmpUnaryOperatorTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/GmpUnaryOperatorTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\HashFunctionsReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/HashFunctionsReturnTypeExtension.php', 'PHPStan\\Type\\Php\\HighlightStringDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/HighlightStringDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\HrtimeFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/HrtimeFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\IdateFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/IdateFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\IdateFunctionReturnTypeHelper' => __DIR__ . '/../..' . '/src/Type/Php/IdateFunctionReturnTypeHelper.php', 'PHPStan\\Type\\Php\\ImplodeFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ImplodeFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\InArrayFunctionTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\IniGetReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/IniGetReturnTypeExtension.php', 'PHPStan\\Type\\Php\\IntdivThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/IntdivThrowTypeExtension.php', 'PHPStan\\Type\\Php\\IsAFunctionTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/IsAFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\IsAFunctionTypeSpecifyingHelper' => __DIR__ . '/../..' . '/src/Type/Php/IsAFunctionTypeSpecifyingHelper.php', 'PHPStan\\Type\\Php\\IsArrayFunctionTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/IsArrayFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\IsCallableFunctionTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/IsCallableFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\IsIterableFunctionTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/IsIterableFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\IsSubclassOfFunctionTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\IteratorToArrayFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/IteratorToArrayFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\JsonThrowOnErrorDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/JsonThrowOnErrorDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\JsonThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/JsonThrowTypeExtension.php', 'PHPStan\\Type\\Php\\LtrimFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/LtrimFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\MbConvertEncodingFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/MbConvertEncodingFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\MbFunctionsReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/MbFunctionsReturnTypeExtension.php', 'PHPStan\\Type\\Php\\MbFunctionsReturnTypeExtensionTrait' => __DIR__ . '/../..' . '/src/Type/Php/MbFunctionsReturnTypeExtensionTrait.php', 'PHPStan\\Type\\Php\\MbStrlenFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/MbStrlenFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\MbSubstituteCharacterDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/MbSubstituteCharacterDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\MethodExistsTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/MethodExistsTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\MicrotimeFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/MicrotimeFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\MinMaxFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/MinMaxFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\NonEmptyStringFunctionsReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/NonEmptyStringFunctionsReturnTypeExtension.php', 'PHPStan\\Type\\Php\\NumberFormatFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/NumberFormatFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\OpenSslCipherMethodsProvider' => __DIR__ . '/../..' . '/src/Type/Php/OpenSslCipherMethodsProvider.php', 'PHPStan\\Type\\Php\\OpenSslEncryptParameterOutTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/OpenSslEncryptParameterOutTypeExtension.php', 'PHPStan\\Type\\Php\\OpensslCipherFunctionsReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/OpensslCipherFunctionsReturnTypeExtension.php', 'PHPStan\\Type\\Php\\PDOConnectReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/PDOConnectReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ParseStrParameterOutTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ParseStrParameterOutTypeExtension.php', 'PHPStan\\Type\\Php\\ParseUrlFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ParseUrlFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\PathinfoFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/PathinfoFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\PdoStatementFetchAllReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/PdoStatementFetchAllReturnTypeExtension.php', 'PHPStan\\Type\\Php\\PowFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/PowFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\PregFilterFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/PregFilterFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\PregMatchParameterOutTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/PregMatchParameterOutTypeExtension.php', 'PHPStan\\Type\\Php\\PregMatchTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/PregMatchTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\PregReplaceCallbackClosureTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/PregReplaceCallbackClosureTypeExtension.php', 'PHPStan\\Type\\Php\\PregSplitDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/PregSplitDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\PropertyExistsTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/PropertyExistsTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\RandomIntFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/RandomIntFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\RangeFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/RangeFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ReflectionClassConstructorThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ReflectionClassConstructorThrowTypeExtension.php', 'PHPStan\\Type\\Php\\ReflectionClassIsSubclassOfTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/ReflectionClassIsSubclassOfTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\ReflectionFunctionConstructorThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ReflectionFunctionConstructorThrowTypeExtension.php', 'PHPStan\\Type\\Php\\ReflectionGetAttributesMethodReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ReflectionGetAttributesMethodReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ReflectionMethodConstructorThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php', 'PHPStan\\Type\\Php\\ReflectionPropertyConstructorThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ReflectionPropertyConstructorThrowTypeExtension.php', 'PHPStan\\Type\\Php\\RegexArrayShapeMatcher' => __DIR__ . '/../..' . '/src/Type/Php/RegexArrayShapeMatcher.php', 'PHPStan\\Type\\Php\\ReplaceFunctionsDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ReplaceFunctionsDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\RoundFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/RoundFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\SetTypeFunctionTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/SetTypeFunctionTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\SimpleXMLElementAsXMLMethodReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/SimpleXMLElementAsXMLMethodReturnTypeExtension.php', 'PHPStan\\Type\\Php\\SimpleXMLElementClassPropertyReflectionExtension' => __DIR__ . '/../..' . '/src/Type/Php/SimpleXMLElementClassPropertyReflectionExtension.php', 'PHPStan\\Type\\Php\\SimpleXMLElementConstructorThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/SimpleXMLElementConstructorThrowTypeExtension.php', 'PHPStan\\Type\\Php\\SimpleXMLElementXpathMethodReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/SimpleXMLElementXpathMethodReturnTypeExtension.php', 'PHPStan\\Type\\Php\\SprintfFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/SprintfFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\SscanfFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/SscanfFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StatDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/StatDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrCaseFunctionsReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/StrCaseFunctionsReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrContainingTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/Php/StrContainingTypeSpecifyingExtension.php', 'PHPStan\\Type\\Php\\StrIncrementDecrementFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/StrIncrementDecrementFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrPadFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/StrPadFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrRepeatFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/StrRepeatFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrSplitFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/StrSplitFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrTokFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/StrTokFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrWordCountFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/StrWordCountFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrlenFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/StrlenFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrrevFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/StrrevFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrtotimeFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/StrtotimeFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\StrvalFamilyFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/StrvalFamilyFunctionReturnTypeExtension.php', 'PHPStan\\Type\\Php\\SubstrDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/SubstrDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\ThrowableReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ThrowableReturnTypeExtension.php', 'PHPStan\\Type\\Php\\TriggerErrorDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/TriggerErrorDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\TrimFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/TrimFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\TypeSpecifyingFunctionsDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/TypeSpecifyingFunctionsDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\VersionCompareFunctionDynamicReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/VersionCompareFunctionDynamicReturnTypeExtension.php', 'PHPStan\\Type\\Php\\VersionCompareFunctionDynamicThrowTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/VersionCompareFunctionDynamicThrowTypeExtension.php', 'PHPStan\\Type\\Php\\XMLReaderOpenReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/XMLReaderOpenReturnTypeExtension.php', 'PHPStan\\Type\\RecursionGuard' => __DIR__ . '/../..' . '/src/Type/RecursionGuard.php', 'PHPStan\\Type\\Regex\\RegexAlternation' => __DIR__ . '/../..' . '/src/Type/Regex/RegexAlternation.php', 'PHPStan\\Type\\Regex\\RegexAstWalkResult' => __DIR__ . '/../..' . '/src/Type/Regex/RegexAstWalkResult.php', 'PHPStan\\Type\\Regex\\RegexCapturingGroup' => __DIR__ . '/../..' . '/src/Type/Regex/RegexCapturingGroup.php', 'PHPStan\\Type\\Regex\\RegexExpressionHelper' => __DIR__ . '/../..' . '/src/Type/Regex/RegexExpressionHelper.php', 'PHPStan\\Type\\Regex\\RegexGroupList' => __DIR__ . '/../..' . '/src/Type/Regex/RegexGroupList.php', 'PHPStan\\Type\\Regex\\RegexGroupParser' => __DIR__ . '/../..' . '/src/Type/Regex/RegexGroupParser.php', 'PHPStan\\Type\\Regex\\RegexGroupWalkResult' => __DIR__ . '/../..' . '/src/Type/Regex/RegexGroupWalkResult.php', 'PHPStan\\Type\\Regex\\RegexNonCapturingGroup' => __DIR__ . '/../..' . '/src/Type/Regex/RegexNonCapturingGroup.php', 'PHPStan\\Type\\ResourceType' => __DIR__ . '/../..' . '/src/Type/ResourceType.php', 'PHPStan\\Type\\SimultaneousTypeTraverser' => __DIR__ . '/../..' . '/src/Type/SimultaneousTypeTraverser.php', 'PHPStan\\Type\\StaticMethodParameterClosureThisExtension' => __DIR__ . '/../..' . '/src/Type/StaticMethodParameterClosureThisExtension.php', 'PHPStan\\Type\\StaticMethodParameterClosureTypeExtension' => __DIR__ . '/../..' . '/src/Type/StaticMethodParameterClosureTypeExtension.php', 'PHPStan\\Type\\StaticMethodParameterOutTypeExtension' => __DIR__ . '/../..' . '/src/Type/StaticMethodParameterOutTypeExtension.php', 'PHPStan\\Type\\StaticMethodTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/StaticMethodTypeSpecifyingExtension.php', 'PHPStan\\Type\\StaticType' => __DIR__ . '/../..' . '/src/Type/StaticType.php', 'PHPStan\\Type\\StaticTypeFactory' => __DIR__ . '/../..' . '/src/Type/StaticTypeFactory.php', 'PHPStan\\Type\\StrictMixedType' => __DIR__ . '/../..' . '/src/Type/StrictMixedType.php', 'PHPStan\\Type\\StringAlwaysAcceptingObjectWithToStringType' => __DIR__ . '/../..' . '/src/Type/StringAlwaysAcceptingObjectWithToStringType.php', 'PHPStan\\Type\\StringNeverAcceptingObjectWithToStringType' => __DIR__ . '/../..' . '/src/Type/StringNeverAcceptingObjectWithToStringType.php', 'PHPStan\\Type\\StringType' => __DIR__ . '/../..' . '/src/Type/StringType.php', 'PHPStan\\Type\\SubtractableType' => __DIR__ . '/../..' . '/src/Type/SubtractableType.php', 'PHPStan\\Type\\ThisType' => __DIR__ . '/../..' . '/src/Type/ThisType.php', 'PHPStan\\Type\\Traits\\ArrayTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/ArrayTypeTrait.php', 'PHPStan\\Type\\Traits\\ConstantNumericComparisonTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/ConstantNumericComparisonTypeTrait.php', 'PHPStan\\Type\\Traits\\ConstantScalarTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/ConstantScalarTypeTrait.php', 'PHPStan\\Type\\Traits\\FalseyBooleanTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/FalseyBooleanTypeTrait.php', 'PHPStan\\Type\\Traits\\LateResolvableTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/LateResolvableTypeTrait.php', 'PHPStan\\Type\\Traits\\MaybeArrayTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/MaybeArrayTypeTrait.php', 'PHPStan\\Type\\Traits\\MaybeCallableTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/MaybeCallableTypeTrait.php', 'PHPStan\\Type\\Traits\\MaybeIterableTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/MaybeIterableTypeTrait.php', 'PHPStan\\Type\\Traits\\MaybeObjectTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/MaybeObjectTypeTrait.php', 'PHPStan\\Type\\Traits\\MaybeOffsetAccessibleTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/MaybeOffsetAccessibleTypeTrait.php', 'PHPStan\\Type\\Traits\\MaybeStringTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/MaybeStringTypeTrait.php', 'PHPStan\\Type\\Traits\\NonArrayTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/NonArrayTypeTrait.php', 'PHPStan\\Type\\Traits\\NonCallableTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/NonCallableTypeTrait.php', 'PHPStan\\Type\\Traits\\NonGeneralizableTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/NonGeneralizableTypeTrait.php', 'PHPStan\\Type\\Traits\\NonGenericTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/NonGenericTypeTrait.php', 'PHPStan\\Type\\Traits\\NonIterableTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/NonIterableTypeTrait.php', 'PHPStan\\Type\\Traits\\NonObjectTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/NonObjectTypeTrait.php', 'PHPStan\\Type\\Traits\\NonOffsetAccessibleTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/NonOffsetAccessibleTypeTrait.php', 'PHPStan\\Type\\Traits\\NonRemoveableTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/NonRemoveableTypeTrait.php', 'PHPStan\\Type\\Traits\\ObjectTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/ObjectTypeTrait.php', 'PHPStan\\Type\\Traits\\SubstractableTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/SubstractableTypeTrait.php', 'PHPStan\\Type\\Traits\\TruthyBooleanTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/TruthyBooleanTypeTrait.php', 'PHPStan\\Type\\Traits\\UndecidedBooleanTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/UndecidedBooleanTypeTrait.php', 'PHPStan\\Type\\Traits\\UndecidedComparisonCompoundTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/UndecidedComparisonCompoundTypeTrait.php', 'PHPStan\\Type\\Traits\\UndecidedComparisonTypeTrait' => __DIR__ . '/../..' . '/src/Type/Traits/UndecidedComparisonTypeTrait.php', 'PHPStan\\Type\\Traverser\\LateResolvableTraverser' => __DIR__ . '/../..' . '/src/Type/Traverser/LateResolvableTraverser.php', 'PHPStan\\Type\\Type' => __DIR__ . '/../..' . '/src/Type/Type.php', 'PHPStan\\Type\\TypeAlias' => __DIR__ . '/../..' . '/src/Type/TypeAlias.php', 'PHPStan\\Type\\TypeAliasResolver' => __DIR__ . '/../..' . '/src/Type/TypeAliasResolver.php', 'PHPStan\\Type\\TypeAliasResolverProvider' => __DIR__ . '/../..' . '/src/Type/TypeAliasResolverProvider.php', 'PHPStan\\Type\\TypeCombinator' => __DIR__ . '/../..' . '/src/Type/TypeCombinator.php', 'PHPStan\\Type\\TypeResult' => __DIR__ . '/../..' . '/src/Type/TypeResult.php', 'PHPStan\\Type\\TypeTraverser' => __DIR__ . '/../..' . '/src/Type/TypeTraverser.php', 'PHPStan\\Type\\TypeTraverserCallable' => __DIR__ . '/../..' . '/src/Type/TypeTraverserCallable.php', 'PHPStan\\Type\\TypeUtils' => __DIR__ . '/../..' . '/src/Type/TypeUtils.php', 'PHPStan\\Type\\TypeWithClassName' => __DIR__ . '/../..' . '/src/Type/TypeWithClassName.php', 'PHPStan\\Type\\TypehintHelper' => __DIR__ . '/../..' . '/src/Type/TypehintHelper.php', 'PHPStan\\Type\\UnaryOperatorTypeSpecifyingExtension' => __DIR__ . '/../..' . '/src/Type/UnaryOperatorTypeSpecifyingExtension.php', 'PHPStan\\Type\\UnaryOperatorTypeSpecifyingExtensionRegistry' => __DIR__ . '/../..' . '/src/Type/UnaryOperatorTypeSpecifyingExtensionRegistry.php', 'PHPStan\\Type\\UnionType' => __DIR__ . '/../..' . '/src/Type/UnionType.php', 'PHPStan\\Type\\UnionTypeHelper' => __DIR__ . '/../..' . '/src/Type/UnionTypeHelper.php', 'PHPStan\\Type\\UsefulTypeAliasResolver' => __DIR__ . '/../..' . '/src/Type/UsefulTypeAliasResolver.php', 'PHPStan\\Type\\ValueOfType' => __DIR__ . '/../..' . '/src/Type/ValueOfType.php', 'PHPStan\\Type\\VerbosityLevel' => __DIR__ . '/../..' . '/src/Type/VerbosityLevel.php', 'PHPStan\\Type\\VoidType' => __DIR__ . '/../..' . '/src/Type/VoidType.php', 'Pdo\\Dblib' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Dblib.php', 'Pdo\\Firebird' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Firebird.php', 'Pdo\\Mysql' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Mysql.php', 'Pdo\\Odbc' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Odbc.php', 'Pdo\\Pgsql' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Pgsql.php', 'Pdo\\Sqlite' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Sqlite.php', 'PhpParser\\Builder' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder.php', 'PhpParser\\BuilderFactory' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/BuilderFactory.php', 'PhpParser\\BuilderHelpers' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/BuilderHelpers.php', 'PhpParser\\Builder\\ClassConst' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/ClassConst.php', 'PhpParser\\Builder\\Class_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Class_.php', 'PhpParser\\Builder\\Declaration' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Declaration.php', 'PhpParser\\Builder\\EnumCase' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php', 'PhpParser\\Builder\\Enum_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Enum_.php', 'PhpParser\\Builder\\FunctionLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php', 'PhpParser\\Builder\\Function_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Function_.php', 'PhpParser\\Builder\\Interface_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Interface_.php', 'PhpParser\\Builder\\Method' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Method.php', 'PhpParser\\Builder\\Namespace_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php', 'PhpParser\\Builder\\Param' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Param.php', 'PhpParser\\Builder\\Property' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Property.php', 'PhpParser\\Builder\\TraitUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php', 'PhpParser\\Builder\\TraitUseAdaptation' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php', 'PhpParser\\Builder\\Trait_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Trait_.php', 'PhpParser\\Builder\\Use_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Use_.php', 'PhpParser\\Comment' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Comment.php', 'PhpParser\\Comment\\Doc' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Comment/Doc.php', 'PhpParser\\ConstExprEvaluationException' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.php', 'PhpParser\\ConstExprEvaluator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php', 'PhpParser\\Error' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Error.php', 'PhpParser\\ErrorHandler' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ErrorHandler.php', 'PhpParser\\ErrorHandler\\Collecting' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php', 'PhpParser\\ErrorHandler\\Throwing' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php', 'PhpParser\\Internal\\DiffElem' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Internal/DiffElem.php', 'PhpParser\\Internal\\Differ' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Internal/Differ.php', 'PhpParser\\Internal\\PrintableNewAnonClassNode' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php', 'PhpParser\\Internal\\TokenPolyfill' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Internal/TokenPolyfill.php', 'PhpParser\\Internal\\TokenStream' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php', 'PhpParser\\JsonDecoder' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/JsonDecoder.php', 'PhpParser\\Lexer' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer.php', 'PhpParser\\Lexer\\Emulative' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php', 'PhpParser\\Lexer\\TokenEmulator\\AsymmetricVisibilityTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AsymmetricVisibilityTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\AttributeEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\EnumTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\ExplicitOctalEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\KeywordEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\MatchTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\NullsafeTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\PipeOperatorEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/PipeOperatorEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\PropertyTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/PropertyTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\ReadonlyFunctionTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyFunctionTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\ReadonlyTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\ReverseEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\TokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\VoidCastEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/VoidCastEmulator.php', 'PhpParser\\Modifiers' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Modifiers.php', 'PhpParser\\NameContext' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NameContext.php', 'PhpParser\\Node' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node.php', 'PhpParser\\NodeAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeAbstract.php', 'PhpParser\\NodeDumper' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeDumper.php', 'PhpParser\\NodeFinder' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeFinder.php', 'PhpParser\\NodeTraverser' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeTraverser.php', 'PhpParser\\NodeTraverserInterface' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php', 'PhpParser\\NodeVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor.php', 'PhpParser\\NodeVisitorAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php', 'PhpParser\\NodeVisitor\\CloningVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php', 'PhpParser\\NodeVisitor\\CommentAnnotatingVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/CommentAnnotatingVisitor.php', 'PhpParser\\NodeVisitor\\FindingVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php', 'PhpParser\\NodeVisitor\\FirstFindingVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php', 'PhpParser\\NodeVisitor\\NameResolver' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php', 'PhpParser\\NodeVisitor\\NodeConnectingVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php', 'PhpParser\\NodeVisitor\\ParentConnectingVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php', 'PhpParser\\Node\\Arg' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Arg.php', 'PhpParser\\Node\\ArrayItem' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/ArrayItem.php', 'PhpParser\\Node\\Attribute' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Attribute.php', 'PhpParser\\Node\\AttributeGroup' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php', 'PhpParser\\Node\\ClosureUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/ClosureUse.php', 'PhpParser\\Node\\ComplexType' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/ComplexType.php', 'PhpParser\\Node\\Const_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Const_.php', 'PhpParser\\Node\\DeclareItem' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/DeclareItem.php', 'PhpParser\\Node\\Expr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr.php', 'PhpParser\\Node\\Expr\\ArrayDimFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php', 'PhpParser\\Node\\Expr\\ArrayItem' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php', 'PhpParser\\Node\\Expr\\Array_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php', 'PhpParser\\Node\\Expr\\ArrowFunction' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php', 'PhpParser\\Node\\Expr\\Assign' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php', 'PhpParser\\Node\\Expr\\AssignOp' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php', 'PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', 'PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', 'PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', 'PhpParser\\Node\\Expr\\AssignOp\\Coalesce' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php', 'PhpParser\\Node\\Expr\\AssignOp\\Concat' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php', 'PhpParser\\Node\\Expr\\AssignOp\\Div' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php', 'PhpParser\\Node\\Expr\\AssignOp\\Minus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php', 'PhpParser\\Node\\Expr\\AssignOp\\Mod' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php', 'PhpParser\\Node\\Expr\\AssignOp\\Mul' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php', 'PhpParser\\Node\\Expr\\AssignOp\\Plus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php', 'PhpParser\\Node\\Expr\\AssignOp\\Pow' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php', 'PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', 'PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', 'PhpParser\\Node\\Expr\\AssignRef' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php', 'PhpParser\\Node\\Expr\\BinaryOp' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php', 'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', 'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', 'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', 'PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', 'PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Coalesce' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Concat' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Div' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Equal' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Greater' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php', 'PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Identical' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php', 'PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', 'PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', 'PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Minus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Mod' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Mul' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php', 'PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', 'PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Pipe' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pipe.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Plus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Pow' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php', 'PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', 'PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', 'PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', 'PhpParser\\Node\\Expr\\BinaryOp\\Spaceship' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', 'PhpParser\\Node\\Expr\\BitwiseNot' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php', 'PhpParser\\Node\\Expr\\BooleanNot' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php', 'PhpParser\\Node\\Expr\\CallLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php', 'PhpParser\\Node\\Expr\\Cast' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php', 'PhpParser\\Node\\Expr\\Cast\\Array_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php', 'PhpParser\\Node\\Expr\\Cast\\Bool_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php', 'PhpParser\\Node\\Expr\\Cast\\Double' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php', 'PhpParser\\Node\\Expr\\Cast\\Int_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php', 'PhpParser\\Node\\Expr\\Cast\\Object_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php', 'PhpParser\\Node\\Expr\\Cast\\String_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php', 'PhpParser\\Node\\Expr\\Cast\\Unset_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php', 'PhpParser\\Node\\Expr\\Cast\\Void_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Void_.php', 'PhpParser\\Node\\Expr\\ClassConstFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php', 'PhpParser\\Node\\Expr\\Clone_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php', 'PhpParser\\Node\\Expr\\Closure' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php', 'PhpParser\\Node\\Expr\\ClosureUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php', 'PhpParser\\Node\\Expr\\ConstFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php', 'PhpParser\\Node\\Expr\\Empty_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php', 'PhpParser\\Node\\Expr\\Error' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php', 'PhpParser\\Node\\Expr\\ErrorSuppress' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php', 'PhpParser\\Node\\Expr\\Eval_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php', 'PhpParser\\Node\\Expr\\Exit_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php', 'PhpParser\\Node\\Expr\\FuncCall' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php', 'PhpParser\\Node\\Expr\\Include_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php', 'PhpParser\\Node\\Expr\\Instanceof_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php', 'PhpParser\\Node\\Expr\\Isset_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php', 'PhpParser\\Node\\Expr\\List_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php', 'PhpParser\\Node\\Expr\\Match_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php', 'PhpParser\\Node\\Expr\\MethodCall' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php', 'PhpParser\\Node\\Expr\\New_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php', 'PhpParser\\Node\\Expr\\NullsafeMethodCall' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php', 'PhpParser\\Node\\Expr\\NullsafePropertyFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php', 'PhpParser\\Node\\Expr\\PostDec' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php', 'PhpParser\\Node\\Expr\\PostInc' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php', 'PhpParser\\Node\\Expr\\PreDec' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php', 'PhpParser\\Node\\Expr\\PreInc' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php', 'PhpParser\\Node\\Expr\\Print_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php', 'PhpParser\\Node\\Expr\\PropertyFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php', 'PhpParser\\Node\\Expr\\ShellExec' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php', 'PhpParser\\Node\\Expr\\StaticCall' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php', 'PhpParser\\Node\\Expr\\StaticPropertyFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php', 'PhpParser\\Node\\Expr\\Ternary' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php', 'PhpParser\\Node\\Expr\\Throw_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php', 'PhpParser\\Node\\Expr\\UnaryMinus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php', 'PhpParser\\Node\\Expr\\UnaryPlus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php', 'PhpParser\\Node\\Expr\\Variable' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php', 'PhpParser\\Node\\Expr\\YieldFrom' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php', 'PhpParser\\Node\\Expr\\Yield_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php', 'PhpParser\\Node\\FunctionLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php', 'PhpParser\\Node\\Identifier' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Identifier.php', 'PhpParser\\Node\\InterpolatedStringPart' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/InterpolatedStringPart.php', 'PhpParser\\Node\\IntersectionType' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php', 'PhpParser\\Node\\MatchArm' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/MatchArm.php', 'PhpParser\\Node\\Name' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Name.php', 'PhpParser\\Node\\Name\\FullyQualified' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php', 'PhpParser\\Node\\Name\\Relative' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php', 'PhpParser\\Node\\NullableType' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/NullableType.php', 'PhpParser\\Node\\Param' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Param.php', 'PhpParser\\Node\\PropertyHook' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/PropertyHook.php', 'PhpParser\\Node\\PropertyItem' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/PropertyItem.php', 'PhpParser\\Node\\Scalar' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar.php', 'PhpParser\\Node\\Scalar\\DNumber' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php', 'PhpParser\\Node\\Scalar\\Encapsed' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php', 'PhpParser\\Node\\Scalar\\EncapsedStringPart' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php', 'PhpParser\\Node\\Scalar\\Float_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/Float_.php', 'PhpParser\\Node\\Scalar\\Int_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/Int_.php', 'PhpParser\\Node\\Scalar\\InterpolatedString' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/InterpolatedString.php', 'PhpParser\\Node\\Scalar\\LNumber' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php', 'PhpParser\\Node\\Scalar\\MagicConst' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php', 'PhpParser\\Node\\Scalar\\MagicConst\\Class_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php', 'PhpParser\\Node\\Scalar\\MagicConst\\Dir' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php', 'PhpParser\\Node\\Scalar\\MagicConst\\File' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php', 'PhpParser\\Node\\Scalar\\MagicConst\\Function_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php', 'PhpParser\\Node\\Scalar\\MagicConst\\Line' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php', 'PhpParser\\Node\\Scalar\\MagicConst\\Method' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php', 'PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', 'PhpParser\\Node\\Scalar\\MagicConst\\Property' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Property.php', 'PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', 'PhpParser\\Node\\Scalar\\String_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php', 'PhpParser\\Node\\StaticVar' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/StaticVar.php', 'PhpParser\\Node\\Stmt' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt.php', 'PhpParser\\Node\\Stmt\\Block' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Block.php', 'PhpParser\\Node\\Stmt\\Break_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php', 'PhpParser\\Node\\Stmt\\Case_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php', 'PhpParser\\Node\\Stmt\\Catch_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php', 'PhpParser\\Node\\Stmt\\ClassConst' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php', 'PhpParser\\Node\\Stmt\\ClassLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php', 'PhpParser\\Node\\Stmt\\ClassMethod' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php', 'PhpParser\\Node\\Stmt\\Class_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php', 'PhpParser\\Node\\Stmt\\Const_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php', 'PhpParser\\Node\\Stmt\\Continue_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php', 'PhpParser\\Node\\Stmt\\DeclareDeclare' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php', 'PhpParser\\Node\\Stmt\\Declare_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php', 'PhpParser\\Node\\Stmt\\Do_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php', 'PhpParser\\Node\\Stmt\\Echo_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php', 'PhpParser\\Node\\Stmt\\ElseIf_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php', 'PhpParser\\Node\\Stmt\\Else_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php', 'PhpParser\\Node\\Stmt\\EnumCase' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php', 'PhpParser\\Node\\Stmt\\Enum_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php', 'PhpParser\\Node\\Stmt\\Expression' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php', 'PhpParser\\Node\\Stmt\\Finally_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php', 'PhpParser\\Node\\Stmt\\For_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php', 'PhpParser\\Node\\Stmt\\Foreach_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php', 'PhpParser\\Node\\Stmt\\Function_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php', 'PhpParser\\Node\\Stmt\\Global_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php', 'PhpParser\\Node\\Stmt\\Goto_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php', 'PhpParser\\Node\\Stmt\\GroupUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php', 'PhpParser\\Node\\Stmt\\HaltCompiler' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php', 'PhpParser\\Node\\Stmt\\If_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php', 'PhpParser\\Node\\Stmt\\InlineHTML' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php', 'PhpParser\\Node\\Stmt\\Interface_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php', 'PhpParser\\Node\\Stmt\\Label' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php', 'PhpParser\\Node\\Stmt\\Namespace_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php', 'PhpParser\\Node\\Stmt\\Nop' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php', 'PhpParser\\Node\\Stmt\\Property' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php', 'PhpParser\\Node\\Stmt\\PropertyProperty' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php', 'PhpParser\\Node\\Stmt\\Return_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php', 'PhpParser\\Node\\Stmt\\StaticVar' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php', 'PhpParser\\Node\\Stmt\\Static_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php', 'PhpParser\\Node\\Stmt\\Switch_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php', 'PhpParser\\Node\\Stmt\\TraitUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php', 'PhpParser\\Node\\Stmt\\TraitUseAdaptation' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', 'PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Alias' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', 'PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Precedence' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', 'PhpParser\\Node\\Stmt\\Trait_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php', 'PhpParser\\Node\\Stmt\\TryCatch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php', 'PhpParser\\Node\\Stmt\\Unset_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php', 'PhpParser\\Node\\Stmt\\UseUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php', 'PhpParser\\Node\\Stmt\\Use_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php', 'PhpParser\\Node\\Stmt\\While_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php', 'PhpParser\\Node\\UnionType' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/UnionType.php', 'PhpParser\\Node\\UseItem' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/UseItem.php', 'PhpParser\\Node\\VarLikeIdentifier' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php', 'PhpParser\\Node\\VariadicPlaceholder' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php', 'PhpParser\\Parser' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser.php', 'PhpParser\\ParserAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ParserAbstract.php', 'PhpParser\\ParserFactory' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ParserFactory.php', 'PhpParser\\Parser\\Php7' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser/Php7.php', 'PhpParser\\Parser\\Php8' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser/Php8.php', 'PhpParser\\PhpVersion' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/PhpVersion.php', 'PhpParser\\PrettyPrinter' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/PrettyPrinter.php', 'PhpParser\\PrettyPrinterAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php', 'PhpParser\\PrettyPrinter\\Standard' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php', 'PhpParser\\Token' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Token.php', 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 'ReflectionConstant' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php', 'ReturnTypeWillChange' => __DIR__ . '/..' . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php', 'RoundingMode' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/RoundingMode.php', 'SQLite3Exception' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php', 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'Symfony\\Polyfill\\Intl\\Grapheme\\Grapheme' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/Grapheme.php', 'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Normalizer.php', 'Symfony\\Polyfill\\Mbstring\\Mbstring' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/Mbstring.php', 'Symfony\\Polyfill\\Php80\\Php80' => __DIR__ . '/..' . '/symfony/polyfill-php80/Php80.php', 'Symfony\\Polyfill\\Php80\\PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/PhpToken.php', 'Symfony\\Polyfill\\Php81\\Php81' => __DIR__ . '/..' . '/symfony/polyfill-php81/Php81.php', 'Symfony\\Polyfill\\Php83\\Php83' => __DIR__ . '/..' . '/symfony/polyfill-php83/Php83.php', 'Symfony\\Polyfill\\Php84\\Php84' => __DIR__ . '/..' . '/symfony/polyfill-php84/Php84.php', 'Symfony\\Polyfill\\Php85\\Php85' => __DIR__ . '/..' . '/symfony/polyfill-php85/Php85.php', 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', '_PHPStan_33c983f26\\Clue\\React\\NDJson\\Decoder' => __DIR__ . '/..' . '/clue/ndjson-react/src/Decoder.php', '_PHPStan_33c983f26\\Clue\\React\\NDJson\\Encoder' => __DIR__ . '/..' . '/clue/ndjson-react/src/Encoder.php', '_PHPStan_33c983f26\\Composer\\Pcre\\MatchAllResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchAllResult.php', '_PHPStan_33c983f26\\Composer\\Pcre\\MatchAllStrictGroupsResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchAllStrictGroupsResult.php', '_PHPStan_33c983f26\\Composer\\Pcre\\MatchAllWithOffsetsResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchAllWithOffsetsResult.php', '_PHPStan_33c983f26\\Composer\\Pcre\\MatchResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchResult.php', '_PHPStan_33c983f26\\Composer\\Pcre\\MatchStrictGroupsResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchStrictGroupsResult.php', '_PHPStan_33c983f26\\Composer\\Pcre\\MatchWithOffsetsResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchWithOffsetsResult.php', '_PHPStan_33c983f26\\Composer\\Pcre\\PcreException' => __DIR__ . '/..' . '/composer/pcre/src/PcreException.php', '_PHPStan_33c983f26\\Composer\\Pcre\\Preg' => __DIR__ . '/..' . '/composer/pcre/src/Preg.php', '_PHPStan_33c983f26\\Composer\\Pcre\\Regex' => __DIR__ . '/..' . '/composer/pcre/src/Regex.php', '_PHPStan_33c983f26\\Composer\\Pcre\\ReplaceResult' => __DIR__ . '/..' . '/composer/pcre/src/ReplaceResult.php', '_PHPStan_33c983f26\\Composer\\Pcre\\UnexpectedNullMatchException' => __DIR__ . '/..' . '/composer/pcre/src/UnexpectedNullMatchException.php', '_PHPStan_33c983f26\\Composer\\Semver\\Comparator' => __DIR__ . '/..' . '/composer/semver/src/Comparator.php', '_PHPStan_33c983f26\\Composer\\Semver\\CompilingMatcher' => __DIR__ . '/..' . '/composer/semver/src/CompilingMatcher.php', '_PHPStan_33c983f26\\Composer\\Semver\\Constraint\\Bound' => __DIR__ . '/..' . '/composer/semver/src/Constraint/Bound.php', '_PHPStan_33c983f26\\Composer\\Semver\\Constraint\\Constraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/Constraint.php', '_PHPStan_33c983f26\\Composer\\Semver\\Constraint\\ConstraintInterface' => __DIR__ . '/..' . '/composer/semver/src/Constraint/ConstraintInterface.php', '_PHPStan_33c983f26\\Composer\\Semver\\Constraint\\MatchAllConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MatchAllConstraint.php', '_PHPStan_33c983f26\\Composer\\Semver\\Constraint\\MatchNoneConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MatchNoneConstraint.php', '_PHPStan_33c983f26\\Composer\\Semver\\Constraint\\MultiConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MultiConstraint.php', '_PHPStan_33c983f26\\Composer\\Semver\\Interval' => __DIR__ . '/..' . '/composer/semver/src/Interval.php', '_PHPStan_33c983f26\\Composer\\Semver\\Intervals' => __DIR__ . '/..' . '/composer/semver/src/Intervals.php', '_PHPStan_33c983f26\\Composer\\Semver\\Semver' => __DIR__ . '/..' . '/composer/semver/src/Semver.php', '_PHPStan_33c983f26\\Composer\\Semver\\VersionParser' => __DIR__ . '/..' . '/composer/semver/src/VersionParser.php', '_PHPStan_33c983f26\\Composer\\XdebugHandler\\PhpConfig' => __DIR__ . '/..' . '/composer/xdebug-handler/src/PhpConfig.php', '_PHPStan_33c983f26\\Composer\\XdebugHandler\\Process' => __DIR__ . '/..' . '/composer/xdebug-handler/src/Process.php', '_PHPStan_33c983f26\\Composer\\XdebugHandler\\Status' => __DIR__ . '/..' . '/composer/xdebug-handler/src/Status.php', '_PHPStan_33c983f26\\Composer\\XdebugHandler\\XdebugHandler' => __DIR__ . '/..' . '/composer/xdebug-handler/src/XdebugHandler.php', '_PHPStan_33c983f26\\Evenement\\EventEmitter' => __DIR__ . '/..' . '/evenement/evenement/src/EventEmitter.php', '_PHPStan_33c983f26\\Evenement\\EventEmitterInterface' => __DIR__ . '/..' . '/evenement/evenement/src/EventEmitterInterface.php', '_PHPStan_33c983f26\\Evenement\\EventEmitterTrait' => __DIR__ . '/..' . '/evenement/evenement/src/EventEmitterTrait.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\CpuCoreCounter' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/CpuCoreCounter.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Diagnoser' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Diagnoser.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Executor\\ProcOpenExecutor' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Executor/ProcOpenExecutor.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Executor\\ProcessExecutor' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Executor/ProcessExecutor.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\CmiCmdletLogicalFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/CmiCmdletLogicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\CmiCmdletPhysicalFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/CmiCmdletPhysicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\CpuCoreFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/CpuCoreFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\CpuInfoFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/CpuInfoFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\DummyCpuCoreFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/DummyCpuCoreFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\EnvVariableFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/EnvVariableFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\FinderRegistry' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/FinderRegistry.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\HwLogicalFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/HwLogicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\HwPhysicalFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/HwPhysicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\LscpuLogicalFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/LscpuLogicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\LscpuPhysicalFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/LscpuPhysicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\NProcFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/NProcFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\NProcessorFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/NProcessorFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\NullCpuCoreFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/NullCpuCoreFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\OnlyInPowerShellFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/OnlyInPowerShellFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\OnlyOnOSFamilyFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/OnlyOnOSFamilyFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\ProcOpenBasedFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/ProcOpenBasedFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\SkipOnOSFamilyFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/SkipOnOSFamilyFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\WindowsRegistryLogicalFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/WindowsRegistryLogicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\WmicLogicalFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/WmicLogicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\WmicPhysicalFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/WmicPhysicalFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\Finder\\_NProcessorFinder' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Finder/_NProcessorFinder.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\NumberOfCpuCoreNotFound' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/NumberOfCpuCoreNotFound.php', '_PHPStan_33c983f26\\Fidry\\CpuCoreCounter\\ParallelisationResult' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/ParallelisationResult.php', '_PHPStan_33c983f26\\GuzzleHttp\\BodySummarizer' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/BodySummarizer.php', '_PHPStan_33c983f26\\GuzzleHttp\\BodySummarizerInterface' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/BodySummarizerInterface.php', '_PHPStan_33c983f26\\GuzzleHttp\\Client' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Client.php', '_PHPStan_33c983f26\\GuzzleHttp\\ClientInterface' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/ClientInterface.php', '_PHPStan_33c983f26\\GuzzleHttp\\ClientTrait' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/ClientTrait.php', '_PHPStan_33c983f26\\GuzzleHttp\\Cookie\\CookieJar' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/CookieJar.php', '_PHPStan_33c983f26\\GuzzleHttp\\Cookie\\CookieJarInterface' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php', '_PHPStan_33c983f26\\GuzzleHttp\\Cookie\\FileCookieJar' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php', '_PHPStan_33c983f26\\GuzzleHttp\\Cookie\\SessionCookieJar' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php', '_PHPStan_33c983f26\\GuzzleHttp\\Cookie\\SetCookie' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/SetCookie.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\BadResponseException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/BadResponseException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\ClientException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/ClientException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\ConnectException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/ConnectException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\GuzzleException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/GuzzleException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\RequestException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/RequestException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\ServerException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/ServerException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\TooManyRedirectsException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Exception\\TransferException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/TransferException.php', '_PHPStan_33c983f26\\GuzzleHttp\\HandlerStack' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/HandlerStack.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\CurlFactory' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/CurlFactory.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\CurlFactoryInterface' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\CurlHandler' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/CurlHandler.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\CurlMultiHandler' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\EasyHandle' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/EasyHandle.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\HeaderProcessor' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\MockHandler' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/MockHandler.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\Proxy' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/Proxy.php', '_PHPStan_33c983f26\\GuzzleHttp\\Handler\\StreamHandler' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/StreamHandler.php', '_PHPStan_33c983f26\\GuzzleHttp\\MessageFormatter' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/MessageFormatter.php', '_PHPStan_33c983f26\\GuzzleHttp\\MessageFormatterInterface' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/MessageFormatterInterface.php', '_PHPStan_33c983f26\\GuzzleHttp\\Middleware' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Middleware.php', '_PHPStan_33c983f26\\GuzzleHttp\\Pool' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Pool.php', '_PHPStan_33c983f26\\GuzzleHttp\\PrepareBodyMiddleware' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\AggregateException' => __DIR__ . '/..' . '/guzzlehttp/promises/src/AggregateException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\CancellationException' => __DIR__ . '/..' . '/guzzlehttp/promises/src/CancellationException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\Coroutine' => __DIR__ . '/..' . '/guzzlehttp/promises/src/Coroutine.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\Create' => __DIR__ . '/..' . '/guzzlehttp/promises/src/Create.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\Each' => __DIR__ . '/..' . '/guzzlehttp/promises/src/Each.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\EachPromise' => __DIR__ . '/..' . '/guzzlehttp/promises/src/EachPromise.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\FulfilledPromise' => __DIR__ . '/..' . '/guzzlehttp/promises/src/FulfilledPromise.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\Is' => __DIR__ . '/..' . '/guzzlehttp/promises/src/Is.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\Promise' => __DIR__ . '/..' . '/guzzlehttp/promises/src/Promise.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\PromiseInterface' => __DIR__ . '/..' . '/guzzlehttp/promises/src/PromiseInterface.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\PromisorInterface' => __DIR__ . '/..' . '/guzzlehttp/promises/src/PromisorInterface.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\RejectedPromise' => __DIR__ . '/..' . '/guzzlehttp/promises/src/RejectedPromise.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\RejectionException' => __DIR__ . '/..' . '/guzzlehttp/promises/src/RejectionException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\TaskQueue' => __DIR__ . '/..' . '/guzzlehttp/promises/src/TaskQueue.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\TaskQueueInterface' => __DIR__ . '/..' . '/guzzlehttp/promises/src/TaskQueueInterface.php', '_PHPStan_33c983f26\\GuzzleHttp\\Promise\\Utils' => __DIR__ . '/..' . '/guzzlehttp/promises/src/Utils.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\AppendStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/AppendStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\BufferStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/BufferStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\CachingStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/CachingStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\DroppingStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/DroppingStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Exception\\MalformedUriException' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Exception/MalformedUriException.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\FnStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/FnStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Header' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Header.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\HttpFactory' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/HttpFactory.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\InflateStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/InflateStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\LazyOpenStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/LazyOpenStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\LimitStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/LimitStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Message' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Message.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\MessageTrait' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/MessageTrait.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\MimeType' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/MimeType.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\MultipartStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/MultipartStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\NoSeekStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/NoSeekStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\PumpStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/PumpStream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Query' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Query.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Request' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Request.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Response' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Response.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Rfc7230' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Rfc7230.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\ServerRequest' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/ServerRequest.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Stream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Stream.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\StreamDecoratorTrait' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/StreamDecoratorTrait.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\StreamWrapper' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/StreamWrapper.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\UploadedFile' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/UploadedFile.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Uri' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Uri.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\UriComparator' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/UriComparator.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\UriNormalizer' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/UriNormalizer.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\UriResolver' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/UriResolver.php', '_PHPStan_33c983f26\\GuzzleHttp\\Psr7\\Utils' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Utils.php', '_PHPStan_33c983f26\\GuzzleHttp\\RedirectMiddleware' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/RedirectMiddleware.php', '_PHPStan_33c983f26\\GuzzleHttp\\RequestOptions' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/RequestOptions.php', '_PHPStan_33c983f26\\GuzzleHttp\\RetryMiddleware' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/RetryMiddleware.php', '_PHPStan_33c983f26\\GuzzleHttp\\TransferStats' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/TransferStats.php', '_PHPStan_33c983f26\\GuzzleHttp\\Utils' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Utils.php', '_PHPStan_33c983f26\\Nette\\ArgumentOutOfRangeException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\Bootstrap\\Configurator' => __DIR__ . '/..' . '/nette/bootstrap/src/Bootstrap/Configurator.php', '_PHPStan_33c983f26\\Nette\\Bootstrap\\Extensions\\ConstantsExtension' => __DIR__ . '/..' . '/nette/bootstrap/src/Bootstrap/Extensions/ConstantsExtension.php', '_PHPStan_33c983f26\\Nette\\Bootstrap\\Extensions\\PhpExtension' => __DIR__ . '/..' . '/nette/bootstrap/src/Bootstrap/Extensions/PhpExtension.php', '_PHPStan_33c983f26\\Nette\\Bridges\\DITracy\\ContainerPanel' => __DIR__ . '/..' . '/nette/di/src/Bridges/DITracy/ContainerPanel.php', '_PHPStan_33c983f26\\Nette\\Configurator' => __DIR__ . '/..' . '/nette/bootstrap/src/Configurator.php', '_PHPStan_33c983f26\\Nette\\DI\\Attributes\\Inject' => __DIR__ . '/..' . '/nette/di/src/DI/Attributes/Inject.php', '_PHPStan_33c983f26\\Nette\\DI\\Autowiring' => __DIR__ . '/..' . '/nette/di/src/DI/Autowiring.php', '_PHPStan_33c983f26\\Nette\\DI\\Compiler' => __DIR__ . '/..' . '/nette/di/src/DI/Compiler.php', '_PHPStan_33c983f26\\Nette\\DI\\CompilerExtension' => __DIR__ . '/..' . '/nette/di/src/DI/CompilerExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Config\\Adapter' => __DIR__ . '/..' . '/nette/di/src/DI/Config/Adapter.php', '_PHPStan_33c983f26\\Nette\\DI\\Config\\Adapters\\NeonAdapter' => __DIR__ . '/..' . '/nette/di/src/DI/Config/Adapters/NeonAdapter.php', '_PHPStan_33c983f26\\Nette\\DI\\Config\\Adapters\\PhpAdapter' => __DIR__ . '/..' . '/nette/di/src/DI/Config/Adapters/PhpAdapter.php', '_PHPStan_33c983f26\\Nette\\DI\\Config\\Helpers' => __DIR__ . '/..' . '/nette/di/src/DI/Config/Helpers.php', '_PHPStan_33c983f26\\Nette\\DI\\Config\\IAdapter' => __DIR__ . '/..' . '/nette/di/src/compatibility.php', '_PHPStan_33c983f26\\Nette\\DI\\Config\\Loader' => __DIR__ . '/..' . '/nette/di/src/DI/Config/Loader.php', '_PHPStan_33c983f26\\Nette\\DI\\Container' => __DIR__ . '/..' . '/nette/di/src/DI/Container.php', '_PHPStan_33c983f26\\Nette\\DI\\ContainerBuilder' => __DIR__ . '/..' . '/nette/di/src/DI/ContainerBuilder.php', '_PHPStan_33c983f26\\Nette\\DI\\ContainerLoader' => __DIR__ . '/..' . '/nette/di/src/DI/ContainerLoader.php', '_PHPStan_33c983f26\\Nette\\DI\\Definitions\\AccessorDefinition' => __DIR__ . '/..' . '/nette/di/src/DI/Definitions/AccessorDefinition.php', '_PHPStan_33c983f26\\Nette\\DI\\Definitions\\Definition' => __DIR__ . '/..' . '/nette/di/src/DI/Definitions/Definition.php', '_PHPStan_33c983f26\\Nette\\DI\\Definitions\\FactoryDefinition' => __DIR__ . '/..' . '/nette/di/src/DI/Definitions/FactoryDefinition.php', '_PHPStan_33c983f26\\Nette\\DI\\Definitions\\ImportedDefinition' => __DIR__ . '/..' . '/nette/di/src/DI/Definitions/ImportedDefinition.php', '_PHPStan_33c983f26\\Nette\\DI\\Definitions\\LocatorDefinition' => __DIR__ . '/..' . '/nette/di/src/DI/Definitions/LocatorDefinition.php', '_PHPStan_33c983f26\\Nette\\DI\\Definitions\\Reference' => __DIR__ . '/..' . '/nette/di/src/DI/Definitions/Reference.php', '_PHPStan_33c983f26\\Nette\\DI\\Definitions\\ServiceDefinition' => __DIR__ . '/..' . '/nette/di/src/DI/Definitions/ServiceDefinition.php', '_PHPStan_33c983f26\\Nette\\DI\\Definitions\\Statement' => __DIR__ . '/..' . '/nette/di/src/DI/Definitions/Statement.php', '_PHPStan_33c983f26\\Nette\\DI\\DependencyChecker' => __DIR__ . '/..' . '/nette/di/src/DI/DependencyChecker.php', '_PHPStan_33c983f26\\Nette\\DI\\DynamicParameter' => __DIR__ . '/..' . '/nette/di/src/DI/DynamicParameter.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\ConstantsExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/ConstantsExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\DIExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/DIExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\DecoratorExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/DecoratorExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\DefinitionSchema' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/DefinitionSchema.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\ExtensionsExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/ExtensionsExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\InjectExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/InjectExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\ParametersExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/ParametersExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\PhpExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/PhpExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\SearchExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/SearchExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Extensions\\ServicesExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/ServicesExtension.php', '_PHPStan_33c983f26\\Nette\\DI\\Helpers' => __DIR__ . '/..' . '/nette/di/src/DI/Helpers.php', '_PHPStan_33c983f26\\Nette\\DI\\InvalidConfigurationException' => __DIR__ . '/..' . '/nette/di/src/DI/exceptions.php', '_PHPStan_33c983f26\\Nette\\DI\\MissingServiceException' => __DIR__ . '/..' . '/nette/di/src/DI/exceptions.php', '_PHPStan_33c983f26\\Nette\\DI\\NotAllowedDuringResolvingException' => __DIR__ . '/..' . '/nette/di/src/DI/exceptions.php', '_PHPStan_33c983f26\\Nette\\DI\\PhpGenerator' => __DIR__ . '/..' . '/nette/di/src/DI/PhpGenerator.php', '_PHPStan_33c983f26\\Nette\\DI\\Resolver' => __DIR__ . '/..' . '/nette/di/src/DI/Resolver.php', '_PHPStan_33c983f26\\Nette\\DI\\ServiceCreationException' => __DIR__ . '/..' . '/nette/di/src/DI/exceptions.php', '_PHPStan_33c983f26\\Nette\\DI\\ServiceDefinition' => __DIR__ . '/..' . '/nette/di/src/compatibility.php', '_PHPStan_33c983f26\\Nette\\DI\\Statement' => __DIR__ . '/..' . '/nette/di/src/compatibility.php', '_PHPStan_33c983f26\\Nette\\DeprecatedException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\DirectoryNotFoundException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\FileNotFoundException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\HtmlStringable' => __DIR__ . '/..' . '/nette/utils/src/HtmlStringable.php', '_PHPStan_33c983f26\\Nette\\IOException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\InvalidArgumentException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\InvalidStateException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\Iterators\\CachingIterator' => __DIR__ . '/..' . '/nette/utils/src/Iterators/CachingIterator.php', '_PHPStan_33c983f26\\Nette\\Iterators\\Mapper' => __DIR__ . '/..' . '/nette/utils/src/Iterators/Mapper.php', '_PHPStan_33c983f26\\Nette\\Loaders\\RobotLoader' => __DIR__ . '/..' . '/nette/robot-loader/src/RobotLoader/RobotLoader.php', '_PHPStan_33c983f26\\Nette\\Localization\\ITranslator' => __DIR__ . '/..' . '/nette/utils/src/compatibility.php', '_PHPStan_33c983f26\\Nette\\Localization\\Translator' => __DIR__ . '/..' . '/nette/utils/src/Translator.php', '_PHPStan_33c983f26\\Nette\\MemberAccessException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\Neon\\Decoder' => __DIR__ . '/..' . '/nette/neon/src/Neon/Decoder.php', '_PHPStan_33c983f26\\Nette\\Neon\\Encoder' => __DIR__ . '/..' . '/nette/neon/src/Neon/Encoder.php', '_PHPStan_33c983f26\\Nette\\Neon\\Entity' => __DIR__ . '/..' . '/nette/neon/src/Neon/Entity.php', '_PHPStan_33c983f26\\Nette\\Neon\\Exception' => __DIR__ . '/..' . '/nette/neon/src/Neon/Exception.php', '_PHPStan_33c983f26\\Nette\\Neon\\Lexer' => __DIR__ . '/..' . '/nette/neon/src/Neon/Lexer.php', '_PHPStan_33c983f26\\Nette\\Neon\\Neon' => __DIR__ . '/..' . '/nette/neon/src/Neon/Neon.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node\\ArrayItemNode' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node/ArrayItemNode.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node\\ArrayNode' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node/ArrayNode.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node\\BlockArrayNode' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node/BlockArrayNode.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node\\EntityChainNode' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node/EntityChainNode.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node\\EntityNode' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node/EntityNode.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node\\InlineArrayNode' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node/InlineArrayNode.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node\\LiteralNode' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node/LiteralNode.php', '_PHPStan_33c983f26\\Nette\\Neon\\Node\\StringNode' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node/StringNode.php', '_PHPStan_33c983f26\\Nette\\Neon\\Parser' => __DIR__ . '/..' . '/nette/neon/src/Neon/Parser.php', '_PHPStan_33c983f26\\Nette\\Neon\\Token' => __DIR__ . '/..' . '/nette/neon/src/Neon/Token.php', '_PHPStan_33c983f26\\Nette\\Neon\\TokenStream' => __DIR__ . '/..' . '/nette/neon/src/Neon/TokenStream.php', '_PHPStan_33c983f26\\Nette\\Neon\\Traverser' => __DIR__ . '/..' . '/nette/neon/src/Neon/Traverser.php', '_PHPStan_33c983f26\\Nette\\NotImplementedException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\NotSupportedException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\OutOfRangeException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Attribute' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Attribute.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\ClassType' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/ClassType.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Closure' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Closure.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Constant' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Constant.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Dumper' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Dumper.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\EnumCase' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/EnumCase.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Extractor' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Extractor.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Factory' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Factory.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\GlobalFunction' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/GlobalFunction.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Helpers' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Helpers.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Literal' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Literal.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Method' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Method.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Parameter' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Parameter.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\PhpFile' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/PhpFile.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\PhpLiteral' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/PhpLiteral.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\PhpNamespace' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/PhpNamespace.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Printer' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Printer.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\PromotedParameter' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/PromotedParameter.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Property' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Property.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\PsrPrinter' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/PsrPrinter.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\TraitUse' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/TraitUse.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Traits\\AttributeAware' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/AttributeAware.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Traits\\CommentAware' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/CommentAware.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Traits\\FunctionLike' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/FunctionLike.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Traits\\NameAware' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/NameAware.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Traits\\VisibilityAware' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/VisibilityAware.php', '_PHPStan_33c983f26\\Nette\\PhpGenerator\\Type' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Type.php', '_PHPStan_33c983f26\\Nette\\Schema\\Context' => __DIR__ . '/..' . '/nette/schema/src/Schema/Context.php', '_PHPStan_33c983f26\\Nette\\Schema\\DynamicParameter' => __DIR__ . '/..' . '/nette/schema/src/Schema/DynamicParameter.php', '_PHPStan_33c983f26\\Nette\\Schema\\Elements\\AnyOf' => __DIR__ . '/..' . '/nette/schema/src/Schema/Elements/AnyOf.php', '_PHPStan_33c983f26\\Nette\\Schema\\Elements\\Base' => __DIR__ . '/..' . '/nette/schema/src/Schema/Elements/Base.php', '_PHPStan_33c983f26\\Nette\\Schema\\Elements\\Structure' => __DIR__ . '/..' . '/nette/schema/src/Schema/Elements/Structure.php', '_PHPStan_33c983f26\\Nette\\Schema\\Elements\\Type' => __DIR__ . '/..' . '/nette/schema/src/Schema/Elements/Type.php', '_PHPStan_33c983f26\\Nette\\Schema\\Expect' => __DIR__ . '/..' . '/nette/schema/src/Schema/Expect.php', '_PHPStan_33c983f26\\Nette\\Schema\\Helpers' => __DIR__ . '/..' . '/nette/schema/src/Schema/Helpers.php', '_PHPStan_33c983f26\\Nette\\Schema\\Message' => __DIR__ . '/..' . '/nette/schema/src/Schema/Message.php', '_PHPStan_33c983f26\\Nette\\Schema\\Processor' => __DIR__ . '/..' . '/nette/schema/src/Schema/Processor.php', '_PHPStan_33c983f26\\Nette\\Schema\\Schema' => __DIR__ . '/..' . '/nette/schema/src/Schema/Schema.php', '_PHPStan_33c983f26\\Nette\\Schema\\ValidationException' => __DIR__ . '/..' . '/nette/schema/src/Schema/ValidationException.php', '_PHPStan_33c983f26\\Nette\\SmartObject' => __DIR__ . '/..' . '/nette/utils/src/SmartObject.php', '_PHPStan_33c983f26\\Nette\\StaticClass' => __DIR__ . '/..' . '/nette/utils/src/StaticClass.php', '_PHPStan_33c983f26\\Nette\\UnexpectedValueException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', '_PHPStan_33c983f26\\Nette\\Utils\\ArrayHash' => __DIR__ . '/..' . '/nette/utils/src/Utils/ArrayHash.php', '_PHPStan_33c983f26\\Nette\\Utils\\ArrayList' => __DIR__ . '/..' . '/nette/utils/src/Utils/ArrayList.php', '_PHPStan_33c983f26\\Nette\\Utils\\Arrays' => __DIR__ . '/..' . '/nette/utils/src/Utils/Arrays.php', '_PHPStan_33c983f26\\Nette\\Utils\\AssertionException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php', '_PHPStan_33c983f26\\Nette\\Utils\\Callback' => __DIR__ . '/..' . '/nette/utils/src/Utils/Callback.php', '_PHPStan_33c983f26\\Nette\\Utils\\DateTime' => __DIR__ . '/..' . '/nette/utils/src/Utils/DateTime.php', '_PHPStan_33c983f26\\Nette\\Utils\\FileSystem' => __DIR__ . '/..' . '/nette/utils/src/Utils/FileSystem.php', '_PHPStan_33c983f26\\Nette\\Utils\\Finder' => __DIR__ . '/..' . '/nette/finder/src/Utils/Finder.php', '_PHPStan_33c983f26\\Nette\\Utils\\Floats' => __DIR__ . '/..' . '/nette/utils/src/Utils/Floats.php', '_PHPStan_33c983f26\\Nette\\Utils\\Helpers' => __DIR__ . '/..' . '/nette/utils/src/Utils/Helpers.php', '_PHPStan_33c983f26\\Nette\\Utils\\Html' => __DIR__ . '/..' . '/nette/utils/src/Utils/Html.php', '_PHPStan_33c983f26\\Nette\\Utils\\IHtmlString' => __DIR__ . '/..' . '/nette/utils/src/compatibility.php', '_PHPStan_33c983f26\\Nette\\Utils\\Image' => __DIR__ . '/..' . '/nette/utils/src/Utils/Image.php', '_PHPStan_33c983f26\\Nette\\Utils\\ImageException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php', '_PHPStan_33c983f26\\Nette\\Utils\\Json' => __DIR__ . '/..' . '/nette/utils/src/Utils/Json.php', '_PHPStan_33c983f26\\Nette\\Utils\\JsonException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php', '_PHPStan_33c983f26\\Nette\\Utils\\ObjectHelpers' => __DIR__ . '/..' . '/nette/utils/src/Utils/ObjectHelpers.php', '_PHPStan_33c983f26\\Nette\\Utils\\ObjectMixin' => __DIR__ . '/..' . '/nette/utils/src/Utils/ObjectMixin.php', '_PHPStan_33c983f26\\Nette\\Utils\\Paginator' => __DIR__ . '/..' . '/nette/utils/src/Utils/Paginator.php', '_PHPStan_33c983f26\\Nette\\Utils\\Random' => __DIR__ . '/..' . '/nette/utils/src/Utils/Random.php', '_PHPStan_33c983f26\\Nette\\Utils\\Reflection' => __DIR__ . '/..' . '/nette/utils/src/Utils/Reflection.php', '_PHPStan_33c983f26\\Nette\\Utils\\RegexpException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php', '_PHPStan_33c983f26\\Nette\\Utils\\Strings' => __DIR__ . '/..' . '/nette/utils/src/Utils/Strings.php', '_PHPStan_33c983f26\\Nette\\Utils\\Type' => __DIR__ . '/..' . '/nette/utils/src/Utils/Type.php', '_PHPStan_33c983f26\\Nette\\Utils\\UnknownImageFileException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php', '_PHPStan_33c983f26\\Nette\\Utils\\Validators' => __DIR__ . '/..' . '/nette/utils/src/Utils/Validators.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\CiDetector' => __DIR__ . '/..' . '/ondram/ci-detector/src/CiDetector.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\CiDetectorInterface' => __DIR__ . '/..' . '/ondram/ci-detector/src/CiDetectorInterface.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\AbstractCi' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/AbstractCi.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\AppVeyor' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/AppVeyor.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\AwsCodeBuild' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/AwsCodeBuild.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\AzurePipelines' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/AzurePipelines.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Bamboo' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/Bamboo.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\BitbucketPipelines' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/BitbucketPipelines.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Buddy' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/Buddy.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\CiInterface' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/CiInterface.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Circle' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/Circle.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Codeship' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/Codeship.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Continuousphp' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/Continuousphp.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Drone' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/Drone.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\GitHubActions' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/GitHubActions.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\GitLab' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/GitLab.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Jenkins' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/Jenkins.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\SourceHut' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/SourceHut.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\TeamCity' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/TeamCity.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Travis' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/Travis.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Ci\\Wercker' => __DIR__ . '/..' . '/ondram/ci-detector/src/Ci/Wercker.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Env' => __DIR__ . '/..' . '/ondram/ci-detector/src/Env.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\Exception\\CiNotDetectedException' => __DIR__ . '/..' . '/ondram/ci-detector/src/Exception/CiNotDetectedException.php', '_PHPStan_33c983f26\\OndraM\\CiDetector\\TrinaryLogic' => __DIR__ . '/..' . '/ondram/ci-detector/src/TrinaryLogic.php', '_PHPStan_33c983f26\\PhpMerge\\GitMerge' => __DIR__ . '/..' . '/ondrejmirtes/php-merge/src/PhpMerge/GitMerge.php', '_PHPStan_33c983f26\\PhpMerge\\MergeConflict' => __DIR__ . '/..' . '/ondrejmirtes/php-merge/src/PhpMerge/MergeConflict.php', '_PHPStan_33c983f26\\PhpMerge\\MergeException' => __DIR__ . '/..' . '/ondrejmirtes/php-merge/src/PhpMerge/MergeException.php', '_PHPStan_33c983f26\\PhpMerge\\PhpMerge' => __DIR__ . '/..' . '/ondrejmirtes/php-merge/src/PhpMerge/PhpMerge.php', '_PHPStan_33c983f26\\PhpMerge\\PhpMergeInterface' => __DIR__ . '/..' . '/ondrejmirtes/php-merge/src/PhpMerge/PhpMergeInterface.php', '_PHPStan_33c983f26\\PhpMerge\\internal\\AbstractMergeBase' => __DIR__ . '/..' . '/ondrejmirtes/php-merge/src/PhpMerge/internal/AbstractMergeBase.php', '_PHPStan_33c983f26\\PhpMerge\\internal\\Hunk' => __DIR__ . '/..' . '/ondrejmirtes/php-merge/src/PhpMerge/internal/Hunk.php', '_PHPStan_33c983f26\\PhpMerge\\internal\\Line' => __DIR__ . '/..' . '/ondrejmirtes/php-merge/src/PhpMerge/internal/Line.php', '_PHPStan_33c983f26\\Psr\\Container\\ContainerExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerExceptionInterface.php', '_PHPStan_33c983f26\\Psr\\Container\\ContainerInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerInterface.php', '_PHPStan_33c983f26\\Psr\\Container\\NotFoundExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/NotFoundExceptionInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Client\\ClientExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/ClientExceptionInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Client\\ClientInterface' => __DIR__ . '/..' . '/psr/http-client/src/ClientInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Client\\NetworkExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/NetworkExceptionInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Client\\RequestExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/RequestExceptionInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\MessageInterface' => __DIR__ . '/..' . '/psr/http-message/src/MessageInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\RequestFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/RequestFactoryInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\RequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/RequestInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\ResponseFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/ResponseFactoryInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\ResponseInterface' => __DIR__ . '/..' . '/psr/http-message/src/ResponseInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\ServerRequestFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/ServerRequestFactoryInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\ServerRequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/ServerRequestInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\StreamFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/StreamFactoryInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\StreamInterface' => __DIR__ . '/..' . '/psr/http-message/src/StreamInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\UploadedFileFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/UploadedFileFactoryInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\UploadedFileInterface' => __DIR__ . '/..' . '/psr/http-message/src/UploadedFileInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\UriFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/UriFactoryInterface.php', '_PHPStan_33c983f26\\Psr\\Http\\Message\\UriInterface' => __DIR__ . '/..' . '/psr/http-message/src/UriInterface.php', '_PHPStan_33c983f26\\Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/src/AbstractLogger.php', '_PHPStan_33c983f26\\Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/src/InvalidArgumentException.php', '_PHPStan_33c983f26\\Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/psr/log/src/LogLevel.php', '_PHPStan_33c983f26\\Psr\\Log\\LoggerAwareInterface' => __DIR__ . '/..' . '/psr/log/src/LoggerAwareInterface.php', '_PHPStan_33c983f26\\Psr\\Log\\LoggerAwareTrait' => __DIR__ . '/..' . '/psr/log/src/LoggerAwareTrait.php', '_PHPStan_33c983f26\\Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/src/LoggerInterface.php', '_PHPStan_33c983f26\\Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/src/LoggerTrait.php', '_PHPStan_33c983f26\\Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/src/NullLogger.php', '_PHPStan_33c983f26\\React\\Cache\\ArrayCache' => __DIR__ . '/..' . '/react/cache/src/ArrayCache.php', '_PHPStan_33c983f26\\React\\Cache\\CacheInterface' => __DIR__ . '/..' . '/react/cache/src/CacheInterface.php', '_PHPStan_33c983f26\\React\\ChildProcess\\Process' => __DIR__ . '/..' . '/react/child-process/src/Process.php', '_PHPStan_33c983f26\\React\\Dns\\BadServerException' => __DIR__ . '/..' . '/react/dns/src/BadServerException.php', '_PHPStan_33c983f26\\React\\Dns\\Config\\Config' => __DIR__ . '/..' . '/react/dns/src/Config/Config.php', '_PHPStan_33c983f26\\React\\Dns\\Config\\HostsFile' => __DIR__ . '/..' . '/react/dns/src/Config/HostsFile.php', '_PHPStan_33c983f26\\React\\Dns\\Model\\Message' => __DIR__ . '/..' . '/react/dns/src/Model/Message.php', '_PHPStan_33c983f26\\React\\Dns\\Model\\Record' => __DIR__ . '/..' . '/react/dns/src/Model/Record.php', '_PHPStan_33c983f26\\React\\Dns\\Protocol\\BinaryDumper' => __DIR__ . '/..' . '/react/dns/src/Protocol/BinaryDumper.php', '_PHPStan_33c983f26\\React\\Dns\\Protocol\\Parser' => __DIR__ . '/..' . '/react/dns/src/Protocol/Parser.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\CachingExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/CachingExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\CancellationException' => __DIR__ . '/..' . '/react/dns/src/Query/CancellationException.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\CoopExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/CoopExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\ExecutorInterface' => __DIR__ . '/..' . '/react/dns/src/Query/ExecutorInterface.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\FallbackExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/FallbackExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\HostsFileExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/HostsFileExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\Query' => __DIR__ . '/..' . '/react/dns/src/Query/Query.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\RetryExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/RetryExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\SelectiveTransportExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/SelectiveTransportExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\TcpTransportExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/TcpTransportExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\TimeoutException' => __DIR__ . '/..' . '/react/dns/src/Query/TimeoutException.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\TimeoutExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/TimeoutExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\Query\\UdpTransportExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/UdpTransportExecutor.php', '_PHPStan_33c983f26\\React\\Dns\\RecordNotFoundException' => __DIR__ . '/..' . '/react/dns/src/RecordNotFoundException.php', '_PHPStan_33c983f26\\React\\Dns\\Resolver\\Factory' => __DIR__ . '/..' . '/react/dns/src/Resolver/Factory.php', '_PHPStan_33c983f26\\React\\Dns\\Resolver\\Resolver' => __DIR__ . '/..' . '/react/dns/src/Resolver/Resolver.php', '_PHPStan_33c983f26\\React\\Dns\\Resolver\\ResolverInterface' => __DIR__ . '/..' . '/react/dns/src/Resolver/ResolverInterface.php', '_PHPStan_33c983f26\\React\\EventLoop\\ExtEvLoop' => __DIR__ . '/..' . '/react/event-loop/src/ExtEvLoop.php', '_PHPStan_33c983f26\\React\\EventLoop\\ExtEventLoop' => __DIR__ . '/..' . '/react/event-loop/src/ExtEventLoop.php', '_PHPStan_33c983f26\\React\\EventLoop\\ExtLibevLoop' => __DIR__ . '/..' . '/react/event-loop/src/ExtLibevLoop.php', '_PHPStan_33c983f26\\React\\EventLoop\\ExtLibeventLoop' => __DIR__ . '/..' . '/react/event-loop/src/ExtLibeventLoop.php', '_PHPStan_33c983f26\\React\\EventLoop\\ExtUvLoop' => __DIR__ . '/..' . '/react/event-loop/src/ExtUvLoop.php', '_PHPStan_33c983f26\\React\\EventLoop\\Factory' => __DIR__ . '/..' . '/react/event-loop/src/Factory.php', '_PHPStan_33c983f26\\React\\EventLoop\\Loop' => __DIR__ . '/..' . '/react/event-loop/src/Loop.php', '_PHPStan_33c983f26\\React\\EventLoop\\LoopInterface' => __DIR__ . '/..' . '/react/event-loop/src/LoopInterface.php', '_PHPStan_33c983f26\\React\\EventLoop\\SignalsHandler' => __DIR__ . '/..' . '/react/event-loop/src/SignalsHandler.php', '_PHPStan_33c983f26\\React\\EventLoop\\StreamSelectLoop' => __DIR__ . '/..' . '/react/event-loop/src/StreamSelectLoop.php', '_PHPStan_33c983f26\\React\\EventLoop\\Tick\\FutureTickQueue' => __DIR__ . '/..' . '/react/event-loop/src/Tick/FutureTickQueue.php', '_PHPStan_33c983f26\\React\\EventLoop\\TimerInterface' => __DIR__ . '/..' . '/react/event-loop/src/TimerInterface.php', '_PHPStan_33c983f26\\React\\EventLoop\\Timer\\Timer' => __DIR__ . '/..' . '/react/event-loop/src/Timer/Timer.php', '_PHPStan_33c983f26\\React\\EventLoop\\Timer\\Timers' => __DIR__ . '/..' . '/react/event-loop/src/Timer/Timers.php', '_PHPStan_33c983f26\\React\\Promise\\Deferred' => __DIR__ . '/..' . '/react/promise/src/Deferred.php', '_PHPStan_33c983f26\\React\\Promise\\Exception\\CompositeException' => __DIR__ . '/..' . '/react/promise/src/Exception/CompositeException.php', '_PHPStan_33c983f26\\React\\Promise\\Exception\\LengthException' => __DIR__ . '/..' . '/react/promise/src/Exception/LengthException.php', '_PHPStan_33c983f26\\React\\Promise\\Internal\\CancellationQueue' => __DIR__ . '/..' . '/react/promise/src/Internal/CancellationQueue.php', '_PHPStan_33c983f26\\React\\Promise\\Internal\\FulfilledPromise' => __DIR__ . '/..' . '/react/promise/src/Internal/FulfilledPromise.php', '_PHPStan_33c983f26\\React\\Promise\\Internal\\RejectedPromise' => __DIR__ . '/..' . '/react/promise/src/Internal/RejectedPromise.php', '_PHPStan_33c983f26\\React\\Promise\\Promise' => __DIR__ . '/..' . '/react/promise/src/Promise.php', '_PHPStan_33c983f26\\React\\Promise\\PromiseInterface' => __DIR__ . '/..' . '/react/promise/src/PromiseInterface.php', '_PHPStan_33c983f26\\React\\Socket\\Connection' => __DIR__ . '/..' . '/react/socket/src/Connection.php', '_PHPStan_33c983f26\\React\\Socket\\ConnectionInterface' => __DIR__ . '/..' . '/react/socket/src/ConnectionInterface.php', '_PHPStan_33c983f26\\React\\Socket\\Connector' => __DIR__ . '/..' . '/react/socket/src/Connector.php', '_PHPStan_33c983f26\\React\\Socket\\ConnectorInterface' => __DIR__ . '/..' . '/react/socket/src/ConnectorInterface.php', '_PHPStan_33c983f26\\React\\Socket\\DnsConnector' => __DIR__ . '/..' . '/react/socket/src/DnsConnector.php', '_PHPStan_33c983f26\\React\\Socket\\FdServer' => __DIR__ . '/..' . '/react/socket/src/FdServer.php', '_PHPStan_33c983f26\\React\\Socket\\FixedUriConnector' => __DIR__ . '/..' . '/react/socket/src/FixedUriConnector.php', '_PHPStan_33c983f26\\React\\Socket\\HappyEyeBallsConnectionBuilder' => __DIR__ . '/..' . '/react/socket/src/HappyEyeBallsConnectionBuilder.php', '_PHPStan_33c983f26\\React\\Socket\\HappyEyeBallsConnector' => __DIR__ . '/..' . '/react/socket/src/HappyEyeBallsConnector.php', '_PHPStan_33c983f26\\React\\Socket\\LimitingServer' => __DIR__ . '/..' . '/react/socket/src/LimitingServer.php', '_PHPStan_33c983f26\\React\\Socket\\SecureConnector' => __DIR__ . '/..' . '/react/socket/src/SecureConnector.php', '_PHPStan_33c983f26\\React\\Socket\\SecureServer' => __DIR__ . '/..' . '/react/socket/src/SecureServer.php', '_PHPStan_33c983f26\\React\\Socket\\Server' => __DIR__ . '/..' . '/react/socket/src/Server.php', '_PHPStan_33c983f26\\React\\Socket\\ServerInterface' => __DIR__ . '/..' . '/react/socket/src/ServerInterface.php', '_PHPStan_33c983f26\\React\\Socket\\SocketServer' => __DIR__ . '/..' . '/react/socket/src/SocketServer.php', '_PHPStan_33c983f26\\React\\Socket\\StreamEncryption' => __DIR__ . '/..' . '/react/socket/src/StreamEncryption.php', '_PHPStan_33c983f26\\React\\Socket\\TcpConnector' => __DIR__ . '/..' . '/react/socket/src/TcpConnector.php', '_PHPStan_33c983f26\\React\\Socket\\TcpServer' => __DIR__ . '/..' . '/react/socket/src/TcpServer.php', '_PHPStan_33c983f26\\React\\Socket\\TimeoutConnector' => __DIR__ . '/..' . '/react/socket/src/TimeoutConnector.php', '_PHPStan_33c983f26\\React\\Socket\\UnixConnector' => __DIR__ . '/..' . '/react/socket/src/UnixConnector.php', '_PHPStan_33c983f26\\React\\Socket\\UnixServer' => __DIR__ . '/..' . '/react/socket/src/UnixServer.php', '_PHPStan_33c983f26\\React\\Stream\\CompositeStream' => __DIR__ . '/..' . '/react/stream/src/CompositeStream.php', '_PHPStan_33c983f26\\React\\Stream\\DuplexResourceStream' => __DIR__ . '/..' . '/react/stream/src/DuplexResourceStream.php', '_PHPStan_33c983f26\\React\\Stream\\DuplexStreamInterface' => __DIR__ . '/..' . '/react/stream/src/DuplexStreamInterface.php', '_PHPStan_33c983f26\\React\\Stream\\ReadableResourceStream' => __DIR__ . '/..' . '/react/stream/src/ReadableResourceStream.php', '_PHPStan_33c983f26\\React\\Stream\\ReadableStreamInterface' => __DIR__ . '/..' . '/react/stream/src/ReadableStreamInterface.php', '_PHPStan_33c983f26\\React\\Stream\\ThroughStream' => __DIR__ . '/..' . '/react/stream/src/ThroughStream.php', '_PHPStan_33c983f26\\React\\Stream\\Util' => __DIR__ . '/..' . '/react/stream/src/Util.php', '_PHPStan_33c983f26\\React\\Stream\\WritableResourceStream' => __DIR__ . '/..' . '/react/stream/src/WritableResourceStream.php', '_PHPStan_33c983f26\\React\\Stream\\WritableStreamInterface' => __DIR__ . '/..' . '/react/stream/src/WritableStreamInterface.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Chunk' => __DIR__ . '/..' . '/sebastian/diff/src/Chunk.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\ConfigurationException' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/ConfigurationException.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Diff' => __DIR__ . '/..' . '/sebastian/diff/src/Diff.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Differ' => __DIR__ . '/..' . '/sebastian/diff/src/Differ.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Exception' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/Exception.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/InvalidArgumentException.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Line' => __DIR__ . '/..' . '/sebastian/diff/src/Line.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\LongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/LongestCommonSubsequenceCalculator.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\MemoryEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Output\\AbstractChunkOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Output\\DiffOnlyOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Output\\DiffOutputBuilderInterface' => __DIR__ . '/..' . '/sebastian/diff/src/Output/DiffOutputBuilderInterface.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Output\\StrictUnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Output\\UnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\Parser' => __DIR__ . '/..' . '/sebastian/diff/src/Parser.php', '_PHPStan_33c983f26\\SebastianBergmann\\Diff\\TimeEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Application' => __DIR__ . '/..' . '/symfony/console/Application.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Attribute\\AsCommand' => __DIR__ . '/..' . '/symfony/console/Attribute/AsCommand.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\CI\\GithubActionReporter' => __DIR__ . '/..' . '/symfony/console/CI/GithubActionReporter.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Color' => __DIR__ . '/..' . '/symfony/console/Color.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => __DIR__ . '/..' . '/symfony/console/CommandLoader/CommandLoaderInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/ContainerCommandLoader.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/FactoryCommandLoader.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Command\\Command' => __DIR__ . '/..' . '/symfony/console/Command/Command.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Command\\CompleteCommand' => __DIR__ . '/..' . '/symfony/console/Command/CompleteCommand.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Command\\DumpCompletionCommand' => __DIR__ . '/..' . '/symfony/console/Command/DumpCompletionCommand.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Command\\HelpCommand' => __DIR__ . '/..' . '/symfony/console/Command/HelpCommand.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Command\\LazyCommand' => __DIR__ . '/..' . '/symfony/console/Command/LazyCommand.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Command\\ListCommand' => __DIR__ . '/..' . '/symfony/console/Command/ListCommand.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Command\\LockableTrait' => __DIR__ . '/..' . '/symfony/console/Command/LockableTrait.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Command\\SignalableCommandInterface' => __DIR__ . '/..' . '/symfony/console/Command/SignalableCommandInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Completion\\CompletionInput' => __DIR__ . '/..' . '/symfony/console/Completion/CompletionInput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Completion\\CompletionSuggestions' => __DIR__ . '/..' . '/symfony/console/Completion/CompletionSuggestions.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Completion\\Output\\BashCompletionOutput' => __DIR__ . '/..' . '/symfony/console/Completion/Output/BashCompletionOutput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Completion\\Output\\CompletionOutputInterface' => __DIR__ . '/..' . '/symfony/console/Completion/Output/CompletionOutputInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Completion\\Suggestion' => __DIR__ . '/..' . '/symfony/console/Completion/Suggestion.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\ConsoleEvents' => __DIR__ . '/..' . '/symfony/console/ConsoleEvents.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Cursor' => __DIR__ . '/..' . '/symfony/console/Cursor.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => __DIR__ . '/..' . '/symfony/console/DependencyInjection/AddConsoleCommandPass.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => __DIR__ . '/..' . '/symfony/console/Descriptor/ApplicationDescription.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Descriptor\\Descriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/Descriptor.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => __DIR__ . '/..' . '/symfony/console/Descriptor/DescriptorInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/JsonDescriptor.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/MarkdownDescriptor.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/TextDescriptor.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/XmlDescriptor.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\EventListener\\ErrorListener' => __DIR__ . '/..' . '/symfony/console/EventListener/ErrorListener.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleCommandEvent.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleErrorEvent.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Event\\ConsoleEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleEvent.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Event\\ConsoleSignalEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleSignalEvent.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleTerminateEvent.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => __DIR__ . '/..' . '/symfony/console/Exception/CommandNotFoundException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/console/Exception/ExceptionInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidArgumentException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Exception\\InvalidOptionException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidOptionException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/console/Exception/LogicException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Exception\\MissingInputException' => __DIR__ . '/..' . '/symfony/console/Exception/MissingInputException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Exception\\NamespaceNotFoundException' => __DIR__ . '/..' . '/symfony/console/Exception/NamespaceNotFoundException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/console/Exception/RuntimeException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatter' => __DIR__ . '/..' . '/symfony/console/Formatter/NullOutputFormatter.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatterStyle' => __DIR__ . '/..' . '/symfony/console/Formatter/NullOutputFormatterStyle.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Formatter\\OutputFormatter' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatter.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyle.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleStack.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Formatter\\WrappableOutputFormatterInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/WrappableOutputFormatterInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DebugFormatterHelper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\DescriptorHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DescriptorHelper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\Dumper' => __DIR__ . '/..' . '/symfony/console/Helper/Dumper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\FormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/FormatterHelper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\Helper' => __DIR__ . '/..' . '/symfony/console/Helper/Helper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\HelperInterface' => __DIR__ . '/..' . '/symfony/console/Helper/HelperInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\HelperSet' => __DIR__ . '/..' . '/symfony/console/Helper/HelperSet.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\InputAwareHelper' => __DIR__ . '/..' . '/symfony/console/Helper/InputAwareHelper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\ProcessHelper' => __DIR__ . '/..' . '/symfony/console/Helper/ProcessHelper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\ProgressBar' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressBar.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\ProgressIndicator' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressIndicator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\QuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/QuestionHelper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/SymfonyQuestionHelper.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\Table' => __DIR__ . '/..' . '/symfony/console/Helper/Table.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\TableCell' => __DIR__ . '/..' . '/symfony/console/Helper/TableCell.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\TableCellStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TableCellStyle.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\TableRows' => __DIR__ . '/..' . '/symfony/console/Helper/TableRows.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\TableSeparator' => __DIR__ . '/..' . '/symfony/console/Helper/TableSeparator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Helper\\TableStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TableStyle.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\ArgvInput' => __DIR__ . '/..' . '/symfony/console/Input/ArgvInput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\ArrayInput' => __DIR__ . '/..' . '/symfony/console/Input/ArrayInput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\Input' => __DIR__ . '/..' . '/symfony/console/Input/Input.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\InputArgument' => __DIR__ . '/..' . '/symfony/console/Input/InputArgument.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\InputAwareInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputAwareInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\InputDefinition' => __DIR__ . '/..' . '/symfony/console/Input/InputDefinition.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\InputInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\InputOption' => __DIR__ . '/..' . '/symfony/console/Input/InputOption.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\StreamableInputInterface' => __DIR__ . '/..' . '/symfony/console/Input/StreamableInputInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Input\\StringInput' => __DIR__ . '/..' . '/symfony/console/Input/StringInput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Logger\\ConsoleLogger' => __DIR__ . '/..' . '/symfony/console/Logger/ConsoleLogger.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\BufferedOutput' => __DIR__ . '/..' . '/symfony/console/Output/BufferedOutput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\ConsoleOutput' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleOutput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleOutputInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\ConsoleSectionOutput' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleSectionOutput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\NullOutput' => __DIR__ . '/..' . '/symfony/console/Output/NullOutput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\Output' => __DIR__ . '/..' . '/symfony/console/Output/Output.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\OutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/OutputInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\StreamOutput' => __DIR__ . '/..' . '/symfony/console/Output/StreamOutput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Output\\TrimmedBufferOutput' => __DIR__ . '/..' . '/symfony/console/Output/TrimmedBufferOutput.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Question\\ChoiceQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ChoiceQuestion.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ConfirmationQuestion.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Question\\Question' => __DIR__ . '/..' . '/symfony/console/Question/Question.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\SignalRegistry\\SignalRegistry' => __DIR__ . '/..' . '/symfony/console/SignalRegistry/SignalRegistry.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\SingleCommandApplication' => __DIR__ . '/..' . '/symfony/console/SingleCommandApplication.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Style\\OutputStyle' => __DIR__ . '/..' . '/symfony/console/Style/OutputStyle.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Style\\StyleInterface' => __DIR__ . '/..' . '/symfony/console/Style/StyleInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Style\\SymfonyStyle' => __DIR__ . '/..' . '/symfony/console/Style/SymfonyStyle.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Terminal' => __DIR__ . '/..' . '/symfony/console/Terminal.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Tester\\ApplicationTester' => __DIR__ . '/..' . '/symfony/console/Tester/ApplicationTester.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Tester\\CommandCompletionTester' => __DIR__ . '/..' . '/symfony/console/Tester/CommandCompletionTester.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Tester\\CommandTester' => __DIR__ . '/..' . '/symfony/console/Tester/CommandTester.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Tester\\Constraint\\CommandIsSuccessful' => __DIR__ . '/..' . '/symfony/console/Tester/Constraint/CommandIsSuccessful.php', '_PHPStan_33c983f26\\Symfony\\Component\\Console\\Tester\\TesterTrait' => __DIR__ . '/..' . '/symfony/console/Tester/TesterTrait.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Comparator\\Comparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/Comparator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Comparator\\DateComparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/DateComparator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Comparator\\NumberComparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/NumberComparator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Exception\\AccessDeniedException' => __DIR__ . '/..' . '/symfony/finder/Exception/AccessDeniedException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Exception\\DirectoryNotFoundException' => __DIR__ . '/..' . '/symfony/finder/Exception/DirectoryNotFoundException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Finder' => __DIR__ . '/..' . '/symfony/finder/Finder.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Gitignore' => __DIR__ . '/..' . '/symfony/finder/Gitignore.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Glob' => __DIR__ . '/..' . '/symfony/finder/Glob.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\CustomFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/CustomFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\DateRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/DateRangeFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\DepthRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/DepthRangeFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\ExcludeDirectoryFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FileTypeFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilecontentFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilenameFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\LazyIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/LazyIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/PathFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/SizeRangeFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\SortableIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/SortableIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\Iterator\\VcsIgnoredFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/VcsIgnoredFilterIterator.php', '_PHPStan_33c983f26\\Symfony\\Component\\Finder\\SplFileInfo' => __DIR__ . '/..' . '/symfony/finder/SplFileInfo.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/process/Exception/ExceptionInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/process/Exception/InvalidArgumentException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/process/Exception/LogicException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Exception\\ProcessFailedException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessFailedException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Exception\\ProcessSignaledException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessSignaledException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessTimedOutException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/process/Exception/RuntimeException.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\ExecutableFinder' => __DIR__ . '/..' . '/symfony/process/ExecutableFinder.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\InputStream' => __DIR__ . '/..' . '/symfony/process/InputStream.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\PhpExecutableFinder' => __DIR__ . '/..' . '/symfony/process/PhpExecutableFinder.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\PhpProcess' => __DIR__ . '/..' . '/symfony/process/PhpProcess.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Pipes\\AbstractPipes' => __DIR__ . '/..' . '/symfony/process/Pipes/AbstractPipes.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Pipes\\PipesInterface' => __DIR__ . '/..' . '/symfony/process/Pipes/PipesInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Pipes\\UnixPipes' => __DIR__ . '/..' . '/symfony/process/Pipes/UnixPipes.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Pipes\\WindowsPipes' => __DIR__ . '/..' . '/symfony/process/Pipes/WindowsPipes.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\Process' => __DIR__ . '/..' . '/symfony/process/Process.php', '_PHPStan_33c983f26\\Symfony\\Component\\Process\\ProcessUtils' => __DIR__ . '/..' . '/symfony/process/ProcessUtils.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\AbstractString' => __DIR__ . '/..' . '/symfony/string/AbstractString.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\AbstractUnicodeString' => __DIR__ . '/..' . '/symfony/string/AbstractUnicodeString.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\ByteString' => __DIR__ . '/..' . '/symfony/string/ByteString.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\CodePointString' => __DIR__ . '/..' . '/symfony/string/CodePointString.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/string/Exception/ExceptionInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/string/Exception/InvalidArgumentException.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/string/Exception/RuntimeException.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\Inflector\\EnglishInflector' => __DIR__ . '/..' . '/symfony/string/Inflector/EnglishInflector.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\Inflector\\FrenchInflector' => __DIR__ . '/..' . '/symfony/string/Inflector/FrenchInflector.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\Inflector\\InflectorInterface' => __DIR__ . '/..' . '/symfony/string/Inflector/InflectorInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\LazyString' => __DIR__ . '/..' . '/symfony/string/LazyString.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\Slugger\\AsciiSlugger' => __DIR__ . '/..' . '/symfony/string/Slugger/AsciiSlugger.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\Slugger\\SluggerInterface' => __DIR__ . '/..' . '/symfony/string/Slugger/SluggerInterface.php', '_PHPStan_33c983f26\\Symfony\\Component\\String\\UnicodeString' => __DIR__ . '/..' . '/symfony/string/UnicodeString.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\Attribute\\Required' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/Required.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/SubscribedService.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\ResetInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ResetInterface.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\ServiceLocatorTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceLocatorTrait.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\ServiceProviderInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceProviderInterface.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberInterface.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberTrait.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\Test\\ServiceLocatorTest' => __DIR__ . '/..' . '/symfony/service-contracts/Test/ServiceLocatorTest.php', '_PHPStan_33c983f26\\Symfony\\Contracts\\Service\\Test\\ServiceLocatorTestCase' => __DIR__ . '/..' . '/symfony/service-contracts/Test/ServiceLocatorTestCase.php', '_PHPStan_33c983f26\\Symfony\\Polyfill\\Ctype\\Ctype' => __DIR__ . '/..' . '/symfony/polyfill-ctype/Ctype.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\AttributeGroupsReflector' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/AttributeGroupsReflector.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Attributes' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/Attributes.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\CachedParser' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/CachedParser.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\ClassAttributeCollector' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/ClassAttributeCollector.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Collection' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/Collection.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Config' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/Config.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Datastore' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/Datastore.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Datastore\\FileDatastore' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/Datastore/FileDatastore.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Datastore\\RuntimeDatastore' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/Datastore/RuntimeDatastore.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\FakeAttribute' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/FakeAttribute.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Filter' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/Filter.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Filter\\Chain' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/Filter/Chain.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Filter\\ContentFilter' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/Filter/ContentFilter.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\ForClass' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/ForClass.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\MemoizeAttributeCollector' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/MemoizeAttributeCollector.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\MemoizeClassMapFilter' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/MemoizeClassMapFilter.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\MemoizeClassMapGenerator' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/MemoizeClassMapGenerator.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\ParameterAttributeCollector' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/ParameterAttributeCollector.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\Plugin' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/Plugin.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TargetClass' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/TargetClass.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TargetMethod' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/TargetMethod.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TargetMethodParameter' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/TargetMethodParameter.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TargetProperty' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/TargetProperty.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TransientCollection' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/TransientCollection.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TransientCollectionRenderer' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/TransientCollectionRenderer.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TransientTargetClass' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/TransientTargetClass.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TransientTargetMethod' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/TransientTargetMethod.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TransientTargetMethodParameter' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/TransientTargetMethodParameter.php', '_PHPStan_33c983f26\\olvlvl\\ComposerAttributeCollector\\TransientTargetProperty' => __DIR__ . '/..' . '/ondrejmirtes/composer-attribute-collector/src/TransientTargetProperty.php', ); public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { $loader->prefixLengthsPsr4 = ComposerStaticInitcd1bbf15618bee29b84872b5979c9478::$prefixLengthsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInitcd1bbf15618bee29b84872b5979c9478::$prefixDirsPsr4; $loader->classMap = ComposerStaticInitcd1bbf15618bee29b84872b5979c9478::$classMap; }, null, ClassLoader::class); } } array( 'name' => 'phpstan/phpstan-src', 'pretty_version' => '2.1.55', 'version' => '2.1.55.0', 'reference' => '33c983f26ff82e8e20904760a35fb7b1752eae3a', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => true, ), 'versions' => array( 'clue/ndjson-react' => array( 'pretty_version' => 'v1.3.0', 'version' => '1.3.0.0', 'reference' => '392dc165fce93b5bb5c637b67e59619223c931b0', 'type' => 'library', 'install_path' => __DIR__ . '/../clue/ndjson-react', 'aliases' => array(), 'dev_requirement' => false, ), 'composer/pcre' => array( 'pretty_version' => '3.3.1', 'version' => '3.3.1.0', 'reference' => '63aaeac21d7e775ff9bc9d45021e1745c97521c4', 'type' => 'library', 'install_path' => __DIR__ . '/./pcre', 'aliases' => array(), 'dev_requirement' => false, ), 'composer/semver' => array( 'pretty_version' => '3.4.4', 'version' => '3.4.4.0', 'reference' => '198166618906cb2de69b95d7d47e5fa8aa1b2b95', 'type' => 'library', 'install_path' => __DIR__ . '/./semver', 'aliases' => array(), 'dev_requirement' => false, ), 'composer/xdebug-handler' => array( 'pretty_version' => '3.0.5', 'version' => '3.0.5.0', 'reference' => '6c1925561632e83d60a44492e0b344cf48ab85ef', 'type' => 'library', 'install_path' => __DIR__ . '/./xdebug-handler', 'aliases' => array(), 'dev_requirement' => false, ), 'cweagans/composer-patches' => array( 'pretty_version' => '1.7.3', 'version' => '1.7.3.0', 'reference' => 'e190d4466fe2b103a55467dfa83fc2fecfcaf2db', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../cweagans/composer-patches', 'aliases' => array(), 'dev_requirement' => true, ), 'doctrine/instantiator' => array( 'pretty_version' => '1.5.0', 'version' => '1.5.0.0', 'reference' => '0a0fa9780f5d4e507415a065172d26a98d02047b', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/instantiator', 'aliases' => array(), 'dev_requirement' => true, ), 'evenement/evenement' => array( 'pretty_version' => 'v3.0.2', 'version' => '3.0.2.0', 'reference' => '0a16b0d71ab13284339abb99d9d2bd813640efbc', 'type' => 'library', 'install_path' => __DIR__ . '/../evenement/evenement', 'aliases' => array(), 'dev_requirement' => false, ), 'fidry/cpu-core-counter' => array( 'pretty_version' => '1.3.0', 'version' => '1.3.0.0', 'reference' => 'db9508f7b1474469d9d3c53b86f817e344732678', 'type' => 'library', 'install_path' => __DIR__ . '/../fidry/cpu-core-counter', 'aliases' => array(), 'dev_requirement' => false, ), 'grogy/php-parallel-lint' => array( 'dev_requirement' => true, 'replaced' => array( 0 => '*', ), ), 'guzzlehttp/guzzle' => array( 'pretty_version' => '7.10.0', 'version' => '7.10.0.0', 'reference' => 'b51ac707cfa420b7bfd4e4d5e510ba8008e822b4', 'type' => 'library', 'install_path' => __DIR__ . '/../guzzlehttp/guzzle', 'aliases' => array(), 'dev_requirement' => false, ), 'guzzlehttp/promises' => array( 'pretty_version' => '2.3.0', 'version' => '2.3.0.0', 'reference' => '481557b130ef3790cf82b713667b43030dc9c957', 'type' => 'library', 'install_path' => __DIR__ . '/../guzzlehttp/promises', 'aliases' => array(), 'dev_requirement' => false, ), 'guzzlehttp/psr7' => array( 'pretty_version' => '2.9.0', 'version' => '2.9.0.0', 'reference' => '7d0ed42f28e42d61352a7a79de682e5e67fec884', 'type' => 'library', 'install_path' => __DIR__ . '/../guzzlehttp/psr7', 'aliases' => array(), 'dev_requirement' => false, ), 'hoa/compiler' => array( 'pretty_version' => '3.17.08.08', 'version' => '3.17.08.08', 'reference' => 'aa09caf0bf28adae6654ca6ee415ee2f522672de', 'type' => 'library', 'install_path' => __DIR__ . '/../hoa/compiler', 'aliases' => array(), 'dev_requirement' => false, ), 'hoa/consistency' => array( 'pretty_version' => '1.17.05.02', 'version' => '1.17.05.02', 'reference' => 'fd7d0adc82410507f332516faf655b6ed22e4c2f', 'type' => 'library', 'install_path' => __DIR__ . '/../hoa/consistency', 'aliases' => array(), 'dev_requirement' => false, ), 'hoa/event' => array( 'pretty_version' => '1.17.01.13', 'version' => '1.17.01.13', 'reference' => '6c0060dced212ffa3af0e34bb46624f990b29c54', 'type' => 'library', 'install_path' => __DIR__ . '/../hoa/event', 'aliases' => array(), 'dev_requirement' => false, ), 'hoa/exception' => array( 'pretty_version' => '1.17.01.16', 'version' => '1.17.01.16', 'reference' => '091727d46420a3d7468ef0595651488bfc3a458f', 'type' => 'library', 'install_path' => __DIR__ . '/../hoa/exception', 'aliases' => array(), 'dev_requirement' => false, ), 'hoa/file' => array( 'pretty_version' => '1.17.07.11', 'version' => '1.17.07.11', 'reference' => '35cb979b779bc54918d2f9a4e02ed6c7a1fa67ca', 'type' => 'library', 'install_path' => __DIR__ . '/../hoa/file', 'aliases' => array(), 'dev_requirement' => false, ), 'hoa/iterator' => array( 'pretty_version' => '2.17.01.10', 'version' => '2.17.01.10', 'reference' => 'd1120ba09cb4ccd049c86d10058ab94af245f0cc', 'type' => 'library', 'install_path' => __DIR__ . '/../hoa/iterator', 'aliases' => array(), 'dev_requirement' => false, ), 'hoa/math' => array( 'pretty_version' => '1.17.05.16', 'version' => '1.17.05.16', 'reference' => '7150785d30f5d565704912116a462e9f5bc83a0c', 'type' => 'library', 'install_path' => __DIR__ . '/../hoa/math', 'aliases' => array(), 'dev_requirement' => false, ), 'hoa/protocol' => array( 'pretty_version' => '1.17.01.14', 'version' => '1.17.01.14', 'reference' => '5c2cf972151c45f373230da170ea015deecf19e2', 'type' => 'library', 'install_path' => __DIR__ . '/../hoa/protocol', 'aliases' => array(), 'dev_requirement' => false, ), 'hoa/regex' => array( 'pretty_version' => '1.17.01.13', 'version' => '1.17.01.13', 'reference' => '7e263a61b6fb45c1d03d8e5ef77668518abd5bec', 'type' => 'library', 'install_path' => __DIR__ . '/../hoa/regex', 'aliases' => array(), 'dev_requirement' => false, ), 'hoa/stream' => array( 'pretty_version' => '1.17.02.21', 'version' => '1.17.02.21', 'reference' => '3293cfffca2de10525df51436adf88a559151d82', 'type' => 'library', 'install_path' => __DIR__ . '/../hoa/stream', 'aliases' => array(), 'dev_requirement' => false, ), 'hoa/ustring' => array( 'pretty_version' => '4.17.01.16', 'version' => '4.17.01.16', 'reference' => 'e6326e2739178799b1fe3fdd92029f9517fa17a0', 'type' => 'library', 'install_path' => __DIR__ . '/../hoa/ustring', 'aliases' => array(), 'dev_requirement' => false, ), 'hoa/visitor' => array( 'pretty_version' => '2.17.01.16', 'version' => '2.17.01.16', 'reference' => 'c18fe1cbac98ae449e0d56e87469103ba08f224a', 'type' => 'library', 'install_path' => __DIR__ . '/../hoa/visitor', 'aliases' => array(), 'dev_requirement' => false, ), 'hoa/zformat' => array( 'pretty_version' => '1.17.01.10', 'version' => '1.17.01.10', 'reference' => '522c381a2a075d4b9dbb42eb4592dd09520e4ac2', 'type' => 'library', 'install_path' => __DIR__ . '/../hoa/zformat', 'aliases' => array(), 'dev_requirement' => false, ), 'jakub-onderka/php-parallel-lint' => array( 'dev_requirement' => true, 'replaced' => array( 0 => '*', ), ), 'jetbrains/phpstorm-stubs' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => 'fd1db82bb399e2cf3485c721337f45c398da5d12', 'type' => 'library', 'install_path' => __DIR__ . '/../jetbrains/phpstorm-stubs', 'aliases' => array( 0 => '9999999-dev', ), 'dev_requirement' => false, ), 'myclabs/deep-copy' => array( 'pretty_version' => '1.13.4', 'version' => '1.13.4.0', 'reference' => '07d290f0c47959fd5eed98c95ee5602db07e0b6a', 'type' => 'library', 'install_path' => __DIR__ . '/../myclabs/deep-copy', 'aliases' => array(), 'dev_requirement' => true, ), 'nette/bootstrap' => array( 'pretty_version' => 'v3.1.4', 'version' => '3.1.4.0', 'reference' => '1a7965b4ee401ad0e3f673b9c016d2481afdc280', 'type' => 'library', 'install_path' => __DIR__ . '/../nette/bootstrap', 'aliases' => array(), 'dev_requirement' => false, ), 'nette/di' => array( 'pretty_version' => 'v3.1.5', 'version' => '3.1.5.0', 'reference' => '00ea0afa643b3b4383a5cd1a322656c989ade498', 'type' => 'library', 'install_path' => __DIR__ . '/../nette/di', 'aliases' => array(), 'dev_requirement' => false, ), 'nette/finder' => array( 'pretty_version' => 'v2.6.0', 'version' => '2.6.0.0', 'reference' => '991aefb42860abeab8e003970c3809a9d83cb932', 'type' => 'library', 'install_path' => __DIR__ . '/../nette/finder', 'aliases' => array(), 'dev_requirement' => false, ), 'nette/neon' => array( 'pretty_version' => 'v3.3.4', 'version' => '3.3.4.0', 'reference' => 'bb88bf3a54dd21bf4dbddb5cd525d7b0c61b7cda', 'type' => 'library', 'install_path' => __DIR__ . '/../nette/neon', 'aliases' => array(), 'dev_requirement' => false, ), 'nette/php-generator' => array( 'pretty_version' => 'v3.6.9', 'version' => '3.6.9.0', 'reference' => 'd31782f7bd2ae84ad06f863391ec3fb77ca4d0a6', 'type' => 'library', 'install_path' => __DIR__ . '/../nette/php-generator', 'aliases' => array(), 'dev_requirement' => false, ), 'nette/robot-loader' => array( 'pretty_version' => 'v3.4.1', 'version' => '3.4.1.0', 'reference' => 'e2adc334cb958164c050f485d99c44c430f51fe2', 'type' => 'library', 'install_path' => __DIR__ . '/../nette/robot-loader', 'aliases' => array(), 'dev_requirement' => false, ), 'nette/schema' => array( 'pretty_version' => 'v1.2.5', 'version' => '1.2.5.0', 'reference' => '0462f0166e823aad657c9224d0f849ecac1ba10a', 'type' => 'library', 'install_path' => __DIR__ . '/../nette/schema', 'aliases' => array(), 'dev_requirement' => false, ), 'nette/utils' => array( 'pretty_version' => 'v3.2.10', 'version' => '3.2.10.0', 'reference' => 'a4175c62652f2300c8017fb7e640f9ccb11648d2', 'type' => 'library', 'install_path' => __DIR__ . '/../nette/utils', 'aliases' => array(), 'dev_requirement' => false, ), 'nikic/php-parser' => array( 'pretty_version' => 'v5.7.0', 'version' => '5.7.0.0', 'reference' => 'dca41cd15c2ac9d055ad70dbfd011130757d1f82', 'type' => 'library', 'install_path' => __DIR__ . '/../nikic/php-parser', 'aliases' => array(), 'dev_requirement' => false, ), 'ondram/ci-detector' => array( 'pretty_version' => '4.2.0', 'version' => '4.2.0.0', 'reference' => '8b0223b5ed235fd377c75fdd1bfcad05c0f168b8', 'type' => 'library', 'install_path' => __DIR__ . '/../ondram/ci-detector', 'aliases' => array(), 'dev_requirement' => false, ), 'ondrejmirtes/better-reflection' => array( 'pretty_version' => '6.70.0.1', 'version' => '6.70.0.1', 'reference' => '5d4c1d6bef6a121f3faae454e0a4eb38d0531936', 'type' => 'library', 'install_path' => __DIR__ . '/../ondrejmirtes/better-reflection', 'aliases' => array(), 'dev_requirement' => false, ), 'ondrejmirtes/composer-attribute-collector' => array( 'pretty_version' => '1.1.1', 'version' => '1.1.1.0', 'reference' => '48124ab07a5e19b7bd0ad20c791a8ff0bf3feab9', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../ondrejmirtes/composer-attribute-collector', 'aliases' => array(), 'dev_requirement' => false, ), 'ondrejmirtes/php-merge' => array( 'pretty_version' => '4.1.2', 'version' => '4.1.2.0', 'reference' => '0c661fbe3efde0619f3652688862ed65f1f34dd1', 'type' => 'library', 'install_path' => __DIR__ . '/../ondrejmirtes/php-merge', 'aliases' => array(), 'dev_requirement' => false, ), '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-parallel-lint/php-parallel-lint' => array( 'pretty_version' => 'v1.4.0', 'version' => '1.4.0.0', 'reference' => '6db563514f27e19595a19f45a4bf757b6401194e', 'type' => 'library', 'install_path' => __DIR__ . '/../php-parallel-lint/php-parallel-lint', 'aliases' => array(), 'dev_requirement' => true, ), 'phpstan/php-8-stubs' => array( 'pretty_version' => '0.4.35', 'version' => '0.4.35.0', 'reference' => '1dbd55178db0faa8f85dc262985b858657990923', 'type' => 'library', 'install_path' => __DIR__ . '/../phpstan/php-8-stubs', 'aliases' => array(), 'dev_requirement' => false, ), 'phpstan/phpdoc-parser' => array( 'pretty_version' => '2.3.2', 'version' => '2.3.2.0', 'reference' => 'a004701b11273a26cd7955a61d67a7f1e525a45a', 'type' => 'library', 'install_path' => __DIR__ . '/../phpstan/phpdoc-parser', 'aliases' => array(), 'dev_requirement' => false, ), 'phpstan/phpstan' => array( 'dev_requirement' => false, 'replaced' => array( 0 => '2.1.x', ), ), 'phpstan/phpstan-deprecation-rules' => array( 'pretty_version' => '2.0.4', 'version' => '2.0.4.0', 'reference' => '6b5571001a7f04fa0422254c30a0017ec2f2cacc', 'type' => 'phpstan-extension', 'install_path' => __DIR__ . '/../phpstan/phpstan-deprecation-rules', 'aliases' => array(), 'dev_requirement' => true, ), 'phpstan/phpstan-nette' => array( 'pretty_version' => '2.0.9', 'version' => '2.0.9.0', 'reference' => 'abd2b295fac8258fb294fd5dc17c5e024c6e3c89', 'type' => 'phpstan-extension', 'install_path' => __DIR__ . '/../phpstan/phpstan-nette', 'aliases' => array(), 'dev_requirement' => true, ), 'phpstan/phpstan-phpunit' => array( 'pretty_version' => '2.0.15', 'version' => '2.0.15.0', 'reference' => '0f6ba8e22a3e919353a8f4615ea3cd2e91626c7f', 'type' => 'phpstan-extension', 'install_path' => __DIR__ . '/../phpstan/phpstan-phpunit', 'aliases' => array(), 'dev_requirement' => true, ), 'phpstan/phpstan-src' => array( 'pretty_version' => '2.1.55', 'version' => '2.1.55.0', 'reference' => '33c983f26ff82e8e20904760a35fb7b1752eae3a', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => false, ), 'phpstan/phpstan-strict-rules' => array( 'pretty_version' => '2.0.10', 'version' => '2.0.10.0', 'reference' => '1aba28b697c1e3b6bbec8a1725f8b11b6d3e5a5f', 'type' => 'phpstan-extension', 'install_path' => __DIR__ . '/../phpstan/phpstan-strict-rules', 'aliases' => array(), 'dev_requirement' => true, ), 'phpunit/php-code-coverage' => array( 'pretty_version' => '9.2.32', 'version' => '9.2.32.0', 'reference' => '85402a822d1ecf1db1096959413d35e1c37cf1a5', 'type' => 'library', 'install_path' => __DIR__ . '/../phpunit/php-code-coverage', 'aliases' => array(), 'dev_requirement' => true, ), 'phpunit/php-file-iterator' => array( 'pretty_version' => '3.0.6', 'version' => '3.0.6.0', 'reference' => 'cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf', 'type' => 'library', 'install_path' => __DIR__ . '/../phpunit/php-file-iterator', 'aliases' => array(), 'dev_requirement' => true, ), 'phpunit/php-invoker' => array( 'pretty_version' => '3.1.1', 'version' => '3.1.1.0', 'reference' => '5a10147d0aaf65b58940a0b72f71c9ac0423cc67', 'type' => 'library', 'install_path' => __DIR__ . '/../phpunit/php-invoker', 'aliases' => array(), 'dev_requirement' => true, ), 'phpunit/php-text-template' => array( 'pretty_version' => '2.0.4', 'version' => '2.0.4.0', 'reference' => '5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28', 'type' => 'library', 'install_path' => __DIR__ . '/../phpunit/php-text-template', 'aliases' => array(), 'dev_requirement' => true, ), 'phpunit/php-timer' => array( 'pretty_version' => '5.0.3', 'version' => '5.0.3.0', 'reference' => '5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2', 'type' => 'library', 'install_path' => __DIR__ . '/../phpunit/php-timer', 'aliases' => array(), 'dev_requirement' => true, ), 'phpunit/phpunit' => array( 'pretty_version' => '9.6.34', 'version' => '9.6.34.0', 'reference' => 'b36f02317466907a230d3aa1d34467041271ef4a', 'type' => 'library', 'install_path' => __DIR__ . '/../phpunit/phpunit', 'aliases' => array(), 'dev_requirement' => true, ), 'psr/container' => array( 'pretty_version' => '1.1.2', 'version' => '1.1.2.0', 'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/container', 'aliases' => array(), 'dev_requirement' => false, ), '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' => false, ), '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, ), 'react/cache' => array( 'pretty_version' => 'v1.2.0', 'version' => '1.2.0.0', 'reference' => 'd47c472b64aa5608225f47965a484b75c7817d5b', 'type' => 'library', 'install_path' => __DIR__ . '/../react/cache', 'aliases' => array(), 'dev_requirement' => false, ), 'react/child-process' => array( 'pretty_version' => '0.7.x-dev', 'version' => '0.7.9999999.9999999-dev', 'reference' => 'dfc3fe92ddf58646a2a17908180db712752f23a9', 'type' => 'library', 'install_path' => __DIR__ . '/../react/child-process', 'aliases' => array(), 'dev_requirement' => false, ), 'react/dns' => array( 'pretty_version' => 'v1.14.0', 'version' => '1.14.0.0', 'reference' => '7562c05391f42701c1fccf189c8225fece1cd7c3', 'type' => 'library', 'install_path' => __DIR__ . '/../react/dns', 'aliases' => array(), 'dev_requirement' => false, ), 'react/event-loop' => array( 'pretty_version' => 'v1.6.0', 'version' => '1.6.0.0', 'reference' => 'ba276bda6083df7e0050fd9b33f66ad7a4ac747a', 'type' => 'library', 'install_path' => __DIR__ . '/../react/event-loop', 'aliases' => array(), 'dev_requirement' => false, ), 'react/promise' => array( 'pretty_version' => 'v3.3.0', 'version' => '3.3.0.0', 'reference' => '23444f53a813a3296c1368bb104793ce8d88f04a', 'type' => 'library', 'install_path' => __DIR__ . '/../react/promise', 'aliases' => array(), 'dev_requirement' => false, ), 'react/socket' => array( 'pretty_version' => 'v1.17.0', 'version' => '1.17.0.0', 'reference' => 'ef5b17b81f6f60504c539313f94f2d826c5faa08', 'type' => 'library', 'install_path' => __DIR__ . '/../react/socket', 'aliases' => array(), 'dev_requirement' => false, ), 'react/stream' => array( 'pretty_version' => 'v1.4.0', 'version' => '1.4.0.0', 'reference' => '1e5b0acb8fe55143b5b426817155190eb6f5b18d', 'type' => 'library', 'install_path' => __DIR__ . '/../react/stream', 'aliases' => array(), 'dev_requirement' => false, ), 'sebastian/cli-parser' => array( 'pretty_version' => '1.0.2', 'version' => '1.0.2.0', 'reference' => '2b56bea83a09de3ac06bb18b92f068e60cc6f50b', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/cli-parser', 'aliases' => array(), 'dev_requirement' => true, ), 'sebastian/code-unit' => array( 'pretty_version' => '1.0.8', 'version' => '1.0.8.0', 'reference' => '1fc9f64c0927627ef78ba436c9b17d967e68e120', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/code-unit', 'aliases' => array(), 'dev_requirement' => true, ), 'sebastian/code-unit-reverse-lookup' => array( 'pretty_version' => '2.0.3', 'version' => '2.0.3.0', 'reference' => 'ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/code-unit-reverse-lookup', 'aliases' => array(), 'dev_requirement' => true, ), 'sebastian/comparator' => array( 'pretty_version' => '4.0.10', 'version' => '4.0.10.0', 'reference' => 'e4df00b9b3571187db2831ae9aada2c6efbd715d', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/comparator', 'aliases' => array(), 'dev_requirement' => true, ), 'sebastian/complexity' => array( 'pretty_version' => '2.0.3', 'version' => '2.0.3.0', 'reference' => '25f207c40d62b8b7aa32f5ab026c53561964053a', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/complexity', 'aliases' => array(), 'dev_requirement' => true, ), 'sebastian/diff' => array( 'pretty_version' => '4.0.6', 'version' => '4.0.6.0', 'reference' => 'ba01945089c3a293b01ba9badc29ad55b106b0bc', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/diff', 'aliases' => array(), 'dev_requirement' => false, ), 'sebastian/environment' => array( 'pretty_version' => '5.1.5', 'version' => '5.1.5.0', 'reference' => '830c43a844f1f8d5b7a1f6d6076b784454d8b7ed', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/environment', 'aliases' => array(), 'dev_requirement' => true, ), 'sebastian/exporter' => array( 'pretty_version' => '4.0.8', 'version' => '4.0.8.0', 'reference' => '14c6ba52f95a36c3d27c835d65efc7123c446e8c', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/exporter', 'aliases' => array(), 'dev_requirement' => true, ), 'sebastian/global-state' => array( 'pretty_version' => '5.0.8', 'version' => '5.0.8.0', 'reference' => 'b6781316bdcd28260904e7cc18ec983d0d2ef4f6', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/global-state', 'aliases' => array(), 'dev_requirement' => true, ), 'sebastian/lines-of-code' => array( 'pretty_version' => '1.0.4', 'version' => '1.0.4.0', 'reference' => 'e1e4a170560925c26d424b6a03aed157e7dcc5c5', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/lines-of-code', 'aliases' => array(), 'dev_requirement' => true, ), 'sebastian/object-enumerator' => array( 'pretty_version' => '4.0.4', 'version' => '4.0.4.0', 'reference' => '5c9eeac41b290a3712d88851518825ad78f45c71', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/object-enumerator', 'aliases' => array(), 'dev_requirement' => true, ), 'sebastian/object-reflector' => array( 'pretty_version' => '2.0.4', 'version' => '2.0.4.0', 'reference' => 'b4f479ebdbf63ac605d183ece17d8d7fe49c15c7', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/object-reflector', 'aliases' => array(), 'dev_requirement' => true, ), 'sebastian/recursion-context' => array( 'pretty_version' => '4.0.6', 'version' => '4.0.6.0', 'reference' => '539c6691e0623af6dc6f9c20384c120f963465a0', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/recursion-context', 'aliases' => array(), 'dev_requirement' => true, ), 'sebastian/resource-operations' => array( 'pretty_version' => '3.0.4', 'version' => '3.0.4.0', 'reference' => '05d5692a7993ecccd56a03e40cd7e5b09b1d404e', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/resource-operations', 'aliases' => array(), 'dev_requirement' => true, ), 'sebastian/type' => array( 'pretty_version' => '3.2.1', 'version' => '3.2.1.0', 'reference' => '75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/type', 'aliases' => array(), 'dev_requirement' => true, ), 'sebastian/version' => array( 'pretty_version' => '3.0.2', 'version' => '3.0.2.0', 'reference' => 'c6c1022351a901512170118436c764e473f6de8c', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/version', 'aliases' => array(), 'dev_requirement' => true, ), 'shipmonk/composer-dependency-analyser' => array( 'pretty_version' => '1.7.0', 'version' => '1.7.0.0', 'reference' => 'bca862b2830a453734aee048eb0cdab82e5c9da3', 'type' => 'library', 'install_path' => __DIR__ . '/../shipmonk/composer-dependency-analyser', 'aliases' => array(), 'dev_requirement' => true, ), 'shipmonk/dead-code-detector' => array( 'pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'dd909a6e267ae03837f166bc5e9d2f0851b14ff0', 'type' => 'phpstan-extension', 'install_path' => __DIR__ . '/../shipmonk/dead-code-detector', 'aliases' => array(), 'dev_requirement' => true, ), 'shipmonk/name-collision-detector' => array( 'pretty_version' => '2.1.1', 'version' => '2.1.1.0', 'reference' => 'e8c8267a9a3774450b64f4cbf0bb035108e78f07', 'type' => 'library', 'install_path' => __DIR__ . '/../shipmonk/name-collision-detector', '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.6.0', 'version' => '3.6.0.0', 'reference' => '63afe740e99a13ba87ec199bb07bbdee937a5b62', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/finder' => array( 'pretty_version' => 'v5.4.45', 'version' => '5.4.45.0', 'reference' => '63741784cd7b9967975eec610b256eed3ede022b', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/finder', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-ctype' => array( 'pretty_version' => 'v1.34.0', 'version' => '1.34.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.34.0', 'version' => '1.34.0.0', 'reference' => 'ad1b7b9092976d6c948b8a187cec9faaea9ec1df', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-intl-normalizer' => array( 'pretty_version' => 'v1.34.0', 'version' => '1.34.0.0', 'reference' => '3833d7255cc303546435cb650316bff708a1c75c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-mbstring' => array( 'pretty_version' => 'v1.34.0', 'version' => '1.34.0.0', 'reference' => '6a21eb99c6973357967f6ce3708cd55a6bec6315', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-php73' => array( 'dev_requirement' => false, 'replaced' => array( 0 => '*', ), ), 'symfony/polyfill-php80' => array( 'pretty_version' => 'v1.34.0', 'version' => '1.34.0.0', 'reference' => 'dfb55726c3a76ea3b6459fcfda1ec2d80a682411', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php80', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-php81' => array( 'pretty_version' => 'v1.34.0', 'version' => '1.34.0.0', 'reference' => '4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php81', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-php83' => array( 'pretty_version' => 'v1.34.0', 'version' => '1.34.0.0', 'reference' => '3600c2cb22399e25bb226e4a135ce91eeb2a6149', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php83', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-php84' => array( 'pretty_version' => 'v1.34.0', 'version' => '1.34.0.0', 'reference' => '88486db2c389b290bf87ff1de7ebc1e13e42bb06', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php84', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-php85' => array( 'pretty_version' => 'v1.34.0', 'version' => '1.34.0.0', 'reference' => '2c408a6bb0313e6001a83628dc5506100474254e', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php85', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/process' => array( 'pretty_version' => 'v5.4.51', 'version' => '5.4.51.0', 'reference' => '467bfc56f18f5ef6d5ccb09324d7e988c1c0a98f', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/process', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/service-contracts' => array( 'pretty_version' => 'v2.5.4', 'version' => '2.5.4.0', 'reference' => 'f37b419f7aea2e9abf10abd261832cace12e3300', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/service-contracts', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/string' => array( 'pretty_version' => 'v5.4.47', 'version' => '5.4.47.0', 'reference' => '136ca7d72f72b599f2631aca474a4f8e26719799', '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, ), ), ); Copyright (C) 2021 Composer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. services: - class: _PHPStan_33c983f26\Composer\Pcre\PHPStan\PregMatchParameterOutTypeExtension tags: - phpstan.staticMethodParameterOutTypeExtension - class: _PHPStan_33c983f26\Composer\Pcre\PHPStan\PregMatchTypeSpecifyingExtension tags: - phpstan.typeSpecifier.staticMethodTypeSpecifyingExtension - class: _PHPStan_33c983f26\Composer\Pcre\PHPStan\PregReplaceCallbackClosureTypeExtension tags: - phpstan.staticMethodParameterClosureTypeExtension rules: - Composer\Pcre\PHPStan\UnsafeStrictGroupsCallRule - Composer\Pcre\PHPStan\InvalidRegexPatternRule * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Pcre; final class MatchAllResult { /** * An array of match group => list of matched strings * * @readonly * @var array> */ public $matches; /** * @readonly * @var 0|positive-int */ public $count; /** * @readonly * @var bool */ public $matched; /** * @param 0|positive-int $count * @param array> $matches */ public function __construct(int $count, array $matches) { $this->matches = $matches; $this->matched = (bool) $count; $this->count = $count; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Pcre; final class MatchAllStrictGroupsResult { /** * An array of match group => list of matched strings * * @readonly * @var array> */ public $matches; /** * @readonly * @var 0|positive-int */ public $count; /** * @readonly * @var bool */ public $matched; /** * @param 0|positive-int $count * @param array> $matches */ public function __construct(int $count, array $matches) { $this->matches = $matches; $this->matched = (bool) $count; $this->count = $count; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Pcre; final class MatchAllWithOffsetsResult { /** * An array of match group => list of matches, every match being a pair of string matched + offset in bytes (or -1 if no match) * * @readonly * @var array> * @phpstan-var array}>> */ public $matches; /** * @readonly * @var 0|positive-int */ public $count; /** * @readonly * @var bool */ public $matched; /** * @param 0|positive-int $count * @param array> $matches * @phpstan-param array}>> $matches */ public function __construct(int $count, array $matches) { $this->matches = $matches; $this->matched = (bool) $count; $this->count = $count; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Pcre; final class MatchResult { /** * An array of match group => string matched * * @readonly * @var array */ public $matches; /** * @readonly * @var bool */ public $matched; /** * @param 0|positive-int $count * @param array $matches */ public function __construct(int $count, array $matches) { $this->matches = $matches; $this->matched = (bool) $count; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Pcre; final class MatchStrictGroupsResult { /** * An array of match group => string matched * * @readonly * @var array */ public $matches; /** * @readonly * @var bool */ public $matched; /** * @param 0|positive-int $count * @param array $matches */ public function __construct(int $count, array $matches) { $this->matches = $matches; $this->matched = (bool) $count; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Pcre; final class MatchWithOffsetsResult { /** * An array of match group => pair of string matched + offset in bytes (or -1 if no match) * * @readonly * @var array * @phpstan-var array}> */ public $matches; /** * @readonly * @var bool */ public $matched; /** * @param 0|positive-int $count * @param array $matches * @phpstan-param array}> $matches */ public function __construct(int $count, array $matches) { $this->matches = $matches; $this->matched = (bool) $count; } } */ class InvalidRegexPatternRule implements Rule { public function getNodeType(): string { return StaticCall::class; } public function processNode(Node $node, Scope $scope): array { $patterns = $this->extractPatterns($node, $scope); $errors = []; foreach ($patterns as $pattern) { $errorMessage = $this->validatePattern($pattern); if ($errorMessage === null) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Regex pattern is invalid: %s', $errorMessage))->identifier('regexp.pattern')->build(); } return $errors; } /** * @return string[] */ private function extractPatterns(StaticCall $node, Scope $scope): array { if (!$node->class instanceof FullyQualified) { return []; } $isRegex = $node->class->toString() === Regex::class; $isPreg = $node->class->toString() === Preg::class; if (!$isRegex && !$isPreg) { return []; } if (!$node->name instanceof Node\Identifier || !Preg::isMatch('{^(match|isMatch|grep|replace|split)}', $node->name->name)) { return []; } $functionName = $node->name->name; if (!isset($node->getArgs()[0])) { return []; } $patternNode = $node->getArgs()[0]->value; $patternType = $scope->getType($patternNode); $patternStrings = []; foreach ($patternType->getConstantStrings() as $constantStringType) { if ($functionName === 'replaceCallbackArray') { continue; } $patternStrings[] = $constantStringType->getValue(); } foreach ($patternType->getConstantArrays() as $constantArrayType) { if (in_array($functionName, ['replace', 'replaceCallback'], \true)) { foreach ($constantArrayType->getValueTypes() as $arrayKeyType) { foreach ($arrayKeyType->getConstantStrings() as $constantString) { $patternStrings[] = $constantString->getValue(); } } } if ($functionName !== 'replaceCallbackArray') { continue; } foreach ($constantArrayType->getKeyTypes() as $arrayKeyType) { foreach ($arrayKeyType->getConstantStrings() as $constantString) { $patternStrings[] = $constantString->getValue(); } } } return $patternStrings; } private function validatePattern(string $pattern): ?string { try { $msg = null; $prev = set_error_handler(function (int $severity, string $message, string $file) use (&$msg): bool { $msg = preg_replace("#^preg_match(_all)?\\(.*?\\): #", '', $message); return \true; }); if ($pattern === '') { return 'Empty string is not a valid regular expression'; } Preg::match($pattern, ''); if ($msg !== null) { return $msg; } } catch (PcreException $e) { if ($e->getCode() === \PREG_INTERNAL_ERROR && $msg !== null) { return $msg; } return preg_replace('{.*? failed executing ".*": }', '', $e->getMessage()); } finally { restore_error_handler(); } return null; } } getType($flagsArg->value); $constantScalars = $flagsType->getConstantScalarValues(); if ($constantScalars === []) { return null; } $internalFlagsTypes = []; foreach ($flagsType->getConstantScalarValues() as $constantScalarValue) { if (!is_int($constantScalarValue)) { return null; } $internalFlagsTypes[] = new ConstantIntegerType($constantScalarValue | \PREG_UNMATCHED_AS_NULL); } return TypeCombinator::union(...$internalFlagsTypes); } public static function removeNullFromMatches(Type $matchesType): Type { return TypeTraverser::map($matchesType, static function (Type $type, callable $traverse): Type { if ($type instanceof UnionType || $type instanceof IntersectionType) { return $traverse($type); } if ($type instanceof ConstantArrayType) { return new ConstantArrayType($type->getKeyTypes(), array_map(static function (Type $valueType) use ($traverse): Type { return $traverse($valueType); }, $type->getValueTypes()), $type->getNextAutoIndexes(), [], $type->isList()); } if ($type instanceof ArrayType) { return new ArrayType($type->getKeyType(), $traverse($type->getItemType())); } return TypeCombinator::removeNull($type); }); } } regexShapeMatcher = $regexShapeMatcher; } public function isStaticMethodSupported(MethodReflection $methodReflection, ParameterReflection $parameter): bool { return $methodReflection->getDeclaringClass()->getName() === Preg::class && in_array($methodReflection->getName(), ['match', 'isMatch', 'matchStrictGroups', 'isMatchStrictGroups', 'matchAll', 'isMatchAll', 'matchAllStrictGroups', 'isMatchAllStrictGroups'], \true) && $parameter->getName() === 'matches'; } public function getParameterOutTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, ParameterReflection $parameter, Scope $scope): ?Type { $args = $methodCall->getArgs(); $patternArg = $args[0] ?? null; $matchesArg = $args[2] ?? null; $flagsArg = $args[3] ?? null; if ($patternArg === null || $matchesArg === null) { return null; } $flagsType = \Composer\Pcre\PHPStan\PregMatchFlags::getType($flagsArg, $scope); if ($flagsType === null) { return null; } if (stripos($methodReflection->getName(), 'matchAll') !== \false) { return $this->regexShapeMatcher->matchAllExpr($patternArg->value, $flagsType, TrinaryLogic::createMaybe(), $scope); } return $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createMaybe(), $scope); } } regexShapeMatcher = $regexShapeMatcher; } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void { $this->typeSpecifier = $typeSpecifier; } public function getClass(): string { return Preg::class; } public function isStaticMethodSupported(MethodReflection $methodReflection, StaticCall $node, TypeSpecifierContext $context): bool { return in_array($methodReflection->getName(), ['match', 'isMatch', 'matchStrictGroups', 'isMatchStrictGroups', 'matchAll', 'isMatchAll', 'matchAllStrictGroups', 'isMatchAllStrictGroups'], \true) && !$context->null(); } public function specifyTypes(MethodReflection $methodReflection, StaticCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes { $args = $node->getArgs(); $patternArg = $args[0] ?? null; $matchesArg = $args[2] ?? null; $flagsArg = $args[3] ?? null; if ($patternArg === null || $matchesArg === null) { return new SpecifiedTypes(); } $flagsType = \Composer\Pcre\PHPStan\PregMatchFlags::getType($flagsArg, $scope); if ($flagsType === null) { return new SpecifiedTypes(); } if (stripos($methodReflection->getName(), 'matchAll') !== \false) { $matchedType = $this->regexShapeMatcher->matchAllExpr($patternArg->value, $flagsType, TrinaryLogic::createFromBoolean($context->true()), $scope); } else { $matchedType = $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createFromBoolean($context->true()), $scope); } if ($matchedType === null) { return new SpecifiedTypes(); } if (in_array($methodReflection->getName(), ['matchStrictGroups', 'isMatchStrictGroups', 'matchAllStrictGroups', 'isMatchAllStrictGroups'], \true)) { $matchedType = \Composer\Pcre\PHPStan\PregMatchFlags::removeNullFromMatches($matchedType); } $overwrite = \false; if ($context->false()) { $overwrite = \true; $context = $context->negate(); } return $this->typeSpecifier->create($matchesArg->value, $matchedType, $context, $overwrite, $scope, $node); } } regexShapeMatcher = $regexShapeMatcher; } public function isStaticMethodSupported(MethodReflection $methodReflection, ParameterReflection $parameter): bool { return in_array($methodReflection->getDeclaringClass()->getName(), [Preg::class, Regex::class], \true) && in_array($methodReflection->getName(), ['replaceCallback', 'replaceCallbackStrictGroups'], \true) && $parameter->getName() === 'replacement'; } public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, ParameterReflection $parameter, Scope $scope): ?Type { $args = $methodCall->getArgs(); $patternArg = $args[0] ?? null; $flagsArg = $args[5] ?? null; if ($patternArg === null) { return null; } $flagsType = \Composer\Pcre\PHPStan\PregMatchFlags::getType($flagsArg, $scope); $matchesType = $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createYes(), $scope); if ($matchesType === null) { return null; } if ($methodReflection->getName() === 'replaceCallbackStrictGroups' && count($matchesType->getConstantArrays()) === 1) { $matchesType = $matchesType->getConstantArrays()[0]; $matchesType = new ConstantArrayType($matchesType->getKeyTypes(), array_map(static function (Type $valueType): Type { if (count($valueType->getConstantArrays()) === 1) { $valueTypeArray = $valueType->getConstantArrays()[0]; return new ConstantArrayType($valueTypeArray->getKeyTypes(), array_map(static function (Type $valueType): Type { return TypeCombinator::removeNull($valueType); }, $valueTypeArray->getValueTypes()), $valueTypeArray->getNextAutoIndexes(), [], $valueTypeArray->isList()); } return TypeCombinator::removeNull($valueType); }, $matchesType->getValueTypes()), $matchesType->getNextAutoIndexes(), [], $matchesType->isList()); } return new ClosureType([new NativeParameterReflection($parameter->getName(), $parameter->isOptional(), $matchesType, $parameter->passedByReference(), $parameter->isVariadic(), $parameter->getDefaultValue())], new StringType()); } } */ final class UnsafeStrictGroupsCallRule implements Rule { /** * @var RegexArrayShapeMatcher */ private $regexShapeMatcher; public function __construct(RegexArrayShapeMatcher $regexShapeMatcher) { $this->regexShapeMatcher = $regexShapeMatcher; } public function getNodeType(): string { return StaticCall::class; } public function processNode(Node $node, Scope $scope): array { if (!$node->class instanceof FullyQualified) { return []; } $isRegex = $node->class->toString() === Regex::class; $isPreg = $node->class->toString() === Preg::class; if (!$isRegex && !$isPreg) { return []; } if (!$node->name instanceof Node\Identifier || !in_array($node->name->name, ['matchStrictGroups', 'isMatchStrictGroups', 'matchAllStrictGroups', 'isMatchAllStrictGroups'], \true)) { return []; } $args = $node->getArgs(); if (!isset($args[0])) { return []; } $patternArg = $args[0] ?? null; if ($isPreg) { if (!isset($args[2])) { // no matches set, skip as the matches won't be used anyway return []; } $flagsArg = $args[3] ?? null; } else { $flagsArg = $args[2] ?? null; } if ($patternArg === null) { return []; } $flagsType = \Composer\Pcre\PHPStan\PregMatchFlags::getType($flagsArg, $scope); if ($flagsType === null) { return []; } $matchedType = $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createYes(), $scope); if ($matchedType === null) { return [RuleErrorBuilder::message(sprintf('The %s call is potentially unsafe as $matches\' type could not be inferred.', $node->name->name))->identifier('composerPcre.maybeUnsafeStrictGroups')->build()]; } if (count($matchedType->getConstantArrays()) === 1) { $matchedType = $matchedType->getConstantArrays()[0]; $nullableGroups = []; foreach ($matchedType->getValueTypes() as $index => $type) { if (TypeCombinator::containsNull($type)) { $nullableGroups[] = $matchedType->getKeyTypes()[$index]->getValue(); } } if (\count($nullableGroups) > 0) { return [RuleErrorBuilder::message(sprintf('The %s call is unsafe as match group%s "%s" %s optional and may be null.', $node->name->name, \count($nullableGroups) > 1 ? 's' : '', implode('", "', $nullableGroups), \count($nullableGroups) > 1 ? 'are' : 'is'))->identifier('composerPcre.unsafeStrictGroups')->build()]; } } return []; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Pcre; class PcreException extends \RuntimeException { /** * @param string $function * @param string|string[] $pattern * @return self */ public static function fromFunction($function, $pattern) { $code = preg_last_error(); if (is_array($pattern)) { $pattern = implode(', ', $pattern); } return new PcreException($function . '(): failed executing "' . $pattern . '": ' . self::pcreLastErrorMessage($code), $code); } /** * @param int $code * @return string */ private static function pcreLastErrorMessage($code) { if (function_exists('preg_last_error_msg')) { return preg_last_error_msg(); } // older php versions did not set the code properly in all cases if (\PHP_VERSION_ID < 70201 && $code === 0) { return 'UNDEFINED_ERROR'; } $constants = get_defined_constants(\true); if (!isset($constants['pcre'])) { return 'UNDEFINED_ERROR'; } foreach ($constants['pcre'] as $const => $val) { if ($val === $code && substr($const, -6) === '_ERROR') { return $const; } } return 'UNDEFINED_ERROR'; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Pcre; class Preg { /** @internal */ public const ARRAY_MSG = '$subject as an array is not supported. You can use \'foreach\' instead.'; /** @internal */ public const INVALID_TYPE_MSG = '$subject must be a string, %s given.'; /** * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * @return 0|1 * * @param-out array $matches */ public static function match(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int { self::checkOffsetCapture($flags, 'matchWithOffsets'); $result = preg_match($pattern, $subject, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset); if ($result === \false) { throw PcreException::fromFunction('preg_match', $pattern); } return $result; } /** * Variant of `match()` which outputs non-null matches (or throws) * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * @return 0|1 * @throws UnexpectedNullMatchException * * @param-out array $matches */ public static function matchStrictGroups(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int { $result = self::match($pattern, $subject, $matchesInternal, $flags, $offset); $matches = self::enforceNonNullMatches($pattern, $matchesInternal, 'match'); return $result; } /** * Runs preg_match with PREG_OFFSET_CAPTURE * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL and PREG_OFFSET_CAPTURE are always set, no other flags are supported * @return 0|1 * * @param-out array}> $matches */ public static function matchWithOffsets(string $pattern, string $subject, ?array &$matches, int $flags = 0, int $offset = 0): int { $result = preg_match($pattern, $subject, $matches, $flags | \PREG_UNMATCHED_AS_NULL | \PREG_OFFSET_CAPTURE, $offset); if ($result === \false) { throw PcreException::fromFunction('preg_match', $pattern); } return $result; } /** * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * @return 0|positive-int * * @param-out array> $matches */ public static function matchAll(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int { self::checkOffsetCapture($flags, 'matchAllWithOffsets'); self::checkSetOrder($flags); $result = preg_match_all($pattern, $subject, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset); if (!is_int($result)) { // PHP < 8 may return null, 8+ returns int|false throw PcreException::fromFunction('preg_match_all', $pattern); } return $result; } /** * Variant of `match()` which outputs non-null matches (or throws) * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * @return 0|positive-int * @throws UnexpectedNullMatchException * * @param-out array> $matches */ public static function matchAllStrictGroups(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int { $result = self::matchAll($pattern, $subject, $matchesInternal, $flags, $offset); $matches = self::enforceNonNullMatchAll($pattern, $matchesInternal, 'matchAll'); return $result; } /** * Runs preg_match_all with PREG_OFFSET_CAPTURE * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL and PREG_MATCH_OFFSET are always set, no other flags are supported * @return 0|positive-int * * @param-out array}>> $matches */ public static function matchAllWithOffsets(string $pattern, string $subject, ?array &$matches, int $flags = 0, int $offset = 0): int { self::checkSetOrder($flags); $result = preg_match_all($pattern, $subject, $matches, $flags | \PREG_UNMATCHED_AS_NULL | \PREG_OFFSET_CAPTURE, $offset); if (!is_int($result)) { // PHP < 8 may return null, 8+ returns int|false throw PcreException::fromFunction('preg_match_all', $pattern); } return $result; } /** * @param string|string[] $pattern * @param string|string[] $replacement * @param string $subject * @param int $count Set by method * * @param-out int<0, max> $count */ public static function replace($pattern, $replacement, $subject, int $limit = -1, ?int &$count = null): string { if (!is_scalar($subject)) { if (is_array($subject)) { throw new \InvalidArgumentException(static::ARRAY_MSG); } throw new \TypeError(sprintf(static::INVALID_TYPE_MSG, gettype($subject))); } $result = preg_replace($pattern, $replacement, $subject, $limit, $count); if ($result === null) { throw PcreException::fromFunction('preg_replace', $pattern); } return $result; } /** * @param string|string[] $pattern * @param ($flags is PREG_OFFSET_CAPTURE ? (callable(array}>): string) : callable(array): string) $replacement * @param string $subject * @param int $count Set by method * @param int-mask $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set * * @param-out int<0, max> $count */ public static function replaceCallback($pattern, callable $replacement, $subject, int $limit = -1, ?int &$count = null, int $flags = 0): string { if (!is_scalar($subject)) { if (is_array($subject)) { throw new \InvalidArgumentException(static::ARRAY_MSG); } throw new \TypeError(sprintf(static::INVALID_TYPE_MSG, gettype($subject))); } $result = preg_replace_callback($pattern, $replacement, $subject, $limit, $count, $flags | \PREG_UNMATCHED_AS_NULL); if ($result === null) { throw PcreException::fromFunction('preg_replace_callback', $pattern); } return $result; } /** * Variant of `replaceCallback()` which outputs non-null matches (or throws) * * @param string $pattern * @param ($flags is PREG_OFFSET_CAPTURE ? (callable(array}>): string) : callable(array): string) $replacement * @param string $subject * @param int $count Set by method * @param int-mask $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set * * @param-out int<0, max> $count */ public static function replaceCallbackStrictGroups(string $pattern, callable $replacement, $subject, int $limit = -1, ?int &$count = null, int $flags = 0): string { return self::replaceCallback($pattern, function (array $matches) use ($pattern, $replacement) { return $replacement(self::enforceNonNullMatches($pattern, $matches, 'replaceCallback')); }, $subject, $limit, $count, $flags); } /** * @param ($flags is PREG_OFFSET_CAPTURE ? (array}>): string>) : array): string>) $pattern * @param string $subject * @param int $count Set by method * @param int-mask $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set * * @param-out int<0, max> $count */ public static function replaceCallbackArray(array $pattern, $subject, int $limit = -1, ?int &$count = null, int $flags = 0): string { if (!is_scalar($subject)) { if (is_array($subject)) { throw new \InvalidArgumentException(static::ARRAY_MSG); } throw new \TypeError(sprintf(static::INVALID_TYPE_MSG, gettype($subject))); } $result = preg_replace_callback_array($pattern, $subject, $limit, $count, $flags | \PREG_UNMATCHED_AS_NULL); if ($result === null) { $pattern = array_keys($pattern); throw PcreException::fromFunction('preg_replace_callback_array', $pattern); } return $result; } /** * @param int-mask $flags PREG_SPLIT_NO_EMPTY or PREG_SPLIT_DELIM_CAPTURE * @return list */ public static function split(string $pattern, string $subject, int $limit = -1, int $flags = 0): array { if (($flags & \PREG_SPLIT_OFFSET_CAPTURE) !== 0) { throw new \InvalidArgumentException('PREG_SPLIT_OFFSET_CAPTURE is not supported as it changes the type of $matches, use splitWithOffsets() instead'); } $result = preg_split($pattern, $subject, $limit, $flags); if ($result === \false) { throw PcreException::fromFunction('preg_split', $pattern); } return $result; } /** * @param int-mask $flags PREG_SPLIT_NO_EMPTY or PREG_SPLIT_DELIM_CAPTURE, PREG_SPLIT_OFFSET_CAPTURE is always set * @return list * @phpstan-return list}> */ public static function splitWithOffsets(string $pattern, string $subject, int $limit = -1, int $flags = 0): array { $result = preg_split($pattern, $subject, $limit, $flags | \PREG_SPLIT_OFFSET_CAPTURE); if ($result === \false) { throw PcreException::fromFunction('preg_split', $pattern); } return $result; } /** * @template T of string|\Stringable * @param string $pattern * @param array $array * @param int-mask $flags PREG_GREP_INVERT * @return array */ public static function grep(string $pattern, array $array, int $flags = 0): array { $result = preg_grep($pattern, $array, $flags); if ($result === \false) { throw PcreException::fromFunction('preg_grep', $pattern); } return $result; } /** * Variant of match() which returns a bool instead of int * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * * @param-out array $matches */ public static function isMatch(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): bool { return (bool) static::match($pattern, $subject, $matches, $flags, $offset); } /** * Variant of `isMatch()` which outputs non-null matches (or throws) * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * @throws UnexpectedNullMatchException * * @param-out array $matches */ public static function isMatchStrictGroups(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): bool { return (bool) self::matchStrictGroups($pattern, $subject, $matches, $flags, $offset); } /** * Variant of matchAll() which returns a bool instead of int * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * * @param-out array> $matches */ public static function isMatchAll(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): bool { return (bool) static::matchAll($pattern, $subject, $matches, $flags, $offset); } /** * Variant of `isMatchAll()` which outputs non-null matches (or throws) * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * * @param-out array> $matches */ public static function isMatchAllStrictGroups(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): bool { return (bool) self::matchAllStrictGroups($pattern, $subject, $matches, $flags, $offset); } /** * Variant of matchWithOffsets() which returns a bool instead of int * * Runs preg_match with PREG_OFFSET_CAPTURE * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * * @param-out array}> $matches */ public static function isMatchWithOffsets(string $pattern, string $subject, ?array &$matches, int $flags = 0, int $offset = 0): bool { return (bool) static::matchWithOffsets($pattern, $subject, $matches, $flags, $offset); } /** * Variant of matchAllWithOffsets() which returns a bool instead of int * * Runs preg_match_all with PREG_OFFSET_CAPTURE * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * * @param-out array}>> $matches */ public static function isMatchAllWithOffsets(string $pattern, string $subject, ?array &$matches, int $flags = 0, int $offset = 0): bool { return (bool) static::matchAllWithOffsets($pattern, $subject, $matches, $flags, $offset); } private static function checkOffsetCapture(int $flags, string $useFunctionName): void { if (($flags & \PREG_OFFSET_CAPTURE) !== 0) { throw new \InvalidArgumentException('PREG_OFFSET_CAPTURE is not supported as it changes the type of $matches, use ' . $useFunctionName . '() instead'); } } private static function checkSetOrder(int $flags): void { if (($flags & \PREG_SET_ORDER) !== 0) { throw new \InvalidArgumentException('PREG_SET_ORDER is not supported as it changes the type of $matches'); } } /** * @param array $matches * @return array * @throws UnexpectedNullMatchException */ private static function enforceNonNullMatches(string $pattern, array $matches, string $variantMethod) { foreach ($matches as $group => $match) { if (is_string($match) || is_array($match) && is_string($match[0])) { continue; } throw new UnexpectedNullMatchException('Pattern "' . $pattern . '" had an unexpected unmatched group "' . $group . '", make sure the pattern always matches or use ' . $variantMethod . '() instead.'); } /** @var array */ return $matches; } /** * @param array> $matches * @return array> * @throws UnexpectedNullMatchException */ private static function enforceNonNullMatchAll(string $pattern, array $matches, string $variantMethod) { foreach ($matches as $group => $groupMatches) { foreach ($groupMatches as $match) { if (null === $match) { throw new UnexpectedNullMatchException('Pattern "' . $pattern . '" had an unexpected unmatched group "' . $group . '", make sure the pattern always matches or use ' . $variantMethod . '() instead.'); } } } /** @var array> */ return $matches; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Pcre; class Regex { /** * @param non-empty-string $pattern */ public static function isMatch(string $pattern, string $subject, int $offset = 0): bool { return (bool) Preg::match($pattern, $subject, $matches, 0, $offset); } /** * @param non-empty-string $pattern * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported */ public static function match(string $pattern, string $subject, int $flags = 0, int $offset = 0): MatchResult { self::checkOffsetCapture($flags, 'matchWithOffsets'); $count = Preg::match($pattern, $subject, $matches, $flags, $offset); return new MatchResult($count, $matches); } /** * Variant of `match()` which returns non-null matches (or throws) * * @param non-empty-string $pattern * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * @throws UnexpectedNullMatchException */ public static function matchStrictGroups(string $pattern, string $subject, int $flags = 0, int $offset = 0): MatchStrictGroupsResult { // @phpstan-ignore composerPcre.maybeUnsafeStrictGroups $count = Preg::matchStrictGroups($pattern, $subject, $matches, $flags, $offset); return new MatchStrictGroupsResult($count, $matches); } /** * Runs preg_match with PREG_OFFSET_CAPTURE * * @param non-empty-string $pattern * @param int-mask $flags PREG_UNMATCHED_AS_NULL and PREG_MATCH_OFFSET are always set, no other flags are supported */ public static function matchWithOffsets(string $pattern, string $subject, int $flags = 0, int $offset = 0): MatchWithOffsetsResult { $count = Preg::matchWithOffsets($pattern, $subject, $matches, $flags, $offset); return new MatchWithOffsetsResult($count, $matches); } /** * @param non-empty-string $pattern * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported */ public static function matchAll(string $pattern, string $subject, int $flags = 0, int $offset = 0): MatchAllResult { self::checkOffsetCapture($flags, 'matchAllWithOffsets'); self::checkSetOrder($flags); $count = Preg::matchAll($pattern, $subject, $matches, $flags, $offset); return new MatchAllResult($count, $matches); } /** * Variant of `matchAll()` which returns non-null matches (or throws) * * @param non-empty-string $pattern * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * @throws UnexpectedNullMatchException */ public static function matchAllStrictGroups(string $pattern, string $subject, int $flags = 0, int $offset = 0): MatchAllStrictGroupsResult { self::checkOffsetCapture($flags, 'matchAllWithOffsets'); self::checkSetOrder($flags); // @phpstan-ignore composerPcre.maybeUnsafeStrictGroups $count = Preg::matchAllStrictGroups($pattern, $subject, $matches, $flags, $offset); return new MatchAllStrictGroupsResult($count, $matches); } /** * Runs preg_match_all with PREG_OFFSET_CAPTURE * * @param non-empty-string $pattern * @param int-mask $flags PREG_UNMATCHED_AS_NULL and PREG_MATCH_OFFSET are always set, no other flags are supported */ public static function matchAllWithOffsets(string $pattern, string $subject, int $flags = 0, int $offset = 0): MatchAllWithOffsetsResult { self::checkSetOrder($flags); $count = Preg::matchAllWithOffsets($pattern, $subject, $matches, $flags, $offset); return new MatchAllWithOffsetsResult($count, $matches); } /** * @param string|string[] $pattern * @param string|string[] $replacement * @param string $subject */ public static function replace($pattern, $replacement, $subject, int $limit = -1): ReplaceResult { $result = Preg::replace($pattern, $replacement, $subject, $limit, $count); return new ReplaceResult($count, $result); } /** * @param string|string[] $pattern * @param ($flags is PREG_OFFSET_CAPTURE ? (callable(array}>): string) : callable(array): string) $replacement * @param string $subject * @param int-mask $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set */ public static function replaceCallback($pattern, callable $replacement, $subject, int $limit = -1, int $flags = 0): ReplaceResult { $result = Preg::replaceCallback($pattern, $replacement, $subject, $limit, $count, $flags); return new ReplaceResult($count, $result); } /** * Variant of `replaceCallback()` which outputs non-null matches (or throws) * * @param string $pattern * @param ($flags is PREG_OFFSET_CAPTURE ? (callable(array}>): string) : callable(array): string) $replacement * @param string $subject * @param int-mask $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set */ public static function replaceCallbackStrictGroups($pattern, callable $replacement, $subject, int $limit = -1, int $flags = 0): ReplaceResult { $result = Preg::replaceCallbackStrictGroups($pattern, $replacement, $subject, $limit, $count, $flags); return new ReplaceResult($count, $result); } /** * @param ($flags is PREG_OFFSET_CAPTURE ? (array}>): string>) : array): string>) $pattern * @param string $subject * @param int-mask $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set */ public static function replaceCallbackArray(array $pattern, $subject, int $limit = -1, int $flags = 0): ReplaceResult { $result = Preg::replaceCallbackArray($pattern, $subject, $limit, $count, $flags); return new ReplaceResult($count, $result); } private static function checkOffsetCapture(int $flags, string $useFunctionName): void { if (($flags & \PREG_OFFSET_CAPTURE) !== 0) { throw new \InvalidArgumentException('PREG_OFFSET_CAPTURE is not supported as it changes the return type, use ' . $useFunctionName . '() instead'); } } private static function checkSetOrder(int $flags): void { if (($flags & \PREG_SET_ORDER) !== 0) { throw new \InvalidArgumentException('PREG_SET_ORDER is not supported as it changes the return type'); } } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Pcre; final class ReplaceResult { /** * @readonly * @var string */ public $result; /** * @readonly * @var 0|positive-int */ public $count; /** * @readonly * @var bool */ public $matched; /** * @param 0|positive-int $count */ public function __construct(int $count, string $result) { $this->count = $count; $this->matched = (bool) $count; $this->result = $result; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Pcre; class UnexpectedNullMatchException extends PcreException { public static function fromFunction($function, $pattern) { throw new \LogicException('fromFunction should not be called on ' . self::class . ', use ' . PcreException::class); } } Copyright (C) 2015 Composer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Semver; use _PHPStan_33c983f26\Composer\Semver\Constraint\Constraint; class Comparator { /** * Evaluates the expression: $version1 > $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function greaterThan($version1, $version2) { return self::compare($version1, '>', $version2); } /** * Evaluates the expression: $version1 >= $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function greaterThanOrEqualTo($version1, $version2) { return self::compare($version1, '>=', $version2); } /** * Evaluates the expression: $version1 < $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function lessThan($version1, $version2) { return self::compare($version1, '<', $version2); } /** * Evaluates the expression: $version1 <= $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function lessThanOrEqualTo($version1, $version2) { return self::compare($version1, '<=', $version2); } /** * Evaluates the expression: $version1 == $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function equalTo($version1, $version2) { return self::compare($version1, '==', $version2); } /** * Evaluates the expression: $version1 != $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function notEqualTo($version1, $version2) { return self::compare($version1, '!=', $version2); } /** * Evaluates the expression: $version1 $operator $version2. * * @param string $version1 * @param string $operator * @param string $version2 * * @return bool * * @phpstan-param Constraint::STR_OP_* $operator */ public static function compare($version1, $operator, $version2) { $constraint = new Constraint($operator, $version2); return $constraint->matchSpecific(new Constraint('==', $version1), \true); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Semver; use _PHPStan_33c983f26\Composer\Semver\Constraint\Constraint; use _PHPStan_33c983f26\Composer\Semver\Constraint\ConstraintInterface; /** * Helper class to evaluate constraint by compiling and reusing the code to evaluate */ class CompilingMatcher { /** * @var array * @phpstan-var array */ private static $compiledCheckerCache = array(); /** * @var array * @phpstan-var array */ private static $resultCache = array(); /** @var bool */ private static $enabled; /** * @phpstan-var array */ private static $transOpInt = array(Constraint::OP_EQ => Constraint::STR_OP_EQ, Constraint::OP_LT => Constraint::STR_OP_LT, Constraint::OP_LE => Constraint::STR_OP_LE, Constraint::OP_GT => Constraint::STR_OP_GT, Constraint::OP_GE => Constraint::STR_OP_GE, Constraint::OP_NE => Constraint::STR_OP_NE); /** * Clears the memoization cache once you are done * * @return void */ public static function clear() { self::$resultCache = array(); self::$compiledCheckerCache = array(); } /** * Evaluates the expression: $constraint match $operator $version * * @param ConstraintInterface $constraint * @param int $operator * @phpstan-param Constraint::OP_* $operator * @param string $version * * @return bool */ public static function match(ConstraintInterface $constraint, $operator, $version) { $resultCacheKey = $operator . $constraint . ';' . $version; if (isset(self::$resultCache[$resultCacheKey])) { return self::$resultCache[$resultCacheKey]; } if (self::$enabled === null) { self::$enabled = !\in_array('eval', explode(',', (string) ini_get('disable_functions')), \true); } if (!self::$enabled) { return self::$resultCache[$resultCacheKey] = $constraint->matches(new Constraint(self::$transOpInt[$operator], $version)); } $cacheKey = $operator . $constraint; if (!isset(self::$compiledCheckerCache[$cacheKey])) { $code = $constraint->compile($operator); self::$compiledCheckerCache[$cacheKey] = $function = eval('return function($v, $b){return ' . $code . ';};'); } else { $function = self::$compiledCheckerCache[$cacheKey]; } return self::$resultCache[$resultCacheKey] = $function($version, strpos($version, 'dev-') === 0); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Semver\Constraint; class Bound { /** * @var string */ private $version; /** * @var bool */ private $isInclusive; /** * @param string $version * @param bool $isInclusive */ public function __construct($version, $isInclusive) { $this->version = $version; $this->isInclusive = $isInclusive; } /** * @return string */ public function getVersion() { return $this->version; } /** * @return bool */ public function isInclusive() { return $this->isInclusive; } /** * @return bool */ public function isZero() { return $this->getVersion() === '0.0.0.0-dev' && $this->isInclusive(); } /** * @return bool */ public function isPositiveInfinity() { return $this->getVersion() === \PHP_INT_MAX . '.0.0.0' && !$this->isInclusive(); } /** * Compares a bound to another with a given operator. * * @param Bound $other * @param string $operator * * @return bool */ public function compareTo(Bound $other, $operator) { if (!\in_array($operator, array('<', '>'), \true)) { throw new \InvalidArgumentException('Does not support any other operator other than > or <.'); } // If they are the same it doesn't matter if ($this == $other) { return \false; } $compareResult = version_compare($this->getVersion(), $other->getVersion()); // Not the same version means we don't need to check if the bounds are inclusive or not if (0 !== $compareResult) { return ('>' === $operator ? 1 : -1) === $compareResult; } // Question we're answering here is "am I higher than $other?" return '>' === $operator ? $other->isInclusive() : !$other->isInclusive(); } public function __toString() { return sprintf('%s [%s]', $this->getVersion(), $this->isInclusive() ? 'inclusive' : 'exclusive'); } /** * @return self */ public static function zero() { return new Bound('0.0.0.0-dev', \true); } /** * @return self */ public static function positiveInfinity() { return new Bound(\PHP_INT_MAX . '.0.0.0', \false); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Semver\Constraint; /** * Defines a constraint. */ class Constraint implements ConstraintInterface { /* operator integer values */ const OP_EQ = 0; const OP_LT = 1; const OP_LE = 2; const OP_GT = 3; const OP_GE = 4; const OP_NE = 5; /* operator string values */ const STR_OP_EQ = '=='; const STR_OP_EQ_ALT = '='; const STR_OP_LT = '<'; const STR_OP_LE = '<='; const STR_OP_GT = '>'; const STR_OP_GE = '>='; const STR_OP_NE = '!='; const STR_OP_NE_ALT = '<>'; /** * Operator to integer translation table. * * @var array * @phpstan-var array */ private static $transOpStr = array('=' => self::OP_EQ, '==' => self::OP_EQ, '<' => self::OP_LT, '<=' => self::OP_LE, '>' => self::OP_GT, '>=' => self::OP_GE, '<>' => self::OP_NE, '!=' => self::OP_NE); /** * Integer to operator translation table. * * @var array * @phpstan-var array */ private static $transOpInt = array(self::OP_EQ => '==', self::OP_LT => '<', self::OP_LE => '<=', self::OP_GT => '>', self::OP_GE => '>=', self::OP_NE => '!='); /** * @var int * @phpstan-var self::OP_* */ protected $operator; /** @var string */ protected $version; /** @var string|null */ protected $prettyString; /** @var Bound */ protected $lowerBound; /** @var Bound */ protected $upperBound; /** * Sets operator and version to compare with. * * @param string $operator * @param string $version * * @throws \InvalidArgumentException if invalid operator is given. * * @phpstan-param self::STR_OP_* $operator */ public function __construct($operator, $version) { if (!isset(self::$transOpStr[$operator])) { throw new \InvalidArgumentException(sprintf('Invalid operator "%s" given, expected one of: %s', $operator, implode(', ', self::getSupportedOperators()))); } $this->operator = self::$transOpStr[$operator]; $this->version = $version; } /** * @return string */ public function getVersion() { return $this->version; } /** * @return string * * @phpstan-return self::STR_OP_* */ public function getOperator() { return self::$transOpInt[$this->operator]; } /** * @param ConstraintInterface $provider * * @return bool */ public function matches(ConstraintInterface $provider) { if ($provider instanceof self) { return $this->matchSpecific($provider); } // turn matching around to find a match return $provider->matches($this); } /** * {@inheritDoc} */ public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } /** * {@inheritDoc} */ public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return $this->__toString(); } /** * Get all supported comparison operators. * * @return array * * @phpstan-return list */ public static function getSupportedOperators() { return array_keys(self::$transOpStr); } /** * @param string $operator * @return int * * @phpstan-param self::STR_OP_* $operator * @phpstan-return self::OP_* */ public static function getOperatorConstant($operator) { return self::$transOpStr[$operator]; } /** * @param string $a * @param string $b * @param string $operator * @param bool $compareBranches * * @throws \InvalidArgumentException if invalid operator is given. * * @return bool * * @phpstan-param self::STR_OP_* $operator */ public function versionCompare($a, $b, $operator, $compareBranches = \false) { if (!isset(self::$transOpStr[$operator])) { throw new \InvalidArgumentException(sprintf('Invalid operator "%s" given, expected one of: %s', $operator, implode(', ', self::getSupportedOperators()))); } $aIsBranch = strpos($a, 'dev-') === 0; $bIsBranch = strpos($b, 'dev-') === 0; if ($operator === '!=' && ($aIsBranch || $bIsBranch)) { return $a !== $b; } if ($aIsBranch && $bIsBranch) { return $operator === '==' && $a === $b; } // when branches are not comparable, we make sure dev branches never match anything if (!$compareBranches && ($aIsBranch || $bIsBranch)) { return \false; } return \version_compare($a, $b, $operator); } /** * {@inheritDoc} */ public function compile($otherOperator) { if (strpos($this->version, 'dev-') === 0) { if (self::OP_EQ === $this->operator) { if (self::OP_EQ === $otherOperator) { return sprintf('$b && $v === %s', \var_export($this->version, \true)); } if (self::OP_NE === $otherOperator) { return sprintf('!$b || $v !== %s', \var_export($this->version, \true)); } return 'false'; } if (self::OP_NE === $this->operator) { if (self::OP_EQ === $otherOperator) { return sprintf('!$b || $v !== %s', \var_export($this->version, \true)); } if (self::OP_NE === $otherOperator) { return 'true'; } return '!$b'; } return 'false'; } if (self::OP_EQ === $this->operator) { if (self::OP_EQ === $otherOperator) { return sprintf('\version_compare($v, %s, \'==\')', \var_export($this->version, \true)); } if (self::OP_NE === $otherOperator) { return sprintf('$b || \version_compare($v, %s, \'!=\')', \var_export($this->version, \true)); } return sprintf('!$b && \version_compare(%s, $v, \'%s\')', \var_export($this->version, \true), self::$transOpInt[$otherOperator]); } if (self::OP_NE === $this->operator) { if (self::OP_EQ === $otherOperator) { return sprintf('$b || (!$b && \version_compare($v, %s, \'!=\'))', \var_export($this->version, \true)); } if (self::OP_NE === $otherOperator) { return 'true'; } return '!$b'; } if (self::OP_LT === $this->operator || self::OP_LE === $this->operator) { if (self::OP_LT === $otherOperator || self::OP_LE === $otherOperator) { return '!$b'; } } else if (self::OP_GT === $otherOperator || self::OP_GE === $otherOperator) { return '!$b'; } if (self::OP_NE === $otherOperator) { return 'true'; } $codeComparison = sprintf('\version_compare($v, %s, \'%s\')', \var_export($this->version, \true), self::$transOpInt[$this->operator]); if ($this->operator === self::OP_LE) { if ($otherOperator === self::OP_GT) { return sprintf('!$b && \version_compare($v, %s, \'!=\') && ', \var_export($this->version, \true)) . $codeComparison; } } elseif ($this->operator === self::OP_GE) { if ($otherOperator === self::OP_LT) { return sprintf('!$b && \version_compare($v, %s, \'!=\') && ', \var_export($this->version, \true)) . $codeComparison; } } return sprintf('!$b && %s', $codeComparison); } /** * @param Constraint $provider * @param bool $compareBranches * * @return bool */ public function matchSpecific(Constraint $provider, $compareBranches = \false) { $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]); $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]); $isEqualOp = self::OP_EQ === $this->operator; $isNonEqualOp = self::OP_NE === $this->operator; $isProviderEqualOp = self::OP_EQ === $provider->operator; $isProviderNonEqualOp = self::OP_NE === $provider->operator; // '!=' operator is match when other operator is not '==' operator or version is not match // these kinds of comparisons always have a solution if ($isNonEqualOp || $isProviderNonEqualOp) { if ($isNonEqualOp && !$isProviderNonEqualOp && !$isProviderEqualOp && strpos($provider->version, 'dev-') === 0) { return \false; } if ($isProviderNonEqualOp && !$isNonEqualOp && !$isEqualOp && strpos($this->version, 'dev-') === 0) { return \false; } if (!$isEqualOp && !$isProviderEqualOp) { return \true; } return $this->versionCompare($provider->version, $this->version, '!=', $compareBranches); } // an example for the condition is <= 2.0 & < 1.0 // these kinds of comparisons always have a solution if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) { return !(strpos($this->version, 'dev-') === 0 || strpos($provider->version, 'dev-') === 0); } $version1 = $isEqualOp ? $this->version : $provider->version; $version2 = $isEqualOp ? $provider->version : $this->version; $operator = $isEqualOp ? $provider->operator : $this->operator; if ($this->versionCompare($version1, $version2, self::$transOpInt[$operator], $compareBranches)) { // special case, e.g. require >= 1.0 and provide < 1.0 // 1.0 >= 1.0 but 1.0 is outside of the provided interval return !(self::$transOpInt[$provider->operator] === $providerNoEqualOp && self::$transOpInt[$this->operator] !== $noEqualOp && \version_compare($provider->version, $this->version, '==')); } return \false; } /** * @return string */ public function __toString() { return self::$transOpInt[$this->operator] . ' ' . $this->version; } /** * {@inheritDoc} */ public function getLowerBound() { $this->extractBounds(); return $this->lowerBound; } /** * {@inheritDoc} */ public function getUpperBound() { $this->extractBounds(); return $this->upperBound; } /** * @return void */ private function extractBounds() { if (null !== $this->lowerBound) { return; } // Branches if (strpos($this->version, 'dev-') === 0) { $this->lowerBound = Bound::zero(); $this->upperBound = Bound::positiveInfinity(); return; } switch ($this->operator) { case self::OP_EQ: $this->lowerBound = new Bound($this->version, \true); $this->upperBound = new Bound($this->version, \true); break; case self::OP_LT: $this->lowerBound = Bound::zero(); $this->upperBound = new Bound($this->version, \false); break; case self::OP_LE: $this->lowerBound = Bound::zero(); $this->upperBound = new Bound($this->version, \true); break; case self::OP_GT: $this->lowerBound = new Bound($this->version, \false); $this->upperBound = Bound::positiveInfinity(); break; case self::OP_GE: $this->lowerBound = new Bound($this->version, \true); $this->upperBound = Bound::positiveInfinity(); break; case self::OP_NE: $this->lowerBound = Bound::zero(); $this->upperBound = Bound::positiveInfinity(); break; } } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Semver\Constraint; /** * DO NOT IMPLEMENT this interface. It is only meant for usage as a type hint * in libraries relying on composer/semver but creating your own constraint class * that implements this interface is not a supported use case and will cause the * composer/semver components to return unexpected results. */ interface ConstraintInterface { /** * Checks whether the given constraint intersects in any way with this constraint * * @param ConstraintInterface $provider * * @return bool */ public function matches(ConstraintInterface $provider); /** * Provides a compiled version of the constraint for the given operator * The compiled version must be a PHP expression. * Executor of compile version must provide 2 variables: * - $v = the string version to compare with * - $b = whether or not the version is a non-comparable branch (starts with "dev-") * * @see Constraint::OP_* for the list of available operators. * @example return '!$b && version_compare($v, '1.0', '>')'; * * @param int $otherOperator one Constraint::OP_* * * @return string * * @phpstan-param Constraint::OP_* $otherOperator */ public function compile($otherOperator); /** * @return Bound */ public function getUpperBound(); /** * @return Bound */ public function getLowerBound(); /** * @return string */ public function getPrettyString(); /** * @param string|null $prettyString * * @return void */ public function setPrettyString($prettyString); /** * @return string */ public function __toString(); } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Semver\Constraint; /** * Defines the absence of a constraint. * * This constraint matches everything. */ class MatchAllConstraint implements ConstraintInterface { /** @var string|null */ protected $prettyString; /** * @param ConstraintInterface $provider * * @return bool */ public function matches(ConstraintInterface $provider) { return \true; } /** * {@inheritDoc} */ public function compile($otherOperator) { return 'true'; } /** * {@inheritDoc} */ public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } /** * {@inheritDoc} */ public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return (string) $this; } /** * {@inheritDoc} */ public function __toString() { return '*'; } /** * {@inheritDoc} */ public function getUpperBound() { return Bound::positiveInfinity(); } /** * {@inheritDoc} */ public function getLowerBound() { return Bound::zero(); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Semver\Constraint; /** * Blackhole of constraints, nothing escapes it */ class MatchNoneConstraint implements ConstraintInterface { /** @var string|null */ protected $prettyString; /** * @param ConstraintInterface $provider * * @return bool */ public function matches(ConstraintInterface $provider) { return \false; } /** * {@inheritDoc} */ public function compile($otherOperator) { return 'false'; } /** * {@inheritDoc} */ public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } /** * {@inheritDoc} */ public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return (string) $this; } /** * {@inheritDoc} */ public function __toString() { return '[]'; } /** * {@inheritDoc} */ public function getUpperBound() { return new Bound('0.0.0.0-dev', \false); } /** * {@inheritDoc} */ public function getLowerBound() { return new Bound('0.0.0.0-dev', \false); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Semver\Constraint; /** * Defines a conjunctive or disjunctive set of constraints. */ class MultiConstraint implements ConstraintInterface { /** * @var ConstraintInterface[] * @phpstan-var non-empty-array */ protected $constraints; /** @var string|null */ protected $prettyString; /** @var string|null */ protected $string; /** @var bool */ protected $conjunctive; /** @var Bound|null */ protected $lowerBound; /** @var Bound|null */ protected $upperBound; /** * @param ConstraintInterface[] $constraints A set of constraints * @param bool $conjunctive Whether the constraints should be treated as conjunctive or disjunctive * * @throws \InvalidArgumentException If less than 2 constraints are passed */ public function __construct(array $constraints, $conjunctive = \true) { if (\count($constraints) < 2) { throw new \InvalidArgumentException('Must provide at least two constraints for a MultiConstraint. Use ' . 'the regular Constraint class for one constraint only or MatchAllConstraint for none. You may use ' . 'MultiConstraint::create() which optimizes and handles those cases automatically.'); } $this->constraints = $constraints; $this->conjunctive = $conjunctive; } /** * @return ConstraintInterface[] */ public function getConstraints() { return $this->constraints; } /** * @return bool */ public function isConjunctive() { return $this->conjunctive; } /** * @return bool */ public function isDisjunctive() { return !$this->conjunctive; } /** * {@inheritDoc} */ public function compile($otherOperator) { $parts = array(); foreach ($this->constraints as $constraint) { $code = $constraint->compile($otherOperator); if ($code === 'true') { if (!$this->conjunctive) { return 'true'; } } elseif ($code === 'false') { if ($this->conjunctive) { return 'false'; } } else { $parts[] = '(' . $code . ')'; } } if (!$parts) { return $this->conjunctive ? 'true' : 'false'; } return $this->conjunctive ? implode('&&', $parts) : implode('||', $parts); } /** * @param ConstraintInterface $provider * * @return bool */ public function matches(ConstraintInterface $provider) { if (\false === $this->conjunctive) { foreach ($this->constraints as $constraint) { if ($provider->matches($constraint)) { return \true; } } return \false; } // when matching a conjunctive and a disjunctive multi constraint we have to iterate over the disjunctive one // otherwise we'd return true if different parts of the disjunctive constraint match the conjunctive one // which would lead to incorrect results, e.g. [>1 and <2] would match [<1 or >2] although they do not intersect if ($provider instanceof MultiConstraint && $provider->isDisjunctive()) { return $provider->matches($this); } foreach ($this->constraints as $constraint) { if (!$provider->matches($constraint)) { return \false; } } return \true; } /** * {@inheritDoc} */ public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } /** * {@inheritDoc} */ public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return (string) $this; } /** * {@inheritDoc} */ public function __toString() { if ($this->string !== null) { return $this->string; } $constraints = array(); foreach ($this->constraints as $constraint) { $constraints[] = (string) $constraint; } return $this->string = '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']'; } /** * {@inheritDoc} */ public function getLowerBound() { $this->extractBounds(); if (null === $this->lowerBound) { throw new \LogicException('extractBounds should have populated the lowerBound property'); } return $this->lowerBound; } /** * {@inheritDoc} */ public function getUpperBound() { $this->extractBounds(); if (null === $this->upperBound) { throw new \LogicException('extractBounds should have populated the upperBound property'); } return $this->upperBound; } /** * Tries to optimize the constraints as much as possible, meaning * reducing/collapsing congruent constraints etc. * Does not necessarily return a MultiConstraint instance if * things can be reduced to a simple constraint * * @param ConstraintInterface[] $constraints A set of constraints * @param bool $conjunctive Whether the constraints should be treated as conjunctive or disjunctive * * @return ConstraintInterface */ public static function create(array $constraints, $conjunctive = \true) { if (0 === \count($constraints)) { return new MatchAllConstraint(); } if (1 === \count($constraints)) { return $constraints[0]; } $optimized = self::optimizeConstraints($constraints, $conjunctive); if ($optimized !== null) { list($constraints, $conjunctive) = $optimized; if (\count($constraints) === 1) { return $constraints[0]; } } return new self($constraints, $conjunctive); } /** * @param ConstraintInterface[] $constraints * @param bool $conjunctive * @return ?array * * @phpstan-return array{0: list, 1: bool}|null */ private static function optimizeConstraints(array $constraints, $conjunctive) { // parse the two OR groups and if they are contiguous we collapse // them into one constraint // [>= 1 < 2] || [>= 2 < 3] || [>= 3 < 4] => [>= 1 < 4] if (!$conjunctive) { $left = $constraints[0]; $mergedConstraints = array(); $optimized = \false; for ($i = 1, $l = \count($constraints); $i < $l; $i++) { $right = $constraints[$i]; if ($left instanceof self && $left->conjunctive && $right instanceof self && $right->conjunctive && \count($left->constraints) === 2 && \count($right->constraints) === 2 && ($left0 = (string) $left->constraints[0]) && $left0[0] === '>' && $left0[1] === '=' && ($left1 = (string) $left->constraints[1]) && $left1[0] === '<' && ($right0 = (string) $right->constraints[0]) && $right0[0] === '>' && $right0[1] === '=' && ($right1 = (string) $right->constraints[1]) && $right1[0] === '<' && substr($left1, 2) === substr($right0, 3)) { $optimized = \true; $left = new MultiConstraint(array($left->constraints[0], $right->constraints[1]), \true); } else { $mergedConstraints[] = $left; $left = $right; } } if ($optimized) { $mergedConstraints[] = $left; return array($mergedConstraints, \false); } } // TODO: Here's the place to put more optimizations return null; } /** * @return void */ private function extractBounds() { if (null !== $this->lowerBound) { return; } foreach ($this->constraints as $constraint) { if (null === $this->lowerBound || null === $this->upperBound) { $this->lowerBound = $constraint->getLowerBound(); $this->upperBound = $constraint->getUpperBound(); continue; } if ($constraint->getLowerBound()->compareTo($this->lowerBound, $this->isConjunctive() ? '>' : '<')) { $this->lowerBound = $constraint->getLowerBound(); } if ($constraint->getUpperBound()->compareTo($this->upperBound, $this->isConjunctive() ? '<' : '>')) { $this->upperBound = $constraint->getUpperBound(); } } } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Semver; use _PHPStan_33c983f26\Composer\Semver\Constraint\Constraint; class Interval { /** @var Constraint */ private $start; /** @var Constraint */ private $end; public function __construct(Constraint $start, Constraint $end) { $this->start = $start; $this->end = $end; } /** * @return Constraint */ public function getStart() { return $this->start; } /** * @return Constraint */ public function getEnd() { return $this->end; } /** * @return Constraint */ public static function fromZero() { static $zero; if (null === $zero) { $zero = new Constraint('>=', '0.0.0.0-dev'); } return $zero; } /** * @return Constraint */ public static function untilPositiveInfinity() { static $positiveInfinity; if (null === $positiveInfinity) { $positiveInfinity = new Constraint('<', \PHP_INT_MAX . '.0.0.0'); } return $positiveInfinity; } /** * @return self */ public static function any() { return new self(self::fromZero(), self::untilPositiveInfinity()); } /** * @return array{'names': string[], 'exclude': bool} */ public static function anyDev() { // any == exclude nothing return array('names' => array(), 'exclude' => \true); } /** * @return array{'names': string[], 'exclude': bool} */ public static function noDev() { // nothing == no names included return array('names' => array(), 'exclude' => \false); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Semver; use _PHPStan_33c983f26\Composer\Semver\Constraint\Constraint; use _PHPStan_33c983f26\Composer\Semver\Constraint\ConstraintInterface; use _PHPStan_33c983f26\Composer\Semver\Constraint\MatchAllConstraint; use _PHPStan_33c983f26\Composer\Semver\Constraint\MatchNoneConstraint; use _PHPStan_33c983f26\Composer\Semver\Constraint\MultiConstraint; /** * Helper class generating intervals from constraints * * This contains utilities for: * * - compacting an existing constraint which can be used to combine several into one * by creating a MultiConstraint out of the many constraints you have. * * - checking whether one subset is a subset of another. * * Note: You should call clear to free memoization memory usage when you are done using this class */ class Intervals { /** * @phpstan-var array */ private static $intervalsCache = array(); /** * @phpstan-var array */ private static $opSortOrder = array('>=' => -3, '<' => -2, '>' => 2, '<=' => 3); /** * Clears the memoization cache once you are done * * @return void */ public static function clear() { self::$intervalsCache = array(); } /** * Checks whether $candidate is a subset of $constraint * * @return bool */ public static function isSubsetOf(ConstraintInterface $candidate, ConstraintInterface $constraint) { if ($constraint instanceof MatchAllConstraint) { return \true; } if ($candidate instanceof MatchNoneConstraint || $constraint instanceof MatchNoneConstraint) { return \false; } $intersectionIntervals = self::get(new MultiConstraint(array($candidate, $constraint), \true)); $candidateIntervals = self::get($candidate); if (\count($intersectionIntervals['numeric']) !== \count($candidateIntervals['numeric'])) { return \false; } foreach ($intersectionIntervals['numeric'] as $index => $interval) { if (!isset($candidateIntervals['numeric'][$index])) { return \false; } if ((string) $candidateIntervals['numeric'][$index]->getStart() !== (string) $interval->getStart()) { return \false; } if ((string) $candidateIntervals['numeric'][$index]->getEnd() !== (string) $interval->getEnd()) { return \false; } } if ($intersectionIntervals['branches']['exclude'] !== $candidateIntervals['branches']['exclude']) { return \false; } if (\count($intersectionIntervals['branches']['names']) !== \count($candidateIntervals['branches']['names'])) { return \false; } foreach ($intersectionIntervals['branches']['names'] as $index => $name) { if ($name !== $candidateIntervals['branches']['names'][$index]) { return \false; } } return \true; } /** * Checks whether $a and $b have any intersection, equivalent to $a->matches($b) * * @return bool */ public static function haveIntersections(ConstraintInterface $a, ConstraintInterface $b) { if ($a instanceof MatchAllConstraint || $b instanceof MatchAllConstraint) { return \true; } if ($a instanceof MatchNoneConstraint || $b instanceof MatchNoneConstraint) { return \false; } $intersectionIntervals = self::generateIntervals(new MultiConstraint(array($a, $b), \true), \true); return \count($intersectionIntervals['numeric']) > 0 || $intersectionIntervals['branches']['exclude'] || \count($intersectionIntervals['branches']['names']) > 0; } /** * Attempts to optimize a MultiConstraint * * When merging MultiConstraints together they can get very large, this will * compact it by looking at the real intervals covered by all the constraints * and then creates a new constraint containing only the smallest amount of rules * to match the same intervals. * * @return ConstraintInterface */ public static function compactConstraint(ConstraintInterface $constraint) { if (!$constraint instanceof MultiConstraint) { return $constraint; } $intervals = self::generateIntervals($constraint); $constraints = array(); $hasNumericMatchAll = \false; if (\count($intervals['numeric']) === 1 && (string) $intervals['numeric'][0]->getStart() === (string) Interval::fromZero() && (string) $intervals['numeric'][0]->getEnd() === (string) Interval::untilPositiveInfinity()) { $constraints[] = $intervals['numeric'][0]->getStart(); $hasNumericMatchAll = \true; } else { $unEqualConstraints = array(); for ($i = 0, $count = \count($intervals['numeric']); $i < $count; $i++) { $interval = $intervals['numeric'][$i]; // if current interval ends with < N and next interval begins with > N we can swap this out for != N // but this needs to happen as a conjunctive expression together with the start of the current interval // and end of next interval, so [>=M, N, [>=M, !=N, getEnd()->getOperator() === '<' && $i + 1 < $count) { $nextInterval = $intervals['numeric'][$i + 1]; if ($interval->getEnd()->getVersion() === $nextInterval->getStart()->getVersion() && $nextInterval->getStart()->getOperator() === '>') { // only add a start if we didn't already do so, can be skipped if we're looking at second // interval in [>=M, N, P, =M, !=N] already and we only want to add !=P right now if (\count($unEqualConstraints) === 0 && (string) $interval->getStart() !== (string) Interval::fromZero()) { $unEqualConstraints[] = $interval->getStart(); } $unEqualConstraints[] = new Constraint('!=', $interval->getEnd()->getVersion()); continue; } } if (\count($unEqualConstraints) > 0) { // this is where the end of the following interval of a != constraint is added as explained above if ((string) $interval->getEnd() !== (string) Interval::untilPositiveInfinity()) { $unEqualConstraints[] = $interval->getEnd(); } // count is 1 if entire constraint is just one != expression if (\count($unEqualConstraints) > 1) { $constraints[] = new MultiConstraint($unEqualConstraints, \true); } else { $constraints[] = $unEqualConstraints[0]; } $unEqualConstraints = array(); continue; } // convert back >= x - <= x intervals to == x if ($interval->getStart()->getVersion() === $interval->getEnd()->getVersion() && $interval->getStart()->getOperator() === '>=' && $interval->getEnd()->getOperator() === '<=') { $constraints[] = new Constraint('==', $interval->getStart()->getVersion()); continue; } if ((string) $interval->getStart() === (string) Interval::fromZero()) { $constraints[] = $interval->getEnd(); } elseif ((string) $interval->getEnd() === (string) Interval::untilPositiveInfinity()) { $constraints[] = $interval->getStart(); } else { $constraints[] = new MultiConstraint(array($interval->getStart(), $interval->getEnd()), \true); } } } $devConstraints = array(); if (0 === \count($intervals['branches']['names'])) { if ($intervals['branches']['exclude']) { if ($hasNumericMatchAll) { return new MatchAllConstraint(); } // otherwise constraint should contain a != operator and already cover this } } else { foreach ($intervals['branches']['names'] as $branchName) { if ($intervals['branches']['exclude']) { $devConstraints[] = new Constraint('!=', $branchName); } else { $devConstraints[] = new Constraint('==', $branchName); } } // excluded branches, e.g. != dev-foo are conjunctive with the interval, so // > 2.0 != dev-foo must return a conjunctive constraint if ($intervals['branches']['exclude']) { if (\count($constraints) > 1) { return new MultiConstraint(array_merge(array(new MultiConstraint($constraints, \false)), $devConstraints), \true); } if (\count($constraints) === 1 && (string) $constraints[0] === (string) Interval::fromZero()) { if (\count($devConstraints) > 1) { return new MultiConstraint($devConstraints, \true); } return $devConstraints[0]; } return new MultiConstraint(array_merge($constraints, $devConstraints), \true); } // otherwise devConstraints contains a list of == operators for branches which are disjunctive with the // rest of the constraint $constraints = array_merge($constraints, $devConstraints); } if (\count($constraints) > 1) { return new MultiConstraint($constraints, \false); } if (\count($constraints) === 1) { return $constraints[0]; } return new MatchNoneConstraint(); } /** * Creates an array of numeric intervals and branch constraints representing a given constraint * * if the returned numeric array is empty it means the constraint matches nothing in the numeric range (0 - +inf) * if the returned branches array is empty it means no dev-* versions are matched * if a constraint matches all possible dev-* versions, branches will contain Interval::anyDev() * * @return array * @phpstan-return array{'numeric': Interval[], 'branches': array{'names': string[], 'exclude': bool}} */ public static function get(ConstraintInterface $constraint) { $key = (string) $constraint; if (!isset(self::$intervalsCache[$key])) { self::$intervalsCache[$key] = self::generateIntervals($constraint); } return self::$intervalsCache[$key]; } /** * @param bool $stopOnFirstValidInterval * * @phpstan-return array{'numeric': Interval[], 'branches': array{'names': string[], 'exclude': bool}} */ private static function generateIntervals(ConstraintInterface $constraint, $stopOnFirstValidInterval = \false) { if ($constraint instanceof MatchAllConstraint) { return array('numeric' => array(new Interval(Interval::fromZero(), Interval::untilPositiveInfinity())), 'branches' => Interval::anyDev()); } if ($constraint instanceof MatchNoneConstraint) { return array('numeric' => array(), 'branches' => array('names' => array(), 'exclude' => \false)); } if ($constraint instanceof Constraint) { return self::generateSingleConstraintIntervals($constraint); } if (!$constraint instanceof MultiConstraint) { throw new \UnexpectedValueException('The constraint passed in should be an MatchAllConstraint, Constraint or MultiConstraint instance, got ' . \get_class($constraint) . '.'); } $constraints = $constraint->getConstraints(); $numericGroups = array(); $constraintBranches = array(); foreach ($constraints as $c) { $res = self::get($c); $numericGroups[] = $res['numeric']; $constraintBranches[] = $res['branches']; } if ($constraint->isDisjunctive()) { $branches = Interval::noDev(); foreach ($constraintBranches as $b) { if ($b['exclude']) { if ($branches['exclude']) { // disjunctive constraint, so only exclude what's excluded in all constraints // !=a,!=b || !=b,!=c => !=b $branches['names'] = array_intersect($branches['names'], $b['names']); } else { // disjunctive constraint so exclude all names which are not explicitly included in the alternative // (==b || ==c) || !=a,!=b => !=a $branches['exclude'] = \true; $branches['names'] = array_diff($b['names'], $branches['names']); } } else if ($branches['exclude']) { // disjunctive constraint so exclude all names which are not explicitly included in the alternative // !=a,!=b || (==b || ==c) => !=a $branches['names'] = array_diff($branches['names'], $b['names']); } else { // disjunctive constraint, so just add all the other branches // (==a || ==b) || ==c => ==a || ==b || ==c $branches['names'] = array_merge($branches['names'], $b['names']); } } } else { $branches = Interval::anyDev(); foreach ($constraintBranches as $b) { if ($b['exclude']) { if ($branches['exclude']) { // conjunctive, so just add all branch names to be excluded // !=a && !=b => !=a,!=b $branches['names'] = array_merge($branches['names'], $b['names']); } else { // conjunctive, so only keep included names which are not excluded // (==a||==c) && !=a,!=b => ==c $branches['names'] = array_diff($branches['names'], $b['names']); } } else if ($branches['exclude']) { // conjunctive, so only keep included names which are not excluded // !=a,!=b && (==a||==c) => ==c $branches['names'] = array_diff($b['names'], $branches['names']); $branches['exclude'] = \false; } else { // conjunctive, so only keep names that are included in both // (==a||==b) && (==a||==c) => ==a $branches['names'] = array_intersect($branches['names'], $b['names']); } } } $branches['names'] = array_unique($branches['names']); if (\count($numericGroups) === 1) { return array('numeric' => $numericGroups[0], 'branches' => $branches); } $borders = array(); foreach ($numericGroups as $group) { foreach ($group as $interval) { $borders[] = array('version' => $interval->getStart()->getVersion(), 'operator' => $interval->getStart()->getOperator(), 'side' => 'start'); $borders[] = array('version' => $interval->getEnd()->getVersion(), 'operator' => $interval->getEnd()->getOperator(), 'side' => 'end'); } } $opSortOrder = self::$opSortOrder; usort($borders, function ($a, $b) use ($opSortOrder) { $order = version_compare($a['version'], $b['version']); if ($order === 0) { return $opSortOrder[$a['operator']] - $opSortOrder[$b['operator']]; } return $order; }); $activeIntervals = 0; $intervals = array(); $index = 0; $activationThreshold = $constraint->isConjunctive() ? \count($numericGroups) : 1; $start = null; foreach ($borders as $border) { if ($border['side'] === 'start') { $activeIntervals++; } else { $activeIntervals--; } if (!$start && $activeIntervals >= $activationThreshold) { $start = new Constraint($border['operator'], $border['version']); } elseif ($start && $activeIntervals < $activationThreshold) { // filter out invalid intervals like > x - <= x, or >= x - < x if (version_compare($start->getVersion(), $border['version'], '=') && ($start->getOperator() === '>' && $border['operator'] === '<=' || $start->getOperator() === '>=' && $border['operator'] === '<')) { unset($intervals[$index]); } else { $intervals[$index] = new Interval($start, new Constraint($border['operator'], $border['version'])); $index++; if ($stopOnFirstValidInterval) { break; } } $start = null; } } return array('numeric' => $intervals, 'branches' => $branches); } /** * @phpstan-return array{'numeric': Interval[], 'branches': array{'names': string[], 'exclude': bool}} */ private static function generateSingleConstraintIntervals(Constraint $constraint) { $op = $constraint->getOperator(); // handle branch constraints first if (strpos($constraint->getVersion(), 'dev-') === 0) { $intervals = array(); $branches = array('names' => array(), 'exclude' => \false); // != dev-foo means any numeric version may match, we treat >/< like != they are not really defined for branches if ($op === '!=') { $intervals[] = new Interval(Interval::fromZero(), Interval::untilPositiveInfinity()); $branches = array('names' => array($constraint->getVersion()), 'exclude' => \true); } elseif ($op === '==') { $branches['names'][] = $constraint->getVersion(); } return array('numeric' => $intervals, 'branches' => $branches); } if ($op[0] === '>') { // > & >= return array('numeric' => array(new Interval($constraint, Interval::untilPositiveInfinity())), 'branches' => Interval::noDev()); } if ($op[0] === '<') { // < & <= return array('numeric' => array(new Interval(Interval::fromZero(), $constraint)), 'branches' => Interval::noDev()); } if ($op === '!=') { // convert !=x to intervals of 0 - x - +inf + dev* return array('numeric' => array(new Interval(Interval::fromZero(), new Constraint('<', $constraint->getVersion())), new Interval(new Constraint('>', $constraint->getVersion()), Interval::untilPositiveInfinity())), 'branches' => Interval::anyDev()); } // convert ==x to an interval of >=x - <=x return array('numeric' => array(new Interval(new Constraint('>=', $constraint->getVersion()), new Constraint('<=', $constraint->getVersion()))), 'branches' => Interval::noDev()); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Semver; use _PHPStan_33c983f26\Composer\Semver\Constraint\Constraint; class Semver { const SORT_ASC = 1; const SORT_DESC = -1; /** @var VersionParser */ private static $versionParser; /** * Determine if given version satisfies given constraints. * * @param string $version * @param string $constraints * * @return bool */ public static function satisfies($version, $constraints) { if (null === self::$versionParser) { self::$versionParser = new VersionParser(); } $versionParser = self::$versionParser; $provider = new Constraint('==', $versionParser->normalize($version)); $parsedConstraints = $versionParser->parseConstraints($constraints); return $parsedConstraints->matches($provider); } /** * Return all versions that satisfy given constraints. * * @param string[] $versions * @param string $constraints * * @return list */ public static function satisfiedBy(array $versions, $constraints) { $versions = array_filter($versions, function ($version) use ($constraints) { return Semver::satisfies($version, $constraints); }); return array_values($versions); } /** * Sort given array of versions. * * @param string[] $versions * * @return list */ public static function sort(array $versions) { return self::usort($versions, self::SORT_ASC); } /** * Sort given array of versions in reverse. * * @param string[] $versions * * @return list */ public static function rsort(array $versions) { return self::usort($versions, self::SORT_DESC); } /** * @param string[] $versions * @param int $direction * * @return list */ private static function usort(array $versions, $direction) { if (null === self::$versionParser) { self::$versionParser = new VersionParser(); } $versionParser = self::$versionParser; $normalized = array(); // Normalize outside of usort() scope for minor performance increase. // Creates an array of arrays: [[normalized, key], ...] foreach ($versions as $key => $version) { $normalizedVersion = $versionParser->normalize($version); $normalizedVersion = $versionParser->normalizeDefaultBranch($normalizedVersion); $normalized[] = array($normalizedVersion, $key); } usort($normalized, function (array $left, array $right) use ($direction) { if ($left[0] === $right[0]) { return 0; } if (Comparator::lessThan($left[0], $right[0])) { return -$direction; } return $direction; }); // Recreate input array, using the original indexes which are now in sorted order. $sorted = array(); foreach ($normalized as $item) { $sorted[] = $versions[$item[1]]; } return $sorted; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\Semver; use _PHPStan_33c983f26\Composer\Semver\Constraint\ConstraintInterface; use _PHPStan_33c983f26\Composer\Semver\Constraint\MatchAllConstraint; use _PHPStan_33c983f26\Composer\Semver\Constraint\MultiConstraint; use _PHPStan_33c983f26\Composer\Semver\Constraint\Constraint; /** * Version parser. * * @author Jordi Boggiano */ class VersionParser { /** * Regex to match pre-release data (sort of). * * Due to backwards compatibility: * - Instead of enforcing hyphen, an underscore, dot or nothing at all are also accepted. * - Only stabilities as recognized by Composer are allowed to precede a numerical identifier. * - Numerical-only pre-release identifiers are not supported, see tests. * * |--------------| * [major].[minor].[patch] -[pre-release] +[build-metadata] * * @var string */ private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)((?:[.-]?\d+)*+)?)?([.-]?dev)?'; /** @var string */ private static $stabilitiesRegex = 'stable|RC|beta|alpha|dev'; /** * Returns the stability of a version. * * @param string $version * * @return string * @phpstan-return 'stable'|'RC'|'beta'|'alpha'|'dev' */ public static function parseStability($version) { $version = (string) preg_replace('{#.+$}', '', (string) $version); if (strpos($version, 'dev-') === 0 || '-dev' === substr($version, -4)) { return 'dev'; } preg_match('{' . self::$modifierRegex . '(?:\+.*)?$}i', strtolower($version), $match); if (!empty($match[3])) { return 'dev'; } if (!empty($match[1])) { if ('beta' === $match[1] || 'b' === $match[1]) { return 'beta'; } if ('alpha' === $match[1] || 'a' === $match[1]) { return 'alpha'; } if ('rc' === $match[1]) { return 'RC'; } } return 'stable'; } /** * @param string $stability * * @return string * @phpstan-return 'stable'|'RC'|'beta'|'alpha'|'dev' */ public static function normalizeStability($stability) { $stability = strtolower((string) $stability); if (!in_array($stability, array('stable', 'rc', 'beta', 'alpha', 'dev'), \true)) { throw new \InvalidArgumentException('Invalid stability string "' . $stability . '", expected one of stable, RC, beta, alpha or dev'); } return $stability === 'rc' ? 'RC' : $stability; } /** * Normalizes a version string to be able to perform comparisons on it. * * @param string $version * @param ?string $fullVersion optional complete version string to give more context * * @throws \UnexpectedValueException * * @return string */ public function normalize($version, $fullVersion = null) { $version = trim((string) $version); $origVersion = $version; if (null === $fullVersion) { $fullVersion = $version; } // strip off aliasing if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $version, $match)) { $version = $match[1]; } // strip off stability flag if (preg_match('{@(?:' . self::$stabilitiesRegex . ')$}i', $version, $match)) { $version = substr($version, 0, strlen($version) - strlen($match[0])); } // normalize master/trunk/default branches to dev-name for BC with 1.x as these used to be valid constraints if (\in_array($version, array('master', 'trunk', 'default'), \true)) { $version = 'dev-' . $version; } // if requirement is branch-like, use full name if (stripos($version, 'dev-') === 0) { return 'dev-' . substr($version, 4); } // strip off build metadata if (preg_match('{^([^,\s+]++)\+[^\s]++$}', $version, $match)) { $version = $match[1]; } // match classical versioning if (preg_match('{^v?(\d{1,5}+)(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) { $version = $matches[1] . (!empty($matches[2]) ? $matches[2] : '.0') . (!empty($matches[3]) ? $matches[3] : '.0') . (!empty($matches[4]) ? $matches[4] : '.0'); $index = 5; // match date(time) based versioning } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3}){0,2})' . self::$modifierRegex . '$}i', $version, $matches)) { $version = (string) preg_replace('{\D}', '.', $matches[1]); $index = 2; } // add version modifiers if a version was matched if (isset($index)) { if (!empty($matches[$index])) { if ('stable' === $matches[$index]) { return $version; } $version .= '-' . $this->expandStability($matches[$index]) . (isset($matches[$index + 1]) && '' !== $matches[$index + 1] ? ltrim($matches[$index + 1], '.-') : ''); } if (!empty($matches[$index + 2])) { $version .= '-dev'; } return $version; } // match dev branches if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) { try { $normalized = $this->normalizeBranch($match[1]); // a branch ending with -dev is only valid if it is numeric // if it gets prefixed with dev- it means the branch name should // have had a dev- prefix already when passed to normalize if (strpos($normalized, 'dev-') === \false) { return $normalized; } } catch (\Exception $e) { } } $extraMessage = ''; if (preg_match('{ +as +' . preg_quote($version) . '(?:@(?:' . self::$stabilitiesRegex . '))?$}', $fullVersion)) { $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version'; } elseif (preg_match('{^' . preg_quote($version) . '(?:@(?:' . self::$stabilitiesRegex . '))? +as +}', $fullVersion)) { $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-'; } throw new \UnexpectedValueException('Invalid version string "' . $origVersion . '"' . $extraMessage); } /** * Extract numeric prefix from alias, if it is in numeric format, suitable for version comparison. * * @param string $branch Branch name (e.g. 2.1.x-dev) * * @return string|false Numeric prefix if present (e.g. 2.1.) or false */ public function parseNumericAliasPrefix($branch) { if (preg_match('{^(?P(\d++\.)*\d++)(?:\.x)?-dev$}i', (string) $branch, $matches)) { return $matches['version'] . '.'; } return \false; } /** * Normalizes a branch name to be able to perform comparisons on it. * * @param string $name * * @return string */ public function normalizeBranch($name) { $name = trim((string) $name); if (preg_match('{^v?(\d++)(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?$}i', $name, $matches)) { $version = ''; for ($i = 1; $i < 5; ++$i) { $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x'; } return str_replace('x', '9999999', $version) . '-dev'; } return 'dev-' . $name; } /** * Normalizes a default branch name (i.e. master on git) to 9999999-dev. * * @param string $name * * @return string * * @deprecated No need to use this anymore in theory, Composer 2 does not normalize any branch names to 9999999-dev anymore */ public function normalizeDefaultBranch($name) { if ($name === 'dev-master' || $name === 'dev-default' || $name === 'dev-trunk') { return '9999999-dev'; } return (string) $name; } /** * Parses a constraint string into MultiConstraint and/or Constraint objects. * * @param string $constraints * * @return ConstraintInterface */ public function parseConstraints($constraints) { $prettyConstraint = (string) $constraints; $orConstraints = preg_split('{\s*\|\|?\s*}', trim((string) $constraints)); if (\false === $orConstraints) { throw new \RuntimeException('Failed to preg_split string: ' . $constraints); } $orGroups = array(); foreach ($orConstraints as $orConstraint) { $andConstraints = preg_split('{(?< ,]) *(? 1) { $constraintObjects = array(); foreach ($andConstraints as $andConstraint) { foreach ($this->parseConstraint($andConstraint) as $parsedAndConstraint) { $constraintObjects[] = $parsedAndConstraint; } } } else { $constraintObjects = $this->parseConstraint($andConstraints[0]); } if (1 === \count($constraintObjects)) { $constraint = $constraintObjects[0]; } else { $constraint = new MultiConstraint($constraintObjects); } $orGroups[] = $constraint; } $parsedConstraint = MultiConstraint::create($orGroups, \false); $parsedConstraint->setPrettyString($prettyConstraint); return $parsedConstraint; } /** * @param string $constraint * * @throws \UnexpectedValueException * * @return array * * @phpstan-return non-empty-array */ private function parseConstraint($constraint) { // strip off aliasing if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $constraint, $match)) { $constraint = $match[1]; } // strip @stability flags, and keep it for later use if (preg_match('{^([^,\s]*?)@(' . self::$stabilitiesRegex . ')$}i', $constraint, $match)) { $constraint = '' !== $match[1] ? $match[1] : '*'; if ($match[2] !== 'stable') { $stabilityModifier = $match[2]; } } // get rid of #refs as those are used by composer only if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraint, $match)) { $constraint = $match[1]; } if (preg_match('{^(v)?[xX*](\.[xX*])*$}i', $constraint, $match)) { if (!empty($match[1]) || !empty($match[2])) { return array(new Constraint('>=', '0.0.0.0-dev')); } return array(new MatchAllConstraint()); } $versionRegex = 'v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.(\d++))?(?:' . self::$modifierRegex . '|\.([xX*][.-]?dev))(?:\+[^\s]+)?'; // Tilde Range // // Like wildcard constraints, unsuffixed tilde constraints say that they must be greater than the previous // version, to ensure that unstable instances of the current version are allowed. However, if a stability // suffix is added to the constraint, then a >= match on the current version is used instead. if (preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) { if (strpos($constraint, '~>') === 0) { throw new \UnexpectedValueException('Could not parse version constraint ' . $constraint . ': ' . 'Invalid operator "~>", you probably meant to use the "~" operator'); } // Work out which position in the version we are operating at if (isset($matches[4]) && '' !== $matches[4] && null !== $matches[4]) { $position = 4; } elseif (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) { $position = 3; } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) { $position = 2; } else { $position = 1; } // when matching 2.x-dev or 3.0.x-dev we have to shift the second or third number, despite no second/third number matching above if (!empty($matches[8])) { $position++; } // Calculate the stability suffix $stabilitySuffix = ''; if (empty($matches[5]) && empty($matches[7]) && empty($matches[8])) { $stabilitySuffix .= '-dev'; } $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1)); $lowerBound = new Constraint('>=', $lowVersion); // For upper bound, we increment the position of one more significance, // but highPosition = 0 would be illegal $highPosition = max(1, $position - 1); $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev'; $upperBound = new Constraint('<', $highVersion); return array($lowerBound, $upperBound); } // Caret Range // // Allows changes that do not modify the left-most non-zero digit in the [major, minor, patch] tuple. // In other words, this allows patch and minor updates for versions 1.0.0 and above, patch updates for // versions 0.X >=0.1.0, and no updates for versions 0.0.X if (preg_match('{^\^' . $versionRegex . '($)}i', $constraint, $matches)) { // Work out which position in the version we are operating at if ('0' !== $matches[1] || '' === $matches[2] || null === $matches[2]) { $position = 1; } elseif ('0' !== $matches[2] || '' === $matches[3] || null === $matches[3]) { $position = 2; } else { $position = 3; } // Calculate the stability suffix $stabilitySuffix = ''; if (empty($matches[5]) && empty($matches[7]) && empty($matches[8])) { $stabilitySuffix .= '-dev'; } $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1)); $lowerBound = new Constraint('>=', $lowVersion); // For upper bound, we increment the position of one more significance, // but highPosition = 0 would be illegal $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev'; $upperBound = new Constraint('<', $highVersion); return array($lowerBound, $upperBound); } // X Range // // Any of X, x, or * may be used to "stand in" for one of the numeric values in the [major, minor, patch] tuple. // A partial version range is treated as an X-Range, so the special character is in fact optional. if (preg_match('{^v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.[xX*])++$}', $constraint, $matches)) { if (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) { $position = 3; } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) { $position = 2; } else { $position = 1; } $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev'; $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev'; if ($lowVersion === '0.0.0.0-dev') { return array(new Constraint('<', $highVersion)); } return array(new Constraint('>=', $lowVersion), new Constraint('<', $highVersion)); } // Hyphen Range // // Specifies an inclusive set. If a partial version is provided as the first version in the inclusive range, // then the missing pieces are replaced with zeroes. If a partial version is provided as the second version in // the inclusive range, then all versions that start with the supplied parts of the tuple are accepted, but // nothing that would be greater than the provided tuple parts. if (preg_match('{^(?P' . $versionRegex . ') +- +(?P' . $versionRegex . ')($)}i', $constraint, $matches)) { // Calculate the stability suffix $lowStabilitySuffix = ''; if (empty($matches[6]) && empty($matches[8]) && empty($matches[9])) { $lowStabilitySuffix = '-dev'; } $lowVersion = $this->normalize($matches['from']); $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix); $empty = function ($x) { return $x === 0 || $x === '0' ? \false : empty($x); }; if (!$empty($matches[12]) && !$empty($matches[13]) || !empty($matches[15]) || !empty($matches[17]) || !empty($matches[18])) { $highVersion = $this->normalize($matches['to']); $upperBound = new Constraint('<=', $highVersion); } else { $highMatch = array('', $matches[11], $matches[12], $matches[13], $matches[14]); // validate to version $this->normalize($matches['to']); $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[12]) ? 1 : 2, 1) . '-dev'; $upperBound = new Constraint('<', $highVersion); } return array($lowerBound, $upperBound); } // Basic Comparators if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) { try { try { $version = $this->normalize($matches[2]); } catch (\UnexpectedValueException $e) { // recover from an invalid constraint like foobar-dev which should be dev-foobar // except if the constraint uses a known operator, in which case it must be a parse error if (substr($matches[2], -4) === '-dev' && preg_match('{^[0-9a-zA-Z-./]+$}', $matches[2])) { $version = $this->normalize('dev-' . substr($matches[2], 0, -4)); } else { throw $e; } } $op = $matches[1] ?: '='; if ($op !== '==' && $op !== '=' && !empty($stabilityModifier) && self::parseStability($version) === 'stable') { $version .= '-' . $stabilityModifier; } elseif ('<' === $op || '>=' === $op) { if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) { if (strpos($matches[2], 'dev-') !== 0) { $version .= '-dev'; } } } return array(new Constraint($matches[1] ?: '=', $version)); } catch (\Exception $e) { } } $message = 'Could not parse version constraint ' . $constraint; if (isset($e)) { $message .= ': ' . $e->getMessage(); } throw new \UnexpectedValueException($message); } /** * Increment, decrement, or simply pad a version number. * * Support function for {@link parseConstraint()} * * @param array $matches Array with version parts in array indexes 1,2,3,4 * @param int $position 1,2,3,4 - which segment of the version to increment/decrement * @param int $increment * @param string $pad The string to pad version parts after $position * * @return string|null The new version * * @phpstan-param string[] $matches */ private function manipulateVersionString(array $matches, $position, $increment = 0, $pad = '0') { for ($i = 4; $i > 0; --$i) { if ($i > $position) { $matches[$i] = $pad; } elseif ($i === $position && $increment) { $matches[$i] += $increment; // If $matches[$i] was 0, carry the decrement if ($matches[$i] < 0) { $matches[$i] = $pad; --$position; // Return null on a carry overflow if ($i === 1) { return null; } } } } return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4]; } /** * Expand shorthand stability string to long version. * * @param string $stability * * @return string */ private function expandStability($stability) { $stability = strtolower($stability); switch ($stability) { case 'a': return 'alpha'; case 'b': return 'beta'; case 'p': case 'pl': return 'patch'; case 'rc': return 'RC'; default: return $stability; } } } MIT License Copyright (c) 2017 Composer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Composer\XdebugHandler; /** * @author John Stevenson * * @phpstan-type restartData array{tmpIni: string, scannedInis: bool, scanDir: false|string, phprc: false|string, inis: string[], skipped: string} */ class PhpConfig { /** * Use the original PHP configuration * * @return string[] Empty array of PHP cli options */ public function useOriginal(): array { $this->getDataAndReset(); return []; } /** * Use standard restart settings * * @return string[] PHP cli options */ public function useStandard(): array { $data = $this->getDataAndReset(); if ($data !== null) { return ['-n', '-c', $data['tmpIni']]; } return []; } /** * Use environment variables to persist settings * * @return string[] Empty array of PHP cli options */ public function usePersistent(): array { $data = $this->getDataAndReset(); if ($data !== null) { $this->updateEnv('PHPRC', $data['tmpIni']); $this->updateEnv('PHP_INI_SCAN_DIR', ''); } return []; } /** * Returns restart data if available and resets the environment * * @phpstan-return restartData|null */ private function getDataAndReset(): ?array { $data = XdebugHandler::getRestartSettings(); if ($data !== null) { $this->updateEnv('PHPRC', $data['phprc']); $this->updateEnv('PHP_INI_SCAN_DIR', $data['scanDir']); } return $data; } /** * Updates a restart settings value in the environment * * @param string $name * @param string|false $value */ private function updateEnv(string $name, $value): void { Process::setEnv($name, \false !== $value ? $value : null); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Composer\XdebugHandler; use _PHPStan_33c983f26\Composer\Pcre\Preg; /** * Process utility functions * * @author John Stevenson */ class Process { /** * Escapes a string to be used as a shell argument. * * From https://github.com/johnstevenson/winbox-args * MIT Licensed (c) John Stevenson * * @param string $arg The argument to be escaped * @param bool $meta Additionally escape cmd.exe meta characters * @param bool $module The argument is the module to invoke */ public static function escape(string $arg, bool $meta = \true, bool $module = \false): string { if (!defined('PHP_WINDOWS_VERSION_BUILD')) { return "'" . str_replace("'", "'\\''", $arg) . "'"; } $quote = strpbrk($arg, " \t") !== \false || $arg === ''; $arg = Preg::replace('/(\\\\*)"/', '$1$1\"', $arg, -1, $dquotes); $dquotes = (bool) $dquotes; if ($meta) { $meta = $dquotes || Preg::isMatch('/%[^%]+%/', $arg); if (!$meta) { $quote = $quote || strpbrk($arg, '^&|<>()') !== \false; } elseif ($module && !$dquotes && $quote) { $meta = \false; } } if ($quote) { $arg = '"' . Preg::replace('/(\\\\*)$/', '$1$1', $arg) . '"'; } if ($meta) { $arg = Preg::replace('/(["^&|<>()%])/', '^$1', $arg); } return $arg; } /** * Escapes an array of arguments that make up a shell command * * @param string[] $args Argument list, with the module name first */ public static function escapeShellCommand(array $args): string { $command = ''; $module = array_shift($args); if ($module !== null) { $command = self::escape($module, \true, \true); foreach ($args as $arg) { $command .= ' ' . self::escape($arg); } } return $command; } /** * Makes putenv environment changes available in $_SERVER and $_ENV * * @param string $name * @param ?string $value A null value unsets the variable */ public static function setEnv(string $name, ?string $value = null): bool { $unset = null === $value; if (!putenv($unset ? $name : $name . '=' . $value)) { return \false; } if ($unset) { unset($_SERVER[$name]); } else { $_SERVER[$name] = $value; } // Update $_ENV if it is being used if (\false !== stripos((string) ini_get('variables_order'), 'E')) { if ($unset) { unset($_ENV[$name]); } else { $_ENV[$name] = $value; } } return \true; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Composer\XdebugHandler; use _PHPStan_33c983f26\Psr\Log\LoggerInterface; use _PHPStan_33c983f26\Psr\Log\LogLevel; /** * @author John Stevenson * @internal */ class Status { const ENV_RESTART = 'XDEBUG_HANDLER_RESTART'; const CHECK = 'Check'; const ERROR = 'Error'; const INFO = 'Info'; const NORESTART = 'NoRestart'; const RESTART = 'Restart'; const RESTARTING = 'Restarting'; const RESTARTED = 'Restarted'; /** @var bool */ private $debug; /** @var string */ private $envAllowXdebug; /** @var string|null */ private $loaded; /** @var LoggerInterface|null */ private $logger; /** @var bool */ private $modeOff; /** @var float */ private $time; /** * @param string $envAllowXdebug Prefixed _ALLOW_XDEBUG name * @param bool $debug Whether debug output is required */ public function __construct(string $envAllowXdebug, bool $debug) { $start = getenv(self::ENV_RESTART); Process::setEnv(self::ENV_RESTART); $this->time = is_numeric($start) ? round((microtime(\true) - $start) * 1000) : 0; $this->envAllowXdebug = $envAllowXdebug; $this->debug = $debug && defined('STDERR'); $this->modeOff = \false; } /** * Activates status message output to a PSR3 logger * * @return void */ public function setLogger(LoggerInterface $logger): void { $this->logger = $logger; } /** * Calls a handler method to report a message * * @throws \InvalidArgumentException If $op is not known */ public function report(string $op, ?string $data): void { if ($this->logger !== null || $this->debug) { $param = (string) $data; switch ($op) { case self::CHECK: $this->reportCheck($param); break; case self::ERROR: $this->reportError($param); break; case self::INFO: $this->reportInfo($param); break; case self::NORESTART: $this->reportNoRestart(); break; case self::RESTART: $this->reportRestart(); break; case self::RESTARTED: $this->reportRestarted(); break; case self::RESTARTING: $this->reportRestarting($param); break; default: throw new \InvalidArgumentException('Unknown op handler: ' . $op); } } } /** * Outputs a status message */ private function output(string $text, ?string $level = null): void { if ($this->logger !== null) { $this->logger->log($level !== null ? $level : LogLevel::DEBUG, $text); } if ($this->debug) { fwrite(\STDERR, sprintf('xdebug-handler[%d] %s', getmypid(), $text . \PHP_EOL)); } } /** * Checking status message */ private function reportCheck(string $loaded): void { list($version, $mode) = explode('|', $loaded); if ($version !== '') { $this->loaded = '(' . $version . ')' . ($mode !== '' ? ' xdebug.mode=' . $mode : ''); } $this->modeOff = $mode === 'off'; $this->output('Checking ' . $this->envAllowXdebug); } /** * Error status message */ private function reportError(string $error): void { $this->output(sprintf('No restart (%s)', $error), LogLevel::WARNING); } /** * Info status message */ private function reportInfo(string $info): void { $this->output($info); } /** * No restart status message */ private function reportNoRestart(): void { $this->output($this->getLoadedMessage()); if ($this->loaded !== null) { $text = sprintf('No restart (%s)', $this->getEnvAllow()); if (!(bool) getenv($this->envAllowXdebug)) { $text .= ' Allowed by ' . ($this->modeOff ? 'xdebug.mode' : 'application'); } $this->output($text); } } /** * Restart status message */ private function reportRestart(): void { $this->output($this->getLoadedMessage()); Process::setEnv(self::ENV_RESTART, (string) microtime(\true)); } /** * Restarted status message */ private function reportRestarted(): void { $loaded = $this->getLoadedMessage(); $text = sprintf('Restarted (%d ms). %s', $this->time, $loaded); $level = $this->loaded !== null ? LogLevel::WARNING : null; $this->output($text, $level); } /** * Restarting status message */ private function reportRestarting(string $command): void { $text = sprintf('Process restarting (%s)', $this->getEnvAllow()); $this->output($text); $text = 'Running: ' . $command; $this->output($text); } /** * Returns the _ALLOW_XDEBUG environment variable as name=value */ private function getEnvAllow(): string { return $this->envAllowXdebug . '=' . getenv($this->envAllowXdebug); } /** * Returns the Xdebug status and version */ private function getLoadedMessage(): string { $loaded = $this->loaded !== null ? sprintf('loaded %s', $this->loaded) : 'not loaded'; return 'The Xdebug extension is ' . $loaded; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Composer\XdebugHandler; use _PHPStan_33c983f26\Composer\Pcre\Preg; use _PHPStan_33c983f26\Psr\Log\LoggerInterface; /** * @author John Stevenson * * @phpstan-import-type restartData from PhpConfig */ class XdebugHandler { const SUFFIX_ALLOW = '_ALLOW_XDEBUG'; const SUFFIX_INIS = '_ORIGINAL_INIS'; const RESTART_ID = 'internal'; const RESTART_SETTINGS = 'XDEBUG_HANDLER_SETTINGS'; const DEBUG = 'XDEBUG_HANDLER_DEBUG'; /** @var string|null */ protected $tmpIni; /** @var bool */ private static $inRestart; /** @var string */ private static $name; /** @var string|null */ private static $skipped; /** @var bool */ private static $xdebugActive; /** @var string|null */ private static $xdebugMode; /** @var string|null */ private static $xdebugVersion; /** @var bool */ private $cli; /** @var string|null */ private $debug; /** @var string */ private $envAllowXdebug; /** @var string */ private $envOriginalInis; /** @var bool */ private $persistent; /** @var string|null */ private $script; /** @var Status */ private $statusWriter; /** * Constructor * * The $envPrefix is used to create distinct environment variables. It is * uppercased and prepended to the default base values. For example 'myapp' * would result in MYAPP_ALLOW_XDEBUG and MYAPP_ORIGINAL_INIS. * * @param string $envPrefix Value used in environment variables * @throws \RuntimeException If the parameter is invalid */ public function __construct(string $envPrefix) { if ($envPrefix === '') { throw new \RuntimeException('Invalid constructor parameter'); } self::$name = strtoupper($envPrefix); $this->envAllowXdebug = self::$name . self::SUFFIX_ALLOW; $this->envOriginalInis = self::$name . self::SUFFIX_INIS; self::setXdebugDetails(); self::$inRestart = \false; if ($this->cli = \PHP_SAPI === 'cli') { $this->debug = (string) getenv(self::DEBUG); } $this->statusWriter = new Status($this->envAllowXdebug, (bool) $this->debug); } /** * Activates status message output to a PSR3 logger */ public function setLogger(LoggerInterface $logger): self { $this->statusWriter->setLogger($logger); return $this; } /** * Sets the main script location if it cannot be called from argv */ public function setMainScript(string $script): self { $this->script = $script; return $this; } /** * Persist the settings to keep Xdebug out of sub-processes */ public function setPersistent(): self { $this->persistent = \true; return $this; } /** * Checks if Xdebug is loaded and the process needs to be restarted * * This behaviour can be disabled by setting the MYAPP_ALLOW_XDEBUG * environment variable to 1. This variable is used internally so that * the restarted process is created only once. */ public function check(): void { $this->notify(Status::CHECK, self::$xdebugVersion . '|' . self::$xdebugMode); $envArgs = explode('|', (string) getenv($this->envAllowXdebug)); if (!(bool) $envArgs[0] && $this->requiresRestart(self::$xdebugActive)) { // Restart required $this->notify(Status::RESTART); $command = $this->prepareRestart(); if ($command !== null) { $this->restart($command); } return; } if (self::RESTART_ID === $envArgs[0] && count($envArgs) === 5) { // Restarted, so unset environment variable and use saved values $this->notify(Status::RESTARTED); Process::setEnv($this->envAllowXdebug); self::$inRestart = \true; if (self::$xdebugVersion === null) { // Skipped version is only set if Xdebug is not loaded self::$skipped = $envArgs[1]; } $this->tryEnableSignals(); // Put restart settings in the environment $this->setEnvRestartSettings($envArgs); return; } $this->notify(Status::NORESTART); $settings = self::getRestartSettings(); if ($settings !== null) { // Called with existing settings, so sync our settings $this->syncSettings($settings); } } /** * Returns an array of php.ini locations with at least one entry * * The equivalent of calling php_ini_loaded_file then php_ini_scanned_files. * The loaded ini location is the first entry and may be an empty string. * * @return non-empty-list */ public static function getAllIniFiles(): array { if (self::$name !== null) { $env = getenv(self::$name . self::SUFFIX_INIS); if (\false !== $env) { return explode(\PATH_SEPARATOR, $env); } } $paths = [(string) php_ini_loaded_file()]; $scanned = php_ini_scanned_files(); if ($scanned !== \false) { $paths = array_merge($paths, array_map('trim', explode(',', $scanned))); } return $paths; } /** * Returns an array of restart settings or null * * Settings will be available if the current process was restarted, or * called with the settings from an existing restart. * * @phpstan-return restartData|null */ public static function getRestartSettings(): ?array { $envArgs = explode('|', (string) getenv(self::RESTART_SETTINGS)); if (count($envArgs) !== 6 || !self::$inRestart && php_ini_loaded_file() !== $envArgs[0]) { return null; } return ['tmpIni' => $envArgs[0], 'scannedInis' => (bool) $envArgs[1], 'scanDir' => '*' === $envArgs[2] ? \false : $envArgs[2], 'phprc' => '*' === $envArgs[3] ? \false : $envArgs[3], 'inis' => explode(\PATH_SEPARATOR, $envArgs[4]), 'skipped' => $envArgs[5]]; } /** * Returns the Xdebug version that triggered a successful restart */ public static function getSkippedVersion(): string { return (string) self::$skipped; } /** * Returns whether Xdebug is loaded and active * * true: if Xdebug is loaded and is running in an active mode. * false: if Xdebug is not loaded, or it is running with xdebug.mode=off. */ public static function isXdebugActive(): bool { self::setXdebugDetails(); return self::$xdebugActive; } /** * Allows an extending class to decide if there should be a restart * * The default is to restart if Xdebug is loaded and its mode is not "off". */ protected function requiresRestart(bool $default): bool { return $default; } /** * Allows an extending class to access the tmpIni * * @param non-empty-list $command */ protected function restart(array $command): void { $this->doRestart($command); } /** * Executes the restarted command then deletes the tmp ini * * @param non-empty-list $command * @phpstan-return never */ private function doRestart(array $command): void { if (\PHP_VERSION_ID >= 70400) { $cmd = $command; $displayCmd = sprintf('[%s]', implode(', ', $cmd)); } else { $cmd = Process::escapeShellCommand($command); if (defined('PHP_WINDOWS_VERSION_BUILD')) { // Outer quotes required on cmd string below PHP 8 $cmd = '"' . $cmd . '"'; } $displayCmd = $cmd; } $this->tryEnableSignals(); $this->notify(Status::RESTARTING, $displayCmd); $process = proc_open($cmd, [], $pipes); if (is_resource($process)) { $exitCode = proc_close($process); } if (!isset($exitCode)) { // Unlikely that php or the default shell cannot be invoked $this->notify(Status::ERROR, 'Unable to restart process'); $exitCode = -1; } else { $this->notify(Status::INFO, 'Restarted process exited ' . $exitCode); } if ($this->debug === '2') { $this->notify(Status::INFO, 'Temp ini saved: ' . $this->tmpIni); } else { @unlink((string) $this->tmpIni); } exit($exitCode); } /** * Returns the command line array if everything was written for the restart * * If any of the following fails (however unlikely) we must return false to * stop potential recursion: * - tmp ini file creation * - environment variable creation * * @return non-empty-list|null */ private function prepareRestart(): ?array { if (!$this->cli) { $this->notify(Status::ERROR, 'Unsupported SAPI: ' . \PHP_SAPI); return null; } if (($argv = $this->checkServerArgv()) === null) { $this->notify(Status::ERROR, '$_SERVER[argv] is not as expected'); return null; } if (!$this->checkConfiguration($info)) { $this->notify(Status::ERROR, $info); return null; } $mainScript = (string) $this->script; if (!$this->checkMainScript($mainScript, $argv)) { $this->notify(Status::ERROR, 'Unable to access main script: ' . $mainScript); return null; } $tmpDir = sys_get_temp_dir(); $iniError = 'Unable to create temp ini file at: ' . $tmpDir; if (($tmpfile = @tempnam($tmpDir, '')) === \false) { $this->notify(Status::ERROR, $iniError); return null; } $error = null; $iniFiles = self::getAllIniFiles(); $scannedInis = count($iniFiles) > 1; if (!$this->writeTmpIni($tmpfile, $iniFiles, $error)) { $this->notify(Status::ERROR, $error ?? $iniError); @unlink($tmpfile); return null; } if (!$this->setEnvironment($scannedInis, $iniFiles, $tmpfile)) { $this->notify(Status::ERROR, 'Unable to set environment variables'); @unlink($tmpfile); return null; } $this->tmpIni = $tmpfile; return $this->getCommand($argv, $tmpfile, $mainScript); } /** * Returns true if the tmp ini file was written * * @param non-empty-list $iniFiles All ini files used in the current process */ private function writeTmpIni(string $tmpFile, array $iniFiles, ?string &$error): bool { // $iniFiles has at least one item and it may be empty if ($iniFiles[0] === '') { array_shift($iniFiles); } $content = ''; $sectionRegex = '/^\s*\[(?:PATH|HOST)\s*=/mi'; $xdebugRegex = '/^\s*(zend_extension\s*=.*xdebug.*)$/mi'; foreach ($iniFiles as $file) { // Check for inaccessible ini files if (($data = @file_get_contents($file)) === \false) { $error = 'Unable to read ini: ' . $file; return \false; } // Check and remove directives after HOST and PATH sections if (Preg::isMatchWithOffsets($sectionRegex, $data, $matches)) { $data = substr($data, 0, $matches[0][1]); } $content .= Preg::replace($xdebugRegex, ';$1', $data) . \PHP_EOL; } // Merge loaded settings into our ini content, if it is valid $config = parse_ini_string($content); $loaded = ini_get_all(null, \false); if (\false === $config || \false === $loaded) { $error = 'Unable to parse ini data'; return \false; } $content .= $this->mergeLoadedConfig($loaded, $config); // Work-around for https://bugs.php.net/bug.php?id=75932 $content .= 'opcache.enable_cli=0' . \PHP_EOL; return (bool) @file_put_contents($tmpFile, $content); } /** * Returns the command line arguments for the restart * * @param non-empty-list $argv * @return non-empty-list */ private function getCommand(array $argv, string $tmpIni, string $mainScript): array { $php = [\PHP_BINARY]; $args = array_slice($argv, 1); if (!$this->persistent) { // Use command-line options array_push($php, '-n', '-c', $tmpIni); } return array_merge($php, [$mainScript], $args); } /** * Returns true if the restart environment variables were set * * No need to update $_SERVER since this is set in the restarted process. * * @param non-empty-list $iniFiles All ini files used in the current process */ private function setEnvironment(bool $scannedInis, array $iniFiles, string $tmpIni): bool { $scanDir = getenv('PHP_INI_SCAN_DIR'); $phprc = getenv('PHPRC'); // Make original inis available to restarted process if (!putenv($this->envOriginalInis . '=' . implode(\PATH_SEPARATOR, $iniFiles))) { return \false; } if ($this->persistent) { // Use the environment to persist the settings if (!putenv('PHP_INI_SCAN_DIR=') || !putenv('PHPRC=' . $tmpIni)) { return \false; } } // Flag restarted process and save values for it to use $envArgs = [self::RESTART_ID, self::$xdebugVersion, (int) $scannedInis, \false === $scanDir ? '*' : $scanDir, \false === $phprc ? '*' : $phprc]; return putenv($this->envAllowXdebug . '=' . implode('|', $envArgs)); } /** * Logs status messages */ private function notify(string $op, ?string $data = null): void { $this->statusWriter->report($op, $data); } /** * Returns default, changed and command-line ini settings * * @param mixed[] $loadedConfig All current ini settings * @param mixed[] $iniConfig Settings from user ini files * */ private function mergeLoadedConfig(array $loadedConfig, array $iniConfig): string { $content = ''; foreach ($loadedConfig as $name => $value) { // Value will either be null, string or array (HHVM only) if (!is_string($value) || strpos($name, 'xdebug') === 0 || $name === 'apc.mmap_file_mask') { continue; } if (!isset($iniConfig[$name]) || $iniConfig[$name] !== $value) { // Double-quote escape each value $content .= $name . '="' . addcslashes($value, '\"') . '"' . \PHP_EOL; } } return $content; } /** * Returns true if the script name can be used * * @param non-empty-list $argv */ private function checkMainScript(string &$mainScript, array $argv): bool { if ($mainScript !== '') { // Allow an application to set -- for standard input return file_exists($mainScript) || '--' === $mainScript; } if (file_exists($mainScript = $argv[0])) { return \true; } // Use a backtrace to resolve Phar and chdir issues. $trace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS); $main = end($trace); if ($main !== \false && isset($main['file'])) { return file_exists($mainScript = $main['file']); } return \false; } /** * Adds restart settings to the environment * * @param non-empty-list $envArgs */ private function setEnvRestartSettings(array $envArgs): void { $settings = [php_ini_loaded_file(), $envArgs[2], $envArgs[3], $envArgs[4], getenv($this->envOriginalInis), self::$skipped]; Process::setEnv(self::RESTART_SETTINGS, implode('|', $settings)); } /** * Syncs settings and the environment if called with existing settings * * @phpstan-param restartData $settings */ private function syncSettings(array $settings): void { if (\false === getenv($this->envOriginalInis)) { // Called by another app, so make original inis available Process::setEnv($this->envOriginalInis, implode(\PATH_SEPARATOR, $settings['inis'])); } self::$skipped = $settings['skipped']; $this->notify(Status::INFO, 'Process called with existing restart settings'); } /** * Returns true if there are no known configuration issues */ private function checkConfiguration(?string &$info): bool { if (!function_exists('proc_open')) { $info = 'proc_open function is disabled'; return \false; } if (!file_exists(\PHP_BINARY)) { $info = 'PHP_BINARY is not available'; return \false; } if (extension_loaded('uopz') && !(bool) ini_get('uopz.disable')) { // uopz works at opcode level and disables exit calls if (function_exists('uopz_allow_exit')) { @uopz_allow_exit(\true); } else { $info = 'uopz extension is not compatible'; return \false; } } // Check UNC paths when using cmd.exe if (defined('PHP_WINDOWS_VERSION_BUILD') && \PHP_VERSION_ID < 70400) { $workingDir = getcwd(); if ($workingDir === \false) { $info = 'unable to determine working directory'; return \false; } if (0 === strpos($workingDir, '\\\\')) { $info = 'cmd.exe does not support UNC paths: ' . $workingDir; return \false; } } return \true; } /** * Enables async signals and control interrupts in the restarted process * * Available on Unix PHP 7.1+ with the pcntl extension and Windows PHP 7.4+. */ private function tryEnableSignals(): void { if (function_exists('pcntl_async_signals') && function_exists('pcntl_signal')) { pcntl_async_signals(\true); $message = 'Async signals enabled'; if (!self::$inRestart) { // Restarting, so ignore SIGINT in parent pcntl_signal(\SIGINT, \SIG_IGN); } elseif (is_int(pcntl_signal_get_handler(\SIGINT))) { // Restarted, no handler set so force default action pcntl_signal(\SIGINT, \SIG_DFL); } } if (!self::$inRestart && function_exists('sapi_windows_set_ctrl_handler')) { // Restarting, so set a handler to ignore CTRL events in the parent. // This ensures that CTRL+C events will be available in the child // process without having to enable them there, which is unreliable. sapi_windows_set_ctrl_handler(function ($evt) { }); } } /** * Returns $_SERVER['argv'] if it is as expected * * @return non-empty-list|null */ private function checkServerArgv(): ?array { $result = []; if (isset($_SERVER['argv']) && is_array($_SERVER['argv'])) { foreach ($_SERVER['argv'] as $value) { if (!is_string($value)) { return null; } $result[] = $value; } } return count($result) > 0 ? $result : null; } /** * Sets static properties $xdebugActive, $xdebugVersion and $xdebugMode */ private static function setXdebugDetails(): void { if (self::$xdebugActive !== null) { return; } self::$xdebugActive = \false; if (!extension_loaded('xdebug')) { return; } $version = phpversion('xdebug'); self::$xdebugVersion = $version !== \false ? $version : 'unknown'; if (version_compare(self::$xdebugVersion, '3.1', '>=')) { $modes = xdebug_info('mode'); self::$xdebugMode = count($modes) === 0 ? 'off' : implode(',', $modes); self::$xdebugActive = self::$xdebugMode !== 'off'; return; } // See if xdebug.mode is supported in this version $iniMode = ini_get('xdebug.mode'); if ($iniMode === \false) { self::$xdebugActive = \true; return; } // Environment value wins but cannot be empty $envMode = (string) getenv('XDEBUG_MODE'); if ($envMode !== '') { self::$xdebugMode = $envMode; } else { self::$xdebugMode = $iniMode !== '' ? $iniMode : 'off'; } // An empty comma-separated list is treated as mode 'off' if (Preg::isMatch('/^,+$/', str_replace(' ', '', self::$xdebugMode))) { self::$xdebugMode = 'off'; } self::$xdebugActive = self::$xdebugMode !== 'off'; } } Copyright (c) 2011 Igor Wiedler 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. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Evenement; class EventEmitter implements EventEmitterInterface { use EventEmitterTrait; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Evenement; interface EventEmitterInterface { public function on($event, callable $listener); public function once($event, callable $listener); public function removeListener($event, callable $listener); public function removeAllListeners($event = null); public function listeners($event = null); public function emit($event, array $arguments = []); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _PHPStan_33c983f26\Evenement; use InvalidArgumentException; use function count; use function array_keys; use function array_merge; use function array_search; use function array_unique; use function array_values; trait EventEmitterTrait { protected $listeners = []; protected $onceListeners = []; public function on($event, callable $listener) { if ($event === null) { throw new InvalidArgumentException('event name must not be null'); } if (!isset($this->listeners[$event])) { $this->listeners[$event] = []; } $this->listeners[$event][] = $listener; return $this; } public function once($event, callable $listener) { if ($event === null) { throw new InvalidArgumentException('event name must not be null'); } if (!isset($this->onceListeners[$event])) { $this->onceListeners[$event] = []; } $this->onceListeners[$event][] = $listener; return $this; } public function removeListener($event, callable $listener) { if ($event === null) { throw new InvalidArgumentException('event name must not be null'); } if (isset($this->listeners[$event])) { $index = array_search($listener, $this->listeners[$event], \true); if (\false !== $index) { unset($this->listeners[$event][$index]); if (count($this->listeners[$event]) === 0) { unset($this->listeners[$event]); } } } if (isset($this->onceListeners[$event])) { $index = array_search($listener, $this->onceListeners[$event], \true); if (\false !== $index) { unset($this->onceListeners[$event][$index]); if (count($this->onceListeners[$event]) === 0) { unset($this->onceListeners[$event]); } } } } public function removeAllListeners($event = null) { if ($event !== null) { unset($this->listeners[$event]); } else { $this->listeners = []; } if ($event !== null) { unset($this->onceListeners[$event]); } else { $this->onceListeners = []; } } public function listeners($event = null): array { if ($event === null) { $events = []; $eventNames = array_unique(array_merge(array_keys($this->listeners), array_keys($this->onceListeners))); foreach ($eventNames as $eventName) { $events[$eventName] = array_merge(isset($this->listeners[$eventName]) ? $this->listeners[$eventName] : [], isset($this->onceListeners[$eventName]) ? $this->onceListeners[$eventName] : []); } return $events; } return array_merge(isset($this->listeners[$event]) ? $this->listeners[$event] : [], isset($this->onceListeners[$event]) ? $this->onceListeners[$event] : []); } public function emit($event, array $arguments = []) { if ($event === null) { throw new InvalidArgumentException('event name must not be null'); } $listeners = []; if (isset($this->listeners[$event])) { $listeners = array_values($this->listeners[$event]); } $onceListeners = []; if (isset($this->onceListeners[$event])) { $onceListeners = array_values($this->onceListeners[$event]); } if (empty($listeners) === \false) { foreach ($listeners as $listener) { $listener(...$arguments); } } if (empty($onceListeners) === \false) { unset($this->onceListeners[$event]); foreach ($onceListeners as $listener) { $listener(...$arguments); } } } } #!/usr/bin/env php * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26; use _PHPStan_33c983f26\Fidry\CpuCoreCounter\Diagnoser; use _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder\FinderRegistry; require_once __DIR__ . '/../vendor/autoload.php'; echo 'Running diagnosis...' . \PHP_EOL . \PHP_EOL; echo Diagnoser::diagnose(FinderRegistry::getAllVariants()) . \PHP_EOL; echo 'Logical CPU cores finders...' . \PHP_EOL . \PHP_EOL; echo Diagnoser::diagnose(FinderRegistry::getDefaultLogicalFinders()) . \PHP_EOL; echo 'Physical CPU cores finders...' . \PHP_EOL . \PHP_EOL; echo Diagnoser::diagnose(FinderRegistry::getDefaultPhysicalFinders()) . \PHP_EOL; #!/usr/bin/env php * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26; use _PHPStan_33c983f26\Fidry\CpuCoreCounter\Diagnoser; use _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder\FinderRegistry; require_once __DIR__ . '/../vendor/autoload.php'; echo 'Executing finders...' . \PHP_EOL . \PHP_EOL; echo Diagnoser::execute(FinderRegistry::getAllVariants()) . \PHP_EOL; #!/usr/bin/env php * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26; use _PHPStan_33c983f26\Fidry\CpuCoreCounter\CpuCoreCounter; use _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder\FinderRegistry; require_once __DIR__ . '/../vendor/autoload.php'; $separator = \str_repeat('–', 80); echo 'With all finders...' . \PHP_EOL . \PHP_EOL; echo (new CpuCoreCounter(FinderRegistry::getAllVariants()))->trace() . \PHP_EOL; echo $separator . \PHP_EOL . \PHP_EOL; echo 'Logical CPU cores finders...' . \PHP_EOL . \PHP_EOL; echo (new CpuCoreCounter(FinderRegistry::getDefaultLogicalFinders()))->trace() . \PHP_EOL; echo $separator . \PHP_EOL . \PHP_EOL; echo 'Physical CPU cores finders...' . \PHP_EOL . \PHP_EOL; echo (new CpuCoreCounter(FinderRegistry::getDefaultPhysicalFinders()))->trace() . \PHP_EOL; echo $separator . \PHP_EOL . \PHP_EOL; * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter; use _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder\CpuCoreFinder; use _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder\EnvVariableFinder; use _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder\FinderRegistry; use InvalidArgumentException; use function implode; use function max; use function sprintf; use function sys_getloadavg; use const PHP_EOL; final class CpuCoreCounter { /** * @var list */ private $finders; /** * @var positive-int|null */ private $count; /** * @param list|null $finders */ public function __construct(?array $finders = null) { $this->finders = $finders ?? FinderRegistry::getDefaultLogicalFinders(); } /** * @param positive-int|0 $reservedCpus Number of CPUs to reserve. This is useful when you want * to reserve some CPUs for other processes. If the main * process is going to be busy still, you may want to set * this value to 1. * @param non-zero-int|null $countLimit The maximum number of CPUs to return. If not provided, it * may look for a limit in the environment variables, e.g. * KUBERNETES_CPU_LIMIT. If negative, the limit will be * the total number of cores found minus the absolute value. * For instance if the system has 10 cores and countLimit=-2, * then the effective limit considered will be 8. * @param float|null $loadLimit Element of [0., 1.]. Percentage representing the * amount of cores that should be used among the available * resources. For instance, if set to 0.7, it will use 70% * of the available cores, i.e. if 1 core is reserved, 11 * cores are available and 5 are busy, it will use 70% * of (11-1-5)=5 cores, so 3 cores. Set this parameter to null * to skip this check. Beware that 1 does not mean "no limit", * but 100% of the _available_ resources, i.e. with the * previous example, it will return 5 cores. How busy is * the system is determined by the system load average * (see $systemLoadAverage). * @param float|null $systemLoadAverage The system load average. If passed, it will use * this information to limit the available cores based * on the _available_ resources. For instance, if there * is 10 cores but 3 are busy, then only 7 cores will * be considered for further calculation. If set to * `null`, it will use `sys_getloadavg()` to check the * load of the system in the past minute. You can * otherwise pass an arbitrary value. Should be a * positive float. * * @see https://php.net/manual/en/function.sys-getloadavg.php */ public function getAvailableForParallelisation(int $reservedCpus = 0, ?int $countLimit = null, ?float $loadLimit = null, ?float $systemLoadAverage = 0.0): ParallelisationResult { self::checkCountLimit($countLimit); self::checkLoadLimit($loadLimit); self::checkSystemLoadAverage($systemLoadAverage); $totalCoreCount = $this->getCountWithFallback(1); $availableCores = max(1, $totalCoreCount - $reservedCpus); // Adjust available CPUs based on current load if (null !== $loadLimit) { // https://github.com/phpstan/phpstan/issues/13198 /** @var float $correctedSystemLoadAverage */ $correctedSystemLoadAverage = null === $systemLoadAverage ? sys_getloadavg()[0] ?? 0.0 : $systemLoadAverage; $availableCores = max(1, $loadLimit * ($availableCores - $correctedSystemLoadAverage)); } if (null === $countLimit) { $correctedCountLimit = self::getKubernetesLimit(); } else { $correctedCountLimit = $countLimit > 0 ? $countLimit : max(1, $totalCoreCount + $countLimit); } if (null !== $correctedCountLimit && $availableCores > $correctedCountLimit) { $availableCores = $correctedCountLimit; } return new ParallelisationResult($reservedCpus, $countLimit, $loadLimit, $systemLoadAverage, $correctedCountLimit, $correctedSystemLoadAverage ?? $systemLoadAverage, $totalCoreCount, (int) $availableCores); } /** * @throws NumberOfCpuCoreNotFound * * @return positive-int */ public function getCount(): int { // Memoize result if (null === $this->count) { $this->count = $this->findCount(); } return $this->count; } /** * @param positive-int $fallback * * @return positive-int */ public function getCountWithFallback(int $fallback): int { try { return $this->getCount(); } catch (NumberOfCpuCoreNotFound $exception) { return $fallback; } } /** * This method is mostly for debugging purposes. */ public function trace(): string { $output = []; foreach ($this->finders as $finder) { $output[] = sprintf('Executing the finder "%s":', $finder->toString()); $output[] = $finder->diagnose(); $cores = $finder->find(); if (null !== $cores) { $output[] = 'Result found: ' . $cores; break; } $output[] = '–––'; } return implode(PHP_EOL, $output); } /** * @throws NumberOfCpuCoreNotFound * * @return positive-int */ private function findCount(): int { foreach ($this->finders as $finder) { $cores = $finder->find(); if (null !== $cores) { return $cores; } } throw NumberOfCpuCoreNotFound::create(); } /** * @throws NumberOfCpuCoreNotFound * * @return array{CpuCoreFinder, positive-int} */ public function getFinderAndCores(): array { foreach ($this->finders as $finder) { $cores = $finder->find(); if (null !== $cores) { return [$finder, $cores]; } } throw NumberOfCpuCoreNotFound::create(); } /** * @return positive-int|null */ public static function getKubernetesLimit(): ?int { $finder = new EnvVariableFinder('KUBERNETES_CPU_LIMIT'); return $finder->find(); } private static function checkCountLimit(?int $countLimit): void { if (0 === $countLimit) { throw new InvalidArgumentException('The count limit must be a non zero integer. Got "0".'); } } private static function checkLoadLimit(?float $loadLimit): void { if (null === $loadLimit) { return; } if ($loadLimit < 0.0 || $loadLimit > 1.0) { throw new InvalidArgumentException(sprintf('The load limit must be in the range [0., 1.], got "%s".', $loadLimit)); } } private static function checkSystemLoadAverage(?float $systemLoadAverage): void { if (null !== $systemLoadAverage && $systemLoadAverage < 0.0) { throw new InvalidArgumentException(sprintf('The system load average must be a positive float, got "%s".', $systemLoadAverage)); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter; use _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder\CpuCoreFinder; use function array_map; use function explode; use function implode; use function max; use function str_repeat; use const PHP_EOL; /** * Utility to debug. * * @private */ final class Diagnoser { /** * Provides an aggregated diagnosis based on each finders diagnosis. * * @param list $finders */ public static function diagnose(array $finders): string { $diagnoses = array_map(static function (CpuCoreFinder $finder): string { return self::diagnoseFinder($finder); }, $finders); return implode(PHP_EOL, $diagnoses); } /** * Executes each finders. * * @param list $finders */ public static function execute(array $finders): string { $diagnoses = array_map(static function (CpuCoreFinder $finder): string { $coresCount = $finder->find(); return implode('', [$finder->toString(), ': ', null === $coresCount ? 'NULL' : $coresCount]); }, $finders); return implode(PHP_EOL, $diagnoses); } private static function diagnoseFinder(CpuCoreFinder $finder): string { $diagnosis = $finder->diagnose(); $maxLineLength = max(array_map('strlen', explode(PHP_EOL, $diagnosis))); $separator = str_repeat('-', $maxLineLength); return implode('', [$finder->toString() . ':' . PHP_EOL, $separator . PHP_EOL, $diagnosis . PHP_EOL, $separator . PHP_EOL]); } private function __construct() { } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Executor; use function fclose; use function function_exists; use function is_resource; use function proc_close; use function proc_open; use function stream_get_contents; final class ProcOpenExecutor implements ProcessExecutor { public function execute(string $command): ?array { if (!function_exists('proc_open')) { return null; } $pipes = []; $process = @proc_open($command, [ ['pipe', 'rb'], ['pipe', 'wb'], // stdout ['pipe', 'wb'], ], $pipes); // https://github.com/phpstan/phpstan/issues/13197 /** @var array{resource, resource, resource} $pipes */ if (!is_resource($process)) { return null; } fclose($pipes[0]); $stdout = stream_get_contents($pipes[1]); $stderr = stream_get_contents($pipes[2]); proc_close($process); return [$stdout, $stderr]; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Executor; interface ProcessExecutor { /** * @return array{string, string}|null STDOUT & STDERR tuple */ public function execute(string $command): ?array; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; use function preg_match; /** * Find the number of logical CPU cores for Windows leveraging the Get-CimInstance * cmdlet, which is a newer version that is recommended over Get-WmiObject. */ final class CmiCmdletLogicalFinder extends ProcOpenBasedFinder { private const CPU_CORE_COUNT_REGEX = '/NumberOfLogicalProcessors[\s\n]-+[\s\n]+(?\d+)/'; protected function getCommand(): string { return 'Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object -Property NumberOfLogicalProcessors'; } public function toString(): string { return 'CmiCmdletLogicalFinder'; } protected function countCpuCores(string $process): ?int { if (0 === preg_match(self::CPU_CORE_COUNT_REGEX, $process, $matches)) { return parent::countCpuCores($process); } /** @phpstan-ignore offsetAccess.notFound */ $count = $matches['count']; return parent::countCpuCores($count); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; use function preg_match; /** * Find the number of physical CPU cores for Windows. * * @see https://github.com/paratestphp/paratest/blob/c163539818fd96308ca8dc60f46088461e366ed4/src/Runners/PHPUnit/Options.php#L912-L916 */ final class CmiCmdletPhysicalFinder extends ProcOpenBasedFinder { private const CPU_CORE_COUNT_REGEX = '/NumberOfCores[\s\n]-+[\s\n]+(?\d+)/'; protected function getCommand(): string { return 'Get-CimInstance -ClassName Win32_Processor | Select-Object -Property NumberOfCores'; } public function toString(): string { return 'CmiCmdletPhysicalFinder'; } protected function countCpuCores(string $process): ?int { if (0 === preg_match(self::CPU_CORE_COUNT_REGEX, $process, $matches)) { return parent::countCpuCores($process); } /** @phpstan-ignore offsetAccess.notFound */ $count = $matches['count']; return parent::countCpuCores($count); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; interface CpuCoreFinder { /** * Provides an explanation which may offer some insight as to what the finder * will be able to find. * * This is practical to have an idea of what each finder will find collect * information for the unit tests, since integration tests are quite complicated * as dependent on complex infrastructures. */ public function diagnose(): string; /** * Find the number of CPU cores. If it could not find it, returns null. The * means used to find the cores are at the implementation discretion. * * @return positive-int|null */ public function find(): ?int; public function toString(): string; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; use function file_get_contents; use function is_file; use function sprintf; use function substr_count; use const PHP_EOL; /** * Find the number of CPU cores looking up at the cpuinfo file which is available * on Linux systems and Windows systems with a Linux sub-system. * * @see https://github.com/paratestphp/paratest/blob/c163539818fd96308ca8dc60f46088461e366ed4/src/Runners/PHPUnit/Options.php#L903-L909 * @see https://unix.stackexchange.com/questions/146051/number-of-processors-in-proc-cpuinfo */ final class CpuInfoFinder implements CpuCoreFinder { private const CPU_INFO_PATH = '/proc/cpuinfo'; public function diagnose(): string { if (!is_file(self::CPU_INFO_PATH)) { return sprintf('The file "%s" could not be found.', self::CPU_INFO_PATH); } $cpuInfo = file_get_contents(self::CPU_INFO_PATH); if (\false === $cpuInfo) { return sprintf('Could not get the content of the file "%s".', self::CPU_INFO_PATH); } return sprintf('Found the file "%s" with the content:%s%s%sWill return "%s".', self::CPU_INFO_PATH, PHP_EOL, $cpuInfo, PHP_EOL, self::countCpuCores($cpuInfo)); } /** * @return positive-int|null */ public function find(): ?int { $cpuInfo = self::getCpuInfo(); return null === $cpuInfo ? null : self::countCpuCores($cpuInfo); } public function toString(): string { return 'CpuInfoFinder'; } private static function getCpuInfo(): ?string { if (!@is_file(self::CPU_INFO_PATH)) { return null; } $cpuInfo = @file_get_contents(self::CPU_INFO_PATH); return \false === $cpuInfo ? null : $cpuInfo; } /** * @internal * * @return positive-int|null */ public static function countCpuCores(string $cpuInfo): ?int { $processorCount = substr_count($cpuInfo, 'processor'); return $processorCount > 0 ? $processorCount : null; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; use function sprintf; /** * This finder returns whatever value you gave to it. This is useful for testing * or as a fallback to avoid to catch the NumberOfCpuCoreNotFound exception. */ final class DummyCpuCoreFinder implements CpuCoreFinder { /** * @var positive-int */ private $count; public function diagnose(): string { return sprintf('Will return "%d".', $this->count); } /** * @param positive-int $count */ public function __construct(int $count) { $this->count = $count; } /** @phpstan-ignore return.unusedType */ public function find(): ?int { return $this->count; } public function toString(): string { return sprintf('DummyCpuCoreFinder(value=%d)', $this->count); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; use function getenv; use function preg_match; use function sprintf; use function var_export; final class EnvVariableFinder implements CpuCoreFinder { /** @var string */ private $environmentVariableName; public function __construct(string $environmentVariableName) { $this->environmentVariableName = $environmentVariableName; } public function diagnose(): string { $value = getenv($this->environmentVariableName); return sprintf('parse(getenv(%s)=%s)=%s', $this->environmentVariableName, var_export($value, \true), self::isPositiveInteger($value) ? $value : 'null'); } public function find(): ?int { $value = getenv($this->environmentVariableName); if (is_string($value) && 1 === preg_match('/^(\d+)m$/', $value, $matches)) { $millicores = $matches[1]; $value = (string) floor($millicores / 1000); } return self::isPositiveInteger($value) ? (int) $value : null; } public function toString(): string { return sprintf('getenv(%s)', $this->environmentVariableName); } /** * @param string|false $value */ private static function isPositiveInteger($value): bool { return \false !== $value && 1 === preg_match('/^\d+$/', $value) && (int) $value > 0; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; final class FinderRegistry { /** * @return list List of all the known finders with all their variants. */ public static function getAllVariants(): array { return [new CpuInfoFinder(), new DummyCpuCoreFinder(1), new HwLogicalFinder(), new HwPhysicalFinder(), new LscpuLogicalFinder(), new LscpuPhysicalFinder(), new _NProcessorFinder(), new NProcessorFinder(), new NProcFinder(\true), new NProcFinder(\false), new NullCpuCoreFinder(), SkipOnOSFamilyFinder::forWindows(new DummyCpuCoreFinder(1)), OnlyOnOSFamilyFinder::forWindows(new DummyCpuCoreFinder(1)), new OnlyInPowerShellFinder(new CmiCmdletLogicalFinder()), new OnlyInPowerShellFinder(new CmiCmdletPhysicalFinder()), new WindowsRegistryLogicalFinder(), new WmicPhysicalFinder(), new WmicLogicalFinder()]; } /** * @return list */ public static function getDefaultLogicalFinders(): array { return [OnlyOnOSFamilyFinder::forWindows(new OnlyInPowerShellFinder(new CmiCmdletLogicalFinder())), OnlyOnOSFamilyFinder::forWindows(new WindowsRegistryLogicalFinder()), OnlyOnOSFamilyFinder::forWindows(new WmicLogicalFinder()), new NProcFinder(), new HwLogicalFinder(), new _NProcessorFinder(), new NProcessorFinder(), new LscpuLogicalFinder(), new CpuInfoFinder()]; } /** * @return list */ public static function getDefaultPhysicalFinders(): array { return [OnlyOnOSFamilyFinder::forWindows(new OnlyInPowerShellFinder(new CmiCmdletPhysicalFinder())), OnlyOnOSFamilyFinder::forWindows(new WmicPhysicalFinder()), new HwPhysicalFinder(), new LscpuPhysicalFinder()]; } private function __construct() { } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; /** * Find the number of logical CPU cores for Linux, BSD and OSX. * * @see https://github.com/paratestphp/paratest/blob/c163539818fd96308ca8dc60f46088461e366ed4/src/Runners/PHPUnit/Options.php#L903-L909 * @see https://opensource.apple.com/source/xnu/xnu-792.2.4/libkern/libkern/sysctl.h.auto.html */ final class HwLogicalFinder extends ProcOpenBasedFinder { protected function getCommand(): string { return 'sysctl -n hw.logicalcpu'; } public function toString(): string { return 'HwLogicalFinder'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; /** * Find the number of physical CPU cores for Linux, BSD and OSX. * * @see https://github.com/paratestphp/paratest/blob/c163539818fd96308ca8dc60f46088461e366ed4/src/Runners/PHPUnit/Options.php#L903-L909 * @see https://opensource.apple.com/source/xnu/xnu-792.2.4/libkern/libkern/sysctl.h.auto.html */ final class HwPhysicalFinder extends ProcOpenBasedFinder { protected function getCommand(): string { return 'sysctl -n hw.physicalcpu'; } public function toString(): string { return 'HwPhysicalFinder'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; use function count; use function explode; use function is_array; use function preg_grep; use const PHP_EOL; /** * The number of logical cores. * * @see https://stackoverflow.com/a/23378780/5846754 */ final class LscpuLogicalFinder extends ProcOpenBasedFinder { public function getCommand(): string { return 'lscpu -p'; } protected function countCpuCores(string $process): ?int { $lines = explode(PHP_EOL, $process); $actualLines = preg_grep('/^\d+,/', $lines); if (!is_array($actualLines)) { return null; } $count = count($actualLines); return 0 === $count ? null : $count; } public function toString(): string { return 'LscpuLogicalFinder'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; use function count; use function explode; use function is_array; use function preg_grep; use function strtok; use const PHP_EOL; /** * The number of physical processors. * * @see https://stackoverflow.com/a/23378780/5846754 */ final class LscpuPhysicalFinder extends ProcOpenBasedFinder { public function toString(): string { return 'LscpuPhysicalFinder'; } public function getCommand(): string { return 'lscpu -p'; } protected function countCpuCores(string $process): ?int { $lines = explode(PHP_EOL, $process); /** @var string[]|false $actualLines */ $actualLines = preg_grep('/^\d+/', $lines); if (!is_array($actualLines)) { return null; } $cores = []; foreach ($actualLines as $line) { strtok($line, ','); $core = strtok(','); if (\false === $core) { continue; } $cores[$core] = \true; } unset($cores['-']); $count = count($cores); return 0 === $count ? null : $count; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; use _PHPStan_33c983f26\Fidry\CpuCoreCounter\Executor\ProcessExecutor; use function sprintf; /** * The number of (logical) cores. * * @see https://github.com/infection/infection/blob/fbd8c44/src/Resource/Processor/CpuCoresCountProvider.php#L69-L82 * @see https://unix.stackexchange.com/questions/146051/number-of-processors-in-proc-cpuinfo */ final class NProcFinder extends ProcOpenBasedFinder { /** * @var bool */ private $all; /** * @param bool $all If disabled will give the number of cores available for the current process * only. This is disabled by default as it is known to be "buggy" on virtual * environments as the virtualization tool, e.g. VMWare, might over-commit * resources by default. */ public function __construct(bool $all = \false, ?ProcessExecutor $executor = null) { parent::__construct($executor); $this->all = $all; } public function toString(): string { return sprintf('NProcFinder(all=%s)', $this->all ? 'true' : 'false'); } protected function getCommand(): string { return 'nproc' . ($this->all ? ' --all' : ''); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; /** * Find the number of logical CPU cores for FreeSBD, Solaris and the likes. * * @see https://twitter.com/freebsdfrau/status/1052016199452700678?s=20&t=M2pHkRqmmna-UF68lfL2hw */ final class NProcessorFinder extends ProcOpenBasedFinder { protected function getCommand(): string { return 'getconf NPROCESSORS_ONLN'; } public function toString(): string { return 'NProcessorFinder'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; /** * This finder returns whatever value you gave to it. This is useful for testing. */ final class NullCpuCoreFinder implements CpuCoreFinder { public function diagnose(): string { return 'Will return "null".'; } public function find(): ?int { return null; } public function toString(): string { return 'NullCpuCoreFinder'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; use function getenv; use function sprintf; final class OnlyInPowerShellFinder implements CpuCoreFinder { /** * @var CpuCoreFinder */ private $decoratedFinder; public function __construct(CpuCoreFinder $decoratedFinder) { $this->decoratedFinder = $decoratedFinder; } public function diagnose(): string { $powerShellModulePath = getenv('PSModulePath'); return $this->skip() ? sprintf('Skipped; no power shell module path detected ("%s").', $powerShellModulePath) : $this->decoratedFinder->diagnose(); } public function find(): ?int { return $this->skip() ? null : $this->decoratedFinder->find(); } public function toString(): string { return sprintf('OnlyInPowerShellFinder(%s)', $this->decoratedFinder->toString()); } private function skip(): bool { return \false === getenv('PSModulePath'); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; use function implode; use function sprintf; use const PHP_OS_FAMILY; final class OnlyOnOSFamilyFinder implements CpuCoreFinder { /** * @var list */ private $skippedOSFamilies; /** * @var CpuCoreFinder */ private $decoratedFinder; /** * @param string|list $skippedOSFamilyOrFamilies */ public function __construct($skippedOSFamilyOrFamilies, CpuCoreFinder $decoratedFinder) { $this->skippedOSFamilies = (array) $skippedOSFamilyOrFamilies; $this->decoratedFinder = $decoratedFinder; } public static function forWindows(CpuCoreFinder $decoratedFinder): self { return new self('Windows', $decoratedFinder); } public static function forBSD(CpuCoreFinder $decoratedFinder): self { return new self('BSD', $decoratedFinder); } public static function forDarwin(CpuCoreFinder $decoratedFinder): self { return new self('Darwin', $decoratedFinder); } public static function forSolaris(CpuCoreFinder $decoratedFinder): self { return new self('Solaris', $decoratedFinder); } public static function forLinux(CpuCoreFinder $decoratedFinder): self { return new self('Linux', $decoratedFinder); } public function diagnose(): string { return $this->skip() ? sprintf('Skipped platform detected ("%s").', PHP_OS_FAMILY) : $this->decoratedFinder->diagnose(); } public function find(): ?int { return $this->skip() ? null : $this->decoratedFinder->find(); } public function toString(): string { return sprintf('OnlyOnOSFamilyFinder(only=(%s),%s)', implode(',', $this->skippedOSFamilies), $this->decoratedFinder->toString()); } private function skip(): bool { return !in_array(PHP_OS_FAMILY, $this->skippedOSFamilies, \true); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; use _PHPStan_33c983f26\Fidry\CpuCoreCounter\Executor\ProcessExecutor; use _PHPStan_33c983f26\Fidry\CpuCoreCounter\Executor\ProcOpenExecutor; use function filter_var; use function function_exists; use function is_int; use function sprintf; use function trim; use const FILTER_VALIDATE_INT; use const PHP_EOL; abstract class ProcOpenBasedFinder implements CpuCoreFinder { /** * @var ProcessExecutor */ private $executor; public function __construct(?ProcessExecutor $executor = null) { $this->executor = $executor ?? new ProcOpenExecutor(); } public function diagnose(): string { if (!function_exists('proc_open')) { return 'The function "proc_open" is not available.'; } $command = $this->getCommand(); $output = $this->executor->execute($command); if (null === $output) { return sprintf('Failed to execute the command "%s".', $command); } [$stdout, $stderr] = $output; $failed = '' !== trim($stderr); return $failed ? sprintf('Executed the command "%s" which wrote the following output to the STDERR:%s%s%sWill return "null".', $command, PHP_EOL, $stderr, PHP_EOL) : sprintf('Executed the command "%s" and got the following (STDOUT) output:%s%s%sWill return "%s".', $command, PHP_EOL, $stdout, PHP_EOL, $this->countCpuCores($stdout) ?? 'null'); } /** * @return positive-int|null */ public function find(): ?int { $output = $this->executor->execute($this->getCommand()); if (null === $output) { return null; } [$stdout, $stderr] = $output; $failed = '' !== trim($stderr); return $failed ? null : $this->countCpuCores($stdout); } /** * @internal * * @return positive-int|null */ protected function countCpuCores(string $process): ?int { $cpuCount = filter_var($process, FILTER_VALIDATE_INT); return is_int($cpuCount) && $cpuCount > 0 ? $cpuCount : null; } abstract protected function getCommand(): string; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; use function implode; use function in_array; use function sprintf; final class SkipOnOSFamilyFinder implements CpuCoreFinder { /** * @var list */ private $skippedOSFamilies; /** * @var CpuCoreFinder */ private $decoratedFinder; /** * @param string|list $skippedOSFamilyOrFamilies */ public function __construct($skippedOSFamilyOrFamilies, CpuCoreFinder $decoratedFinder) { $this->skippedOSFamilies = (array) $skippedOSFamilyOrFamilies; $this->decoratedFinder = $decoratedFinder; } public static function forWindows(CpuCoreFinder $decoratedFinder): self { return new self('Windows', $decoratedFinder); } public static function forBSD(CpuCoreFinder $decoratedFinder): self { return new self('BSD', $decoratedFinder); } public static function forDarwin(CpuCoreFinder $decoratedFinder): self { return new self('Darwin', $decoratedFinder); } public static function forSolaris(CpuCoreFinder $decoratedFinder): self { return new self('Solaris', $decoratedFinder); } public static function forLinux(CpuCoreFinder $decoratedFinder): self { return new self('Linux', $decoratedFinder); } public function diagnose(): string { return $this->skip() ? sprintf('Skipped platform detected ("%s").', \PHP_OS_FAMILY) : $this->decoratedFinder->diagnose(); } public function find(): ?int { return $this->skip() ? null : $this->decoratedFinder->find(); } public function toString(): string { return sprintf('SkipOnOSFamilyFinder(skip=(%s),%s)', implode(',', $this->skippedOSFamilies), $this->decoratedFinder->toString()); } private function skip(): bool { return in_array(\PHP_OS_FAMILY, $this->skippedOSFamilies, \true); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; use function array_filter; use function count; use function explode; use const PHP_EOL; /** * Find the number of logical CPU cores for Windows. * * @see https://knowledge.informatica.com/s/article/151521 */ final class WindowsRegistryLogicalFinder extends ProcOpenBasedFinder { protected function getCommand(): string { return 'reg query HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor'; } public function toString(): string { return 'WindowsRegistryLogicalFinder'; } protected function countCpuCores(string $process): ?int { $count = count(array_filter(explode(PHP_EOL, $process), static function (string $line): bool { return '' !== trim($line); })); return $count > 0 ? $count : null; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; use function preg_match; /** * Find the number of logical CPU cores for Windows. * * @see https://github.com/paratestphp/paratest/blob/c163539818fd96308ca8dc60f46088461e366ed4/src/Runners/PHPUnit/Options.php#L912-L916 */ final class WmicLogicalFinder extends ProcOpenBasedFinder { private const CPU_CORE_COUNT_REGEX = '/NumberOfLogicalProcessors[\s\n]+(?\d+)/'; protected function getCommand(): string { return 'wmic cpu get NumberOfLogicalProcessors'; } public function toString(): string { return 'WmicLogicalFinder'; } protected function countCpuCores(string $process): ?int { if (0 === preg_match(self::CPU_CORE_COUNT_REGEX, $process, $matches)) { return parent::countCpuCores($process); } /** @phpstan-ignore offsetAccess.notFound */ $count = $matches['count']; return parent::countCpuCores($count); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; use function preg_match; /** * Find the number of physical CPU cores for Windows. * * @see https://github.com/paratestphp/paratest/blob/c163539818fd96308ca8dc60f46088461e366ed4/src/Runners/PHPUnit/Options.php#L912-L916 */ final class WmicPhysicalFinder extends ProcOpenBasedFinder { private const CPU_CORE_COUNT_REGEX = '/NumberOfCores[\s\n]+(?\d+)/'; protected function getCommand(): string { return 'wmic cpu get NumberOfCores'; } public function toString(): string { return 'WmicPhysicalFinder'; } protected function countCpuCores(string $process): ?int { if (0 === preg_match(self::CPU_CORE_COUNT_REGEX, $process, $matches)) { return parent::countCpuCores($process); } /** @phpstan-ignore offsetAccess.notFound */ $count = $matches['count']; return parent::countCpuCores($count); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter\Finder; /** * Find the number of logical CPU cores for Linux and the likes. * * @see https://twitter.com/freebsdfrau/status/1052016199452700678?s=20&t=M2pHkRqmmna-UF68lfL2hw */ final class _NProcessorFinder extends ProcOpenBasedFinder { protected function getCommand(): string { return 'getconf _NPROCESSORS_ONLN'; } public function toString(): string { return '_NProcessorFinder'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter; use RuntimeException; final class NumberOfCpuCoreNotFound extends RuntimeException { public static function create(): self { return new self('Could not find the number of CPU cores available.'); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare (strict_types=1); namespace _PHPStan_33c983f26\Fidry\CpuCoreCounter; /** * @readonly */ final class ParallelisationResult { /** * @var positive-int|0 */ public $passedReservedCpus; /** * @var non-zero-int|null */ public $passedCountLimit; /** * @var float|null */ public $passedLoadLimit; /** * @var float|null */ public $passedSystemLoadAverage; /** * @var non-zero-int|null */ public $correctedCountLimit; /** * @var float|null */ public $correctedSystemLoadAverage; /** * @var positive-int */ public $totalCoresCount; /** * @var positive-int */ public $availableCpus; /** * @param positive-int|0 $passedReservedCpus * @param non-zero-int|null $passedCountLimit * @param non-zero-int|null $correctedCountLimit * @param positive-int $totalCoresCount * @param positive-int $availableCpus */ public function __construct(int $passedReservedCpus, ?int $passedCountLimit, ?float $passedLoadLimit, ?float $passedSystemLoadAverage, ?int $correctedCountLimit, ?float $correctedSystemLoadAverage, int $totalCoresCount, int $availableCpus) { $this->passedReservedCpus = $passedReservedCpus; $this->passedCountLimit = $passedCountLimit; $this->passedLoadLimit = $passedLoadLimit; $this->passedSystemLoadAverage = $passedSystemLoadAverage; $this->correctedCountLimit = $correctedCountLimit; $this->correctedSystemLoadAverage = $correctedSystemLoadAverage; $this->totalCoresCount = $totalCoresCount; $this->availableCpus = $availableCpus; } } 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. { "name": "guzzle", "lockfileVersion": 3, "requires": true, "packages": {} } 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. * - **: any request option * * @param array $config Client configuration settings. * * @see RequestOptions for a list of available request options. */ public function __construct(array $config = []) { if (!isset($config['handler'])) { $config['handler'] = HandlerStack::create(); } elseif (!\is_callable($config['handler'])) { throw new InvalidArgumentException('handler must be a callable'); } // 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) { if (\count($args) < 1) { throw new InvalidArgumentException('Magic request methods require a URI and optional options array'); } $uri = $args[0]; $opts = $args[1] ?? []; return \substr($method, -5) === 'Async' ? $this->requestAsync(\substr($method, 0, -5), $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 \GuzzleHttp\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), $request->hasHeader('Host')), $options); } /** * Send an HTTP request. * * @param array $options Request options to apply to the given * request and to the transfer. See \GuzzleHttp\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 \GuzzleHttp\RequestOptions. */ public function requestAsync(string $method, $uri = '', array $options = []): PromiseInterface { $options = $this->prepareDefaults($options); // Remove request modifying parameter because it can be done up-front. $headers = $options['headers'] ?? []; $body = $options['body'] ?? null; $version = $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(); } $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 \GuzzleHttp\RequestOptions. * * @throws GuzzleException */ public function request(string $method, $uri = '', array $options = []): ResponseInterface { $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 * * @deprecated Client::getConfig will be removed in guzzlehttp/guzzle:8.0. */ 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); } if (isset($config['idn_conversion']) && $config['idn_conversion'] !== \false) { $idnOptions = $config['idn_conversion'] === \true ? \IDNA_DEFAULT : $config['idn_conversion']; $uri = Utils::idnUriConvert($uri, $idnOptions); } return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri; } /** * 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]; // 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. foreach (\array_keys($this->config['headers']) as $name) { if (\strtolower($name) === 'user-agent') { return; } } $this->config['headers']['User-Agent'] = Utils::defaultUserAgent(); } } /** * Merges default options into the array. * * @param array $options Options to modify by reference */ private function prepareDefaults(array $options): array { $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]); } } return $result; } /** * 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 \GuzzleHttp\RequestOptions. */ private function transfer(RequestInterface $request, array $options): PromiseInterface { $request = $this->applyOptions($request, $options); /** @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.'); } $modify['set_headers'] = $options['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($options['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'])) { $options['body'] = Utils::jsonEncode($options['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 (!empty($options['decode_content']) && $options['decode_content'] !== \true) { // 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'] = $options['decode_content']; } if (isset($options['body'])) { if (\is_array($options['body'])) { throw $this->invalidBody(); } $modify['body'] = Psr7\Utils::streamFor($options['body']); unset($options['body']); } if (!empty($options['auth']) && \is_array($options['auth'])) { $value = $options['auth']; $type = isset($value[2]) ? \strtolower($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': $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($value, '', '&', \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'] = $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) { if (!$request->hasHeader($k)) { $modify['set_headers'][$k] = $v; } } $request = Psr7\Utils::modifyRequest($request, $modify); // Don't pass this internal value along to middleware/handlers. unset($options['_conditional']); } return $request; } /** * 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 && \strcasecmp($cookie->getName(), $name) === 0) { 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) { $this->cookies = []; return; } elseif (!$path) { $this->cookies = \array_filter($this->cookies, static function (SetCookie $cookie) use ($domain): bool { return !$cookie->matchesDomain($domain); }); } elseif (!$name) { $this->cookies = \array_filter($this->cookies, static function (SetCookie $cookie) use ($path, $domain): bool { return !($cookie->matchesPath($path) && $cookie->matchesDomain($domain)); }); } else { $this->cookies = \array_filter($this->cookies, static function (SetCookie $cookie) use ($path, $domain, $name) { return !($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; } // 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->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')) { foreach ($cookieHeader as $cookie) { $sc = SetCookie::fromString($cookie); if (!$sc->getDomain()) { $sc->setDomain($request->getUri()->getHost()); } 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. $this->setCookie($sc); } } } /** * 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 = []; $uri = $request->getUri(); $scheme = $uri->getScheme(); $host = $uri->getHost(); $path = $uri->getPath() ?: '/'; foreach ($this->cookies as $cookie) { if ($cookie->matchesPath($path) && $cookie->matchesDomain($host) && !$cookie->isExpired() && (!$cookie->getSecure() || $scheme === 'https')) { $values[] = $cookie->getName() . '=' . $cookie->getValue(); } } 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 === '') { $this->clear($cookie->getDomain(), $cookie->getPath(), $cookie->getName()); } } } */ 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)) { $json[] = $cookie->toArray(); } } $jsonStr = Utils::jsonEncode($json); 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 = Utils::jsonDecode($json, \true); if (\is_array($data)) { foreach ($data as $cookie) { $this->setCookie(new 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)) { $json[] = $cookie->toArray(); } } $_SESSION[$this->sessionKey] = \json_encode($json); } /** * Load the contents of the client session into the data array */ protected function load(): void { if (!isset($_SESSION[$this->sessionKey])) { return; } $data = \json_decode($_SESSION[$this->sessionKey], \true); if (\is_array($data)) { foreach ($data as $cookie) { $this->setCookie(new SetCookie($cookie)); } } elseif (\strlen($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; /** * 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('trim', \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]); $value = isset($cookieParts[1]) ? \trim($cookieParts[1], " \n\r\t\x00\v") : \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 (!\strcasecmp($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; } } $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 (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 if (!$this->getExpires() && $this->getMaxAge()) { // Calculate the Expires date $this->setExpires(\time() + $this->getMaxAge()); } elseif (null !== ($expires = $this->getExpires()) && !\is_numeric($expires)) { $this->setExpires($expires); } } public function __toString() { $str = $this->data['Name'] . '=' . ($this->data['Value'] ?? '') . '; '; foreach ($this->data as $k => $v) { 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 { return $this->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 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__); } $this->data['Expires'] = null === $timestamp ? null : (\is_numeric($timestamp) ? (int) $timestamp : \strtotime((string) $timestamp)); } /** * 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 \true; } // Remove the leading '.' as per spec in RFC 6265. // https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.3 $cookieDomain = \ltrim(\strtolower($cookieDomain), '.'); $domain = \strtolower($domain); // Domain not set or exact match. if ('' === $cookieDomain || $domain === $cookieDomain) { return \true; } // 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, '/') . '$/', $domain); } /** * 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)) { 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 can be 0. "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 === '') { 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 */ public static function wrapException(RequestInterface $request, \Throwable $e): RequestException { 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 = \_PHPStan_33c983f26\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; } public function create(RequestInterface $request, array $options): EasyHandle { $protocolVersion = $request->getProtocolVersion(); if ('2' === $protocolVersion || '2.0' === $protocolVersion) { if (!self::supportsHttp2()) { 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']); } $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']); } $conf[\CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy); $easy->handle = $this->handles ? \array_pop($this->handles) : \curl_init(); curl_setopt_array($easy->handle, $conf); return $easy; } private static function supportsHttp2(): bool { static $supportsHttp2 = null; if (null === $supportsHttp2) { $supportsHttp2 = self::supportsTls12() && defined('CURL_VERSION_HTTP2') && \CURL_VERSION_HTTP2 & \curl_version()['features']; } return $supportsHttp2; } private static function supportsTls12(): bool { static $supportsTls12 = null; if (null === $supportsTls12) { $supportsTls12 = \CURL_SSLVERSION_TLSv1_2 & \curl_version()['features']; } return $supportsTls12; } private static function supportsTls13(): bool { static $supportsTls13 = null; if (null === $supportsTls13) { $supportsTls13 = defined('CURL_SSLVERSION_TLSv1_3') && \CURL_SSLVERSION_TLSv1_3 & \curl_version()['features']; } return $supportsTls13; } public function release(EasyHandle $easy): void { $resource = $easy->handle; unset($easy->handle); if (\count($this->handles) >= $this->maxHandles) { if (\PHP_VERSION_ID < 80000) { \curl_close($resource); } } else { // 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); \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'])) { self::invokeStats($easy); } 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(); } 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] = self::getCurlVersion(); $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 getCurlVersion(): string { static $curlVersion = null; if (null === $curlVersion) { $curlVersion = \curl_version()['version']; } return $curlVersion; } 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]; if ($easy->createResponseException) { return P\Create::rejectionFor(new RequestException('An error was encountered while creating the response', $easy->request, $easy->response, $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)); } $uri = $easy->request->getUri(); $sanitizedError = self::sanitizeCurlError($ctx['error'] ?? '', $uri); $message = \sprintf('cURL error %s: %s (%s)', $ctx['errno'], $sanitizedError, 'see https://curl.haxx.se/libcurl/c/libcurl-errors.html'); if ('' !== $sanitizedError) { $redactedUriString = \_PHPStan_33c983f26\GuzzleHttp\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 { if ('' === $error) { return $error; } $baseUri = $uri->withQuery('')->withFragment(''); $baseUriString = $baseUri->__toString(); if ('' === $baseUriString) { return $error; } $redactedUriString = \_PHPStan_33c983f26\GuzzleHttp\Psr7\Utils::redactUserInfo($baseUri)->__toString(); return str_replace($baseUriString, $redactedUriString, $error); } /** * @return array */ private function getDefaultConf(EasyHandle $easy): array { $conf = ['_headers' => $easy->request->getHeaders(), \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(), \CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''), \CURLOPT_RETURNTRANSFER => \false, \CURLOPT_HEADER => \false, \CURLOPT_CONNECTTIMEOUT => 300]; if (\defined('CURLOPT_PROTOCOLS')) { $conf[\CURLOPT_PROTOCOLS] = \CURLPROTO_HTTP | \CURLPROTO_HTTPS; } $version = $easy->request->getProtocolVersion(); if ('2' === $version || '2.0' === $version) { $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0; } elseif ('1.1' === $version) { $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1; } else { $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0; } return $conf; } private function applyMethod(EasyHandle $easy, array &$conf): void { $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'; } } elseif ($method === 'HEAD') { $conf[\CURLOPT_NOBODY] = \true; unset($conf[\CURLOPT_WRITEFUNCTION], $conf[\CURLOPT_READFUNCTION], $conf[\CURLOPT_FILE], $conf[\CURLOPT_INFILE]); } } 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(); } $conf[\CURLOPT_READFUNCTION] = static function ($ch, $fd, $length) use ($body) { return $body->read($length); }; } // 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) { 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 (!\strcasecmp($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]) && !empty($options['decode_content'])) { $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'] = \_PHPStan_33c983f26\GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'w+'); } $sink = $options['sink']; if (!\is_string($sink)) { $sink = \_PHPStan_33c983f26\GuzzleHttp\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 && \strtoupper(\substr(\PHP_OS, 0, 3)) !== 'WIN') { $conf[\CURLOPT_NOSIGNAL] = \true; } if (isset($options['proxy'])) { if (!\is_array($options['proxy'])) { $conf[\CURLOPT_PROXY] = $options['proxy']; } else { $scheme = $easy->request->getUri()->getScheme(); if (isset($options['proxy'][$scheme])) { $host = $easy->request->getUri()->getHost(); if (isset($options['proxy']['no']) && Utils::isHostInNoProxy($host, $options['proxy']['no'])) { unset($conf[\CURLOPT_PROXY]); } else { $conf[\CURLOPT_PROXY] = $options['proxy'][$scheme]; } } } } if (isset($options['crypto_method'])) { $protocolVersion = $easy->request->getProtocolVersion(); // If HTTP/2, upgrade TLS 1.0 and 1.1 to 1.2 if ('2' === $protocolVersion || '2.0' === $protocolVersion) { if (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method'] || \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method'] || \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) { $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2; } elseif (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) { if (!self::supportsTls13()) { throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL'); } $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3; } else { throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided'); } } elseif (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']) { $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_0; } elseif (\STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method']) { $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_1; } elseif (\STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) { if (!self::supportsTls12()) { throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.2 not supported by your version of cURL'); } $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2; } elseif (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) { if (!self::supportsTls13()) { throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL'); } $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3; } else { throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided'); } } if (isset($options['cert'])) { $cert = $options['cert']; if (\is_array($cert)) { $conf[\CURLOPT_SSLCERTPASSWD] = $cert[1]; $cert = $cert[0]; } 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 (preg_match('#^(der|p12)$#i', $ext)) { $conf[\CURLOPT_SSLCERTTYPE] = strtoupper($ext); } $conf[\CURLOPT_SSLCERT] = $cert; } if (isset($options['ssl_key'])) { if (\is_array($options['ssl_key'])) { if (\count($options['ssl_key']) === 2) { [$sslKey, $conf[\CURLOPT_SSLKEYPASSWD]] = $options['ssl_key']; } else { [$sslKey] = $options['ssl_key']; } } $sslKey = $sslKey ?? $options['ssl_key']; if (!\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; } } /** * 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); } 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; } return static function ($ch, $h) use ($onHeaders, $easy, &$startingResponse) { $value = \trim($h); if ($value === '') { $startingResponse = \true; try { $easy->createResponse(); } catch (\Exception $e) { $easy->createResponseException = $e; return -1; } if ($onHeaders !== null) { try { $onHeaders($easy->response); } catch (\Exception $e) { // Associate the exception with the handle and trigger // a curl header write error by returning 0. $easy->onHeadersException = $e; return -1; } } } elseif ($startingResponse) { $startingResponse = \false; $easy->headers = [$value]; } else { $easy->headers[] = $value; } return \strlen($h); }; } public function __destruct() { foreach ($this->handles as $id => $handle) { if (\PHP_VERSION_ID < 80000) { \curl_close($handle); } unset($this->handles[$id]); } } } factory = $options['handle_factory'] ?? new CurlFactory(3); } public function __invoke(RequestInterface $request, array $options): PromiseInterface { if (isset($options['delay'])) { \usleep($options['delay'] * 1000); } $easy = $this->factory->create($request, $options); \curl_exec($easy->handle); $easy->errno = \curl_errno($easy->handle); return CurlFactory::finish($this, $easy, $this->factory); } } 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 resource|\CurlMultiHandle */ private $_mh; /** * This handler accepts the following options: * * - handle_factory: An optional factory used to create curl handles * - select_timeout: Optional timeout (in seconds) to block before timing * out while selecting curl handles. Defaults to 1 second. * - options: An associative array of CURLMOPT_* options and * corresponding values for curl_multi_setopt() */ public function __construct(array $options = []) { $this->factory = $options['handle_factory'] ?? new CurlFactory(50); if (isset($options['select_timeout'])) { $this->selectTimeout = $options['select_timeout']; } elseif ($selectTimeout = Utils::getenv('GUZZLE_CURL_SELECT_TIMEOUT')) { @trigger_error('Since guzzlehttp/guzzle 7.2.0: Using environment variable GUZZLE_CURL_SELECT_TIMEOUT is deprecated. Use option "select_timeout" instead.', \E_USER_DEPRECATED); $this->selectTimeout = (int) $selectTimeout; } else { $this->selectTimeout = 1; } $this->options = $options['options'] ?? []; // 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 */ 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.'); } $this->_mh = $multiHandle; foreach ($this->options as $option => $value) { // A warning is raised in case of a wrong option. curl_multi_setopt($this->_mh, $option, $value); } return $this->_mh; } public function __destruct() { if (isset($this->_mh)) { \curl_multi_close($this->_mh); unset($this->_mh); } } public function __invoke(RequestInterface $request, array $options): PromiseInterface { $easy = $this->factory->create($request, $options); $id = (int) $easy->handle; $promise = new Promise([$this, 'execute'], function () use ($id) { return $this->cancel($id); }); $this->addRequest(['easy' => $easy, 'deferred' => $promise]); return $promise; } /** * Ticks the curl event loop. */ public function tick(): void { // Add any delayed handles if needed. if ($this->delays) { $currentTime = Utils::currentTime(); foreach ($this->delays as $id => $delay) { if ($currentTime >= $delay) { unset($this->delays[$id]); \curl_multi_add_handle($this->_mh, $this->handles[$id]['easy']->handle); } } } // Run curl_multi_exec in the queue to enable other async tasks to run P\Utils::queue()->add(Closure::fromCallable([$this, 'tickInQueue'])); // Step through the task queue which may add additional requests. P\Utils::queue()->run(); if ($this->active && \curl_multi_select($this->_mh, $this->selectTimeout) === -1) { // Perform a usleep if a select returns -1. // See: https://bugs.php.net/bug.php?id=61141 \usleep(250); } while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) { // Prevent busy looping for slow HTTP requests. \curl_multi_select($this->_mh, $this->selectTimeout); } $this->processMessages(); } /** * Runs \curl_multi_exec() inside the event loop, to prevent busy looping */ private function tickInQueue(): void { if (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) { \curl_multi_select($this->_mh, 0); P\Utils::queue()->add(Closure::fromCallable([$this, 'tickInQueue'])); } } /** * Runs until all outstanding connections have completed. */ public function execute(): void { $queue = P\Utils::queue(); while ($this->handles || !$queue->isEmpty()) { // If there are no transfers, then sleep for the next delay if (!$this->active && $this->delays) { \usleep($this->timeToNext()); } $this->tick(); } } private function addRequest(array $entry): void { $easy = $entry['easy']; $id = (int) $easy->handle; $this->handles[$id] = $entry; if (empty($easy->options['delay'])) { \curl_multi_add_handle($this->_mh, $easy->handle); } else { $this->delays[$id] = Utils::currentTime() + $easy->options['delay'] / 1000; } } /** * Cancels a handle from sending and removes references to it. * * @param int $id Handle ID to cancel and remove. * * @return bool True on success, false on failure. */ private function cancel($id): bool { if (!is_int($id)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an integer to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } // Cannot cancel if it has been processed. if (!isset($this->handles[$id])) { return \false; } $handle = $this->handles[$id]['easy']->handle; unset($this->delays[$id], $this->handles[$id]); \curl_multi_remove_handle($this->_mh, $handle); if (\PHP_VERSION_ID < 80000) { \curl_close($handle); } return \true; } private function processMessages(): void { 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; } $id = (int) $done['handle']; \curl_multi_remove_handle($this->_mh, $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']; $entry['deferred']->resolve(CurlFactory::finish($this, $entry['easy'], $this->factory)); } } private function timeToNext(): int { $currentTime = Utils::currentTime(); $nextTime = \PHP_INT_MAX; foreach ($this->delays as $time) { if ($time < $nextTime) { $nextTime = $time; } } return (int) \max(0, $nextTime - $currentTime) * 1000000; } } headers); $normalizedKeys = Utils::normalizeHeaderKeys($headers); if (!empty($this->options['decode_content']) && 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']] = $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); } } |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 ' . Utils::describeType($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); } } } getProtocolVersion(); 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; 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 ((0 === \strcasecmp('PUT', $request->getMethod()) || 0 === \strcasecmp('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) { // Determine if the error was a networking error. $message = $e->getMessage(); // This list can probably get more comprehensive. if (\false !== \strpos($message, 'getaddrinfo') || \false !== \strpos($message, 'Connection refused') || \false !== \strpos($message, "couldn't connect to host") || \false !== \strpos($message, 'connection attempt failed')) { $e = new ConnectException($e->getMessage(), $request, $e); } else { $e = RequestException::wrapException($request, $e); } $this->invokeStats($options, $request, $startTime, null, $e); return P\Create::rejectionFor($e); } } 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 (\Exception $e) { return P\Create::rejectionFor(new RequestException('An error was encountered while creating the response', $request, null, $e)); } [$stream, $headers] = $this->checkDecode($options, $headers, $stream); $stream = Psr7\Utils::streamFor($stream); $sink = $stream; if (\strcasecmp('HEAD', $request->getMethod())) { $sink = $this->createSink($stream, $options); } try { $response = new Psr7\Response($status, $headers, $sink, $ver, $reason); } catch (\Exception $e) { return P\Create::rejectionFor(new RequestException('An error was encountered while creating the response', $request, null, $e)); } if (isset($options['on_headers'])) { try { $options['on_headers']($response); } catch (\Exception $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 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 (!empty($options['decode_content'])) { $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']]); // Fix content-length header if (isset($normalizedKeys['content-length'])) { $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']]; $length = (int) $stream->getSize(); if ($length === 0) { unset($headers[$normalizedKeys['content-length']]); } else { $headers[$normalizedKeys['content-length']] = [$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)); } return $resource; } /** * @return resource */ private function createStream(RequestInterface $request, array $options) { static $methods; if (!$methods) { $methods = \array_flip(\get_class_methods(__CLASS__)); } if (!\in_array($request->getUri()->getScheme(), ['http', 'https'])) { throw new RequestException(\sprintf("The scheme '%s' is not supported.", $request->getUri()->getScheme()), $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'); } if (!empty($options)) { foreach ($options as $key => $value) { $method = "add_{$key}"; if (isset($methods[$method])) { $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'); } $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')) { /** @var array|null */ $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', $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(); if (isset($options['force_ip_resolve']) && !\filter_var($uri->getHost(), \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; } private function getDefaultContext(RequestInterface $request): array { $headers = ''; foreach ($request->getHeaders() as $name => $value) { 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' => $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']); return $context; } /** * @param mixed $value as passed via Request transfer options. */ private function add_proxy(RequestInterface $request, array &$options, $value, array &$params): void { $uri = null; if (!\is_array($value)) { $uri = $value; } else { $scheme = $request->getUri()->getScheme(); if (isset($value[$scheme])) { if (!isset($value['no']) || !Utils::isHostInNoProxy($request->getUri()->getHost(), $value['no'])) { $uri = $value[$scheme]; } } } if (!$uri) { return; } $parsed = $this->parse_proxy($uri); $options['http']['proxy'] = $parsed['proxy']; if ($parsed['auth']) { if (!isset($options['http']['header'])) { $options['http']['header'] = []; } $options['http']['header'] .= "\r\nProxy-Authorization: {$parsed['auth']}"; } } /** * 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); if ($parsed !== \false && isset($parsed['scheme']) && $parsed['scheme'] === 'http') { if (isset($parsed['host']) && isset($parsed['port'])) { $auth = null; if (isset($parsed['user']) && isset($parsed['pass'])) { $auth = \base64_encode("{$parsed['user']}:{$parsed['pass']}"); } return ['proxy' => "tcp://{$parsed['host']}:{$parsed['port']}", 'auth' => $auth ? "Basic {$auth}" : null]; } } // 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_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 { if (\is_array($value)) { $options['ssl']['passphrase'] = $value[1]; $value = $value[0]; } if (!\file_exists($value)) { throw new \RuntimeException("SSL certificate not found: {$value}"); } $options['ssl']['local_cert'] = $value; } /** * @param mixed $value as passed via Request transfer options. */ private function add_progress(RequestInterface $request, array &$options, $value, array &$params): void { 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; $idx = \is_callable($remove) ? 0 : 1; $this->stack = \array_values(\array_filter($this->stack, static function ($tuple) use ($idx, $remove) { return $tuple[$idx] !== $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 = []; /** @var string */ return \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()) . ' 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); } /** * 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); } } 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 Psr7\Http\Message\RequestInterface or a callable that returns a promise that fulfills with a Psr7\Message\Http\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'] = $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()); } $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']) { $safeMethods = ['GET', 'HEAD', 'OPTIONS']; $requestMethod = $request->getMethod(); $modify['method'] = in_array($requestMethod, $safeMethods) ? $requestMethod : 'GET'; $modify['body'] = ''; } $uri = self::redirectUri($request, $response, $protocols); if (isset($options['idn_conversion']) && $options['idn_conversion'] !== \false) { $idnOptions = $options['idn_conversion'] === \true ? \IDNA_DEFAULT : $options['idn_conversion']; $uri = Utils::idnUriConvert($uri, $idnOptions); } $modify['uri'] = $uri; Psr7\Message::rewindBody($request); // 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(''); $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; } } decider = $decider; $this->nextHandler = $nextHandler; $this->delay = $delay ?: __CLASS__ . '::exponentialDelay'; } /** * Default exponential backoff delay function. * * @return int milliseconds. */ public static function exponentialDelay(int $retries): int { 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; } } = 0) { if (\function_exists('curl_multi_exec') && \function_exists('curl_exec')) { $handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler()); } elseif (\function_exists('curl_exec')) { $handler = new CurlHandler(); } elseif (\function_exists('curl_multi_exec')) { $handler = new CurlMultiHandler(); } } if (\ini_get('allow_url_fopen')) { $handler = $handler ? Proxy::wrapStreaming($handler, new StreamHandler()) : new StreamHandler(); } elseif (!$handler) { throw new \RuntimeException('GuzzleHttp requires cURL, the allow_url_fopen ini setting, or a custom HTTP handler.'); } return $handler; } /** * 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 { 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(<<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. 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 { $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); } 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 { 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 { return self::ofLimit($iterable, $concurrency, $onFulfilled, function ($reason, $idx, PromiseInterface $aggregate): void { $aggregate->reject($reason); }); } } 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(); } 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 { 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; } } }); // 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; $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) { return \false; } $this->mutex = \true; try { $this->iterable->next(); $this->mutex = \false; return \true; } catch (\Throwable $e) { $this->aggregate->reject($e); $this->mutex = \false; return \false; } } 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(); } } 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 (RejectionException $e) { return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()]; } catch (\Throwable $e) { 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 { $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 { $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 { $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) { 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 { $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 { 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 { $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; }); } } 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. 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 (!$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 { $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 { throw new \RuntimeException('Cannot write to an AppendStream'); } /** * @return mixed */ public function getMetadata($key = null) { 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 { 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 { $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 { $this->buffer .= $string; if (strlen($this->buffer) >= $this->hwm) { return 0; } return strlen($string); } /** * @return mixed */ public function getMetadata($key = null) { 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 { $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 ($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()) { $this->read($diff); $diff = $byte - $this->stream->getSize(); } } else { // We can just do a normal seek since we've already seen this byte. $this->stream->seek($byte); } } public function read($length): string { // 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; $this->stream->write($remoteData); } return $data; } public function write($string): int { // 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(); } /** * Close both the remote stream and buffer stream */ public function close(): void { $this->remoteStream->close(); $this->stream->close(); } 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 { $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 functions 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 closure * * @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 { ($this->_fn_seek)($offset, $whence); } public function isWritable(): bool { return ($this->_fn_isWritable)(); } public function write($string): int { return ($this->_fn_write)($string); } public function isReadable(): bool { return ($this->_fn_isReadable)(); } public function read($length): string { return ($this->_fn_read)($length); } public function getContents(): string { return ($this->_fn_getContents)(); } /** * @return mixed */ public function getMetadata($key = null) { 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; } /** * 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 { $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); 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); 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; } elseif ($this->limit === -1) { return $length - $this->offset; } return min($this->limit, $length - $this->offset); } /** * Allow for a bounded seek on the read limited stream */ public function seek($offset, $whence = \SEEK_SET): void { 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 ($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()) . ' 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) && strtolower($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); $body->rewind(); if ($size > $truncateAt) { $summary .= ' (truncated...)'; } // 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; } /** * 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 || 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 || count($headerParts) !== 2) { throw new \InvalidArgumentException('Invalid message: Missing status line'); } [$startLine, $rawHeaders] = $headerParts; if (preg_match("/(?:^HTTP\\/|^[A-Z]+ \\S+ HTTP\\/)(\\d+(?:\\.\\d+)?)/i", $startLine, $matches) && $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); } /** @var array[] $headerLines */ $count = preg_match_all(Rfc7230::HEADER_REGEX, $rawHeaders, $headerLines, \PREG_SET_ORDER); // 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 if (preg_match(Rfc7230::HEADER_FOLD_REGEX, $rawHeaders)) { 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 { $hostKey = array_filter(array_keys($headers), function ($k) { // Numeric array keys are converted to int by PHP. $k = (string) $k; return strtolower($k) === 'host'; }); // If no host is found, then a full URI cannot be constructed. if (!$hostKey) { return $path; } $host = $headers[reset($hostKey)][0]; $scheme = substr($host, -4) === ':443' ? 'https' : 'http'; return $scheme . '://' . $host . '/' . ltrim($path, '/'); } /** * 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); $matches = []; if (!preg_match('/^[\S]+\s+([a-zA-Z]+:\/\/|\/).*/', $data['start-line'], $matches)) { 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); // 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. if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) { 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 ($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[strtolower($header)]); } public function getHeader($header): array { $header = strtolower($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); $value = $this->normalizeHeaderValue($value); $normalized = strtolower($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); $value = $this->normalizeHeaderValue($value); $normalized = strtolower($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 = strtolower($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); $value = $this->normalizeHeaderValue($value); $normalized = strtolower($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)) { 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))); } $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)); } } /** * @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[strtolower($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 string[] $headers */ private function getHeaders(array $headers): string { $str = ''; foreach ($headers as $key => $value) { $str .= "{$key}: {$value}\r\n"; } return "--{$this->boundary}\r\n" . trim($str) . "\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; } $element['contents'] = Utils::streamFor($element['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 string[] $headers * * @return array{0: StreamInterface, 1: string[]} */ private function createElement(string $name, StreamInterface $stream, ?string $filename, array $headers): array { // 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 string[] $headers */ private static function getHeader(array $headers, string $key): ?string { $lowercaseHeader = strtolower($key); foreach ($headers as $k => $v) { if (strtolower((string) $k) === $lowercaseHeader) { return $v; } } return null; } } 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 { throw new \RuntimeException('Cannot seek a PumpStream'); } public function isWritable(): bool { return \false; } public function write($string): int { throw new \RuntimeException('Cannot write to a PumpStream'); } public function isReadable(): bool { return \true; } public function read($length): string { $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) { 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) : $v; if ($v !== null) { $qs .= '=' . $encoder((string) $v); } $qs .= '&'; } else { foreach ($v as $vv) { $qs .= $k; $vv = is_bool($vv) ? $castBool($vv) : $vv; if ($vv !== null) { $qs .= '=' . $encoder((string) $vv); } $qs .= '&'; } } } return $qs ? (string) substr($qs, 0, -1) : ''; } } assertMethod($method); if (!$uri instanceof UriInterface) { $uri = new Uri($uri); } $this->method = strtoupper($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 { if (preg_match('#\s#', $requestTarget)) { 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); $new = clone $this; $new->method = strtoupper($method); return $new; } public function getUri(): UriInterface { return $this->uri; } public function withUri(UriInterface $uri, $preserveHost = \false): RequestInterface { 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; } if (($port = $this->uri->getPort()) !== null) { $host .= ':' . $port; } 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.'); } } } '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->statusCode = $status; if ($body !== '' && $body !== null) { $this->stream = Utils::streamFor($body); } $this->setHeaders($headers); if ($reason == '' && isset(self::PHRASES[$this->statusCode])) { $this->reasonPhrase = self::PHRASES[$this->statusCode]; } else { $this->reasonPhrase = (string) $reason; } $this->protocol = $version; } public function getStatusCode(): int { return $this->statusCode; } public function getReasonPhrase(): string { return $this->reasonPhrase; } public function withStatus($code, $reasonPhrase = ''): ResponseInterface { $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]; } $new->reasonPhrase = (string) $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- ]++):[ \t]*+((?:[ \t]*+[!-~\x80-\xff]++)*+)[ \t]*+\r?\n)m"; public const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)"; } 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 = $_SERVER['REQUEST_METHOD'] ?? 'GET'; $headers = getallheaders(); $uri = self::getUriFromGlobals(); $body = new CachingStream(new LazyOpenStream('php://input', 'r+')); $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1'; $serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER); return $serverRequest->withCookieParams($_COOKIE)->withQueryParams($_GET)->withParsedBody($_POST)->withUploadedFiles(self::normalizeFiles($_FILES)); } private static function extractHostAndPortFromAuthority(string $authority): array { $uri = 'http://' . $authority; $parts = parse_url($uri); if (\false === $parts) { return [null, null]; } $host = $parts['host'] ?? null; $port = $parts['port'] ?? null; return [$host, $port]; } /** * Get a Uri populated with values from $_SERVER. */ public static function getUriFromGlobals(): UriInterface { $uri = new Uri(''); $uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http'); $hasPort = \false; if (isset($_SERVER['HTTP_HOST'])) { [$host, $port] = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']); if ($host !== null) { $uri = $uri->withHost($host); } if ($port !== null) { $hasPort = \true; $uri = $uri->withPort($port); } } elseif (isset($_SERVER['SERVER_NAME'])) { $uri = $uri->withHost($_SERVER['SERVER_NAME']); } elseif (isset($_SERVER['SERVER_ADDR'])) { $uri = $uri->withHost($_SERVER['SERVER_ADDR']); } if (!$hasPort && isset($_SERVER['SERVER_PORT'])) { $uri = $uri->withPort($_SERVER['SERVER_PORT']); } $hasQuery = \false; if (isset($_SERVER['REQUEST_URI'])) { $requestUriParts = explode('?', $_SERVER['REQUEST_URI'], 2); $uri = $uri->withPath($requestUriParts[0]); if (isset($requestUriParts[1])) { $hasQuery = \true; $uri = $uri->withQuery($requestUriParts[1]); } } if (!$hasQuery && isset($_SERVER['QUERY_STRING'])) { $uri = $uri->withQuery($_SERVER['QUERY_STRING']); } return $uri; } public function getServerParams(): array { return $this->serverParams; } public function getUploadedFiles(): array { return $this->uploadedFiles; } public function withUploadedFiles(array $uploadedFiles): ServerRequestInterface { $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 { $new = clone $this; $new->parsedBody = $data; return $new; } public function getAttributes(): array { return $this->attributes; } /** * @return mixed */ public function getAttribute($attribute, $default = null) { if (\false === array_key_exists($attribute, $this->attributes)) { return $default; } return $this->attributes[$attribute]; } public function withAttribute($attribute, $value): ServerRequestInterface { $new = clone $this; $new->attributes[$attribute] = $value; return $new; } public function withoutAttribute($attribute): ServerRequestInterface { 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 = $this->getMetadata('uri'); } /** * 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 { $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 (!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 (!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 (!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) { 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 { $this->stream->seek($offset, $whence); } public function read($length): string { return $this->stream->read($length); } public function write($string): int { 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.'); } return fopen('guzzle://stream', $mode, \false, self::createStreamContext($stream)); } /** * 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]; /** * Unreserved characters for use in a regex. * * @see https://datatracker.ietf.org/doc/html/rfc3986#section-2.3 */ private const CHAR_UNRESERVED = 'a-zA-Z0-9_\-\.~'; /** * Sub-delims for use in a regex. * * @see https://datatracker.ietf.org/doc/html/rfc3986#section-2.2 */ private const CHAR_SUB_DELIMS = '!\$&\'\(\)\*\+,;='; 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 = ''; /** @var string|null String representation */ private $composedComponents; public function __construct(string $uri = '') { if ($uri !== '') { $parts = self::parse($uri); if ($parts === \false) { throw new MalformedUriException("Unable to parse URI: {$uri}"); } $this->applyParts($parts); } } /** * 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 IPv6 $prefix = ''; if (preg_match('%^(.*://\[[0-9:a-fA-F]+\])(.*?)$%', $url, $matches)) { /** @var array{0:string, 1:string, 2:string} $matches */ $prefix = $matches[1]; $url = $matches[2]; } /** @var string */ $encodedUrl = preg_replace_callback('%[^:/@?&=#]+%usD', static function ($matches) { return urlencode($matches[0]); }, $url); $result = parse_url($prefix . $encodedUrl); if ($result === \false) { return \false; } return array_map('urldecode', $result); } public function __toString(): string { if ($this->composedComponents === null) { $this->composedComponents = self::composeComponents($this->scheme, $this->getAuthority(), $this->path, $this->query, $this->fragment); } return $this->composedComponents; } /** * 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 ? (string) $value : null); } return $uri->withQuery(implode('&', $result)); } /** * 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(); $uri->applyParts($parts); $uri->validateState(); return $uri; } 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->composedComponents = null; $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->composedComponents = null; $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->composedComponents = null; $new->validateState(); return $new; } public function withPort($port): UriInterface { $port = $this->filterPort($port); if ($this->port === $port) { return $this; } $new = clone $this; $new->port = $port; $new->composedComponents = null; $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->composedComponents = null; $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; $new->composedComponents = null; return $new; } public function withFragment($fragment): UriInterface { $fragment = $this->filterQueryAndFragment($fragment); if ($this->fragment === $fragment) { return $this; } $new = clone $this; $new->fragment = $fragment; $new->composedComponents = null; 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'); } return \strtr($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); } /** * @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 preg_replace_callback('/(?:[^%' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . ']+|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $component); } /** * @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'); } return \strtr($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); } /** * @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 preg_replace_callback('/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\/]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $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 preg_replace_callback('/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $str); } 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()) !== 0) { 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; } return 'https' === $uri->getScheme() ? 443 : 80; } 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) { $uri = $uri->withPath(preg_replace('#//++#', '/', $uri->getPath())); } 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 strtoupper($match[0]); }; return $uri->withPath(preg_replace_callback($regex, $callback, $uri->getPath()))->withQuery(preg_replace_callback($regex, $callback, $uri->getQuery())); } 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(preg_replace_callback($regex, $callback, $uri->getPath()))->withQuery(preg_replace_callback($regex, $callback, $uri->getQuery())); } private function __construct() { // cannot be instantiated } } getScheme() != '') { return $rel->withPath(self::removeDotSegments($rel->getPath())); } if ($rel->getAuthority() != '') { $targetAuthority = $rel->getAuthority(); $targetPath = self::removeDotSegments($rel->getPath()); $targetQuery = $rel->getQuery(); } else { $targetAuthority = $base->getAuthority(); if ($rel->getPath() === '') { $targetPath = $base->getPath(); $targetQuery = $rel->getQuery() != '' ? $rel->getQuery() : $base->getQuery(); } else { if ($rel->getPath()[0] === '/') { $targetPath = $rel->getPath(); } else if ($targetAuthority != '' && $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 new Uri(Uri::composeComponents($base->getScheme(), $targetAuthority, $targetPath, $targetQuery, $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(strtolower((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. * * @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()) { if (!$dest->write($source->read($bufferSize))) { break; } } } else { $remaining = $maxLen; while ($remaining > 0 && !$source->eof()) { $buf = $source->read(min($bufferSize, $remaining)); $len = strlen($buf); if (!$len) { break; } $remaining -= $len; $dest->write($buf); } } } /** * 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. * - remove_headers: (array) Remove the given headers. * - body: (mixed) Sets the given body. * - 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; } $headers = $request->getHeaders(); if (!isset($changes['uri'])) { $uri = $request->getUri(); } else { // Remove the host header if one is on the URI if ($host = $changes['uri']->getHost()) { $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']); } if ($request instanceof ServerRequestInterface) { $new = (new ServerRequest($changes['method'] ?? $request->getMethod(), $uri, $headers, $changes['body'] ?? $request->getBody(), $changes['version'] ?? $request->getProtocolVersion(), $request->getServerParams()))->withParsedBody($request->getParsedBody())->withQueryParams($request->getQueryParams())->withCookieParams($request->getCookieParams())->withUploadedFiles($request->getUploadedFiles()); foreach ($request->getAttributes() as $key => $value) { $new = $new->withAttribute($key, $value); } return $new; } return new Request($changes['method'] ?? $request->getMethod(), $uri, $headers, $changes['body'] ?? $request->getBody(), $changes['version'] ?? $request->getProtocolVersion()); } /** * 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 is passed, a read-only stream object will be * created that invokes the given callable. The callable is invoked with the * number of suggested bytes to read. The callable can return any number of * bytes, but MUST return `false` when there is no more data to return. The * stream object that wraps the callable will invoke the callable until the * number of requested bytes are available. Any additional bytes will be * buffered and used in subsequent reads. * * @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)) { $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'); } } getOption($v)) { switch ($c) { case 'v': switch (strtolower($v)) { case 'dump': $visitor = 'Hoa\Compiler\Visitor\Dump'; break; default: return $this->usage(); } break; case 'c': $visitor = str_replace('.', '\\', $v); break; case 's': $tokenSequence = \true; break; case 't': $trace = \true; break; case '__ambiguous': $this->resolveOptionAmbiguity($v); break; case 'h': case '?': default: return $this->usage(); } } $this->parser->listInputs($grammar, $language); if (empty($grammar) || empty($language) && '0' !== $language) { return $this->usage(); } $compiler = Compiler\Llk::load(new File\Read($grammar)); $stream = new File\Read($language); $data = $stream->readAll(); try { $ast = $compiler->parse($data); } catch (Compiler\Exception $e) { if (\true === $tokenSequence) { $this->printTokenSequence($compiler, $data); echo "\n\n"; } throw $e; return 1; } if (\true === $tokenSequence) { $this->printTokenSequence($compiler, $data); echo "\n\n"; } if (\true === $trace) { $this->printTrace($compiler); echo "\n\n"; } if (null !== $visitor) { $visitor = Consistency\Autoloader::dnew($visitor); echo $visitor->visit($ast); } return; } /** * Print trace. * * @param \Hoa\Compiler\Llk\Parser $compiler Compiler. * @return void */ protected function printTrace(Compiler\Llk\Parser $compiler) { $i = 0; foreach ($compiler->getTrace() as $element) { if ($element instanceof Compiler\Llk\Rule\Entry) { $ruleName = $element->getRule(); $rule = $compiler->getRule($ruleName); echo str_repeat('> ', ++$i), 'enter ', $ruleName; if (null !== $id = $rule->getNodeId()) { echo ' (', $id, ')'; } echo "\n"; } elseif ($element instanceof Compiler\Llk\Rule\Token) { echo str_repeat(' ', $i + 1), 'token ', $element->getTokenName(), ', consumed ', $element->getValue(), "\n"; } else { echo str_repeat('< ', $i--), 'ekzit ', $element->getRule(), "\n"; } } return; } /** * Print token sequence. * * @param \Hoa\Compiler\Llk\Parser $compiler Compiler. * @param string $data Data to lex. * @return void */ protected function printTokenSequence(Compiler\Llk\Parser $compiler, $data) { $lexer = new Compiler\Llk\Lexer(); $sequence = $lexer->lexMe($data, $compiler->getTokens()); $format = '%' . (strlen((string) count($sequence)) + 1) . 's ' . '%-13s %-20s %s %6s' . "\n"; $header = sprintf($format, '#', 'namespace', 'token name', 'token value ', 'offset'); echo $header, str_repeat('-', strlen($header)), "\n"; foreach ($sequence as $i => $token) { printf($format, $i, $token['namespace'], $token['token'], (30 < $token['length'] ? mb_substr($token['value'], 0, 29) . '…' : 'EOF' === $token['token']) ? str_repeat(' ', 30) : $token['value'] . str_repeat(' ', 30 - $token['length']), $token['offset']); } return; } /** * The command usage. * * @return int */ public function usage() { echo 'Usage : compiler:pp [grammar.pp] [language]', "\n", 'Options :', "\n", $this->makeUsageOptionsList(['v' => 'Visitor name (only “dump” is supported).', 'c' => 'Visitor classname (using . instead of \ works).', 's' => 'Print token sequence.', 't' => 'Print trace.', 'help' => 'This help.']), "\n"; return; } } __halt_compiler(); Compile and visit languages with grammars.

Compilers allow to analyze and manipulate textual data. There is numerous usages. Hoa\Compiler offers to manipulate several compilers based on needs.

Table of contents

Introduction

What is conceived well is expressed clearly, and the right words come easily.

A language is a way to express or to formulate a solution to a problem. And there exists a lot of problems. We read and write in several languages daily, and some of these languages are understood by machines. This operation is possible thanks to compilers.

Formal languages is a theory that includes the automatic analysis of those languages through tools like automata or grammars. It is necessary to have a detailed explanation to understand well all these concepts. However, we are going to popularise as much as needed to allow a correct usage of Hoa\Compiler.

Language and grammar

A language is a set of words. Each word is a sequence of symbols belonging to an alphabet. A symbol represents the smallest lexical unit of a language, it is atomic and we will call it a lexeme (also often mentionned as a token). These sequences of lexemes representing words are built with rules. From a word and a root rule, we will try to derive its sub-rules. If a derivation exists, then the word is considered as valid, else it is considered as invalid. We also speak about words matching. For example, if we consider the following rules:

    exp ::= exp + exp
          | number
 number ::= digit number
          | digit
digit   ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

The word that we are going to match is 7 + 35. The root rule is exp. If we derive (from the left to the right and from the top to the bottom), we can have exp + exp or number (the disjunction, i.e. the “or”, is represented by the “|” symbol):

exp + exp | number
→ exp + exp
→ ( exp + exp | number ) + exp
→ number + exp
→ ( digit number | digit ) + exp

We continue to derive until we eliminate every rules in order to have only lexemes:

…
→ ( digit number | digit ) + exp
→ digit + exp
→ ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ) + exp
→ 7 + exp
→ 7 + ( exp + exp | number )
→ 7 + number
→ 7 + ( digit number | digit )
→ 7 + digit number
→ 7 + ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ) number
→ 7 + 3 number
→ 7 + 3 ( digit number | digit )
→ 7 + 3 digit
→ 7 + 3 ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 )
→ 7 + 3 5

A derivation exists to match the word 7 + 35, thus it is a valid word for those rules.

A set of rules is called a grammar. And so, a grammar represents a language!

However, these are different kinds of grammars. In 1956, the Chomsky hierarchy has been formulated, classifying grammars in four levels:

  1. unrestricted grammars, matching langages known as Turing languages, rules have no restriction,
  2. context-sensitive grammars, matching contextual languages,
  3. context-free grammars, matching algebraic languages, based on stacked automata,
  4. regular grammars, matching regular languages.

Each level includes the next level. Hoa\Compiler only treats languages defined by grammars of level 3 and 4. To give a quick idea, regular grammars can be connected to regular expressions (like PCRE), well-known by developers. But regular grammars are not able to match a pair of symbols (like parentheses, braces or quotes), while algebraic languages allow that (thanks to the concept of stack of lexemes).

Matching words

In general, the compilation process begins with two analyzes: lexical and syntactic. A lexical analysis splits a word in a sequence of lexemes. This sequence will thereafter be used by the syntactic analyzer in order to verify that the word belongs to the language.

According to the grammar, the matching will not be done in the same way, but the principle stays the same: using lexemes one after the other in the sequence and verify that they allow going forward in the derivation of grammar's rules.

Syntactic analyzes are also classified into categories: LL, LR, LALR etc. Hoa\Compiler only offers LL syntactic analyzers, stands for Left-to-right Leftmost derivation, i.e. from the topest rule to the deepest, and rules are derived from the left to the right. Here, again, there is sub-categories, whose two supported by Hoa\Compiler: LL(1) and LL(*). Globally, we speak about LL(k) syntactic analyzer: if a lexeme does not allow to derive a rule as expected, then the analyzer is allowed to go back to k step backward; we also speak about backtrack. Put another way, rules can be ambiguous: each time we derive a rule of the grammar, we have several possible choices and the analyzer can be wrong, this is why it needs to backtrack sometimes. The k variable defines the ambiguity level. If a grammar can be analyzed by a LL(1) syntactic analyzer, it is known as unambiguous: each time a lexeme is used to derive our rules, there is only one choice. And if we have a LL(*) syntactic analyzer, it means that the k variable is undefined. The following example illustrates an unambiguous grammar:

rule ::= a b c | d e f

And this example illustrates an ambiguous grammar:

rule1 ::= a rule2
rule2 ::= b rule3 | b rule4
rule3 ::= c d
rule4 ::= e f

Let's see what happens when trying to find a derivation for the word abef from the root rule rule1:

rule1
→ a rule2                      a  bef ✔
  → a (b rule3 | b rule4)      a  bef
    → a b rule3               ab  ef  ✔
      → a b c d              abe  f   ✖
    ← a b rule3               ab  ef  ✖
  ← a (b rule3 | b rule4)      a  bef
    → a b rule4               ab  ef  ✔
      → a b e f             abef      ✔

The rule2 rule is ambiguous, which can lead to a bad derivation and consequently a backtrack.

LL(k) compiler-compiler

Writing compilers is a laborious task. It is not always difficult but most of the time, it is repetitive and it takes time. This is why there exists compilers of compilers, or in other words, compilers generators. Most of the time, these compiler-compilers use an intermediary language to write a grammar. The Hoa\Compiler library provides the Hoa\Compiler\Llk\Llk class that allows the writing of compiler-compilers through a dedicated language.

PP language

The PP language, standing for PHP Parser, allows to express algebraic grammars. It is written in files having the .pp extension (please, see the hoa://Library/Compiler/.Mime file).

A grammar is composed of lexemes and rules. The declaration of a lexeme has the following syntax: %token namespace_in:name value -> namespace_out, where name represents the name of the lexeme, value represents its value, expressed with the PCRE format (take care to not match an empty value, in which case an exception will be thrown), and namespace_in and namespace_out represent the names of namespaces and are optional (the default name is default). For example number describing a number composed of digits from 0 to 9:

%token number \d+

Namespaces represent disjointed subsets of lexemes, used to ease analyzes. A %skip declaration is similar to %token excepts that it represents a lexeme to skip, it means to not consider. A common example of %skip lexemes are spaces:

%skip space \s

To explain rules, we will use the Json.pp grammar as an example, which is a softly simplified version of the JSON language (please, see the RFC4627). The complete grammar is located in the hoa://Library/Json/Grammar.pp file. Thus:

%skip   space          \s
// Scalars.
%token  true           true
%token  false          false
%token  null           null
// Strings.
%token  quote_         "        -> string
%token  string:string  [^"]+
%token  string:_quote  "        -> default
// Objects.
%token  brace_         {
%token _brace          }
// Arrays.
%token  bracket_       \[
%token _bracket        \]
// Rest.
%token  colon          :
%token  comma          ,
%token  number         \d+

value:
    &lt;true> | &lt;false> | &lt;null> | string() | object() | array() | number()

string:
    ::quote_:: &lt;string> ::_quote::

number:
    &lt;number>

#object:
    ::brace_:: pair() ( ::comma:: pair() )* ::_brace::

#pair:
    string() ::colon:: value()

#array:
    ::bracket_:: value() ( ::comma:: value() )* ::_bracket::

Notice that we have two namespaces of lexemes: default and string (it allows to avoid confusion with the quote_ and string::_quote lexemes that have the same representation). We also notice the value rule, which is a disjunction of several lexemes and rules. The constructions of the PP language are the following:

  • rule() to call a rule,
  • &lt;token> and ::token:: to declare a lexeme (namespaces do not appear here),
  • | for a disjunction (a choice),
  • () for a group,
  • e? to say that e is optional,
  • e+ to say that e can be present 1 or more times,
  • e* to say that e can be present 0 or more times,
  • e{x,y} to say that e can be present between x and y times,
  • #node to create a node node in the resulting tree,
  • token[i] to unify lexemes between each others.

Few constructions but largely enough.

Finally, the grammar of the PP language is written… with the PP language! You can find it in the hoa://Library/Compiler/Llk/Llk.pp file.

Compilation process

The compilation process used by Hoa\Compiler\Llk\Llk is classical: it starts by lexically analyzing the textual data, the word, i.e. to transform our data in a sequence of lexemes. The declaration order of the lexemes is primordial because the lexical analyzer will use them one after the other. Next, the syntactic analyzer comes into play in order to match our data.

If the syntactic analysis is successful, we obtain a trace. This trace can be transformed into an AST, stands for Abstract Syntax Tree. This tree represents our textual data after the analysis. One advantage is that it can visited (we will detail this part later), which allows us to add new constraints which can be not be expressed in the grammar, such as type verification.

Let's manipulate Hoa\Compiler\Llk\Llk a little bit. This class is a helper to easily read a grammar expressed with the PP format. This class takes only one argument, which is an input stream that points to the grammar and returns a Hoa\Compiler\Llk\Parser compiler ready to use. On this compiler, we will call the Hoa\Compiler\Llk\Parser::parse to analyze a JSON data. If the data is correct, we will get an AST, otherwise an exception will be thrown. Finally, we will use the Hoa\Compiler\Visitor\Dump visitor to print our AST:

// 1. Load grammar.
$compiler = Hoa\Compiler\Llk\Llk::load(new Hoa\File\Read('Json.pp'));

// 2. Parse a data.
$ast      = $compiler->parse('{"foo": true, "bar": [null, 42]}');

// 3. Dump the AST.
$dump     = new Hoa\Compiler\Visitor\Dump();
echo $dump->visit($ast);

/**
 * Will output:
 *     >  #object
 *     >  >  #pair
 *     >  >  >  token(string:string, foo)
 *     >  >  >  token(true, true)
 *     >  >  #pair
 *     >  >  >  token(string:string, bar)
 *     >  >  >  #array
 *     >  >  >  >  token(null, null)
 *     >  >  >  >  token(number, 42)
 */

When we write and test a grammar, we will repeat these three tasks very often. This is why the hoa script provides the compiler:pp command. This command proposes to analyze a data based on a grammar and to apply a visitor if needed on the resulting AST. Notice that the grammar can be read through a pipe:

$ echo '[1, [1, [2, 3], 5], 8]' | hoa compiler:pp Json.pp 0 --visitor dump
>  #array
>  >  token(number, 1)
>  >  #array
>  >  >  token(number, 1)
>  >  >  #array
>  >  >  >  token(number, 2)
>  >  >  >  token(number, 3)
>  >  >  token(number, 5)
>  >  token(number, 8)

This is a useful way to quickly test a data against a grammar. Do not hesitate to read the help of the compiler:pp command to get more details!

The analyzes start with the root rule but we can use another rule thanks to the second argument of the Hoa\Compiler\Llk\Parser::parse method:

$compiler->parse('{"foo": true, "bar": [null, 42]}', 'object');

To use the root rule, we have to use null.

And finally, to not generate the AST but only know if a data is valid or not, we can use the last argument of this method by using false:

$valid = $compiler->parse('{"foo": true, "bar": [null, 42]}', null, false);
var_dump($valid);

/**
 * Will output:
 *     bool(true)
 */

Errors

The compilation errors are represented by exceptions, thus:

$ echo '{"foo" true}' | hoa compiler:pp Json.pp 0 --visitor dump
Uncaught exception (Hoa\Compiler\Exception\UnexpectedToken):
Hoa\Compiler\Llk\Parser::parse(): (0) Unexpected token "true" (true) at line 1
and column 8:
{"foo" true}
       ↑
in hoa://Library/Compiler/Llk/Parser.php at line 1

Several exceptions can be thrown according to the context:

  • during the lexical analysis, Hoa\Compiler\Exception\UnrecognizedToken when a lexeme is not recognized, i.e. when the textual data can not be split into a sequence of lexemes, and Hoa\Compiler\Exception\Lexer when other more general errors happen, for example if a lexeme matches an empty value,
  • during the syntactic analysis, Hoa\Compiler\Exception\UnexpectedToken when a lexeme is not expected, i.e. it is not able to derive the rules of the grammar.

The parent exception is Hoa\Compiler\Exception\Exception.

Nodes

The compilation process very often succeeds by the production of an AST. It is important to control its form, its size, the data it holds etc. This is why it is necessary to understand the #node notation because it allows to create nodes in the AST. First, lexemes declared with the &lt;token> syntax will appear in the tree, while the other lexemes, declared with the ::token:: syntax, will not appear. Indeed, in our last example, the quote_, brace_, colon, comma etc. lexemes do not appear. Next, it is important to notice that the declaration of nodes can be overwritten inside a same rule. Finally, a rule name can be preceeded by #, just like the #array rule, that allows to define a default node, but it can be overwritten. For example, if we replace the array rule by:

#array:
    ::bracket_:: value() ( ::comma:: value() #bigarray )* ::_bracket::

If the array contains only one value, the node will be named #array, else it will be named #bigarray. Let's see:

$ echo '[42]' | hoa compiler:pp Json.pp 0 --visitor dump
>  #array
>  >  token(number, 42)
$ echo '[4, 2]' | hoa compiler:pp Json.pp 0 --visitor dump
>  #bigarray
>  >  token(number, 4)
>  >  token(number, 2)

Of course, a node can be created or not based on the derivation of a rule. The mecanism is normally pretty much intuitive.

Namespaces

Let's detail a little bit the behavior of the lexical analyzer regarding the namespaces.

Lexemes are put in namespaces, it means that only the lexemes of the current namespace are used by the lexical analyzer. The default namespace is default. To declare the namespace of a lexeme, we have to use the : operator. When a lexeme is consumed, it is able to change the current namespace for the rest of the lexical analysis, thanks to the -> operator. Thus, we will declare five lexemes: foo and bar in the default namespace, baz in ns1 and qux and foo in ns2. The fact that foo is declared two times is not embarrassing because it is put in different namespaces:

%token      foo   fo+     -> ns1
%token      bar   ba?r+   -> ns2
%token  ns1:baz   ba?z+   -> default
%token  ns2:qux   qux+
%token  ns2:foo   FOO     -> ns1

Writing default:bar is strictly equivalent to bar. The foo lexeme leads into ns1, bar into ns2, ns1:baz into default, ns2:qux stays in ns2 and ns2:foo leads into ns1. Let's observe the sequence of lexemes produced by the lexical analyzer with the following data fooooobzzbarrrquxFOObaz:

$pp = '%token      foo   fo+     -> ns1'     . "\n" .
      '%token      bar   ba?r+   -> ns2'     . "\n" .
      '%token  ns1:baz   ba?z+   -> default' . "\n" .
      '%token  ns2:qux   qux+'               . "\n" .
      '%token  ns2:foo   FOO     -> ns1';

// 1. Parse PP.
Hoa\Compiler\Llk\Llk::parsePP($pp, $tokens, $rawRules);

// 2. Run the lexical analyzer.
$lexer    = new Hoa\Compiler\Llk\Lexer();
$sequence = $lexer->lexMe('fooooobzzbarrrquxFOObaz', $tokens);

// 3. Pretty-print the result.
$format   = '%' . (strlen((string) count($sequence)) + 1) . 's  ' .
            '%-13s %-20s  %-20s  %6s' . "\n";
$header   = sprintf($format, '#', 'namespace', 'token name', 'token value', 'offset');

echo $header, str_repeat('-', strlen($header)), "\n";

foreach ($sequence as $i => $token) {
    printf(
        $format,
        $i,
        $token['namespace'],
        $token['token'],
        $token['value'],
        $token['offset']
    );
}

/**
 * Will output:
 *      #  namespace     token name            token value           offset
 *     ---------------------------------------------------------------------
 *      0  default       foo                   fooooo                     0
 *      1  ns1           baz                   bzz                        6
 *      2  default       bar                   barrr                      9
 *      3  ns2           qux                   qux                       14
 *      4  ns2           foo                   FOO                       17
 *      5  ns1           baz                   baz                       20
 *      6  default       EOF                   EOF                       23
 */

We read the lexemes, their namespace and their default value in the table. The data has been successfully splitted, and we have jumped from one namespace to the other. If this time we try with the foqux data, we will have an error: fo is matched by the foo lexeme in the default namespace, we then jump to the ns1 namespace, and here, no lexeme in this namespace is able to recognize at least q. An error is thrown.

So far, we have seen how to jump from one namespace to another with the -> operator. No history about the used namespaces is stored. However, in some rare cases, it is able for a lexeme to be accessible through several namespaces and we would like that a lexeme jumps back to the previous namespace. Put another way, we would like a history of the used namespaces and being able to navigate (backward only) in it. This is the role of the __shift__ * n keyword, in conjunction with the -> operator as usual. __shift__ is equivalent to say: jump back to the previous namespace. __shift__ is equivalent to __shift__ * 1, and __shift__ * n to say: jump back n times to the previous namespace.

When the __shift__ keyword appears in the grammar, namespaces are managed like a stack, hence the shift vocabulary. We have to take care to shift namespaces regularly in order to avoid a huge stack.

Let's take the example of the following grammar:

%token       foo1  a    -> ns1
%token       foo2  x    -> ns2
%token       end   e

%token   ns1:bar   b
%token   ns1:baz   c    -> ns3
%token   ns1:tada  t    -> __shift__

%token   ns2:bar   y
%token   ns2:baz   z    -> ns3
%token   ns2:tada  T    -> __shift__

%token   ns3:qux   =   -> __shift__

#test:
    ( &lt;foo1> | &lt;foo2> ) &lt;bar> &lt;baz> &lt;qux> &lt;tada> &lt;end>

This grammar recognizes two data: abc=te and xyz=Te. If the first lexeme foo1 is matched, the syntactic analyzer will jump to the ns1 namespace. When it will match the ns1:baz namespace, it will jump into ns3. Then, when it will match ns3:qux, it will jump back to the previous namespace, being ns1. And so on. Now, if it does not match foo1 but foo2, it will jump to the ns2 namespace, and then in ns3 and then in ns2 again. The __shift__ keywords in ns1:tada and ns2:tada are only used to shift namespaces but no ambiguity exists: these namespaces are accessible by only one namespace, namely default.

Now, let's save this grammar in the NamespaceStack.pp file and use the -s/--token-sequence option of the hoa compiler:pp command:

$ echo -n 'abc=te' | hoa compiler:pp NamespaceStack.pp 0 --token-sequence
 #  namespace     token name            token value                     offset
-------------------------------------------------------------------------------
 0  default       foo1                  a                                    0
 1  ns1           bar                   b                                    1
 2  ns1           baz                   c                                    2
 3  ns3           qux                   =                                    3
 4  ns1           tada                  t                                    4
 5  default       end                   e                                    5
 6  default       EOF                   EOF                                  6

$ echo -n 'xyz=Te' | hoa compiler:pp NamespaceStack.pp 0 --token-sequence
 #  namespace     token name            token value                     offset
-------------------------------------------------------------------------------
 0  default       foo2                  x                                    0
 1  ns2           bar                   y                                    1
 2  ns2           baz                   z                                    2
 3  ns3           qux                   =                                    3
 4  ns2           tada                  T                                    4
 5  default       end                   e                                    5
 6  default       EOF                   EOF                                  6

We see that the lexical analyzer has successfully jumped between all namespaces, as expected. We had two ways to access to the ns3 namespace: either from ns1 or from ns2. The analyzer has succeeded to create a history of namespaces and navigate in it.

Unification

A new feature brought by the PP language regarding other grammar languages is the capability to express a unification of lexemes. Let's imagine the following grammar:

%token  quote   '|"
%token  string  \w+

rule:
    ::quote:: &lt;string> ::quote::

The quotes surrounding the string can be of two kinds: simple, with the “'” symbol, or double, with the “"” symbol. Thus, the "foo" and 'foo' data are valid, but also "foo' and 'foo"!

The unification of lexemes allows to add an additionnal constraint on the value of lexemes at runtime. The syntax is the following: token[i]. The value of i indicates what lexemes will have the same value. And finally, the unification is locale to an instance of a rule, it means that there is no unification between lexemes of different rules and the unification is only applied on the current rule. Thus, the example becomes:

rule:
    ::quote[0]:: &lt;string> ::quote[0]::

Which invalidates the "foo' and 'foo" data.

Unification finds numerous applications, such as the name of opening and closing tags in the XML language.

Abstract Syntax Tree

An abstract syntax tree represents a textual data in a structural form. Each node of this tree is represented by the Hoa\Compiler\Llk\TreeNode class. Among the most useful methods, we find:

  • getId to get the identifier of the node,
  • getValueToken to get the name of the lexeme,
  • getValueValue to get the value of the lexeme,
  • isToken if the token represents a lexeme,
  • getChild($i) to get the $i-th child of the node,
  • getChildren to get all the children,
  • getChildrenNumber to count the number of children,
  • getParent to get the parent node,
  • getData to get a reference to a data array,
  • accept to apply the visitor.

Visitors are the most simple way to cross an AST. As an example, let's write the PrettyPrinter visitor which will rewrite a JSON data with our own conventions (spacing, line breaking etc.). A visitor must implement the Hoa\Visitor\Visit interface and will have only one method to implement: visit with three arguments: the element and two optional arguments (by reference and by copy). Let's see:

class PrettyPrinter implements Hoa\Visitor\Visit
{
    public function visit (
        Hoa\Visitor\Element $element,
        &amp;$handle = null,
        $eldnah = null
    ) {
        static $i      = 0;
        static $indent = '    ';

        // One behaviour per node in the AST.
        switch ($element->getId()) {
            // Object: { … }.
            case '#object':
                echo '{', "\n";
                ++$i;

                foreach ($element->getChildren() as $e => $child) {
                    if (0 &lt; $e) {
                        echo ',', "\n";
                    }

                    echo str_repeat($indent, $i);
                    $child->accept($this, $handle, $eldnah);
                }

                echo "\n", str_repeat($indent, --$i), '}';

                break;

            // Array: [ … ].
            case '#array':
                echo '[', "\n";
                ++$i;

                foreach ($element->getChildren() as $e => $child) {
                    if (0 &lt; $e) {
                        echo ',', "\n";
                    }

                    echo str_repeat($indent, $i);
                    $child->accept($this, $handle, $eldnah);
                }

                echo "\n", str_repeat($indent, --$i), ']';

                break;

            // Pair: "…": ….
            case '#pair':
                echo
                    $element->getChild(0)->accept($this, $handle, $eldnah),
                    ': ',
                    $element->getChild(1)->accept($this, $handle, $eldnah);

                break;

            // Many tokens.
            case 'token':
                switch ($element->getValueToken()) {
                    // String: "…".
                    case 'string':
                        echo '"', $element->getValueValue(), '"';

                        break;

                    // Booleans.
                    case 'true':
                    case 'false':

                    // Null.
                    case 'null':

                    // Number.
                    case 'number':
                        echo $element->getValueValue();

                        break;
                }

                break;
        }
    }
}

We are going to see an example:

$compiler    = Hoa\Compiler\Llk\Llk::load(new Hoa\File\Read('Json.pp'));
$ast         = $compiler->parse('{"foo": true, "bar": [null, 42]}');
$prettyPrint = new PrettyPrinter();
echo $prettyPrint->visit($ast);

/**
 * Will output:
 *     {
 *         "foo": true,
 *         "bar": [
 *             null,
 *             42
 *         ]
 *     }
 */

The getData method is very useful to store data that are likely to be reused, for example from one visitor to another. This method returns a reference to an array; thus:

$data = $element->getData();

if (!isset($data['previousComputing'])) {
    throw new Exception('Need a previous computing.', 0);
}

$previous = $data['previousComputing'];

It is common to use one visitor per constraint: verification of symbols, verification of types etc. Some of them can set data for the next ones. The getData method does not require any data structure, it only provides an access to an array. Feel free to do what you want with it.

Using the Hoa\Compiler\Llk\TreeNode is very trivial and we will use it most of the time with a visitor.

Traces

The LL(k) compiler provided by Hoa is clearly composed of layers. Each layer can be used with a maximal modularity and extensibility. When the grammar is translated into “machine rules” and that the lexical and syntactic analyzers have validated a data, a trace is computed. This trace is a flat array containing only three kind of classes:

  • Hoa\Compiler\Llk\Rule\Entry when the syntactic analyzer has opened a rule,
  • Hoa\Compiler\Llk\Rule\Ekzit when the syntactic analyzer has closed a rule,
  • Hoa\Compiler\Llk\Rule\Token when the syntactic analyzer has encountered a lexeme.

We can get the trace with the Hoa\Compiler\Llk\Parser::getTrace method. To understand this trace, we will start with an example:

$compiler = Hoa\Compiler\Llk\Llk::load(new Hoa\File\Read('Json.pp'));
$ast      = $compiler->parse('{"foo": true, "bar": [null, 42]}');
$i        = 0;

foreach ($compiler->getTrace() as $element) {
    if ($element instanceof Hoa\Compiler\Llk\Rule\Entry) {
        echo str_repeat('>   ', ++$i), 'enter ', $element->getRule(), "\n";
    } elseif ($element instanceof Hoa\Compiler\Llk\Rule\Token) {
        echo
            str_repeat('    ', $i + 1), 'token ', $element->getTokenName(),
            ', consumed ', $element->getValue(), "\n";
    } else {
        echo str_repeat('&lt;   ', $i--), 'ekzit ', $element->getRule(), "\n";
    }
}

/**
 * Will output:
 *     >   enter value
 *     >   >   enter object
 *                 token brace_, consumed {
 *     >   >   >   enter pair
 *     >   >   >   >   enter string
 *                         token quote_, consumed "
 *                         token string, consumed foo
 *                         token _quote, consumed "
 *     &lt;   &lt;   &lt;   &lt;   ekzit string
 *                     token colon, consumed :
 *     >   >   >   >   enter value
 *                         token true, consumed true
 *     &lt;   &lt;   &lt;   &lt;   ekzit value
 *     &lt;   &lt;   &lt;   ekzit pair
 *     >   >   >   enter 13
 *     >   >   >   >   enter 12
 *                         token comma, consumed ,
 *     >   >   >   >   >   enter pair
 *     >   >   >   >   >   >   enter string
 *                                 token quote_, consumed "
 *                                 token string, consumed bar
 *                                 token _quote, consumed "
 *     &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   ekzit string
 *                             token colon, consumed :
 *     >   >   >   >   >   >   enter value
 *     >   >   >   >   >   >   >   enter array
 *                                     token bracket_, consumed [
 *     >   >   >   >   >   >   >   >   enter value
 *                                         token null, consumed null
 *     &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   ekzit value
 *     >   >   >   >   >   >   >   >   enter 21
 *     >   >   >   >   >   >   >   >   >   enter 20
 *                                             token comma, consumed ,
 *     >   >   >   >   >   >   >   >   >   >   enter value
 *                                                 token number, consumed 42
 *     &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   ekzit value
 *     &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   ekzit 20
 *     &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   ekzit 21
 *                                     token _bracket, consumed ]
 *     &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   ekzit array
 *     &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   ekzit value
 *     &lt;   &lt;   &lt;   &lt;   &lt;   ekzit pair
 *     &lt;   &lt;   &lt;   &lt;   ekzit 12
 *     &lt;   &lt;   &lt;   ekzit 13
 *                 token _brace, consumed }
 *     &lt;   &lt;   ekzit object
 *     &lt;   ekzit value
 */

This example reveals several things. First, the informations given by the trace can be useful: if we are on a rule, we have its name (with the getRule method), and if we are on a lexeme, we have its name (with the getTokenName method), its representation (expressed in the PCRE format, with the getRepresentation method), its value (with the getValue method), if it is a node to keep in the AST (with the isKept method) and its unification index if it exists (with the getUnificationIndex method). Of course, all these informations can be edited, which can influence the construction of the AST which is the (optional) next step.

Next, we notice that sometimes we enter in a rule that exists in the grammar, like object, pair, value etc., and sometimes we enter in a numerical rule, like 13, 12, 21, 20 etc. When the grammar is interpreted in order to be translated into “machine rules”, each one of these rules is linearized regarding the PP operators:

  • Hoa\Compiler\Llk\Rule\Choice for a disjunction
  • Hoa\Compiler\Llk\Rule\Concatenation for a concatenation,
  • Hoa\Compiler\Llk\Rule\Repetition for a repetition,
  • Hoa\Compiler\Llk\Rule\Token for a token (like seen above).

All these rules in this format are accessible through the Hoa\Compiler\Llk\Parser::getRules methods, represented by an array. We will print all the accessible rules from the root for a better understanding:

$compiler = Hoa\Compiler\Llk\Llk::load(new Hoa\File\Read('Json.pp'));

// 1. Get all rules.
$rules    = $compiler->getRules();

// 2. Start with the root rule.
$stack    = [$compiler->getRootRule() => true];

while (false !== current($stack)) {
    $rule = key($stack);
    next($stack);
    echo
        "\n", '"', $rule, '" is a ',
        strtolower(substr(get_class($rules[$rule]), 22));

    $subrules = $rules[$rule]->getContent();

    // 3a. Token.
    if (null === $subrules) {
        continue;
    }

    echo ' of rules: ';

    // 3b. Other rules.
    foreach ((array) $rules[$rule]->getContent() as $subrule) {
        if (!array_key_exists($subrule, $stack)) {
            // 4. Unshift new rules to print.
            $stack[$subrule] = true;
        }

        echo $subrule, ' ';
    }
}

/**
 * Will output:
 *     "value" is a choice of rules: 1 2 3 string object array number
 *     "1" is a token
 *     "2" is a token
 *     "3" is a token
 *     "string" is a concatenation of rules: 5 6 7
 *     "object" is a concatenation of rules: 10 pair 13 14
 *     "array" is a concatenation of rules: 18 value 21 22
 *     "number" is a token
 *     "5" is a token
 *     "6" is a token
 *     "7" is a token
 *     "10" is a token
 *     "pair" is a concatenation of rules: string 16 value
 *     "13" is a repetition of rules: 12
 *     "14" is a token
 *     "18" is a token
 *     "21" is a repetition of rules: 20
 *     "22" is a token
 *     "16" is a token
 *     "12" is a concatenation of rules: 11 pair
 *     "20" is a concatenation of rules: 19 value
 *     "11" is a token
 *     "19" is a token
 */

If we read the object rule, we know that it is a concatenation of the 10, pair, 13 and 14 rules. 10 is a lexeme, pair is a concatenation of the string, 16 and value rules, and so on. The initial grammar is translated in order to be in its tiniest form. It allows to reason on rules in an easier and faster way. Indeed, computations on the grammar are not restricted to AST. In the previous step, with the trace, we are already able to apply computations.

Generation

A grammar can be used to satisfy two goals: to validate a data (if we see it as an automata) or to generate a data. So far, we have seen how to validate a data through several steps: initialization of our compiler, running of the lexical and syntactic analyzers, producing a trace, transformation of this trace into an AST in order to visit that tree. But we can stop at the first step, the initialization of our compiler, to exploit the rules in order to generate a data which will be valid regarding our grammar.

Hoa\Compiler\Llk\Sampler provides three data generation algorithms:

  • random uniform generation,
  • bounded exhaustive generation,
  • grammar coverage-based generation.

Why providing three algorithms? Because it is illusory to think that one algorithm can satisfy numerous context of usages. Each one fits different needs, we will explain them later.

Generating a data based on a grammar requires two steps:

  1. generating values for all lexemes in order to get raw data,
  2. generating a path in the rules of the grammar.

A path is equivalent to a derivation, the vocabulary is different according to our goal: validation or generation.

Isotropic generation of lexemes

In order to generate values for lexemes, no matter what algorithm is used, it has to be fast. We are going to use a process called isotropic. We start with a rule and we go forward only by using random and locally uniform (only for this choice) choices. For instance, if we have a disjunction between three sub-rules, we will randomly and uniformly choose between 1 and 3. If we have a concatenation, we will just concatenate each parts. And finally, a repetition is nothing more than a disjunction of concatenation: indeed, e{1,3} is strictly equivalent to e | ee | eee. Let's see:

([ae]+|[x-z]!){1,3}              repeat [ae]+|[x-z]! 2 times
→ ([ae]+|[x-z]!)([ae]+|[x-z]!)  choose between [ae]+ and [x-z]!
→ ([ae]+)([ae]+|[x-z]!)         repeat ae 2 times
→ [ae][ae]([ae]+|[x-z]!)        choose between a and e
→ e[ae]([ae]+|[x-z]!)           again
→ ea([ae]+|[x-z]!)              choose between [ae]+ and [x-z]!
→ ea([x-z]!)                    choose between x, y and z
→ eay!

This generation is naive but this is not important. What is important is the path generation in rules, or put another way, the generation of sequences of lexemes.

Random uniform generation

The first algorithm is the random and uniform generation. This algorithm is useful if we would like to generate sequences of lexemes of a given size n with a uniformity, not local (like in the isotropic generation), but on the set of all the possible sequences. Succinctly, the algorithm works in two steps: pre-computation (once per size) followed by a generation. The pre-computation is an automatic step and computes the number of all the possible sequences and sub-sequences of size n. This step helps to compute cumulative distribution functions in order to guide the final sequences of lexemes.

We will generate 10 random data of size 7, it means composed of 7 lexemes. That's why we will use the Hoa\Compiler\Llk\Sampler\Uniform class that takes our grammar in first argument, the lexeme value generator in second argument (here Hoa\Regex\Visitor\Isotropic) and finally a size:

$sampler = new Hoa\Compiler\Llk\Sampler\Uniform(
    // Grammar.
    Hoa\Compiler\Llk\Llk::load(new Hoa\File\Read('Json.pp')),
    // Token sampler.
    new Hoa\Regex\Visitor\Isotropic(new Hoa\Math\Sampler\Random()),
    // Length.
    7
);

for ($i = 0; $i &lt; 10; ++$i) {
    echo $i, ' => ', $sampler->uniform(), "\n";
}

/**
 * Will output:
 *     0 => [ false , null , null ]
 *     1 => [ " l " , null ]
 *     2 => [ [ true ] , true ]
 *     3 => [ [ [ 4435 ] ] ]
 *     4 => [ [ [ 9366 ] ] ]
 *     5 => [ true , false , null ]
 *     6 => { " |h&lt;# " : false }
 *     7 => [ [ [ false ] ] ]
 *     8 => [ false , true , 7 ]
 *     9 => [ false , 5 , 79 ]
 */

We can redefine the size with the Hoa\Compiler\Llk\Sampler\Uniform::setLength method. We have noticed that some repetition operators have no upper bound, like + or *; in this case, we set it to n.

Bounded exhaustive generation

The second algorithm is the bounded exhaustive generation. This algorithm generates all sequences of lexemes (for the exhaustive side) from size 1 to n (for the bounded side). An interesting aspect of this algorithm is that the exhaustivity is kind of a proof! The algorithm behaves like an iterator and is very simple to use:

$sampler = new Hoa\Compiler\Llk\Sampler\BoundedExhaustive(
    // Grammar.
    Hoa\Compiler\Llk\Llk::load(new Hoa\File\Read('Json.pp')),
    // Token sampler.
    new Hoa\Regex\Visitor\Isotropic(new Hoa\Math\Sampler\Random()),
    // Length.
    7
);

foreach ($sampler as $i => $data) {
    echo $i, ' => ', $data, "\n";
}

/**
 * Will output:
 *     0 => true
 *     1 => false
 *     2 => null
 *     3 => " 8u2 "
 *     4 => { " ,M@aj{ " : true }
 *     5 => { " x`|V " : false }
 *     6 => { " NttB " : null }
 *     7 => { " eJWwA " : 0 }
 *     8 => [ true ]
 *     9 => [ true , true ]
 *     10 => [ true , true , true ]
 *     11 => [ true , true , false ]
 *     12 => [ true , true , null ]
 *     13 => [ true , true , 32 ]
 *     14 => [ true , false ]
 *     15 => [ true , false , true ]
 *     16 => [ true , false , false ]
 *     17 => [ true , false , null ]
 *     18 => [ true , false , 729 ]
 *     19 => [ true , null ]
 *     20 => [ true , null , true ]
 *     21 => [ true , null , false ]
 *     …
 *     157 => [ 780 , 01559 , 32 ]
 *     158 => 344
 */

Like the previous algorithm, we can redefine the upper bound with the Hoa\Compiler\Llk\Sampler\BoundedExhaustive::setLength method. And the repetition operators with no upper bounds are bounded to n.

Grammar coverage-based generation

The last algorithm is the grammar coverage-based generation. This algorithm reduces the combinatory explosion encountered with the previous algorithm but the goal is different: it will generate sequences of lexemes that will “activate” all the rules branches of the grammar. A rule is said covered if and only if all its sub-rules are covered, and a lexeme is said covered if it has been used in a sequence. To ensure a diversity in the produced sequences, choice points between uncovered sub-rules are resolved randomly. The algorithm also behaves like an iterator:

$sampler = new Hoa\Compiler\Llk\Sampler\Coverage(
    // Grammar.
    Hoa\Compiler\Llk\Llk::load(new Hoa\File\Read('Json.pp')),
    // Token sampler.
    new Hoa\Regex\Visitor\Isotropic(new Hoa\Math\Sampler\Random())
);

foreach ($sampler as $i => $data) {
    echo $i, ' => ', $data, "\n";
}

/**
 * Will output:
 *     0 => true
 *     1 => { " )o?bz " : null , " %3W) " : [ false , 130 , " 6 " ] }
 *     2 => [ { " ny  " : true } ]
 *     3 => { " Ne;[3 " : [ true , true ] , " th: " : true , " C[8} " : true }
 */

To avoid the combinatory explosion and to ensure the termination of the algorithm, we will use the following heuristic on the repetition operators: * will repeat 0, 1 and 2 times, + will repeat 1 and 2 times, and finally {x,y} will repeat x, x + 1, y - 1 and y times. This heuristic finds its origin in the limit testing.

We notice in our example that 4 data are generated and are enough to cover entirely our grammar!

Comparison between algorithms

Here are some clues to know when to use one algorithm instead of another.

Random uniform generation:
  • fast for small data, high data diversity and fixed size,
  • the pre-computation step is exponential and therefore long while, next, the generation is very fast.
Bounded exhaustive generation:
  • fast for small data and exhaustivity is efficient,
  • exponential number of data.
Grammar coverage-based generation:
  • fast for average or big data, and diversity of data,
  • do not consider size.

LL(1) compiler-compiler

The documentation of the LL(1) compiler, through the Hoa\Compiler\Ll1 class, is not written yet. The goal is different regarding Hoa\Compiler\Llk: there is no grammar description language, automata are hard-coded with arrays and this type of compiler is high performance oriented. That's why its behavior is monolitic.

Conclusion

Hoa\Compiler provides two compiler-compilers: Hoa\Compiler\Llk and Hoa\Compiler\Ll1, in order to validate data. The PP language allows to write algebraic grammars in a simple and natural way. The LL(k) compiler-compiler is split in distinct processus, which encourages hackability. Finally, several algorithms allows to generate data based on a grammar according to specific usages.

Les compilateurs permettent d'analyser et manipuler des données textuelles. Leurs applications sont très nombreuses. Hoa\Compiler propose de manipuler plusieurs compilateurs selon les besoins.

Table des matières

Introduction

Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire viennent aisément.

Un langage est une façon d'exprimer ou de formuler une solution à un problème. Et des problèmes, il en existe beaucoup. Nous lisons et écrivons dans plusieurs langages au quotidien, et certains de ces langages sont compris par des machines. Cette opération est possible grâce aux compilateurs.

La théorie des langages étudie entre autres l'analyse automatique de ces langages à travers des outils comme des automates ou des grammaires. Il est nécessaire d'avoir un cours détaillé pour bien comprendre tous ces concepts. Toutefois, nous allons essayer de vulgariser un minimum pour permettre une utilisation correcte de Hoa\Compiler.

Langage et grammaire

Un langage est un ensemble de mots. Chaque mot est une séquence de symboles appartenant à un alphabet. Un symbole représente la plus petite unité lexicale d'un langage, il est atomique et nous l'appellons lexème (ou token en anglais). Les séquences de lexèmes représentant les mots sont construites avec des règles. À partir d'un mot et d'une règle racine, nous allons essayer de dériver ses sous-règles. Si une dérivation existe, alors le mot est considéré comme valide, sinon il est considéré comme invalide. Nous parlons aussi de reconnaissance de mots. Par exemple, si nous considérons les règles suivantes :

    exp ::= exp + exp
          | nombre
 nombre ::= chiffre nombre
          | chiffre
chiffre ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

Le mot que nous voulons reconnaître est 7 + 35. La règle racine est exp. Si nous la dérivons (de gauche à droite et de haut en bas, ou left-to-right et top-to-bottom en anglais), nous pouvons avoir exp + exp ou nombre (la disjonction, i.e. le « ou », est représentée par le symbole « | ») :

exp + exp | nombre
→ exp + exp
→ ( exp + exp | nombre ) + exp
→ nombre + exp
→ ( chiffre nombre | chiffre ) + exp

Nous continuons à dériver jusqu'à éliminer toutes les règles et n'avoir que des lexèmes :

…
→ ( chiffre nombre | chiffre ) + exp
→ chiffre + exp
→ ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ) + exp
→ 7 + exp
→ 7 + ( exp + exp | nombre )
→ 7 + nombre
→ 7 + ( chiffre nombre | chiffre )
→ 7 + chiffre nombre
→ 7 + ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ) nombre
→ 7 + 3 nombre
→ 7 + 3 ( chiffre nombre | chiffre )
→ 7 + 3 chiffre
→ 7 + 3 ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 )
→ 7 + 3 5

Une dériviation existe bel et bien pour reconnaître le mot 7 + 35, c'est donc un mot valide pour ces règles.

Un ensemble de règles est appelé une grammaire. Et donc, une grammaire représente un langage !

Toutefois, il existe plusieurs catégories de grammaires. C'est en 1956 qu'a été formulée la hiérarchie de Chomsky, classant les grammaires en quatre niveaux :

  1. grammaires générales, ou unrestricted grammars, reconnaissant les langages dits de Turing, aucune restriction n'est imposée aux règles ;
  2. grammaires contextuelles, ou context-sensitive grammars, reconnaissant les langages contextuels ;
  3. grammaires algébriques, ou context-free grammars, reconnaissant les langages algébriques, basés sur les automates à pile ;
  4. grammaires régulières, ou regular grammars, reconnaissant les langages réguliers.

Chaque niveau reconnait le niveau suivant. Hoa\Compiler ne traite que les langages définis par les grammaires de niveau 3 et 4. Pour donner rapidement une idée, les grammaires régulières peuvent s'apparenter aux expressions régulières (comme les PCRE), bien connues des développeurs. Mais les grammaires régulières ne permettent pas par exemple de reconnaître des couples de symboles (comme des parenthèses, des accolades ou des guillemets), alors que les grammaires algébriques le permettent (grâce à la notion de piles de lexèmes).

Reconnaissance de mots

En général, le processus de compilation débute par deux analyses : lexicale et syntaxique. Une analyse lexicale consiste à découper un mot en une séquence de lexèmes. Cette séquence sera ensuite utilisée par l'analyseur syntaxique afin de vérifier que le mot appartient au langage.

Selon la grammaire, la reconnaissance ne se fera pas de la même manière, mais le principe reste identique : prendre les lexèmes les uns après les autres dans la séquence et vérifier qu'ils permettent d'avancer dans la dérivation des règles de notre grammaire.

Les analyses syntaxiques sont aussi classées en catégories : LL, LR, LALR etc. Hoa\Compiler ne propose que des analyseurs syntaxiques LL, pour Left-to-right Leftmost derivation, i.e. de la plus haute règle vers la plus profonde, et les règles sont dérivées de la gauche vers la droite. Là encore, il existe des sous-catégories, dont deux que traite Hoa\Compiler : LL(1) et LL(*). D'une manière générale, nous parlons d'analyseurs syntaxiques LL(k) : si un lexème ne permet pas de dériver une règle comme il faut, alors l'analyseur peut revenir jusqu'à k étapes en arrière ; nous parlons aussi de backtrack. Autrement dit, les règles peuvent être ambiguës : à chaque fois que nous dérivons une règle de la grammaire, nous avons plusieurs choix possibles et l'analyseur peut se tromper, c'est pourquoi il doit parfois revenir en arrière. La variable k permet de définir le niveau d'ambiguïté. Si une grammaire peut être analysée par un analyseur syntaxique LL(1), elle est dite non-ambiguë : à chaque lexème utilisé pour dériver nos règles, il n'y a qu'un seul choix possible. Et si nous avons un analyseur syntaxique LL(*), cela signifie que la variable k est indéfinie. L'exemple suivant illustre une grammaire non-ambiguë :

rule ::= a b c | d e f

Et cet exemple illustre une grammaire ambiguë :

rule1 ::= a rule2
rule2 ::= b rule3 | b rule4
rule3 ::= c d
rule4 ::= e f

Voyons quand nous essayons de trouver une dérivation pour le mot abef à partir de la règle racine rule1 :

rule1
→ a rule2                      a  bef ✔
  → a (b rule3 | b rule4)      a  bef
    → a b rule3               ab  ef  ✔
      → a b c d              abe  f   ✖
    ← a b rule3               ab  ef  ✖
  ← a (b rule3 | b rule4)      a  bef
    → a b rule4               ab  ef  ✔
      → a b e f             abef      ✔

La règle rule2 est ambiguë, ce qui peut entraîner une mauvaise dérivation et donc un retour en arrière, un backtracking.

Compilateur de compilateurs LL(k)

Écrire des compilateurs est une tâche laborieuse. Ce n'est pas forcément toujours difficile mais souvent répétitif et long. C'est pourquoi il existe des compilateurs de compilateurs, ou autrement dit, des générateurs de compilateurs. La plupart du temps, ces compilateurs de compilateurs utilisent un langage intermédiaire pour écrire une grammaire. La bibliothèque Hoa\Compiler propose la classe Hoa\Compiler\Llk\Llk qui permet l'écriture de compilateurs de compilateurs à travers un langage dédié.

Langage PP

Le langage PP, pour PHP Parser, permet d'exprimer des grammaires algébriques. Il s'écrit dans des fichiers portant l'extension .pp (voir le fichier hoa://Library/Compiler/.Mime).

Une grammaire est constituée de lexèmes et de règles. La déclaration d'un lexème se fait de la manière suivante : %token namespace_in:name value -> namespace_out, où name représente le nom du lexème, value représente sa valeur, au format PCRE (attention à ne pas reconnaître de valeur vide, auquel cas une exception sera levée), et namespace_in et namespace_out représentent les noms des espaces de noms et sont optionels (vaut default par défaut). Par exemple number qui représente un nombre composé de chiffres de 0 à 9 :

%token number \d+

Les espaces de noms représentent des sous-ensembles disjoints de lexèmes, utilisés pour faciliter les analyses. Une déclaration %skip est similaire à %token excepté qu'elle représente un lexème à sauter, c'est à dire à ne pas considérer. Un exemple courant de lexèmes %skip est les espaces :

%skip space \s

Pour expliquer les règles, nous allons utiliser comme exemple la grammaire Json.pp, grammaire légèrement simplifiée du langage JSON (voir la RFC4627). La grammaire complète se situe dans le fichier hoa://Library/Json/Grammar.pp. Ainsi :

%skip   space          \s
// Scalars.
%token  true           true
%token  false          false
%token  null           null
// Strings.
%token  quote_         "        -> string
%token  string:string  [^"]+
%token  string:_quote  "        -> default
// Objects.
%token  brace_         {
%token _brace          }
// Arrays.
%token  bracket_       \[
%token _bracket        \]
// Rest.
%token  colon          :
%token  comma          ,
%token  number         \d+

value:
    &lt;true> | &lt;false> | &lt;null> | string() | object() | array() | number()

string:
    ::quote_:: &lt;string> ::_quote::

number:
    &lt;number>

#object:
    ::brace_:: pair() ( ::comma:: pair() )* ::_brace::

#pair:
    string() ::colon:: value()

#array:
    ::bracket_:: value() ( ::comma:: value() )* ::_bracket::

Nous remarquons que nous avons deux espaces de noms pour les lexèmes : default et string (cela permet de ne pas confondre les lexèmes quote_ et string:_quote qui ont la même représentation). Nous remarquons ensuite la règle value qui est une disjonction de plusieurs lexèmes et règles. Les constructions du langage PP sont les suivantes :

  • rule() pour appeler une règle ;
  • &lt;token> et ::token:: pour déclarer un lexème (les espaces de noms n'apparaissent pas ici) ;
  • | pour une disjonction (un choix) ;
  • () pour grouper ;
  • e? pour dire que e est optionel ;
  • e+ pour dire que e peut apparaître 1 ou plusieurs fois ;
  • e* pour dire que e peut apparaître 0 ou plusieurs fois ;
  • e{x,y} pour dire que e peut apparaître entre x et y fois ;
  • #node pour créer un nœud node dans l'arbre ;
  • token[i] pour unifier des lexèmes entre eux.

Peu de constructions mais amplement suffisantes.

Enfin, la grammaire du langage PP est écrite… dans le langage PP ! Vous pourrez la trouver dans le fichier hoa://Library/Compiler/Llk/Llk.pp.

Processus de compilation

Le processus de compilation qu'utilise Hoa\Compiler\Llk\Llk est classique. Il commence par analyser lexicalement la donnée textuelle, le mot, i.e. à transformer notre donnée en une séquence de lexèmes. L'ordre de déclaration des lexèmes est primordial car l'analyseur lexical va les prendre les uns après les autres. Ensuite, c'est l'analyseur syntaxique qui entre en jeu afin de reconnaître notre donnée.

Si l'analyse syntaxique est un succès, nous obtenons une trace. Cette trace peut être transformée en AST, pour Abstract Syntax Tree. Cet arbre représente notre donnée textuelle après analyse. Il a l'avantage de pouvoir être visité (nous détaillerons plus loin), ce qui permet par exemple d'ajouter de nouvelles contraintes qui ne peuvent pas être exprimées dans la grammaire, comme une vérification de type.

Manipulons un peu Hoa\Compiler\Llk\Llk. Cette classe est un assistant pour lire une grammaire au format PP facilement. Elle prend en seul argument un flux en lecture vers la grammaire et retourne un compilateur Hoa\Compiler\Llk\Parser prêt à l'emploi. Sur ce compilateur, nous allons appeler la méthode Hoa\Compiler\Llk\Parser::parse pour analyser une donnée JSON. Si la donnée est correcte, nous aurons en retour un AST, sinon une exception sera levée. Enfin, nous allons utiliser le visiteur Hoa\Compiler\Visitor\Dump pour afficher notre AST :

// 1. Load grammar.
$compiler = Hoa\Compiler\Llk\Llk::load(new Hoa\File\Read('Json.pp'));

// 2. Parse a data.
$ast      = $compiler->parse('{"foo": true, "bar": [null, 42]}');

// 3. Dump the AST.
$dump     = new Hoa\Compiler\Visitor\Dump();
echo $dump->visit($ast);

/**
 * Will output:
 *     >  #object
 *     >  >  #pair
 *     >  >  >  token(string:string, foo)
 *     >  >  >  token(true, true)
 *     >  >  #pair
 *     >  >  >  token(string:string, bar)
 *     >  >  >  #array
 *     >  >  >  >  token(null, null)
 *     >  >  >  >  token(number, 42)
 */

Quand nous écrivons et testons une grammaire, nous allons répéter ces trois tâches très régulièrement. C'est pourquoi, le script hoa propose la commande compiler:pp. Cette commande propose d'analyser une donnée par rapport à une grammaire et d'appliquer un visiteur si besoin sur l'AST résultant. Notons que la lecture de la donnée peut se faire à travers un pipe :

$ echo '[1, [1, [2, 3], 5], 8]' | hoa compiler:pp Json.pp 0 --visitor dump
>  #array
>  >  token(number, 1)
>  >  #array
>  >  >  token(number, 1)
>  >  >  #array
>  >  >  >  token(number, 2)
>  >  >  >  token(number, 3)
>  >  >  token(number, 5)
>  >  token(number, 8)

C'est un moyen pratique pour tester rapidement des données par rapport à notre grammaire. Il ne faut pas hésiter à regarder l'aide de la commande compiler:pp pour plus de détails !

Les analyses s'effectuent sur la règle racine mais nous pouvons préciser une autre règle à l'aide du deuxième argument de la méthode Hoa\Compiler\Llk\Parser::parse :

$compiler->parse('{"foo": true, "bar": [null, 42]}', 'object');

Pour utiliser la règle racine, il suffit de passer null.

Et enfin, pour ne pas générer l'AST mais uniquement savoir si la donnée est valide ou pas, nous pouvons utiliser le dernier argument de notre méthode en lui passant false :

$valid = $compiler->parse('{"foo": true, "bar": [null, 42]}', null, false);
var_dump($valid);

/**
 * Will output:
 *     bool(true)
 */

Erreurs

Les erreurs de compilation sont remontées à travers des exceptions, ainsi :

$ echo '{"foo" true}' | hoa compiler:pp Json.pp 0 --visitor dump
Uncaught exception (Hoa\Compiler\Exception\UnexpectedToken):
Hoa\Compiler\Llk\Parser::parse(): (0) Unexpected token "true" (true) at line 1
and column 8:
{"foo" true}
       ↑
in hoa://Library/Compiler/Llk/Parser.php at line 1

Plusieurs exceptions peuvent remonter selon le contexte :

  • durant l'analyse lexicale, Hoa\Compiler\Exception\UnrecognizedToken quand un lexème n'est pas reconnu, i.e. quand la donnée textuelle ne peut plus être découpée en une séquence de lexèmes, et Hoa\Compiler\Exception\Lexer quand d'autres erreurs plus générales arrivent, par exemple si un lexème reconnaît une valeur vide ;
  • durant l'analyse syntaxique, Hoa\Compiler\Exception\UnexpectedToken quand un lexème n'est pas attendu, i.e. qu'il ne permet plus de dériver les règles de la grammaire.

L'exception parente est Hoa\Compiler\Exception\Exception.

Nœuds

Le processus de compilation aboutit très souvent à la production d'un AST. Il est important de contrôler sa forme, sa taille, les données qu'il contient etc. C'est pourquoi il est nécessaire de comprendre la notation #node car elle permet de créer des nœuds dans l'AST. Une précision tout d'abord, les lexèmes déclarés avec la syntaxe &lt;token> apparaîtront dans l'arbre, alors que les autres lexèmes, déclarés avec la syntaxe ::token::, n'y apparaîtront pas. En effet, dans notre dernier exemple, les lexèmes quote_, brace_, colon, comma etc. n'apparaissent pas. Ensuite, il est important de noter que les déclarations de nœuds se surchargent les unes par rapport aux autres au sein d'une même règle. Enfin, un nom de règle peut être précédé par #, comme pour la règle #array, qui permet de définir un nœud par défaut, mais il peut être surchargé. Par exemple, si nous remplaçons la règle array par :

#array:
    ::bracket_:: value() ( ::comma:: value() #bigarray )* ::_bracket::

Si le tableau ne contient qu'une seule valeur, le nœud s'appelera #array, sinon il s'appelera #bigarray ; voyons plutôt :

$ echo '[42]' | hoa compiler:pp Json.pp 0 --visitor dump
>  #array
>  >  token(number, 42)
$ echo '[4, 2]' | hoa compiler:pp Json.pp 0 --visitor dump
>  #bigarray
>  >  token(number, 4)
>  >  token(number, 2)

Bien sûr, il peut arriver qu'un nœud soit créé ou pas selon le dérivation empruntée dans la règle. Le mécanisme est normalement assez intuitif.

Espace de noms

Détaillons un peu le fonctionnement de l'analyseur lexical vis à vis des espaces de noms.

Les lexèmes sont placés dans des espaces de noms, c'est à dire que seuls les lexèmes de l'espace de noms courant seront utilisés par l'analyseur lexical. L'espace de noms par défaut est default. Pour déclarer l'espace de noms d'un lexème, il faut utiliser l'opérateur :. Quand un lexème est consommé, il peut changer l'espace courant pour la suite de l'analyse lexicale, grâce à l'opérateur ->. Ainsi, nous allons déclarer cinq lexèmes : foo et bar dans l'espace default, baz dans ns1 et qux et foo dans ns2. Le fait de déclarer deux fois foo n'est pas gênant car ils sont dans des espaces de noms différent :

%token      foo   fo+     -> ns1
%token      bar   ba?r+   -> ns2
%token  ns1:baz   ba?z+   -> default
%token  ns2:qux   qux+
%token  ns2:foo   FOO     -> ns1

Écrire default:bar est strictement équivalent à bar. Le lexème foo emmène dans ns1, bar dans ns2, ns1:baz dans default, ns2:qux reste dans ns2 et ns2:foo emmène dans ns1. Observons la séquence de lexèmes produite par l'analyseur lexical avec la donnée fooooobzzbarrrquxFOObaz :

$pp = '%token      foo   fo+     -> ns1'     . "\n" .
      '%token      bar   ba?r+   -> ns2'     . "\n" .
      '%token  ns1:baz   ba?z+   -> default' . "\n" .
      '%token  ns2:qux   qux+'               . "\n" .
      '%token  ns2:foo   FOO     -> ns1';

// 1. Parse PP.
Hoa\Compiler\Llk\Llk::parsePP($pp, $tokens, $rawRules);

// 2. Run the lexical analyzer.
$lexer    = new Hoa\Compiler\Llk\Lexer();
$sequence = $lexer->lexMe('fooooobzzbarrrquxFOObaz', $tokens);

// 3. Pretty-print the result.
$format   = '%' . (strlen((string) count($sequence)) + 1) . 's  ' .
            '%-13s %-20s  %-20s  %6s' . "\n";
$header   = sprintf($format, '#', 'namespace', 'token name', 'token value', 'offset');

echo $header, str_repeat('-', strlen($header)), "\n";

foreach ($sequence as $i => $token) {
    printf(
        $format,
        $i,
        $token['namespace'],
        $token['token'],
        $token['value'],
        $token['offset']
    );
}

/**
 * Will output:
 *      #  namespace     token name            token value           offset
 *     ---------------------------------------------------------------------
 *      0  default       foo                   fooooo                     0
 *      1  ns1           baz                   bzz                        6
 *      2  default       bar                   barrr                      9
 *      3  ns2           qux                   qux                       14
 *      4  ns2           foo                   FOO                       17
 *      5  ns1           baz                   baz                       20
 *      6  default       EOF                   EOF                       23
 */

Nous lisons les lexèmes, leur espace et leur valeur dans le tableau. La donnée a pu être découpée, et nous sommes passés d'un espace à un autre. Si cette fois nous essayons avec la donnée foqux, nous aurons une erreur : fo correspond au lexème foo dans l'espace default, nous changeons alors d'espace pour ns1, et là, aucun lexème dans cet espace ne peut reconnaître au moins q. Une erreur sera levée.

Jusqu'à maintenant, nous avons vu comment passer d'un espace à l'autre avec l'opérateur ->. Aucun historique sur les espaces traversés n'est conservé. Toutefois, dans certains cas rares, il peut arriver qu'un espace de lexèmes soit accessible via plusieurs autres et que nous aimerions qu'un lexème déclenche le retour vers l'espace de noms précédent. Autrement dit, nous aimerions un historique des espaces traversés et pouvoir y naviguer (en arrière uniquement). C'est le rôle du mot-clé __shift__ * n, à utiliser après l'opérateur -> et à la place du nom d'un espace. __shift__ est équivalent à dire : revient à l'espace précédent. __shift__ est équivalent à __shift__ * 1, et __shift__ * n à : revient n fois à l'espace précédent.

Lorsque le mot-clé __shift__ apparaît dans la grammaire, les espaces sont gérés comme une pile, d'où le vocabulaire shift. Il faut faire attention à bien dépiler les espaces pour ne pas avoir une pile trop conséquente.

Prenons en exemple la grammaire suivante :

%token       foo1  a    -> ns1
%token       foo2  x    -> ns2
%token       end   e

%token   ns1:bar   b
%token   ns1:baz   c    -> ns3
%token   ns1:tada  t    -> __shift__

%token   ns2:bar   y
%token   ns2:baz   z    -> ns3
%token   ns2:tada  T    -> __shift__

%token   ns3:qux   =   -> __shift__

#test:
    ( &lt;foo1> | &lt;foo2> ) &lt;bar> &lt;baz> &lt;qux> &lt;tada> &lt;end>

Cette grammaire reconnaît deux données : abc=te et xyz=Te. Si le premier lexème foo1 est rencontré, l'analyseur syntaxique changera d'espace pour ns1. Quand il rencontrera le lexème ns1:baz, il passera dans ns3. Ensuite, quand il rencontrera ns3:qux, il reviendra à l'espace précédent, soit ns1. Et ainsi de suite. Maintenant, s'il ne rencontre pas foo1 mais foo2, il ira dans l'espace ns2, puis dans ns3 puis à nouveau ns2. Les mots-clés __shift__ pour ns1:tada et ns2:tada n'ont pas d'autres buts que de dépiler les espaces, mais aucune ambiguïté n'existe : ces espaces ne sont accessibles que par un seul espace, à savoir default.

Maintenant, enregistrons cette grammaire dans un fichier NamespaceStack.pp et utilisons l'option -s/--token-sequence de la commande hoa compiler:pp :

$ echo -n 'abc=te' | hoa compiler:pp NamespaceStack.pp 0 --token-sequence
 #  namespace     token name            token value                     offset
-------------------------------------------------------------------------------
 0  default       foo1                  a                                    0
 1  ns1           bar                   b                                    1
 2  ns1           baz                   c                                    2
 3  ns3           qux                   =                                    3
 4  ns1           tada                  t                                    4
 5  default       end                   e                                    5
 6  default       EOF                   EOF                                  6

$ echo -n 'xyz=Te' | hoa compiler:pp NamespaceStack.pp 0 --token-sequence
 #  namespace     token name            token value                     offset
-------------------------------------------------------------------------------
 0  default       foo2                  x                                    0
 1  ns2           bar                   y                                    1
 2  ns2           baz                   z                                    2
 3  ns3           qux                   =                                    3
 4  ns2           tada                  T                                    4
 5  default       end                   e                                    5
 6  default       EOF                   EOF                                  6

Nous voyons que l'analyse lexicale a réussi à jongler avec les espaces de noms, comme attendu. Nous avions deux façons d'accéder à l'espace ns3 : soit depuis ns1, soit depuis ns2. L'analyseur a réussi à créer un historique des espaces et à y naviguer.

Unification

Une caractéristique qu'apporte le langage PP par rapport à d'autres langages de grammaires connus est la capacité d'exprimer une unification de lexèmes. Imaginons la grammaire suivante :

%token  quote   '|"
%token  string  \w+

rule:
    ::quote:: &lt;string> ::quote::

Les guillemets qui entourent la chaîne de caractère peuvent être de deux sortes : simple, avec le symbole « ' », ou double, avec le symbole « " ». Ainsi, les données "foo" et 'foo' sont valides, mais également "foo' et 'foo" !

L'unification des lexèmes permet d'ajouter une contrainte supplémentaire sur la valeur des lexèmes à l'exécution. La syntaxe est la suivante : token[i]. La valeur de i indique quels lexèmes vont devoir porter la même valeur. Et enfin, l'unification est locale à une instance d'une règle, c'est à dire qu'il n'y a pas d'unification entre les lexèmes de plusieurs règles et que cela s'applique sur la règle appelée uniquement. Ainsi, l'exemple devient :

rule:
    ::quote[0]:: &lt;string> ::quote[0]::

Ce qui invalide les données "foo' et 'foo".

L'unification trouve de nombreuses applications, comme par exemple unifier les noms des balises ouvrantes et fermantes du langage XML.

Abstract Syntax Tree

Un arbre syntaxique abstrait représente une donnée textuelle sous forme structurelle. Chaque nœud de cet arbre est représenté par la classe Hoa\Compiler\Llk\TreeNode. Parmis les méthodes utiles, nous trouvons :

  • getId pour obtenir l'identifiant du nœud ;
  • getValueToken pour obtenir le nom du lexème ;
  • getValueValue pour obtenir la valeur du lexème ;
  • isToken si le nœud représente un lexème ;
  • getChild($i) pour obtenir le $i-ème enfant d'un nœud ;
  • getChildren pour obtenir tous les nœuds ;
  • getChildrenNumber pour connaître le nombre d'enfants ;
  • getParent pour obtenir le nœud parent ;
  • getData pour obtenir une référence vers un tableau de données ;
  • accept pour appliquer un visiteur.

Les visiteurs sont le moyen le plus pratique pour parcourir un AST. En guise d'exemple, nous allons écrire le visiteur PrettyPrinter qui va réécrire une donnée JSON avec notre propre convention (espacements, retours à la ligne etc.). Un visiteur doit implémenter l'interface Hoa\Visitor\Visit et n'aura qu'une seule méthode à écrire : visit qui prend trois arguments : l'élément et deux arguments accessoires (en référence et en copie). Voyons plutôt :

class PrettyPrinter implements Hoa\Visitor\Visit
{
    public function visit (
        Hoa\Visitor\Element $element,
        &amp;$handle = null,
        $eldnah = null
    ) {
        static $i      = 0;
        static $indent = '    ';

        // One behaviour per node in the AST.
        switch ($element->getId()) {
            // Object: { … }.
            case '#object':
                echo '{', "\n";
                ++$i;

                foreach ($element->getChildren() as $e => $child) {
                    if (0 &lt; $e) {
                        echo ',', "\n";
                    }

                    echo str_repeat($indent, $i);
                    $child->accept($this, $handle, $eldnah);
                }

                echo "\n", str_repeat($indent, --$i), '}';

                break;

            // Array: [ … ].
            case '#array':
                echo '[', "\n";
                ++$i;

                foreach ($element->getChildren() as $e => $child) {
                    if (0 &lt; $e) {
                        echo ',', "\n";
                    }

                    echo str_repeat($indent, $i);
                    $child->accept($this, $handle, $eldnah);
                }

                echo "\n", str_repeat($indent, --$i), ']';

                break;

            // Pair: "…": ….
            case '#pair':
                echo
                    $element->getChild(0)->accept($this, $handle, $eldnah),
                    ': ',
                    $element->getChild(1)->accept($this, $handle, $eldnah);

                break;

            // Many tokens.
            case 'token':
                switch ($element->getValueToken()) {
                    // String: "…".
                    case 'string':
                        echo '"', $element->getValueValue(), '"';

                        break;

                    // Booleans.
                    case 'true':
                    case 'false':

                    // Null.
                    case 'null':

                    // Number.
                    case 'number':
                        echo $element->getValueValue();

                        break;
                }

                break;
        }
    }
}

Nous allons voir tout de suite un exemple d'utilisation :

$compiler    = Hoa\Compiler\Llk\Llk::load(new Hoa\File\Read('Json.pp'));
$ast         = $compiler->parse('{"foo": true, "bar": [null, 42]}');
$prettyPrint = new PrettyPrinter();
echo $prettyPrint->visit($ast);

/**
 * Will output:
 *     {
 *         "foo": true,
 *         "bar": [
 *             null,
 *             42
 *         ]
 *     }
 */

La méthode getData est très pratique pour stocker des données susceptibles d'être réutilisées, par exemple d'un visiteur à l'autre. Cette méthode retourne une référence sur un tableau ; ainsi :

$data = $element->getData();

if (!isset($data['previousComputing'])) {
    throw new Exception('Need a previous computing.', 0);
}

$previous = $data['previousComputing'];

Il est courant d'utiliser un visiteur par contrainte : vérifiation des symboles, vérification de types etc. Certains peuvent laisser des données nécessaires pour le suivant. La méthode getData n'impose aucune structuration des données, elle propose uniquement un accès à un tableau. Ce sera à vous de faire le reste.

Utiliser la classe Hoa\Compiler\Llk\TreeNode est vraiment trivial et nous l'utiliserons la plupart du temps avec un visiteur.

Traces

Le compilateur LL(k) que propose Hoa est clairement découpé en plusieurs couches. Chaque couche est exploitable pour permettre une modularité maximum. Quand la grammaire est traduite en « règles machines » et que les analyseurs lexical et syntaxique ont validé une donnée, il en résulte une trace. Cette trace est un tableau composé de trois classes seulement :

  • Hoa\Compiler\Llk\Rule\Entry quand l'analyseur syntaxique est rentré dans une règle ;
  • Hoa\Compiler\Llk\Rule\Ekzit quand l'analyseur syntaxique est sorti d'une règle ;
  • Hoa\Compiler\Llk\Rule\Token quand l'analyseur syntaxique a rencontré un lexème.

Nous pouvons l'obtenir grâce à la méthode Hoa\Compiler\Llk\Parser::getTrace. Pour bien comprendre cette trace, nous allons commencer par un exemple :

$compiler = Hoa\Compiler\Llk\Llk::load(new Hoa\File\Read('Json.pp'));
$ast      = $compiler->parse('{"foo": true, "bar": [null, 42]}');
$i        = 0;

foreach ($compiler->getTrace() as $element) {
    if ($element instanceof Hoa\Compiler\Llk\Rule\Entry) {
        echo str_repeat('>   ', ++$i), 'enter ', $element->getRule(), "\n";
    } elseif ($element instanceof Hoa\Compiler\Llk\Rule\Token) {
        echo
            str_repeat('    ', $i + 1), 'token ', $element->getTokenName(),
            ', consumed ', $element->getValue(), "\n";
    } else {
        echo str_repeat('&lt;   ', $i--), 'ekzit ', $element->getRule(), "\n";
    }
}

/**
 * Will output:
 *     >   enter value
 *     >   >   enter object
 *                 token brace_, consumed {
 *     >   >   >   enter pair
 *     >   >   >   >   enter string
 *                         token quote_, consumed "
 *                         token string, consumed foo
 *                         token _quote, consumed "
 *     &lt;   &lt;   &lt;   &lt;   ekzit string
 *                     token colon, consumed :
 *     >   >   >   >   enter value
 *                         token true, consumed true
 *     &lt;   &lt;   &lt;   &lt;   ekzit value
 *     &lt;   &lt;   &lt;   ekzit pair
 *     >   >   >   enter 13
 *     >   >   >   >   enter 12
 *                         token comma, consumed ,
 *     >   >   >   >   >   enter pair
 *     >   >   >   >   >   >   enter string
 *                                 token quote_, consumed "
 *                                 token string, consumed bar
 *                                 token _quote, consumed "
 *     &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   ekzit string
 *                             token colon, consumed :
 *     >   >   >   >   >   >   enter value
 *     >   >   >   >   >   >   >   enter array
 *                                     token bracket_, consumed [
 *     >   >   >   >   >   >   >   >   enter value
 *                                         token null, consumed null
 *     &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   ekzit value
 *     >   >   >   >   >   >   >   >   enter 21
 *     >   >   >   >   >   >   >   >   >   enter 20
 *                                             token comma, consumed ,
 *     >   >   >   >   >   >   >   >   >   >   enter value
 *                                                 token number, consumed 42
 *     &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   ekzit value
 *     &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   ekzit 20
 *     &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   ekzit 21
 *                                     token _bracket, consumed ]
 *     &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   ekzit array
 *     &lt;   &lt;   &lt;   &lt;   &lt;   &lt;   ekzit value
 *     &lt;   &lt;   &lt;   &lt;   &lt;   ekzit pair
 *     &lt;   &lt;   &lt;   &lt;   ekzit 12
 *     &lt;   &lt;   &lt;   ekzit 13
 *                 token _brace, consumed }
 *     &lt;   &lt;   ekzit object
 *     &lt;   ekzit value
 */

Cet exemple nous révèle plusieurs choses. Tout d'abord, les informations que nous donne la trace peuvent être utiles : si nous sommes sur une règle, nous avons son nom (avec la méthode getRule), et si nous sommes sur un lexème, nous avons son nom (avec la méthode getTokenName), sa représentation (sous la forme d'une PCRE, avec la méthode getRepresentation), sa valeur (avec la méthode getValue), si c'est un nœud à conserver dans l'AST (avec la méthode isKept) et son index d'unification s'il existe (avec la méthode getUnificationIndex). Bien sûr, tout ceci est modifiable, ce qui peut influencer la construction de l'AST qui est le processus (optionnel) suivant.

Ensuite, nous remarquons que parfois nous entrons dans une règle qui existe dans la grammaire, comme object, pair, value etc., et parfois nous entrons dans une règle numérique, comme 13, 12, 21, 20 etc. Quand la grammaire est interprétée pour être transformée en « règles machines », chacune de ses règles est linéarisée selon les opérateurs du langage PP :

  • Hoa\Compiler\Llk\Rule\Choice pour une disjonction ;
  • Hoa\Compiler\Llk\Rule\Concatenation pour une concaténation ;
  • Hoa\Compiler\Llk\Rule\Repetition pour une répétition ;
  • Hoa\Compiler\Llk\Rule\Token pour un lexème (déjà vu précédemment).

Toutes les règles sous ce format sont accessibles à travers la méthode Hoa\Compiler\Llk\Parser::getRules sous la forme d'un tableau. Nous allons afficher toutes les règles accessibles depuis la règle racine pour mieux comprendre :

$compiler = Hoa\Compiler\Llk\Llk::load(new Hoa\File\Read('Json.pp'));

// 1. Get all rules.
$rules    = $compiler->getRules();

// 2. Start with the root rule.
$stack    = [$compiler->getRootRule() => true];

while (false !== current($stack)) {
    $rule = key($stack);
    next($stack);
    echo
        "\n", '"', $rule, '" is a ',
        strtolower(substr(get_class($rules[$rule]), 22));

    $subrules = $rules[$rule]->getContent();

    // 3a. Token.
    if (null === $subrules) {
        continue;
    }

    echo ' of rules: ';

    // 3b. Other rules.
    foreach ((array) $rules[$rule]->getContent() as $subrule) {
        if (!array_key_exists($subrule, $stack)) {
            // 4. Unshift new rules to print.
            $stack[$subrule] = true;
        }

        echo $subrule, ' ';
    }
}

/**
 * Will output:
 *     "value" is a choice of rules: 1 2 3 string object array number
 *     "1" is a token
 *     "2" is a token
 *     "3" is a token
 *     "string" is a concatenation of rules: 5 6 7
 *     "object" is a concatenation of rules: 10 pair 13 14
 *     "array" is a concatenation of rules: 18 value 21 22
 *     "number" is a token
 *     "5" is a token
 *     "6" is a token
 *     "7" is a token
 *     "10" is a token
 *     "pair" is a concatenation of rules: string 16 value
 *     "13" is a repetition of rules: 12
 *     "14" is a token
 *     "18" is a token
 *     "21" is a repetition of rules: 20
 *     "22" is a token
 *     "16" is a token
 *     "12" is a concatenation of rules: 11 pair
 *     "20" is a concatenation of rules: 19 value
 *     "11" is a token
 *     "19" is a token
 */

Si nous lisons la règle object, nous savons que c'est la concaténation des règles 10, pair, 13 et 14. 10 est un lexème, pair est la concaténation des règles string, 16 et value, et ainsi de suite. La grammaire initiale est transformée pour être sous sa forme la plus réduite possible. Ceci permet de raisonner beaucoup plus facilement et rapidement sur les règles. En effet, les traitements sur la grammaire ne sont pas réservés aux AST. À l'étape précédente, avec la trace, nous pouvons déjà effectuer des traitements.

Génération

Une grammaire peut être utile pour deux objectifs : valider une donnée (si nous la voyons comme un automate) ou générer des données. Jusqu'à présent, nous avons vu comment valider une donnée à travers plusieurs processus : préparation de notre compilateur, exécution des analyseurs lexical et syntaxique résultant sur une trace, transformation de la trace vers un AST pour enfin visiter cet arbre. Mais nous pouvons nous arrêter à la première étape, la préparation de notre compilateur, pour exploiter les règles afin de générer une donnée qui sera valide par rapport à notre grammaire.

Hoa\Compiler\Llk\Sampler propose trois algorithmes de générations de données :

  • génération aléatoire et uniforme ;
  • génération exhaustive bornée ;
  • génération basée sur la couverture.

Pourquoi proposer trois algorithmes ? Parce qu'il est illusoire de penser qu'un seul algorithme peut suffir aux nombreux contextes d'utilisations. Chacun répond à des besoins différents, nous l'expliquerons plus loin.

Générer une donnée à partir d'une grammaire se fait en deux étapes :

  1. générer des valeurs pour les lexèmes afin d'avoir des données brutes ;
  2. générer un chemin dans les règles de la grammaire.

Un chemin est équivalent à une dérivation, le vocabulaire est différent selon notre objectif : validation ou génération.

Génération isotropique de lexèmes

Pour générer les valeurs des lexèmes, peu importe l'algorithme utilisé, il doit être rapide. Nous allons utiliser un parcours dit isotrope. Nous partons d'une règle et nous avançons uniquement à partir de choix aléatoires et uniformes localement (uniquement pour ce choix). Par exemple si nous avons une disjonction entre trois sous-règles, nous allons tirer aléatoirement et uniformément entre 1 et 3. Si nous avons une concaténation, nous allons juste concaténer chaque partie. Et enfin, une répétition n'est rien d'autre qu'une disjonction de concaténation : en effet, e{1,3} est strictement équivalent à e | ee | eee. Illustrons plutôt :

([ae]+|[x-z]!){1,3}              repeat [ae]+|[x-z]! 2 times
→ ([ae]+|[x-z]!)([ae]+|[x-z]!)  choose between [ae]+ and [x-z]!
→ ([ae]+)([ae]+|[x-z]!)         repeat ae 2 times
→ [ae][ae]([ae]+|[x-z]!)        choose between a and e
→ e[ae]([ae]+|[x-z]!)           again
→ ea([ae]+|[x-z]!)              choose between [ae]+ and [x-z]!
→ ea([x-z]!)                    choose between x, y and z
→ eay!

Cette génération est naïve mais ce n'est pas important. Ce qui est vraiment important est la génération des chemins dans les règles, ou autrement dit, la génération des séquences de lexèmes.

Génération aléatoire et uniforme

Le premier algorithme est celui de la génération aléatoire et uniforme. Cet algorithme est utile si nous voulons générer des séquences de lexèmes de taille n fixe et avec une uniformité non pas locale (comme avec un parcours isotrope) mais sur l'ensemble de toutes les séquences possibles. Succinctement, l'algorithme travaille en deux étapes : pré-calcul (une seule fois par taille) puis génération. Le pré-calcul est une étape automatique et calcule le nombre de séquences et sous-séquences possibles de taille n. Cette étape aide au calcul de fonctions de répartions pour guider la génération des séquences de lexèmes finales.

Nous allons générer 10 données aléatoires de taille 7, c'est à dire composées de 7 lexèmes. Pour cela, nous allons utiliser la classe Hoa\Compiler\Llk\Sampler\Uniform qui prend en premier argument notre grammaire, en deuxième le générateur de valeurs de lexèmes (ici Hoa\Regex\Visitor\Isototropic) et enfin la taille :

$sampler = new Hoa\Compiler\Llk\Sampler\Uniform(
    // Grammar.
    Hoa\Compiler\Llk\Llk::load(new Hoa\File\Read('Json.pp')),
    // Token sampler.
    new Hoa\Regex\Visitor\Isotropic(new Hoa\Math\Sampler\Random()),
    // Length.
    7
);

for ($i = 0; $i &lt; 10; ++$i) {
    echo $i, ' => ', $sampler->uniform(), "\n";
}

/**
 * Will output:
 *     0 => [ false , null , null ]
 *     1 => [ " l " , null ]
 *     2 => [ [ true ] , true ]
 *     3 => [ [ [ 4435 ] ] ]
 *     4 => [ [ [ 9366 ] ] ]
 *     5 => [ true , false , null ]
 *     6 => { " |h&lt;# " : false }
 *     7 => [ [ [ false ] ] ]
 *     8 => [ false , true , 7 ]
 *     9 => [ false , 5 , 79 ]
 */

Nous pouvons redéfinir la taille avec la méthode Hoa\Compiler\Llk\Sampler\Uniform::setLength. Nous aurons peut-être remarqué que certains opérateurs de répétition n'ont pas de bornes supérieures, comme + ou * ; dans ce cas, nous la définissons à n.

Génération exhaustive bornée

Le deuxième algorithme est celui de la génération exhaustive bornée. Cet algorithme génère toutes les séquences (c'est le côté exhaustif) de lexèmes de taille 1 jusqu'à n (c'est le caractère borné). Un aspect très intéressant de cet algorithme est que l'exhaustivité est une forme de preuve ! L'algorithme fonctionne comme un itérateur et est très simple à utiliser :

$sampler = new Hoa\Compiler\Llk\Sampler\BoundedExhaustive(
    // Grammar.
    Hoa\Compiler\Llk\Llk::load(new Hoa\File\Read('Json.pp')),
    // Token sampler.
    new Hoa\Regex\Visitor\Isotropic(new Hoa\Math\Sampler\Random()),
    // Length.
    7
);

foreach ($sampler as $i => $data) {
    echo $i, ' => ', $data, "\n";
}

/**
 * Will output:
 *     0 => true
 *     1 => false
 *     2 => null
 *     3 => " 8u2 "
 *     4 => { " ,M@aj{ " : true }
 *     5 => { " x`|V " : false }
 *     6 => { " NttB " : null }
 *     7 => { " eJWwA " : 0 }
 *     8 => [ true ]
 *     9 => [ true , true ]
 *     10 => [ true , true , true ]
 *     11 => [ true , true , false ]
 *     12 => [ true , true , null ]
 *     13 => [ true , true , 32 ]
 *     14 => [ true , false ]
 *     15 => [ true , false , true ]
 *     16 => [ true , false , false ]
 *     17 => [ true , false , null ]
 *     18 => [ true , false , 729 ]
 *     19 => [ true , null ]
 *     20 => [ true , null , true ]
 *     21 => [ true , null , false ]
 *     …
 *     157 => [ 780 , 01559 , 32 ]
 *     158 => 344
 */

A l'instar de l'algorithme précédent, nous pouvons redéfinir la borne maximum avec la méthode Hoa\Compiler\Llk\Sampler\BoundedExhaustive::setLength. Et les opérateurs de répétition sans borne supérieure utilisent n.

Génération basée sur la couverture

Le dernier algorithme est celui de la génération basée sur la couverture. Cet algorithme réduit l'explosion combinatoire rencontrée avec l'algorithme précédent mais l'objectif est tout autre : il va générer des séquences de lexèmes qui vont « activer » toutes les branches des règles de la grammaire. Une règle est dite couverte si et seulement si ses sous-règles sont toutes couvertes, et un lexème est dit couvert s'il a été utilisé dans une séquence. Pour assurer une diversité dans les séquences produites, les points de choix entre des sous-règles non couvertes sont résolus par tirages aléatoires. L'algorithme fonctionne également comme un itérateur :

$sampler = new Hoa\Compiler\Llk\Sampler\Coverage(
    // Grammar.
    Hoa\Compiler\Llk\Llk::load(new Hoa\File\Read('Json.pp')),
    // Token sampler.
    new Hoa\Regex\Visitor\Isotropic(new Hoa\Math\Sampler\Random())
);

foreach ($sampler as $i => $data) {
    echo $i, ' => ', $data, "\n";
}

/**
 * Will output:
 *     0 => true
 *     1 => { " )o?bz " : null , " %3W) " : [ false , 130 , " 6 " ] }
 *     2 => [ { " ny  " : true } ]
 *     3 => { " Ne;[3 " : [ true , true ] , " th: " : true , " C[8} " : true }
 */

Pour éviter l'explosion combinatoire et assurer la termination de l'algorithme, nous utilisons l'heuristique suivante sur les opérateurs de répétition : * répétera 0, 1 et 2 fois, + répétera 1 et 2 fois, et enfin {x,y} répétera x, x + 1, y - 1 et y fois. Cette heuristique trouve ses origines dans le test aux limites.

Nous remarquons dans notre exemple que 4 données sont générées et suffisent à couvrir l'ensemble de notre grammaire !

Comparaison entre les algorithmes

Voici quelques indices pour savoir quand utiliser tel ou tel autre algorithme.

Génération aléatoire et uniforme :
  • rapide pour des petites données, grande diversité dans les données et taille fixe ;
  • la phase de pré-calcul est exponentielle et donc longue bien que, ensuite, la génération soit très rapide.
Génération exhaustive bornée :
  • rapide pour des petites données et l'exhaustivité est efficace ;
  • nombre exponentiel de données.
Génération basée sur la couverture :
  • rapide pour des données de taille moyenne ou grande, et diversité des données ;
  • ne considère pas de taille.

Compilateur de compilateurs LL(1)

La documentation pour le compilateur LL(1), à travers la classe Hoa\Compiler\Ll1, n'est pas encore écrite. L'objectif est différent de Hoa\Compiler\Llk : il n'existe pas de langage intermédiaire, les automates sont codés en dur avec des tableaux et ce type de compilateurs est orienté haute performance. C'est pourquoi son comportement est monolithique.

Conclusion

Hoa\Compiler propose deux compilateurs de compilateurs : Hoa\Compiler\Llk et Hoa\Compiler\Ll1, afin de valider des données. Le langage PP permet d'écrire des grammaires algébriques de manière simple et naturelle. Le compilateur de compilateurs LL(k) est découpé en processus distincts ce qui le rend très hackable. Enfin, différents algorithmes permettent de générer des données à partir d'une grammaire selon le contexte d'utilisation.

line = $line; $this->column = $column; return; } /** * Get column. * * @return int */ public function getColumn() { return $this->column; } } line = $line; $this->column = $column; return; } /** * Get column. * * @return int */ public function getColumn() { return $this->column; } } 0, it means a link to a sub-automata (sub-automata index + 1). * * When we write our consume() method, it's just a simple switch receiving * an action. It receives only character. It's like a “goto” in our * compiler, and allows us to execute code when skiming through the graph. * * Negative/special actions are used to auto-fill or empty buffers. * E.g: -1 will fill the buffer 0, -2 will empty the buffer 0, * -3 will fill the buffer 1, -4 will empty the buffer 1, * -5 will fill the buffer 2, -6 will empty the buffer 2 etc. * A formula appears: * y = |x| * fill buffer (x - 2) / 2 if x & 1 = 1 * empty buffer (x - 1) / 2 if x & 1 = 0 * * Positive/link actions are used to make an epsilon-transition (or a link) * between two sub-automata. * Sub-automata are indexed from 0, but our links must be index + 1. Example * given: the sub-automata 0 in our example has a link to the sub-automata 1 * through OK[{] = 2. Take attention to this :-). * And another thing which must be carefully studying is the place of the * link. For example, with our sub-automata 1 (the big one), we have an * epsilon-transition to the sub-automata 2 through VA["] = 3. It means: * when we arrived in the state VA from the token ", we go in the * sub-automata 3 (the 2nd one actually). And when the linked sub-automata * has finished, we are back in our state and continue our parsing. Take * care of this :-). * * Finally, it is possible to combine positive and char action, separated by a comma. Thus: 7,f is equivalent to make an epsilon-transition to the * automata 7, then consume the action f. * * @var array */ protected $_actions = []; /** * Names of automata. */ protected $_names = []; /** * Recursive stack. * * @var array */ private $_stack = []; /** * Buffers. * * @var array */ protected $buffers = []; /** * Current token's line. * * @var int */ protected $line = 0; /** * Current token's column. * * @var int */ protected $column = 0; /** * Cache compiling result. * * @var array */ protected static $_cache = []; /** * Whether cache is enabled or not. * * @var bool */ protected static $_cacheEnabled = \true; /** * Singleton, and set parameters. * * @param array $skip Skip. * @param array $tokens Tokens. * @param array $states States. * @param array $terminal Terminal states. * @param array $transitions Transitions table. * @param array $actions Actions table. * @param array $names Names of automata. */ public function __construct(array $skip, array $tokens, array $states, array $terminal, array $transitions, array $actions, array $names = []) { $this->setSkip($skip); $this->setTokens($tokens); $this->setStates($states); $this->setTerminal($terminal); $this->setTransitions($transitions); $this->setActions($actions); $this->setNames($names); return; } /** * Compile a source code. * * @param string $in Source code. * @return void * @throws \Hoa\Compiler\Exception\FinalStateHasNotBeenReached * @throws \Hoa\Compiler\Exception\IllegalToken */ public function compile($in) { $cacheId = md5($in); if (\true === self::$_cacheEnabled && \true === array_key_exists($cacheId, self::$_cache)) { return self::$_cache[$cacheId]; } $d = 0; $c = 0; // current automata. $_skip = array_flip($this->_skip); $_tokens = array_flip($this->_tokens[$c]); $_states = array_flip($this->_states[$c]); $_actions = [$c => 0]; $nextChar = null; $nextToken = 0; $nextState = $_states['GO']; $nextAction = $_states['GO']; $this->line = $this->getInitialLine(); $this->column = 0; $this->buffers = []; $line = $this->line; $column = $this->column; $this->pre($in); for ($i = 0, $max = strlen($in); $i <= $max; $i++) { //echo "\n---\n\n"; // End of parsing (not automata). if ($i == $max) { while ($c > 0 && in_array($this->_states[$c][$nextState], $this->_terminal[$c])) { list($c, $nextState, ) = array_pop($this->_stack); } if (in_array($this->_states[$c][$nextState], $this->_terminal[$c]) && 0 === $c && \true === $this->end()) { //echo '*********** END REACHED **********' . "\n"; if (\true === self::$_cacheEnabled) { self::$_cache[$cacheId] = $this->getResult(); } return \true; } throw new \Hoa\Compiler\Exception\FinalStateHasNotBeenReached('End of code has been reached but not correctly; ' . 'maybe your program is not complete?', 0); } $nextChar = $in[$i]; // Skip. if (isset($_skip[$nextChar])) { if ("\n" === $nextChar) { $line++; $column = 0; } else { $column++; } continue; } else { $continue = \false; $handle = substr($in, $i); foreach ($_skip as $sk => $e) { if ($sk[0] != '#') { continue; } $sk = str_replace('#', '\#', substr($sk, 1)); if (0 != preg_match('#^(' . $sk . ')#u', $handle, $match)) { $strlen = strlen($match[1]); if ($strlen > 0) { if (\false !== $offset = strrpos($match[1], "\n")) { $column = $strlen - $offset - 1; } else { $column += $strlen; } $line += substr_count($match[1], "\n"); $i += $strlen - 1; $continue = \true; break; } } } if (\true === $continue) { continue; } } // Epsilon-transition. $epsilon = \false; while (array_key_exists($nextToken, $this->_actions[$c][$nextState]) && (is_array($this->_actions[$c][$nextState][$nextToken]) && 0 < ($foo = $this->_actions[$c][$nextState][$nextToken][0]) || is_int($this->_actions[$c][$nextState][$nextToken]) && 0 < $foo = $this->_actions[$c][$nextState][$nextToken])) { $epsilon = \true; if ($_actions[$c] == 0) { //echo '*** Change automata (up to ' . ($foo - 1) . ')' . "\n"; $this->_stack[$d] = [$c, $nextState, $nextToken]; end($this->_stack); $c = $foo - 1; $_tokens = array_flip($this->_tokens[$c]); $_states = array_flip($this->_states[$c]); $nextState = $_states['GO']; $nextAction = $_states['GO']; $nextToken = 0; $_actions[$c] = 0; $d++; } elseif ($_actions[$c] == 2) { $_actions[$c] = 0; break; } } if (\true === $epsilon) { $epsilon = \false; $nextToken = \false; } // Token. if (isset($_tokens[$nextChar])) { $token = $nextChar; $nextToken = $_tokens[$token]; if ("\n" === $nextChar) { $line++; $column = 0; } else { $column++; } } else { $nextToken = \false; $handle = substr($in, $i); foreach ($_tokens as $token => $e) { if ('#' !== $token[0]) { continue; } $ntoken = str_replace('#', '\#', substr($token, 1)); if (0 != preg_match('#^(' . $ntoken . ')#u', $handle, $match)) { $strlen = strlen($match[1]); if ($strlen > 0) { if (\false !== $offset = strrpos($match[1], "\n")) { $column = $strlen - $offset - 1; } else { $column += $strlen; } $nextChar = $match[1]; $nextToken = $e; $i += $strlen - 1; $line += substr_count($match[1], "\n"); break; } } } } /* echo '>>> Automata ' . $c . "\n" . '>>> Next state ' . $nextState . "\n" . '>>> Token ' . $token . "\n" . '>>> Next char ' . $nextChar . "\n"; */ // Got it! if (\false !== $nextToken) { if (is_array($this->_actions[$c][$nextState][$nextToken])) { $nextAction = $this->_actions[$c][$nextState][$nextToken][1]; } else { $nextAction = $this->_actions[$c][$nextState][$nextToken]; } $nextState = $_states[$this->_transitions[$c][$nextState][$nextToken]]; } // Oh :-(. if (\false === $nextToken || $nextState === $_states['__']) { $pop = array_pop($this->_stack); $d--; // Go back to a parent automata. if (in_array($this->_states[$c][$nextState], $this->_terminal[$c]) && null !== $pop || $nextState === $_states['__'] && null !== $pop) { //echo '!!! Change automata (down)' . "\n"; list($c, $nextState, $nextToken) = $pop; $_actions[$c] = 2; $i -= strlen($nextChar); $_tokens = array_flip($this->_tokens[$c]); $_states = array_flip($this->_states[$c]); /* echo '!!! Automata ' . $c . "\n" . '!!! Next state ' . $nextState . "\n"; */ continue; } $error = explode("\n", $in); $error = $error[$this->line]; throw new \Hoa\Compiler\Exception\IllegalToken('Illegal token at line ' . ($this->line + 1) . ' and column ' . ($this->column + 1) . "\n" . $error . "\n" . str_repeat(' ', $this->column) . '↑', 1, [], $this->line + 1, $this->column + 1); } $this->line = $line; $this->column = $column; //echo '<<< Next state ' . $nextState . "\n"; $this->buffers[-1] = $nextChar; // Special actions. if ($nextAction < 0) { $buffer = abs($nextAction); if (($buffer & 1) == 0) { $this->buffers[($buffer - 2) / 2] = null; } else { $buffer = ($buffer - 1) / 2; if (!isset($this->buffers[$buffer])) { $this->buffers[$buffer] = null; } $this->buffers[$buffer] .= $nextChar; } continue; } if (0 !== $nextAction) { $this->consume($nextAction); } } return; } /** * Consume actions. * Please, see the actions table definition to learn more. * * @param int $action Action. * @return void */ abstract protected function consume($action); /** * Compute source code before compiling it. * * @param string &$in Source code. * @return void */ protected function pre(&$in) { return; } /** * Verify compiler state when ending the source code. * * @return bool */ protected function end() { return \true; } /** * Get the result of the compiling. * * @return mixed */ abstract public function getResult(); /** * Set initial line. * * @param int $line Initial line. * @return int */ public function setInitialLine($line) { $old = $this->_initialLine; $this->_initialLine = $line; return $old; } /** * Set tokens to skip. * * @param array $skip Skip. * @return array */ public function setSkip(array $skip) { $old = $this->_skip; $this->_skip = $skip; return $old; } /** * Set tokens. * * @param array $tokens Tokens. * @return array */ public function setTokens(array $tokens) { $old = $this->_tokens; $this->_tokens = $tokens; return $old; } /** * Set states. * * @param array $states States. * @return array */ public function setStates(array $states) { $old = $this->_states; $this->_states = $states; return $old; } /** * Set terminal states. * * @param array $terminal Terminal states. * @return array */ public function setTerminal(array $terminal) { $old = $this->_terminal; $this->_terminal = $terminal; return $old; } /** * Set transitions table. * * @param array $transitions Transitions table. * @return array */ public function setTransitions(array $transitions) { $old = $this->_transitions; $this->_transitions = $transitions; return $old; } /** * Set actions table. * * @param array $actions Actions table. * @return array */ public function setActions(array $actions) { foreach ($actions as $e => $automata) { foreach ($automata as $i => $state) { foreach ($state as $j => $token) { if (0 != preg_match('#^(\d+),(.*)$#', $token, $matches)) { $actions[$e][$i][$j] = [(int) $matches[1], $matches[2]]; } } } } $old = $this->_actions; $this->_actions = $actions; return $old; } /** * Set names of automata. * * @param array $names Names of automata. * @return array */ public function setNames(array $names) { $old = $this->_names; $this->_names = $names; return $old; } /** * Get initial line. * * @return int */ public function getInitialLine() { return $this->_initialLine; } /** * Get skip tokens. * * @return array */ public function getSkip() { return $this->_skip; } /** * Get tokens. * * @return array */ public function getTokens() { return $this->_tokens; } /** * Get states. * * @return array */ public function getStates() { return $this->_states; } /** * Get terminal states. * * @return array */ public function getTerminal() { return $this->_terminal; } /** * Get transitions table. * * @return array */ public function getTransitions() { return $this->_transitions; } /** * Get actions table. * * @return array */ public function getActions() { return $this->_actions; } /** * Get names of automata. * * @return array */ public function getNames() { return $this->_names; } /** * Enable cache * * @return bool */ public static function enableCache() { $old = self::$_cacheEnabled; self::$_cacheEnabled = \true; return $old; } /** * Disable cache * * @return bool */ public static function disableCache() { $old = self::$_cacheEnabled; self::$_cacheEnabled = \false; return $old; } /** * Transform automatas into DOT language. * * @return void */ public function __toString() { $out = 'digraph ' . str_replace('\\', '', get_class($this)) . ' {' . "\n" . ' rankdir=LR;' . "\n" . ' label="Automata of ' . str_replace('\\', '\\\\', get_class($this)) . '";'; $transitions = array_reverse($this->_transitions, \true); foreach ($transitions as $e => $automata) { $out .= "\n\n" . ' subgraph cluster_' . $e . ' {' . "\n" . ' label="Automata #' . $e . (isset($this->_names[$e]) ? ' (' . str_replace('"', '\"', $this->_names[$e]) . ')' : '') . '";' . "\n"; if (!empty($this->_terminal[$e])) { $out .= ' node[shape=doublecircle] "' . $e . '_' . implode('" "' . $e . '_', $this->_terminal[$e]) . '";' . "\n"; } $out .= ' node[shape=circle];' . "\n"; foreach ($this->_states[$e] as $i => $state) { $name = []; $label = $state; if (__ != $state) { foreach ($this->_transitions[$e][$i] as $j => $foo) { $ep = $this->_actions[$e][$i][$j]; if (is_array($ep)) { $ep = $ep[0]; } if (is_int($ep)) { $ep--; if (0 < $ep && !isset($name[$ep])) { $name[$ep] = $ep; } } } if (!empty($name)) { $label .= ' (' . implode(', ', $name) . ')'; } $out .= ' "' . $e . '_' . $state . '" ' . '[label="' . $label . '"];' . "\n"; } } foreach ($automata as $i => $transition) { $transition = array_reverse($transition, \true); foreach ($transition as $j => $state) { if (__ != $this->_states[$e][$i] && __ != $state) { $label = str_replace('\\', '\\\\', $this->_tokens[$e][$j]); $label = str_replace('"', '\"', $label); if ('#' === $label[0]) { $label = substr($label, 1); } $out .= ' "' . $e . '_' . $this->_states[$e][$i] . '" -> "' . $e . '_' . $state . '"' . ' [label="' . $label . '"];' . "\n"; } } } $out .= ' node[shape=point,label=""] "' . $e . '_";' . "\n" . ' "' . $e . '_" -> "' . $e . '_GO";' . "\n" . ' }'; } $out .= "\n" . '}' . "\n"; return $out; } } _pcreOptions .= 'u'; } return; } /** * Text tokenizer: splits the text in parameter in an ordered array of * tokens. * * @param string $text Text to tokenize. * @param array $tokens Tokens to be returned. * @return \Generator * @throws \Hoa\Compiler\Exception\UnrecognizedToken */ public function lexMe($text, array $tokens) { $this->_text = $text; $this->_tokens = $tokens; $this->_nsStack = null; $offset = 0; $maxOffset = strlen($this->_text); $this->_lexerState = 'default'; $stack = \false; foreach ($this->_tokens as &$tokens) { $_tokens = []; foreach ($tokens as $fullLexeme => $regex) { if (\false === strpos($fullLexeme, ':')) { $_tokens[$fullLexeme] = [$regex, null]; continue; } list($lexeme, $namespace) = explode(':', $fullLexeme, 2); $stack |= '__shift__' === substr($namespace, 0, 9); unset($tokens[$fullLexeme]); $_tokens[$lexeme] = [$regex, $namespace]; } $tokens = $_tokens; } if (\true == $stack) { $this->_nsStack = new \SplStack(); } while ($offset < $maxOffset) { $nextToken = $this->nextToken($offset); if (null === $nextToken) { throw new Compiler\Exception\UnrecognizedToken('Unrecognized token "%s" at line 1 and column %d:' . "\n" . '%s' . "\n" . str_repeat(' ', mb_strlen(substr($text, 0, $offset))) . '↑', 0, [mb_substr(substr($text, $offset), 0, 1), $offset + 1, $text], 1, $offset); } if (\true === $nextToken['keep']) { $nextToken['offset'] = $offset; yield $nextToken; } $offset += strlen($nextToken['value']); } yield ['token' => 'EOF', 'value' => 'EOF', 'length' => 0, 'namespace' => 'default', 'keep' => \true, 'offset' => $offset]; } /** * Compute the next token recognized at the beginning of the string. * * @param int $offset Offset. * @return array * @throws \Hoa\Compiler\Exception\Lexer */ protected function nextToken($offset) { $tokenArray =& $this->_tokens[$this->_lexerState]; foreach ($tokenArray as $lexeme => $bucket) { list($regex, $nextState) = $bucket; if (null === $nextState) { $nextState = $this->_lexerState; } $out = $this->matchLexeme($lexeme, $regex, $offset); if (null !== $out) { $out['namespace'] = $this->_lexerState; $out['keep'] = 'skip' !== $lexeme; if ($nextState !== $this->_lexerState) { $shift = \false; if (null !== $this->_nsStack && 0 !== preg_match('#^__shift__(?:\s*\*\s*(\d+))?$#', $nextState, $matches)) { $i = isset($matches[1]) ? intval($matches[1]) : 1; if ($i > $c = count($this->_nsStack)) { throw new Compiler\Exception\Lexer('Cannot shift namespace %d-times, from token ' . '%s in namespace %s, because the stack ' . 'contains only %d namespaces.', 1, [$i, $lexeme, $this->_lexerState, $c]); } while (1 <= $i--) { $previousNamespace = $this->_nsStack->pop(); } $nextState = $previousNamespace; $shift = \true; } if (!isset($this->_tokens[$nextState])) { throw new Compiler\Exception\Lexer('Namespace %s does not exist, called by token %s ' . 'in namespace %s.', 2, [$nextState, $lexeme, $this->_lexerState]); } if (null !== $this->_nsStack && \false === $shift) { $this->_nsStack[] = $this->_lexerState; } $this->_lexerState = $nextState; } return $out; } } return null; } /** * Check if a given lexeme is matched at the beginning of the text. * * @param string $lexeme Name of the lexeme. * @param string $regex Regular expression describing the lexeme. * @param int $offset Offset. * @return array * @throws \Hoa\Compiler\Exception\Lexer */ protected function matchLexeme($lexeme, $regex, $offset) { $_regex = str_replace('#', '\#', $regex); $preg = preg_match('#\G(?|' . $_regex . ')#' . $this->_pcreOptions, $this->_text, $matches, 0, $offset); if (0 === $preg || $preg === \false) { return null; } if ('' === $matches[0]) { throw new Compiler\Exception\Lexer('A lexeme must not match an empty value, which is the ' . 'case of "%s" (%s).', 3, [$lexeme, $regex]); } return ['token' => $lexeme, 'value' => $matches[0], 'length' => mb_strlen($matches[0])]; } } readAll(); if (empty($pp)) { $message = 'The grammar is empty'; if ($stream instanceof Stream\IStream\Pointable) { if (0 < $stream->tell()) { $message .= ': The stream ' . $stream->getStreamName() . ' is pointable and not rewinded, maybe it ' . 'could be the reason'; } else { $message .= ': Nothing to read on the stream ' . $stream->getStreamName(); } } throw new Compiler\Exception($message . '.', 0); } static::parsePP($pp, $tokens, $rawRules, $pragmas, $stream->getStreamName()); $ruleAnalyzer = new \Hoa\Compiler\Llk\Rule\Analyzer($tokens); $rules = $ruleAnalyzer->analyzeRules($rawRules); return new \Hoa\Compiler\Llk\Parser($tokens, $rules, $pragmas); } /** * Save in-memory parser to PHP code. * The generated PHP code will load the same in-memory parser. The state * will be reset. The parser will be saved as a class, named after * `$className`. To retrieve the parser, one must instanciate this class. * * @param \Hoa\Compiler\Llk\Parser $parser Parser to save. * @param string $className Parser classname. * @return string */ public static function save(\Hoa\Compiler\Llk\Parser $parser, $className) { $out = null; $outTokens = null; $outRules = null; $outPragmas = null; $outExtra = null; $escapeRuleName = function ($ruleName) use ($parser) { if (\true == $parser->getRule($ruleName)->isTransitional()) { return $ruleName; } return '\'' . $ruleName . '\''; }; foreach ($parser->getTokens() as $namespace => $tokens) { $outTokens .= ' \'' . $namespace . '\' => [' . "\n"; foreach ($tokens as $tokenName => $tokenValue) { $outTokens .= ' \'' . $tokenName . '\' => \'' . str_replace(['\'', '\\\\'], ['\\\'', '\\\\\\'], $tokenValue) . '\',' . "\n"; } $outTokens .= ' ],' . "\n"; } foreach ($parser->getRules() as $rule) { $arguments = []; // Name. $arguments['name'] = $escapeRuleName($rule->getName()); if ($rule instanceof \Hoa\Compiler\Llk\Rule\Token) { // Token name. $arguments['tokenName'] = '\'' . $rule->getTokenName() . '\''; } else { if ($rule instanceof \Hoa\Compiler\Llk\Rule\Repetition) { // Minimum. $arguments['min'] = $rule->getMin(); // Maximum. $arguments['max'] = $rule->getMax(); } // Children. $ruleChildren = $rule->getChildren(); if (null === $ruleChildren) { $arguments['children'] = 'null'; } elseif (\false === is_array($ruleChildren)) { $arguments['children'] = $escapeRuleName($ruleChildren); } else { $arguments['children'] = '[' . implode(', ', array_map($escapeRuleName, $ruleChildren)) . ']'; } } // Node ID. $nodeId = $rule->getNodeId(); if (null === $nodeId) { $arguments['nodeId'] = 'null'; } else { $arguments['nodeId'] = '\'' . $nodeId . '\''; } if ($rule instanceof \Hoa\Compiler\Llk\Rule\Token) { // Unification. $arguments['unification'] = $rule->getUnificationIndex(); // Kept. $arguments['kept'] = $rule->isKept() ? 'true' : 'false'; } // Default node ID. if (null !== $defaultNodeId = $rule->getDefaultId()) { $defaultNodeOptions = $rule->getDefaultOptions(); if (!empty($defaultNodeOptions)) { $defaultNodeId .= ':' . implode('', $defaultNodeOptions); } $outExtra .= "\n" . ' $this->getRule(' . $arguments['name'] . ')->setDefaultId(' . '\'' . $defaultNodeId . '\'' . ');'; } // PP representation. if (null !== $ppRepresentation = $rule->getPPRepresentation()) { $outExtra .= "\n" . ' $this->getRule(' . $arguments['name'] . ')->setPPRepresentation(' . '\'' . str_replace('\'', '\\\'', $ppRepresentation) . '\'' . ');'; } $outRules .= "\n" . ' ' . $arguments['name'] . ' => new \\' . get_class($rule) . '(' . implode(', ', $arguments) . '),'; } foreach ($parser->getPragmas() as $pragmaName => $pragmaValue) { $outPragmas .= "\n" . ' \'' . $pragmaName . '\' => ' . (is_bool($pragmaValue) ? \true === $pragmaValue ? 'true' : 'false' : (is_int($pragmaValue) ? $pragmaValue : '\'' . $pragmaValue . '\'')) . ','; } $out .= 'class ' . $className . ' extends \Hoa\Compiler\Llk\Parser' . "\n" . '{' . "\n" . ' public function __construct()' . "\n" . ' {' . "\n" . ' parent::__construct(' . "\n" . ' [' . "\n" . $outTokens . ' ],' . "\n" . ' [' . $outRules . "\n" . ' ],' . "\n" . ' [' . $outPragmas . "\n" . ' ]' . "\n" . ' );' . "\n" . $outExtra . "\n" . ' }' . "\n" . '}' . "\n"; return $out; } /** * Parse the grammar description language. * * @param string $pp Grammar description. * @param array $tokens Extracted tokens. * @param array $rules Extracted raw rules. * @param array $pragmas Extracted raw pragmas. * @param string $streamName The name of the stream containing the grammar. * @return void * @throws \Hoa\Compiler\Exception */ public static function parsePP($pp, &$tokens, &$rules, &$pragmas, $streamName) { $lines = explode("\n", $pp); $pragmas = []; $tokens = ['default' => []]; $rules = []; for ($i = 0, $m = count($lines); $i < $m; ++$i) { $line = rtrim($lines[$i]); if (0 === strlen($line) || '//' == substr($line, 0, 2)) { continue; } if ('%' == $line[0]) { if (0 !== preg_match('#^%pragma\h+([^\h]+)\h+(.*)$#u', $line, $matches)) { switch ($matches[2]) { case 'true': $pragmaValue = \true; break; case 'false': $pragmaValue = \false; break; default: if (\true === ctype_digit($matches[2])) { $pragmaValue = intval($matches[2]); } else { $pragmaValue = $matches[2]; } } $pragmas[$matches[1]] = $pragmaValue; } elseif (0 !== preg_match('#^%skip\h+(?:([^:]+):)?([^\h]+)\h+(.*)$#u', $line, $matches)) { if (empty($matches[1])) { $matches[1] = 'default'; } if (!isset($tokens[$matches[1]])) { $tokens[$matches[1]] = []; } if (!isset($tokens[$matches[1]]['skip'])) { $tokens[$matches[1]]['skip'] = $matches[3]; } else { $tokens[$matches[1]]['skip'] = '(?:' . $tokens[$matches[1]]['skip'] . '|' . $matches[3] . ')'; } } elseif (0 !== preg_match('#^%token\h+(?:([^:]+):)?([^\h]+)\h+(.*?)(?:\h+->\h+(.*))?$#u', $line, $matches)) { if (empty($matches[1])) { $matches[1] = 'default'; } if (isset($matches[4]) && !empty($matches[4])) { $matches[2] = $matches[2] . ':' . $matches[4]; } if (!isset($tokens[$matches[1]])) { $tokens[$matches[1]] = []; } $tokens[$matches[1]][$matches[2]] = $matches[3]; } else { throw new Compiler\Exception('Unrecognized instructions:' . "\n" . ' %s' . "\n" . 'in file %s at line %d.', 1, [$line, $streamName, $i + 1]); } continue; } $ruleName = substr($line, 0, -1); $rule = null; ++$i; while ($i < $m && isset($lines[$i][0]) && (' ' === $lines[$i][0] || "\t" === $lines[$i][0] || '//' === substr($lines[$i], 0, 2))) { if ('//' === substr($lines[$i], 0, 2)) { ++$i; continue; } $rule .= ' ' . trim($lines[$i++]); } if (isset($lines[$i][0])) { --$i; } $rules[$ruleName] = $rule; } return; } } /** * Flex entity. */ Consistency::flexEntity('Hoa\Compiler\Llk\Llk'); // // 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\Compiler\Llk. // // Provide grammar for the LL(k) parser. // // @copyright Copyright © 2007-2017, Hoa community. // @license New BSD License // %skip space \s %token or \| %token zero_or_one \? %token one_or_more \+ %token zero_or_more \* %token n_to_m \{[0-9]+,[0-9]+\} %token zero_to_m \{,[0-9]+\} %token n_or_more \{[0-9]+,\} %token exactly_n \{[0-9]+\} %token token [a-zA-Z_][a-zA-Z0-9_]* %token skipped :: %token kept_ < %token _kept > %token named \(\) %token node #[a-zA-Z_][a-zA-Z0-9_]*(:[mM])? %token capturing_ \( %token _capturing \) %token unification_ \[ %token unification [0-9]+ %token _unification \] #rule: choice() choice: concatenation() ( ::or:: concatenation() #choice )* concatenation: repetition() ( repetition() #concatenation )* repetition: simple() ( quantifier() #repetition )? ? simple: ::capturing_:: choice() ::_capturing:: | ::skipped:: ( ::unification_:: ::_unification:: )? ::skipped:: #skipped | ::kept_:: ( ::unification_:: ::_unification:: )? ::_kept:: #kept | ::named:: quantifier: | | | | | token regex), to be defined in * precedence order. * * @var array */ protected $_tokens = null; /** * Rules, to be defined as associative array, name => Rule object. * * @var array */ protected $_rules = null; /** * Lexer iterator. * * @var \Hoa\Iterator\Lookahead */ protected $_tokenSequence = null; /** * Possible token causing an error. * * @var array */ protected $_errorToken = null; /** * Trace of activated rules. * * @var array */ protected $_trace = []; /** * Stack of todo list. * * @var array */ protected $_todo = null; /** * AST. * * @var \Hoa\Compiler\Llk\TreeNode */ protected $_tree = null; /** * Current depth while building the trace. * * @var int */ protected $_depth = -1; /** * Construct the parser. * * @param array $tokens Tokens. * @param array $rules Rules. * @param array $pragmas Pragmas. */ public function __construct(array $tokens = [], array $rules = [], array $pragmas = []) { $this->_tokens = $tokens; $this->_rules = $rules; $this->_pragmas = $pragmas; return; } /** * Parse :-). * * @param string $text Text to parse. * @param string $rule The axiom, i.e. root rule. * @param bool $tree Whether build tree or not. * @return mixed * @throws \Hoa\Compiler\Exception\UnexpectedToken */ public function parse($text, $rule = null, $tree = \true) { $k = 1024; if (isset($this->_pragmas['parser.lookahead'])) { $k = max(0, intval($this->_pragmas['parser.lookahead'])); } $lexer = new \Hoa\Compiler\Llk\Lexer($this->_pragmas); $this->_tokenSequence = new Iterator\Buffer($lexer->lexMe($text, $this->_tokens), $k); $this->_tokenSequence->rewind(); $this->_errorToken = null; $this->_trace = []; $this->_todo = []; if (\false === array_key_exists($rule ?? '', $this->_rules)) { $rule = $this->getRootRule(); } $closeRule = new \Hoa\Compiler\Llk\Rule\Ekzit($rule, 0); $openRule = new \Hoa\Compiler\Llk\Rule\Entry($rule, 0, [$closeRule]); $this->_todo = [$closeRule, $openRule]; do { $out = $this->unfold(); if (null !== $out && 'EOF' === $this->_tokenSequence->current()['token']) { break; } if (\false === $this->backtrack()) { $token = $this->_errorToken; if (null === $this->_errorToken) { $token = $this->_tokenSequence->current(); } $offset = $token['offset']; $line = 1; $column = 1; if (!empty($text)) { if (0 === $offset) { $leftnl = 0; } else { $leftnl = strrpos($text, "\n", -(strlen($text) - $offset) - 1) ?: 0; } $rightnl = strpos($text, "\n", $offset); $line = substr_count($text, "\n", 0, $leftnl + 1) + 1; $column = $offset - $leftnl + (0 === $leftnl); if (\false !== $rightnl) { $text = trim(substr($text, $leftnl, $rightnl - $leftnl), "\n"); } } throw new Compiler\Exception\UnexpectedToken('Unexpected token "%s" (%s) at line %d and column %d:' . "\n" . '%s' . "\n" . str_repeat(' ', $column - 1) . '↑', 0, [$token['value'], $token['token'], $line, $column, $text], $line, $column); } } while (\true); if (\false === $tree) { return \true; } $tree = $this->_buildTree(); if (!$tree instanceof \Hoa\Compiler\Llk\TreeNode) { throw new Compiler\Exception('Parsing error: cannot build AST, the trace is corrupted.', 1); } return $this->_tree = $tree; } /** * Unfold trace. * * @return mixed */ protected function unfold() { while (0 < count($this->_todo)) { $rule = array_pop($this->_todo); if ($rule instanceof \Hoa\Compiler\Llk\Rule\Ekzit) { $rule->setDepth($this->_depth); $this->_trace[] = $rule; if (\false === $rule->isTransitional()) { --$this->_depth; } } else { $ruleName = $rule->getRule(); $next = $rule->getData(); $zeRule = $this->_rules[$ruleName]; $out = $this->_parse($zeRule, $next); if (\false === $out && \false === $this->backtrack()) { return null; } } } return \true; } /** * Parse current rule. * * @param \Hoa\Compiler\Llk\Rule $zeRule Current rule. * @param int $next Next rule index. * @return bool */ protected function _parse(\Hoa\Compiler\Llk\Rule $zeRule, $next) { if ($zeRule instanceof \Hoa\Compiler\Llk\Rule\Token) { $name = $this->_tokenSequence->current()['token']; if ($zeRule->getTokenName() !== $name) { return \false; } $value = $this->_tokenSequence->current()['value']; if (0 <= $unification = $zeRule->getUnificationIndex()) { for ($skip = 0, $i = count($this->_trace) - 1; $i >= 0; --$i) { $trace = $this->_trace[$i]; if ($trace instanceof \Hoa\Compiler\Llk\Rule\Entry) { if (\false === $trace->isTransitional()) { if ($trace->getDepth() <= $this->_depth) { break; } --$skip; } } elseif ($trace instanceof \Hoa\Compiler\Llk\Rule\Ekzit && \false === $trace->isTransitional()) { $skip += $trace->getDepth() > $this->_depth; } if (0 < $skip) { continue; } if ($trace instanceof \Hoa\Compiler\Llk\Rule\Token && $unification === $trace->getUnificationIndex() && $value !== $trace->getValue()) { return \false; } } } $namespace = $this->_tokenSequence->current()['namespace']; $zzeRule = clone $zeRule; $zzeRule->setValue($value); $zzeRule->setNamespace($namespace); if (isset($this->_tokens[$namespace][$name])) { $zzeRule->setRepresentation($this->_tokens[$namespace][$name]); } else { foreach ($this->_tokens[$namespace] as $_name => $regex) { if (\false === $pos = strpos($_name, ':')) { continue; } $_name = substr($_name, 0, $pos); if ($_name === $name) { break; } } $zzeRule->setRepresentation($regex); } array_pop($this->_todo); $this->_trace[] = $zzeRule; $this->_tokenSequence->next(); $this->_errorToken = $this->_tokenSequence->current(); return \true; } elseif ($zeRule instanceof \Hoa\Compiler\Llk\Rule\Concatenation) { if (\false === $zeRule->isTransitional()) { ++$this->_depth; } $this->_trace[] = new \Hoa\Compiler\Llk\Rule\Entry($zeRule->getName(), 0, null, $this->_depth); $children = $zeRule->getChildren(); for ($i = count($children) - 1; $i >= 0; --$i) { $nextRule = $children[$i]; $this->_todo[] = new \Hoa\Compiler\Llk\Rule\Ekzit($nextRule, 0); $this->_todo[] = new \Hoa\Compiler\Llk\Rule\Entry($nextRule, 0); } return \true; } elseif ($zeRule instanceof \Hoa\Compiler\Llk\Rule\Choice) { $children = $zeRule->getChildren(); if ($next >= count($children)) { return \false; } if (\false === $zeRule->isTransitional()) { ++$this->_depth; } $this->_trace[] = new \Hoa\Compiler\Llk\Rule\Entry($zeRule->getName(), $next, $this->_todo, $this->_depth); $nextRule = $children[$next]; $this->_todo[] = new \Hoa\Compiler\Llk\Rule\Ekzit($nextRule, 0); $this->_todo[] = new \Hoa\Compiler\Llk\Rule\Entry($nextRule, 0); return \true; } elseif ($zeRule instanceof \Hoa\Compiler\Llk\Rule\Repetition) { $nextRule = $zeRule->getChildren(); if (0 === $next) { $name = $zeRule->getName(); $min = $zeRule->getMin(); if (\false === $zeRule->isTransitional()) { ++$this->_depth; } $this->_trace[] = new \Hoa\Compiler\Llk\Rule\Entry($name, $min, null, $this->_depth); array_pop($this->_todo); $this->_todo[] = new \Hoa\Compiler\Llk\Rule\Ekzit($name, $min, $this->_todo); for ($i = 0; $i < $min; ++$i) { $this->_todo[] = new \Hoa\Compiler\Llk\Rule\Ekzit($nextRule, 0); $this->_todo[] = new \Hoa\Compiler\Llk\Rule\Entry($nextRule, 0); } return \true; } else { $max = $zeRule->getMax(); if (-1 != $max && $next > $max) { return \false; } $this->_todo[] = new \Hoa\Compiler\Llk\Rule\Ekzit($zeRule->getName(), $next, $this->_todo); $this->_todo[] = new \Hoa\Compiler\Llk\Rule\Ekzit($nextRule, 0); $this->_todo[] = new \Hoa\Compiler\Llk\Rule\Entry($nextRule, 0); return \true; } } return \false; } /** * Backtrack the trace. * * @return bool */ protected function backtrack() { $found = \false; do { $last = array_pop($this->_trace); if ($last instanceof \Hoa\Compiler\Llk\Rule\Entry) { $zeRule = $this->_rules[$last->getRule()]; $found = $zeRule instanceof \Hoa\Compiler\Llk\Rule\Choice; } elseif ($last instanceof \Hoa\Compiler\Llk\Rule\Ekzit) { $zeRule = $this->_rules[$last->getRule()]; $found = $zeRule instanceof \Hoa\Compiler\Llk\Rule\Repetition; } elseif ($last instanceof \Hoa\Compiler\Llk\Rule\Token) { $this->_tokenSequence->previous(); if (\false === $this->_tokenSequence->valid()) { return \false; } } } while (0 < count($this->_trace) && \false === $found); if (\false === $found) { return \false; } $rule = $last->getRule(); $next = $last->getData() + 1; $this->_depth = $last->getDepth(); $this->_todo = $last->getTodo(); $this->_todo[] = new \Hoa\Compiler\Llk\Rule\Entry($rule, $next); return \true; } /** * Build AST from trace. * Walk through the trace iteratively and recursively. * * @param int $i Current trace index. * @param array &$children Collected children. * @return \Hoa\Compiler\Llk\TreeNode */ protected function _buildTree($i = 0, &$children = []) { $max = count($this->_trace); while ($i < $max) { $trace = $this->_trace[$i]; if ($trace instanceof \Hoa\Compiler\Llk\Rule\Entry) { $ruleName = $trace->getRule(); $rule = $this->_rules[$ruleName]; $isRule = \false === $trace->isTransitional(); $nextTrace = $this->_trace[$i + 1]; $id = $rule->getNodeId(); // Optimization: Skip empty trace sequence. if ($nextTrace instanceof \Hoa\Compiler\Llk\Rule\Ekzit && $ruleName == $nextTrace->getRule()) { $i += 2; continue; } if (\true === $isRule) { $children[] = $ruleName; } if (null !== $id) { $children[] = ['id' => $id, 'options' => $rule->getNodeOptions()]; } $i = $this->_buildTree($i + 1, $children); if (\false === $isRule) { continue; } $handle = []; $cId = null; $cOptions = []; do { $pop = array_pop($children); if (\true === is_object($pop)) { $handle[] = $pop; } elseif (\true === is_array($pop) && null === $cId) { $cId = $pop['id']; $cOptions = $pop['options']; } elseif ($ruleName == $pop) { break; } } while (null !== $pop); if (null === $cId) { $cId = $rule->getDefaultId(); $cOptions = $rule->getDefaultOptions(); } if (null === $cId) { for ($j = count($handle) - 1; $j >= 0; --$j) { $children[] = $handle[$j]; } continue; } if (\true === in_array('M', $cOptions) && \true === $this->mergeTree($children, $handle, $cId)) { continue; } if (\true === in_array('m', $cOptions) && \true === $this->mergeTree($children, $handle, $cId, \true)) { continue; } $cTree = new \Hoa\Compiler\Llk\TreeNode($id ?: $cId); foreach ($handle as $child) { $child->setParent($cTree); $cTree->prependChild($child); } $children[] = $cTree; } elseif ($trace instanceof \Hoa\Compiler\Llk\Rule\Ekzit) { return $i + 1; } else { if (\false === $trace->isKept()) { ++$i; continue; } $child = new \Hoa\Compiler\Llk\TreeNode('token', ['token' => $trace->getTokenName(), 'value' => $trace->getValue(), 'namespace' => $trace->getNamespace()]); $children[] = $child; ++$i; } } return $children[0]; } /** * Try to merge directly children into an existing node. * * @param array &$children Current children being gathering. * @param array &$handle Children of the new node. * @param string $cId Node ID. * @param bool $recursive Whether we should merge recursively or * not. * @return bool */ protected function mergeTree(&$children, &$handle, $cId, $recursive = \false) { end($children); $last = current($children); if (!is_object($last)) { return \false; } if ($cId !== $last->getId()) { return \false; } if (\true === $recursive) { foreach ($handle as $child) { $this->mergeTreeRecursive($last, $child); } return \true; } foreach ($handle as $child) { $last->appendChild($child); $child->setParent($last); } return \true; } /** * Merge recursively. * Please, see self::mergeTree() to know the context. * * @param \Hoa\Compiler\Llk\TreeNode $node Node that receives. * @param \Hoa\Compiler\Llk\TreeNode $newNode Node to merge. * @return void */ protected function mergeTreeRecursive(\Hoa\Compiler\Llk\TreeNode $node, \Hoa\Compiler\Llk\TreeNode $newNode) { $nNId = $newNode->getId(); if ('token' === $nNId) { $node->appendChild($newNode); $newNode->setParent($node); return; } $children = $node->getChildren(); end($children); $last = current($children); if ($last->getId() !== $nNId) { $node->appendChild($newNode); $newNode->setParent($node); return; } foreach ($newNode->getChildren() as $child) { $this->mergeTreeRecursive($last, $child); } return; } /** * Get AST. * * @return \Hoa\Compiler\Llk\TreeNode */ public function getTree() { return $this->_tree; } /** * Get trace. * * @return array */ public function getTrace() { return $this->_trace; } /** * Get pragmas. * * @return array */ public function getPragmas() { return $this->_pragmas; } /** * Get tokens. * * @return array */ public function getTokens() { return $this->_tokens; } /** * Get the lexer iterator. * * @return \Hoa\Iterator\Buffer */ public function getTokenSequence() { return $this->_tokenSequence; } /** * Get rule by name. * * @param string $name Rule name. * @return \Hoa\Compiler\Llk\Rule */ public function getRule($name) { if (!isset($this->_rules[$name])) { return null; } return $this->_rules[$name]; } /** * Get rules. * * @return array */ public function getRules() { return $this->_rules; } /** * Get root rule. * * @return string */ public function getRootRule() { foreach ($this->_rules as $rule => $_) { if (!is_int($rule)) { break; } } return $rule; } } ['skip' => '\s', 'or' => '\|', 'zero_or_one' => '\?', 'one_or_more' => '\+', 'zero_or_more' => '\*', 'n_to_m' => '\{[0-9]+,[0-9]+\}', 'zero_to_m' => '\{,[0-9]+\}', 'n_or_more' => '\{[0-9]+,\}', 'exactly_n' => '\{[0-9]+\}', 'skipped' => '::[a-zA-Z_][a-zA-Z0-9_]*(\[\d+\])?::', 'kept' => '<[a-zA-Z_][a-zA-Z0-9_]*(\[\d+\])?>', 'named' => '[a-zA-Z_][a-zA-Z0-9_]*\(\)', 'node' => '#[a-zA-Z_][a-zA-Z0-9_]*(:[mM])?', 'capturing_' => '\(', '_capturing' => '\)']]; /** * Lexer iterator. * * @var \Hoa\Iterator\Lookahead */ protected $_lexer = null; /** * Tokens representing rules. * * @var array */ protected $_tokens = null; /** * Rules. * * @var array */ protected $_rules = null; /** * Rule name being analyzed. * * @var string */ private $_ruleName = null; /** * Parsed rules. * * @var array */ protected $_parsedRules = null; /** * Counter to auto-name transitional rules. * * @var int */ protected $_transitionalRuleCounter = 0; /** * Constructor. * * @param array $tokens Tokens. */ public function __construct(array $tokens) { $this->_tokens = $tokens; return; } /** * Build the analyzer of the rules (does not analyze the rules). * * @param array $rules Rule to be analyzed. * @return void * @throws \Hoa\Compiler\Exception */ public function analyzeRules(array $rules) { if (empty($rules)) { throw new Compiler\Exception\Rule('No rules specified!', 0); } $this->_parsedRules = []; $this->_rules = $rules; $lexer = new Compiler\Llk\Lexer(); foreach ($rules as $key => $value) { $this->_lexer = new Iterator\Lookahead($lexer->lexMe($value, static::$_ppLexemes)); $this->_lexer->rewind(); $this->_ruleName = $key; $nodeId = null; if ('#' === $key[0]) { $nodeId = $key; $key = substr($key, 1); } $pNodeId = $nodeId; $rule = $this->rule($pNodeId); if (null === $rule) { throw new Compiler\Exception('Error while parsing rule %s.', 1, $key); } $zeRule = $this->_parsedRules[$rule]; $zeRule->setName($key); $zeRule->setPPRepresentation($value); if (null !== $nodeId) { $zeRule->setDefaultId($nodeId); } unset($this->_parsedRules[$rule]); $this->_parsedRules[$key] = $zeRule; } return $this->_parsedRules; } /** * Implementation of “rule”. * * @return mixed */ protected function rule(&$pNodeId) { return $this->choice($pNodeId); } /** * Implementation of “choice”. * * @return mixed */ protected function choice(&$pNodeId) { $children = []; // concatenation() … $nNodeId = $pNodeId; $rule = $this->concatenation($nNodeId); if (null === $rule) { return null; } if (null !== $nNodeId) { $this->_parsedRules[$rule]->setNodeId($nNodeId); } $children[] = $rule; $others = \false; // … ( ::or:: concatenation() )* while ('or' === $this->_lexer->current()['token']) { $this->_lexer->next(); $others = \true; $nNodeId = $pNodeId; $rule = $this->concatenation($nNodeId); if (null === $rule) { return null; } if (null !== $nNodeId) { $this->_parsedRules[$rule]->setNodeId($nNodeId); } $children[] = $rule; } $pNodeId = null; if (\false === $others) { return $rule; } $name = $this->_transitionalRuleCounter++; $this->_parsedRules[$name] = new \Hoa\Compiler\Llk\Rule\Choice($name, $children); return $name; } /** * Implementation of “concatenation”. * * @return mixed */ protected function concatenation(&$pNodeId) { $children = []; // repetition() … $rule = $this->repetition($pNodeId); if (null === $rule) { return null; } $children[] = $rule; $others = \false; // … repetition()* while (null !== $r1 = $this->repetition($pNodeId)) { $children[] = $r1; $others = \true; } if (\false === $others && null === $pNodeId) { return $rule; } $name = $this->_transitionalRuleCounter++; $this->_parsedRules[$name] = new \Hoa\Compiler\Llk\Rule\Concatenation($name, $children, null); return $name; } /** * Implementation of “repetition”. * * @return mixed * @throws \Hoa\Compiler\Exception */ protected function repetition(&$pNodeId) { // simple() … $children = $this->simple($pNodeId); if (null === $children) { return null; } // … quantifier()? switch ($this->_lexer->current()['token']) { case 'zero_or_one': $min = 0; $max = 1; $this->_lexer->next(); break; case 'one_or_more': $min = 1; $max = -1; $this->_lexer->next(); break; case 'zero_or_more': $min = 0; $max = -1; $this->_lexer->next(); break; case 'n_to_m': $handle = trim($this->_lexer->current()['value'], '{}'); $nm = explode(',', $handle); $min = (int) trim($nm[0]); $max = (int) trim($nm[1]); $this->_lexer->next(); break; case 'zero_to_m': $min = 0; $max = (int) trim($this->_lexer->current()['value'], '{,}'); $this->_lexer->next(); break; case 'n_or_more': $min = (int) trim($this->_lexer->current()['value'], '{,}'); $max = -1; $this->_lexer->next(); break; case 'exactly_n': $handle = trim($this->_lexer->current()['value'], '{}'); $min = (int) $handle; $max = $min; $this->_lexer->next(); break; } // … ? if ('node' === $this->_lexer->current()['token']) { $pNodeId = $this->_lexer->current()['value']; $this->_lexer->next(); } if (!isset($min)) { return $children; } if (-1 != $max && $max < $min) { throw new Compiler\Exception('Upper bound %d must be greater or ' . 'equal to lower bound %d in rule %s.', 2, [$max, $min, $this->_ruleName]); } $name = $this->_transitionalRuleCounter++; $this->_parsedRules[$name] = new \Hoa\Compiler\Llk\Rule\Repetition($name, $min, $max, $children, null); return $name; } /** * Implementation of “simple”. * * @return mixed * @throws \Hoa\Compiler\Exception * @throws \Hoa\Compiler\Exception\Rule */ protected function simple(&$pNodeId) { if ('capturing_' === $this->_lexer->current()['token']) { $this->_lexer->next(); $rule = $this->choice($pNodeId); if (null === $rule) { return null; } if ('_capturing' != $this->_lexer->current()['token']) { return null; } $this->_lexer->next(); return $rule; } if ('skipped' === $this->_lexer->current()['token']) { $tokenName = trim($this->_lexer->current()['value'], ':'); if (']' === substr($tokenName, -1)) { $uId = (int) substr($tokenName, strpos($tokenName, '[') + 1, -1); $tokenName = substr($tokenName, 0, strpos($tokenName, '[')); } else { $uId = -1; } $exists = \false; foreach ($this->_tokens as $namespace => $tokens) { foreach ($tokens as $token => $value) { if ($token === $tokenName || substr($token, 0, strpos($token, ':')) === $tokenName) { $exists = \true; break 2; } } } if (\false == $exists) { throw new Compiler\Exception('Token ::%s:: does not exist in rule %s.', 3, [$tokenName, $this->_ruleName]); } $name = $this->_transitionalRuleCounter++; $this->_parsedRules[$name] = new \Hoa\Compiler\Llk\Rule\Token($name, $tokenName, null, $uId); $this->_lexer->next(); return $name; } if ('kept' === $this->_lexer->current()['token']) { $tokenName = trim($this->_lexer->current()['value'], '<>'); if (']' === substr($tokenName, -1)) { $uId = (int) substr($tokenName, strpos($tokenName, '[') + 1, -1); $tokenName = substr($tokenName, 0, strpos($tokenName, '[')); } else { $uId = -1; } $exists = \false; foreach ($this->_tokens as $namespace => $tokens) { foreach ($tokens as $token => $value) { if ($token === $tokenName || substr($token, 0, strpos($token, ':')) === $tokenName) { $exists = \true; break 2; } } } if (\false == $exists) { throw new Compiler\Exception('Token <%s> does not exist in rule %s.', 4, [$tokenName, $this->_ruleName]); } $name = $this->_transitionalRuleCounter++; $token = new \Hoa\Compiler\Llk\Rule\Token($name, $tokenName, null, $uId, \true); $this->_parsedRules[$name] = $token; $this->_lexer->next(); return $name; } if ('named' === $this->_lexer->current()['token']) { $tokenName = rtrim($this->_lexer->current()['value'], '()'); if (\false === array_key_exists($tokenName, $this->_rules) && \false === array_key_exists('#' . $tokenName, $this->_rules)) { throw new Compiler\Exception\Rule('Cannot call rule %s() in rule %s because it does not exist.', 5, [$tokenName, $this->_ruleName]); } if (0 === $this->_lexer->key() && 'EOF' === $this->_lexer->getNext()['token']) { $name = $this->_transitionalRuleCounter++; $this->_parsedRules[$name] = new \Hoa\Compiler\Llk\Rule\Concatenation($name, [$tokenName], null); } else { $name = $tokenName; } $this->_lexer->next(); return $name; } return null; } } _rule = $rule; $this->_data = $data; $this->_todo = $todo; $this->_depth = $depth; $this->_transitional = is_int($rule); return; } /** * Get rule name. * * @return string */ public function getRule() { return $this->_rule; } /** * Get data. * * @return mixed */ public function getData() { return $this->_data; } /** * Get todo sequence. * * @return array */ public function getTodo() { return $this->_todo; } /** * Set depth in trace. * * @param int $depth Depth. * @return int */ public function setDepth($depth) { $old = $this->_depth; $this->_depth = $depth; return $old; } /** * Get depth in trace. * * @return int */ public function getDepth() { return $this->_depth; } /** * Check whether the rule is transitional or not. * * @return bool */ public function isTransitional() { return $this->_transitional; } } $max) { throw new Compiler\Exception\Rule('Cannot repeat with a min (%d) greater than max (%d).', 0, [$min, $max]); } $this->_min = $min; $this->_max = $max; return; } /** * Get minimum bound. * * @return int */ public function getMin() { return $this->_min; } /** * Get maximum bound. * * @return int */ public function getMax() { return $this->_max; } /** * Check whether the maximum repetition is unbounded. * * @return bool */ public function isInfinite() { return -1 === $this->getMax(); } } setName($name); $this->setChildren($children); if ($nodeId !== null) { $this->setNodeId($nodeId); } return; } /** * Set rule name. * * @param string $name Rule name. * @return string */ public function setName($name) { $old = $this->_name; $this->_name = $name; return $old; } /** * Get rule name. * * @return string */ public function getName() { return $this->_name; } /** * Set rule's children. * * @param mixed $children Children. * @return mixed */ protected function setChildren($children) { $old = $this->_children; $this->_children = $children; return $old; } /** * Get rule's children. * * @return mixed */ public function getChildren() { return $this->_children; } /** * Set node ID. * * @param string $nodeId Node ID. * @return string */ public function setNodeId($nodeId) { $old = $this->_nodeId; if (\false !== $pos = strpos($nodeId, ':')) { $this->_nodeId = substr($nodeId, 0, $pos); $this->_nodeOptions = str_split(substr($nodeId, $pos + 1)); } else { $this->_nodeId = $nodeId; $this->_nodeOptions = []; } return $old; } /** * Get node ID. * * @return string */ public function getNodeId() { return $this->_nodeId; } /** * Get node options. * * @retrun array */ public function getNodeOptions() { return $this->_nodeOptions; } /** * Set default ID. * * @param string $defaultId Default ID. * @return string */ public function setDefaultId($defaultId) { $old = $this->_defaultId; if (\false !== $pos = strpos($defaultId, ':')) { $this->_defaultId = substr($defaultId, 0, $pos); $this->_defaultOptions = str_split(substr($defaultId, $pos + 1)); } else { $this->_defaultId = $defaultId; $this->_defaultOptions = []; } return $old; } /** * Get default ID. * * @return string */ public function getDefaultId() { return $this->_defaultId; } /** * Get default options. * * @return array */ public function getDefaultOptions() { return $this->_defaultOptions; } /** * Set PP representation of the rule. * * @param string $pp PP representation. * @return string */ public function setPPRepresentation($pp) { $old = $this->_pp; $this->_pp = $pp; $this->_transitional = \false; return $old; } /** * Get PP representation of the rule. * * @return string */ public function getPPRepresentation() { return $this->_pp; } /** * Check whether the rule is transitional or not. * * @return bool */ public function isTransitional() { return $this->_transitional; } } /** * Flex entity. */ Consistency::flexEntity('Hoa\Compiler\Llk\Rule\Rule'); _tokenName = $tokenName; $this->_unification = $unification; $this->setKept($kept); return; } /** * Get token name. * * @return string */ public function getTokenName() { return $this->_tokenName; } /** * Set token namespace. * * @param string $namespace Namespace. * @return string */ public function setNamespace($namespace) { $old = $this->_namespace; $this->_namespace = $namespace; return $old; } /** * Get token namespace. * * @return string */ public function getNamespace() { return $this->_namespace; } /** * Set representation. * * @param string $regex Representation. * @return string */ public function setRepresentation($regex) { $old = $this->_regex; $this->_regex = $regex; return $old; } /** * Get token representation. * * @return string */ public function getRepresentation() { return $this->_regex; } /** * Get AST of the token representation. * * @return \Hoa\Compiler\Llk\TreeNode */ public function getAST() { if (null === static::$_regexCompiler) { $stream = new File\Read('hoa://Library/Regex/Grammar.pp'); $stream->rewind(); static::$_regexCompiler = Compiler\Llk::load($stream); } if (null === $this->_ast) { $this->_ast = static::$_regexCompiler->parse($this->getRepresentation()); } return $this->_ast; } /** * Set token value. * * @param string $value Value. * @return string */ public function setValue($value) { $old = $this->_value; $this->_value = $value; return $old; } /** * Get token value. * * @return string */ public function getValue() { return $this->_value; } /** * Set whether the token is kept or not in the AST. * * @param bool $kept Kept. * @return bool */ public function setKept($kept) { $old = $this->_kept; $this->_kept = $kept; return $old; } /** * Check whether the token is kept in the AST or not. * * @return bool */ public function isKept() { return $this->_kept; } /** * Get unification index. * * @return int */ public function getUnificationIndex() { return $this->_unification; } } setLength($length); return; } /** * Get the current iterator value. * * @return string */ public function current() { return $this->_current; } /** * Get the current iterator key. * * @return int */ public function key() { return $this->_key; } /** * Useless here. * * @return void */ public function next() { return; } /** * Rewind the internal iterator pointer. * * @return void */ public function rewind() { $ruleName = $this->_rootRuleName; $this->_current = null; $this->_key = -1; $this->_trace = []; $handle = new Compiler\Llk\Rule\Ekzit($ruleName, 0); $this->_todo = [$handle, new Compiler\Llk\Rule\Entry($ruleName, 0, [$handle])]; return; } /** * Compute the current iterator value, i.e. generate a new solution. * * @return bool */ public function valid() { if (\false === $this->unfold()) { return \false; } $handle = null; foreach ($this->_trace as $trace) { if ($trace instanceof Compiler\Llk\Rule\Token) { $handle .= $this->generateToken($trace); } } ++$this->_key; $this->_current = $handle; return $this->backtrack(); } /** * Unfold rules from the todo stack. * * @return bool */ protected function unfold() { while (0 < count($this->_todo)) { $pop = array_pop($this->_todo); if ($pop instanceof Compiler\Llk\Rule\Ekzit) { $this->_trace[] = $pop; } else { $ruleName = $pop->getRule(); $next = $pop->getData(); $rule = $this->_rules[$ruleName]; $out = $this->boundedExhaustive($rule, $next); if (\true !== $out && \true !== $this->backtrack()) { return \false; } } } return \true; } /** * The bounded-exhaustive algorithm. * * @param \Hoa\Compiler\Llk\Rule $rule Rule to cover. * @param int $next Next rule. * @return bool */ protected function boundedExhaustive(Compiler\Llk\Rule $rule, $next) { $children = $rule->getChildren(); if ($rule instanceof Compiler\Llk\Rule\Repetition) { if (0 === $next) { $this->_trace[] = new Compiler\Llk\Rule\Entry($rule->getName(), $rule->getMin()); array_pop($this->_todo); $this->_todo[] = new Compiler\Llk\Rule\Ekzit($rule->getName(), $rule->getMin(), $this->_todo); for ($i = 0, $min = $rule->getMin(); $i < $min; ++$i) { $this->_todo[] = new Compiler\Llk\Rule\Ekzit($children, 0); $this->_todo[] = new Compiler\Llk\Rule\Entry($children, 0); } } else { $nbToken = 0; foreach ($this->_trace as $trace) { if ($trace instanceof Compiler\Llk\Rule\Token) { ++$nbToken; } } $max = $rule->getMax(); if (-1 != $max && $next > $max) { return \false; } $this->_todo[] = new Compiler\Llk\Rule\Ekzit($rule->getName(), $next, $this->_todo); $this->_todo[] = new Compiler\Llk\Rule\Ekzit($children, 0); $this->_todo[] = new Compiler\Llk\Rule\Entry($children, 0); } return \true; } elseif ($rule instanceof Compiler\Llk\Rule\Choice) { if (count($children) <= $next) { return \false; } $this->_trace[] = new Compiler\Llk\Rule\Entry($rule->getName(), $next, $this->_todo); $nextRule = $children[$next]; $this->_todo[] = new Compiler\Llk\Rule\Ekzit($nextRule, 0); $this->_todo[] = new Compiler\Llk\Rule\Entry($nextRule, 0); return \true; } elseif ($rule instanceof Compiler\Llk\Rule\Concatenation) { $this->_trace[] = new Compiler\Llk\Rule\Entry($rule->getName(), $next); for ($i = count($children) - 1; $i >= 0; --$i) { $nextRule = $children[$i]; $this->_todo[] = new Compiler\Llk\Rule\Ekzit($nextRule, 0); $this->_todo[] = new Compiler\Llk\Rule\Entry($nextRule, 0); } return \true; } elseif ($rule instanceof Compiler\Llk\Rule\Token) { $nbToken = 0; foreach ($this->_trace as $trace) { if ($trace instanceof Compiler\Llk\Rule\Token) { ++$nbToken; } } if ($nbToken >= $this->getLength()) { return \false; } $this->_trace[] = $rule; array_pop($this->_todo); return \true; } return \false; } /** * Backtrack to the previous choice-point. * * @return bool */ protected function backtrack() { $found = \false; do { $last = array_pop($this->_trace); if ($last instanceof Compiler\Llk\Rule\Entry) { $rule = $this->_rules[$last->getRule()]; $found = $rule instanceof Compiler\Llk\Rule\Choice; } elseif ($last instanceof Compiler\Llk\Rule\Ekzit) { $rule = $this->_rules[$last->getRule()]; $found = $rule instanceof Compiler\Llk\Rule\Repetition; } } while (0 < count($this->_trace) && \false === $found); if (\false === $found) { return \false; } $rule = $last->getRule(); $next = $last->getData() + 1; $this->_todo = $last->getTodo(); $this->_todo[] = new Compiler\Llk\Rule\Entry($rule, $next, $this->_todo); return \true; } /** * Set upper-bound, the maximum data length. * * @param int $length Length. * @return int * @throws \Hoa\Compiler\Exception */ public function setLength($length) { if (0 >= $length) { throw new \Hoa\Compiler\Llk\Sampler\Exception('Length must be greater than 0, given %d.', 0, $length); } $old = $this->_length; $this->_length = $length; return $old; } /** * Get upper-bound. * * @return int */ public function getLength() { return $this->_length; } } _current; } /** * Get the current iterator key. * * @return int */ public function key() { return $this->_key; } /** * Useless here. * * @return void */ public function next() { return; } /** * Rewind the internal iterator pointer. * * @return void */ public function rewind() { $this->_key = -1; $this->_current = null; $this->_tests = []; $this->_coveredRules = []; foreach ($this->_rules as $name => $rule) { $this->_coveredRules[$name] = []; if ($rule instanceof Compiler\Llk\Rule\Repetition) { $min = $rule->getMin(); $min1 = $min + 1; $max = -1 == $rule->getMax() ? 2 : $rule->getMax(); $max1 = $max - 1; if ($min == $max) { $this->_coveredRules[$name][$min] = 0; } else { $this->_coveredRules[$name][$min] = 0; $this->_coveredRules[$name][$min1] = 0; $this->_coveredRules[$name][$max1] = 0; $this->_coveredRules[$name][$max] = 0; } } elseif ($rule instanceof Compiler\Llk\Rule\Choice) { for ($i = 0, $max = count($rule->getChildren()); $i < $max; ++$i) { $this->_coveredRules[$name][$i] = 0; } } else { $this->_coveredRules[$name][0] = 0; } } return; } /** * Compute the current iterator value, i.e. generate a new solution. * * @return bool */ public function valid() { $ruleName = $this->_rootRuleName; if (\true !== in_array(0, $this->_coveredRules[$ruleName]) && \true !== in_array(0.5, $this->_coveredRules[$ruleName])) { return \false; } $this->_trace = []; $this->_todo = [new Compiler\Llk\Rule\Entry($ruleName, $this->_coveredRules)]; $result = $this->unfold(); if (\true !== $result) { return \false; } $handle = null; foreach ($this->_trace as $trace) { if ($trace instanceof Compiler\Llk\Rule\Token) { $handle .= $this->generateToken($trace); } } ++$this->_key; $this->_current = $handle; $this->_tests[] = $this->_trace; foreach ($this->_coveredRules as $key => $value) { foreach ($value as $k => $v) { if (-1 == $v) { $this->_coveredRules[$key][$k] = 0; } } } return \true; } /** * Unfold rules from the todo stack. * * @return bool */ protected function unfold() { while (0 < count($this->_todo)) { $pop = array_pop($this->_todo); if ($pop instanceof Compiler\Llk\Rule\Ekzit) { $this->_trace[] = $pop; $this->updateCoverage($pop); } else { $out = $this->coverage($this->_rules[$pop->getRule()]); if (\true !== $out && \true !== $this->backtrack()) { return \false; } } } return \true; } /** * The coverage algorithm. * * @param \Hoa\Compiler\Llk\Rule $rule Rule to cover. * @return bool */ protected function coverage(Compiler\Llk\Rule $rule) { $children = $rule->getChildren(); if ($rule instanceof Compiler\Llk\Rule\Repetition) { $uncovered = []; $inprogress = []; $already = []; foreach ($this->_coveredRules[$rule->getName()] as $child => $value) { if (0 == $value || 0.5 == $value) { $uncovered[] = $child; } elseif (-1 == $value) { $inprogress[] = $child; } else { $already[] = $child; } } if (empty($uncovered)) { if (empty($already)) { $rand = $inprogress[rand(0, count($inprogress) - 1)]; } else { $rand = $already[rand(0, count($already) - 1)]; } $this->_trace[] = new Compiler\Llk\Rule\Entry($rule->getName(), $this->_coveredRules, $this->_todo); $this->_todo[] = new Compiler\Llk\Rule\Ekzit($rule->getName(), $rand); if ($this->_rules[$children] instanceof Compiler\Llk\Rule\Token) { for ($i = 0; $i < $rand; ++$i) { $this->_todo[] = new Compiler\Llk\Rule\Entry($children, $this->_coveredRules, $this->_todo); } } else { $sequence = $this->extract([$children]); if (null === $sequence) { return null; } for ($i = 0; $i < $rand; ++$i) { foreach ($sequence as $seq) { $this->_trace[] = $seq; if ($seq instanceof Compiler\Llk\Rule\Ekzit) { $this->updateCoverage($seq); } } } } } else { $rand = $uncovered[rand(0, count($uncovered) - 1)]; $this->_coveredRules[$rule->getName()][$rand] = -1; $this->_trace[] = new Compiler\Llk\Rule\Entry($rule->getName(), $this->_coveredRules, $this->_todo); $this->_todo[] = new Compiler\Llk\Rule\Ekzit($rule->getName(), $rand); for ($i = 0; $i < $rand; ++$i) { $this->_todo[] = new Compiler\Llk\Rule\Entry($children, $this->_coveredRules, $this->_todo); } } return \true; } elseif ($rule instanceof Compiler\Llk\Rule\Choice) { $uncovered = []; $inprogress = []; $already = []; foreach ($this->_coveredRules[$rule->getName()] as $child => $value) { if (0 == $value || 0.5 == $value) { $uncovered[] = $child; } elseif (-1 == $value) { $inprogress[] = $child; } else { $already[] = $child; } } if (empty($uncovered)) { $this->_trace[] = new Compiler\Llk\Rule\Entry($rule->getName(), $this->_coveredRules, $this->_todo); $sequence = $this->extract($children); if (null === $sequence) { return null; } foreach ($sequence as $seq) { $this->_trace[] = $seq; if ($seq instanceof Compiler\Llk\Rule\Ekzit) { $this->updateCoverage($seq); } } if (empty($already)) { $rand = $inprogress[rand(0, count($inprogress) - 1)]; } else { $rand = $already[rand(0, count($already) - 1)]; } $this->_todo[] = new Compiler\Llk\Rule\Ekzit($rule->getName(), $rand); } else { $rand = $uncovered[rand(0, count($uncovered) - 1)]; $this->_trace[] = new Compiler\Llk\Rule\Entry($rule->getName(), $this->_coveredRules, $this->_todo); $this->_coveredRules[$rule->getName()][$rand] = -1; $this->_todo[] = new Compiler\Llk\Rule\Ekzit($rule->getName(), $rand); $this->_todo[] = new Compiler\Llk\Rule\Entry($children[$rand], $this->_coveredRules, $this->_todo); } return \true; } elseif ($rule instanceof Compiler\Llk\Rule\Concatenation) { $this->_coveredRules[$rule->getName()][0] = -1; $this->_trace[] = new Compiler\Llk\Rule\Entry($rule->getName(), \false); $this->_todo[] = new Compiler\Llk\Rule\Ekzit($rule->getName(), \false); for ($i = count($children) - 1; $i >= 0; --$i) { $this->_todo[] = new Compiler\Llk\Rule\Entry($children[$i], \false, $this->_todo); } return \true; } elseif ($rule instanceof Compiler\Llk\Rule\Token) { $this->_trace[] = new Compiler\Llk\Rule\Entry($rule->getName(), \false); $this->_trace[] = $rule; $this->_todo[] = new Compiler\Llk\Rule\Ekzit($rule->getName(), \false); return \true; } return \false; } /** * Extract a given sequence from existing traces. * * @param array $rules Rules to consider. * @return array */ protected function extract(array $rules) { $out = []; foreach ($rules as $rule) { foreach ($this->_tests as $test) { $opened = 0; foreach ($test as $t) { if ($t instanceof Compiler\Llk\Rule\Entry && $t->getRule() == $rule) { ++$opened; } if (0 < $opened) { $out[] = $t; if ($t instanceof Compiler\Llk\Rule\Ekzit && $t->getRule() == $rule) { --$opened; if (0 === $opened) { return $out; } } } } } } foreach ($rules as $rule) { $out = []; $closed = 0; foreach ($this->_trace as $t) { if ($t instanceof Compiler\Llk\Rule\Ekzit && $t->getRule() == $rule) { ++$closed; } if (0 < $closed) { $out[] = $t; if ($t instanceof Compiler\Llk\Rule\Ekzit && $t->getRule() == $rule) { --$closed; if (0 === $closed) { return array_reverse($out); } } } } } return null; } /** * Backtrack to the previous choice-point. * * @return bool */ protected function backtrack() { $found = \false; do { $pop = array_pop($this->_trace); if ($pop instanceof Compiler\Llk\Rule\Entry) { $rule = $this->_rules[$pop->getRule()]; $found = $rule instanceof Compiler\Llk\Rule\Choice || $rule instanceof Compiler\Llk\Rule\Repetition; } } while (0 < count($this->_trace) && \false === $found); if (\false === $found) { return \false; } $ruleName = $pop->getRule(); $this->_covered = $pop->getData(); $this->_todo = $pop->getTodo(); $this->_todo[] = new Compiler\Llk\Rule\Entry($ruleName, $this->_covered, $this->_todo); return \true; } /** * Update coverage of a rule. * * @param \Hoa\Compiler\Llk\Rule\Ekzit $rule Rule to consider. * @return void */ protected function updateCoverage(Compiler\Llk\Rule\Ekzit $Rule) { $ruleName = $Rule->getRule(); $child = $Rule->getData(); $rule = $this->_rules[$ruleName]; $children = $rule->getChildren(); if ($rule instanceof Compiler\Llk\Rule\Repetition) { if (0 === $child) { $this->_coveredRules[$ruleName][$child] = 1; } else if (\true === $this->allCovered($children) || \true === $this->checkRuleRoot($children)) { $this->_coveredRules[$ruleName][$child] = 1; foreach ($this->_coveredRules[$ruleName] as $child => $value) { if (0.5 == $value) { $this->_coveredRules[$ruleName][$child] = 1; } } } else { $this->_coveredRules[$ruleName][$child] = 0.5; } } elseif ($rule instanceof Compiler\Llk\Rule\Choice) { if (\true === $this->allCovered($children[$child]) || \true === $this->checkRuleRoot($children[$child])) { $this->_coveredRules[$ruleName][$child] = 1; } else { $this->_coveredRules[$ruleName][$child] = 0.5; } } elseif ($rule instanceof Compiler\Llk\Rule\Concatenation) { $isCovered = \true; for ($i = count($children) - 1; $i >= 0 && \true === $isCovered; --$i) { if (\false === $this->allCovered($children[$i]) && \false === $this->checkRuleRoot($children[$i])) { $isCovered = \false; } } $this->_coveredRules[$ruleName][0] = \true === $isCovered ? 1 : 0.5; } elseif ($rule instanceof Compiler\Llk\Rule\Token) { $this->_coveredRules[$ruleName][0] = 1; } return; } /** * Check if all rules have been entirely covered. * * @param string $ruleName Rule name. * @return bool */ protected function allCovered($ruleName) { foreach ($this->_coveredRules[$ruleName] as $value) { if (1 !== $value) { return \false; } } return \true; } /** * Check if a rule is a root rule that is currently being processed. * * @param string $ruleName Rule name. * @return bool */ protected function checkRuleRoot($ruleName) { if (\true === $this->_rules[$ruleName]->isTransitional()) { return \false; } $i = count($this->_trace) - 1; $nb = 0; while ($i >= 0) { $lastRule = $this->_trace[$i]; if ($lastRule instanceof Compiler\Llk\Rule\Entry) { if ($lastRule->getRule() == $ruleName) { ++$nb; } } elseif ($lastRule instanceof Compiler\Llk\Rule\Ekzit) { if ($lastRule->getRule() == $ruleName) { --$nb; } } --$i; } return 0 < $nb; } } _compiler = $compiler; $this->_tokens = $compiler->getTokens(); $this->_rules = $compiler->getRules(); $this->_tokenSampler = $tokenSampler; $this->_rootRuleName = $compiler->getRootRule(); return; } /** * Get compiler. * * @return \Hoa\Compiler\Llk\Parser */ public function getCompiler() { return $this->_compiler; } /** * Get the AST of the current namespace skip token. * * @return \Hoa\Compiler\Llk\TreeNode */ protected function getSkipTokenAST() { if (!isset($this->_skipTokenAST[$this->_currentNamespace])) { $token = new Compiler\Llk\Rule\Token(-1, 'skip', null, -1); $token->setRepresentation($this->_tokens[$this->_currentNamespace]['skip']); $this->_skipTokenAST[$this->_currentNamespace] = $token->getAST(); } return $this->_skipTokenAST[$this->_currentNamespace]; } /** * Complete a token (namespace and representation). * It returns the next namespace. * * @param \Hoa\Compiler\Llk\Rule\Token $token Token. * @return string */ protected function completeToken(Compiler\Llk\Rule\Token $token) { if (null !== $token->getRepresentation()) { return $this->_currentNamespace; } $name = $token->getTokenName(); $token->setNamespace($this->_currentNamespace); $toNamespace = $this->_currentNamespace; if (isset($this->_tokens[$this->_currentNamespace][$name])) { $token->setRepresentation($this->_tokens[$this->_currentNamespace][$name]); } else { foreach ($this->_tokens[$this->_currentNamespace] as $_name => $regex) { if (\false === strpos($_name, ':')) { continue; } list($_name, $toNamespace) = explode(':', $_name, 2); if ($_name === $name) { break; } } $token->setRepresentation($regex); } return $toNamespace; } /** * Set current token namespace. * * @param string $namespace Token namespace. * @return string */ protected function setCurrentNamespace($namespace) { $old = $this->_currentNamespace; $this->_currentNamespace = $namespace; return $old; } /** * Generate a token value. * Complete and set next token namespace. * * @param \Hoa\Compiler\Llk\Rule\Token $token Token. * @return string */ protected function generateToken(Compiler\Llk\Rule\Token $token) { $toNamespace = $this->completeToken($token); $this->setCurrentNamespace($toNamespace); $out = $this->_tokenSampler->visit($token->getAST()); if (isset($this->_tokens[$this->_currentNamespace]['skip'])) { $out .= $this->_tokenSampler->visit($this->getSkipTokenAST()); } return $out; } } /** * Flex entity. */ Consistency::flexEntity('Hoa\Compiler\Llk\Sampler\Sampler'); _rules as $name => $_) { $this->_data[$name] = []; } $this->setLength($length); $this->_sampler = new Math\Sampler\Random(); return; } /** * The random and uniform algorithm. * * @param \Hoa\Compiler\Llk\Rule $rule Rule to start. * @param int $n Size. * @return string */ public function uniform(Compiler\Llk\Rule $rule = null, $n = -1) { if (null === $rule && -1 === $n) { $rule = $this->_rules[$this->_rootRuleName]; $n = $this->getLength(); } $data =& $this->_data[$rule->getName()][$n]; $computed = $data['n']; if (0 === $n || 0 === $computed) { return null; } if ($rule instanceof Compiler\Llk\Rule\Choice) { $children = $rule->getChildren(); $stat = []; foreach ($children as $c => $child) { $stat[$c] = $this->_data[$child][$n]['n']; } $i = $this->_sampler->getInteger(1, $computed); for ($e = 0, $b = $stat[$e], $max = count($stat) - 1; $e < $max && $i > $b; $b += $stat[++$e]) { } return $this->uniform($this->_rules[$children[$e]], $n); } elseif ($rule instanceof Compiler\Llk\Rule\Concatenation) { $children = $rule->getChildren(); $out = null; $Γ = $data['Γ']; $γ = $Γ[$this->_sampler->getInteger(0, count($Γ) - 1)]; foreach ($children as $i => $child) { $out .= $this->uniform($this->_rules[$child], $γ[$i]); } return $out; } elseif ($rule instanceof Compiler\Llk\Rule\Repetition) { $out = null; $stat =& $data['xy']; $child = $this->_rules[$rule->getChildren()]; $b = 0; $i = $this->_sampler->getInteger(1, $computed); foreach ($stat as $α => $st) { if ($i <= $b += $st['n']) { break; } } $Γ =& $st['Γ']; $γ =& $Γ[$this->_sampler->getInteger(0, count($Γ) - 1)]; for ($j = 0; $j < $α; ++$j) { $out .= $this->uniform($child, $γ[$j]); } return $out; } elseif ($rule instanceof Compiler\Llk\Rule\Token) { return $this->generateToken($rule); } return null; } /** * Recursive method applied to our problematic. * * @param \Hoa\Compiler\Llk\Rule $rule Rule to start. * @param int $n Size. * @return int */ public function count(Compiler\Llk\Rule $rule = null, $n = -1) { if (null === $rule || -1 === $n) { return 0; } $ruleName = $rule->getName(); if (isset($this->_data[$ruleName][$n])) { return $this->_data[$ruleName][$n]['n']; } $this->_data[$ruleName][$n] = ['n' => 0]; $out =& $this->_data[$ruleName][$n]['n']; $rule = $this->_rules[$ruleName]; if ($rule instanceof Compiler\Llk\Rule\Choice) { foreach ($rule->getChildren() as $child) { $out += $this->count($this->_rules[$child], $n); } } elseif ($rule instanceof Compiler\Llk\Rule\Concatenation) { $children = $rule->getChildren(); $Γ = new Math\Combinatorics\Combination\Gamma(count($children), $n); $this->_data[$ruleName][$n]['Γ'] = []; $handle =& $this->_data[$ruleName][$n]['Γ']; foreach ($Γ as $γ) { $oout = 1; foreach ($γ as $α => $_γ) { $oout *= $this->count($this->_rules[$children[$α]], $_γ); } if (0 !== $oout) { $handle[] = $γ; } $out += $oout; } } elseif ($rule instanceof Compiler\Llk\Rule\Repetition) { $this->_data[$ruleName][$n]['xy'] = []; $handle =& $this->_data[$ruleName][$n]['xy']; $child = $this->_rules[$rule->getChildren()]; $x = $rule->getMin(); $y = $rule->getMax(); if (-1 === $y) { $y = $n; } else { $y = min($n, $y); } if (0 === $x && $x === $y) { $out = 1; } else { for ($α = $x; $α <= $y; ++$α) { $ut = 0; $handle[$α] = ['n' => 0, 'Γ' => []]; $Γ = new Math\Combinatorics\Combination\Gamma($α, $n); foreach ($Γ as $γ) { $oout = 1; foreach ($γ as $β => $_γ) { $oout *= $this->count($child, $_γ); } if (0 !== $oout) { $handle[$α]['Γ'][] = $γ; } $ut += $oout; } $handle[$α]['n'] = $ut; $out += $ut; } } } elseif ($rule instanceof Compiler\Llk\Rule\Token) { $out = Math\Util::δ($n, 1); } return $out; } /** * Set upper-bound, the maximum data length. * * @param int $length Length. * @return int * @throws \Hoa\Compiler\Exception */ public function setLength($length) { if (0 >= $length) { throw new \Hoa\Compiler\Llk\Sampler\Exception('Length must be greater than 0, given %d.', 0, $length); } $old = $this->_length; $this->_length = $length; $this->count($this->_compiler->getRule($this->_rootRuleName), $length); return $old; } /** * Get upper-bound. * * @return int */ public function getLength() { return $this->_length; } } setId($id); if (!empty($value)) { $this->setValue($value); } $this->setChildren($children); if (null !== $parent) { $this->setParent($parent); } return; } /** * Set ID. * * @param string $id ID. * @return string */ public function setId($id) { $old = $this->_id; $this->_id = $id; return $old; } /** * Get ID. * * @return string */ public function getId() { return $this->_id; } /** * Set value. * * @param array $value Value (token & value). * @return array */ public function setValue(array $value) { $old = $this->_value; $this->_value = $value; return $old; } /** * Get value. * * @return array */ public function getValue() { return $this->_value; } /** * Get value token. * * @return string */ public function getValueToken() { return isset($this->_value['token']) ? $this->_value['token'] : null; } /** * Get value value. * * @return string */ public function getValueValue() { return isset($this->_value['value']) ? $this->_value['value'] : null; } /** * Check if the node represents a token or not. * * @return bool */ public function isToken() { return !empty($this->_value); } /** * Prepend a child. * * @param \Hoa\Compiler\Llk\TreeNode $child Child. * @return \Hoa\Compiler\Llk\TreeNode */ public function prependChild(\Hoa\Compiler\Llk\TreeNode $child) { array_unshift($this->_children, $child); return $this; } /** * Append a child. * * @param \Hoa\Compiler\Llk\TreeNode $child Child. * @return \Hoa\Compiler\Llk\TreeNode */ public function appendChild(\Hoa\Compiler\Llk\TreeNode $child) { $this->_children[] = $child; return $this; } /** * Set children. * * @param array $children Children. * @return array */ public function setChildren(array $children) { $old = $this->_children; $this->_children = $children; return $old; } /** * Get child. * * @param int $i Index. * @return \Hoa\Compiler\Llk\TreeNode */ public function getChild($i) { return \true === $this->childExists($i) ? $this->_children[$i] : null; } /** * Get children. * * @return array */ public function getChildren() { return $this->_children; } /** * Get number of children. * * @return int */ public function getChildrenNumber() { return count($this->_children); } /** * Check if a child exists. * * @param int $i Index. * @return bool */ public function childExists($i) { return array_key_exists($i, $this->_children); } /** * Set parent. * * @param \Hoa\Compiler\Llk\TreeNode $parent Parent. * @return \Hoa\Compiler\Llk\TreeNode */ public function setParent(\Hoa\Compiler\Llk\TreeNode $parent) { $old = $this->_parent; $this->_parent = $parent; return $old; } /** * Get parent. * * @return \Hoa\Compiler\Llk\TreeNode */ public function getParent() { return $this->_parent; } /** * Get data. * * @return array */ public function &getData() { return $this->_data; } /** * Accept a visitor. * * @param \Hoa\Visitor\Visit $visitor Visitor. * @param mixed &$handle Handle (reference). * @param mixed $eldnah Handle (no reference). * @return mixed */ public function accept(Visitor\Visit $visitor, &$handle = null, $eldnah = null) { return $visitor->visit($this, $handle, $eldnah); } /** * Remove circular reference to the parent (help the garbage collector). * * @return void */ public function __destruct() { unset($this->_parent); return; } } This file was automatically generated by Composer Patches (https://github.com/cweagans/composer-patches) Patches applied to this directory: 0 Source: patches/HoaException.patch 1 Source: patches/HoaParser.patch 2 Source: patches/Invocation.patch 3 Source: patches/Rule.patch 4 Source: patches/Lexer.patch 5 Source: patches/TreeNode.patch string %token string:string [^"]+ %token string:_quote " -> default // Objects. %token brace_ { %token _brace } // Arrays. %token bracket_ \\[ %token _bracket \\] // Rest. %token colon : %token comma , %token number \\d+ value: | | | string() | object() | array() | number() string: ::quote_:: ::_quote:: number: #object: ::brace_:: pair() ( ::comma:: pair() )* ::_brace:: #pair: string() ::colon:: value() #array: ::bracket_:: value() ( ::comma:: value() )* ::_bracket:: GRAMMAR; $_result = << #object > > #pair > > > token(string:string, foo) > > > token(true, true) > > #pair > > > token(string:string, bar) > > > #array > > > > token(null, null) > > > > token(number, 42) GRAMMAR; $this->given($grammar = new File\ReadWrite('hoa://Test/Vfs/Json.pp?type=file'), $grammar->writeAll($_grammar), $compiler = LUT\Llk::load($grammar))->when($ast = $compiler->parse('{"foo": true, "bar": [null, 42]}'))->then->object($ast)->given($dump = new LUT\Visitor\Dump())->when($result = $dump->visit($ast))->then->string($result)->isEqualTo($_result); } } ::quote:: GRAMMAR; $this->given($grammar = new File\ReadWrite('hoa://Test/Vfs/WithoutUnification.pp?type=file'), $grammar->writeAll($_grammar), $compiler = LUT\Llk::load($grammar))->when($result = $compiler->parse('"foo"', null, \false))->then->boolean($result)->isTrue()->when($result = $compiler->parse('\'foo"', null, \false))->then->boolean($result)->isTrue()->when($result = $compiler->parse('"foo\'', null, \false))->then->boolean($result)->isTrue()->when($result = $compiler->parse('\'foo\'', null, \false))->then->boolean($result)->isTrue(); } public function case_unification() { $_grammar = << ::quote[0]:: GRAMMAR; $this->given($grammar = new File\ReadWrite('hoa://Test/Vfs/Unification.pp?type=file'), $grammar->writeAll($_grammar), $compiler = LUT\Llk::load($grammar))->when($result = $compiler->parse('"foo"', null, \false))->then->boolean($result)->isTrue()->when($result = $compiler->parse('\'foo\'', null, \false))->then->boolean($result)->isTrue()->exception(function () use (&$compiler) { $compiler->parse('\'foo"', null, \false); })->isInstanceOf(LUT\Exception\UnexpectedToken::class)->exception(function () use (&$compiler) { $compiler->parse('"foo\'', null, \false); })->isInstanceOf(LUT\Exception\UnexpectedToken::class); } public function case_unification_palindrome() { $_grammar = <<given($grammar = new File\ReadWrite('hoa://Test/Vfs/Palindrome.pp?type=file'), $grammar->writeAll($_grammar), $compiler = LUT\Llk::load($grammar))->when($result = $compiler->parse('aa', null, \false))->then->boolean($result)->isTrue()->when($result = $compiler->parse('abba', null, \false))->then->boolean($result)->isTrue()->when($result = $compiler->parse('abccba', null, \false))->then->boolean($result)->isTrue()->when($result = $compiler->parse('abcddcba', null, \false))->then->boolean($result)->isTrue()->exception(function () use (&$compiler) { $compiler->parse('abcdcba', null, \false); })->isInstanceOf(LUT\Exception\UnexpectedToken::class); } } _case_simple_token(\true); } public function case_simple_skipped_token() { return $this->_case_simple_token(\false); } protected function _case_simple_token($kept) { $this->given($tokens = ['default' => ['foo' => 'bar']], $ruleA = $kept ? '' : '::foo::', $analyzer = new SUT($tokens), $_ruleA = new Rule\Token('ruleA', 'foo', null, -1, $kept), $_ruleA->setPPRepresentation($ruleA))->when($result = $analyzer->analyzeRules(['ruleA' => $ruleA]))->then->array($result)->isEqualTo(['ruleA' => $_ruleA]); } public function case_simple_named() { $this->given($tokens = ['default' => ['foo' => 'bar']], $rules = ['ruleA' => 'ruleB()', 'ruleB' => ''], $analyzer = new SUT($tokens), $_ruleA = new Rule\Concatenation('ruleA', ['ruleB']), $_ruleA->setPPRepresentation($rules['ruleA']), $_ruleB = new Rule\Token('ruleB', 'foo', null, -1, \true), $_ruleB->setPPRepresentation($rules['ruleB']))->when($result = $analyzer->analyzeRules($rules))->then->array($result)->isEqualTo(['ruleA' => $_ruleA, 'ruleB' => $_ruleB]); } public function case_simple_kept_unified_token() { return $this->_case_simple_unified_token(\true); } public function case_simple_skipped_unified_token() { return $this->_case_simple_unified_token(\false); } protected function _case_simple_unified_token($kept) { $this->given($tokens = ['default' => ['foo' => 'bar']], $ruleA = $kept ? '' : '::foo[42]::', $analyzer = new SUT($tokens), $_ruleA = new Rule\Token('ruleA', 'foo', null, 42, $kept), $_ruleA->setPPRepresentation($ruleA))->when($result = $analyzer->analyzeRules(['ruleA' => $ruleA]))->then->array($result)->isEqualTo(['ruleA' => $_ruleA]); } public function case_repetition_zero_or_one() { return $this->_case_repetition('?', 0, 1); } public function case_repetition_one_or_more() { return $this->_case_repetition('+', 1, -1); } public function case_repetition_zero_or_more() { return $this->_case_repetition('*', 0, -1); } public function case_repetition_n_to_m() { return $this->_case_repetition('{7,42}', 7, 42); } public function case_repetition_n_or_more() { return $this->_case_repetition('{7,}', 7, -1); } public function case_repetition_exactly_n() { return $this->_case_repetition('{7}', 7, 7); } protected function _case_repetition($quantifier, $min, $max) { $this->given($tokens = ['default' => ['foo' => 'bar']], $ruleA = '' . $quantifier, $analyzer = new SUT($tokens), $_ruleA = new Rule\Repetition('ruleA', $min, $max, 0, null), $_ruleA->setPPRepresentation($ruleA), $_rule0 = new Rule\Token(0, 'foo', null, -1, \true))->when($result = $analyzer->analyzeRules(['ruleA' => $ruleA]))->then->array($result)->isEqualTo(['0' => $_rule0, 'ruleA' => $_ruleA]); } public function case_concatenation() { $this->given($tokens = ['default' => ['foo' => 'bar', 'baz' => 'qux']], $ruleA = ' ', $analyzer = new SUT($tokens), $_ruleA = new Rule\Concatenation('ruleA', [0, 1], null), $_ruleA->setPPRepresentation($ruleA), $_rule0 = new Rule\Token(0, 'foo', null, -1, \true), $_rule1 = new Rule\Token(1, 'baz', null, -1, \true))->when($result = $analyzer->analyzeRules(['ruleA' => $ruleA]))->then->array($result)->isEqualTo([0 => $_rule0, 1 => $_rule1, 'ruleA' => $_ruleA]); } public function case_choice() { $this->given($tokens = ['default' => ['foo' => 'bar', 'baz' => 'qux']], $ruleA = ' | ', $analyzer = new SUT($tokens), $_ruleA = new Rule\Choice('ruleA', [0, 1], null), $_ruleA->setPPRepresentation($ruleA), $_rule0 = new Rule\Token(0, 'foo', null, -1, \true), $_rule1 = new Rule\Token(1, 'baz', null, -1, \true))->when($result = $analyzer->analyzeRules(['ruleA' => $ruleA]))->then->array($result)->isEqualTo([0 => $_rule0, 1 => $_rule1, 'ruleA' => $_ruleA]); } public function case_rule() { $this->given($tokens = ['default' => ['foo' => 'bar', 'baz' => 'qux']], $ruleA = ' | ', $analyzer = new SUT($tokens), $_ruleA = new Rule\Choice('ruleA', [0, 1], null), $_ruleA->setPPRepresentation($ruleA), $_rule0 = new Rule\Token(0, 'foo', null, -1, \true), $_rule1 = new Rule\Token(1, 'baz', null, -1, \true))->when($result = $analyzer->analyzeRules(['ruleA' => $ruleA]))->then->array($result)->isEqualTo([0 => $_rule0, 1 => $_rule1, 'ruleA' => $_ruleA]); } public function case_full() { $this->given($tokens = ['default' => ['foo' => 'bar', 'baz' => 'qux']], $ruleA = '+ | ruleB() ::foo::', $ruleB = ' ruleA()', $analyzer = new SUT($tokens), $_rule0 = new Rule\Token(0, 'foo', null, -1, \true), $_rule1 = new Rule\Repetition('1', 1, -1, '0', null), $_rule2 = new Rule\Token(2, 'foo', null, -1, \false), $_rule3 = new Rule\Concatenation('3', ['ruleB', 2]), $_ruleA = new Rule\Choice('ruleA', [1, 3], null), $_ruleA->setPPRepresentation($ruleA), $_rule5 = new Rule\Token(5, 'baz', null, -1, \true), $_ruleB = new Rule\Concatenation('ruleB', [5, 'ruleA']), $_ruleB->setPPRepresentation($ruleB))->when($result = $analyzer->analyzeRules(['ruleA' => $ruleA, 'ruleB' => $ruleB]))->then->array($result)->isEqualTo([0 => $_rule0, 1 => $_rule1, 2 => $_rule2, 3 => $_rule3, 'ruleA' => $_ruleA, 5 => $_rule5, 'ruleB' => $_ruleB]); } public function case_no_rule() { $this->given($analyzer = new SUT([]))->exception(function () use ($analyzer) { $analyzer->analyzeRules([]); })->isInstanceOf(LUT\Exception::class)->hasMessage('No rules specified!'); } public function case_error_while_parsing_rule() { $this->given($tokens = ['default' => ['foo' => 'bar']], $ruleA = '{2,1}', $analyzer = new SUT($tokens))->exception(function () use ($analyzer, $ruleA) { $analyzer->analyzeRules(['ruleA' => $ruleA]); })->isInstanceOf(LUT\Exception::class)->hasMessage('Upper bound 1 must be greater or equal to lower bound ' . '2 in rule ruleA.'); } public function case_kept_token_does_not_exist() { $this->given($tokens = [], $ruleA = '', $analyzer = new SUT($tokens))->exception(function () use ($analyzer, $ruleA) { $analyzer->analyzeRules(['ruleA' => $ruleA]); })->isInstanceOf(LUT\Exception::class)->hasMessage('Token does not exist in rule ruleA.'); } public function case_skipped_token_does_not_exist() { $this->given($tokens = [], $ruleA = '::foo::', $analyzer = new SUT($tokens))->exception(function () use ($analyzer, $ruleA) { $analyzer->analyzeRules(['ruleA' => $ruleA]); })->isInstanceOf(LUT\Exception::class)->hasMessage('Token ::foo:: does not exist in rule ruleA.'); } public function case_rule_does_not_exist() { $this->given($tokens = [], $ruleA = 'ruleB()', $analyzer = new SUT($tokens))->exception(function () use ($analyzer, $ruleA) { $analyzer->analyzeRules(['ruleA' => $ruleA]); })->isInstanceOf(LUT\Exception::class)->hasMessage('Cannot call rule ruleB() in rule ruleA because it does not exist.'); } } when($result = new SUT('foo', 0))->then->object($result)->isInstanceOf(HoaException::class); } } when($result = new SUT('foo', 0))->then->object($result)->isInstanceOf(LUT\Exception::class); } } given($line = 7, $column = 42)->when($result = new SUT('foo', 0, 'bar', $line, $column))->then->object($result)->isInstanceOf(LUT\Exception::class)->integer($result->getLine())->isEqualTo($line)->integer($result->getColumn())->isEqualTo($column); } } when($result = new SUT('foo', 0))->then->object($result)->isInstanceOf(LUT\Exception::class); } } when($result = new SUT('foo', 0))->then->object($result)->isInstanceOf(LUT\Exception::class); } } given($line = 7, $column = 42)->when($result = new SUT('foo', 0, 'bar', $line, $column))->then->object($result)->isInstanceOf(LUT\Exception::class)->integer($result->getLine())->isEqualTo($line)->integer($result->getColumn())->isEqualTo($column); } } given($line = 7, $column = 42)->when($result = new SUT('foo', 0, 'bar', $line, $column))->then->object($result)->isInstanceOf(LUT\Exception::class)->integer($result->getLine())->isEqualTo($line)->integer($result->getColumn())->isEqualTo($column); } } given($lexer = new SUT(), $datum = 'abc', $tokens = ['default' => ['abc' => 'abc']])->when($result = $lexer->lexMe($datum, $tokens))->then->object($result)->isInstanceOf(\Generator::class); } public function case_last_token_is_EOF() { $this->given($lexer = new SUT(), $datum = 'ghidefabc', $tokens = ['default' => ['abc' => 'abc', 'def' => 'def', 'tail' => '\w{3}']])->when($result = $lexer->lexMe($datum, $tokens))->then->object($result)->isInstanceOf(\Generator::class)->array($result->current())->isEqualTo(['token' => 'tail', 'value' => 'ghi', 'length' => 3, 'namespace' => 'default', 'keep' => \true, 'offset' => 0])->let($result->next())->array($result->current())->isEqualTo(['token' => 'def', 'value' => 'def', 'length' => 3, 'namespace' => 'default', 'keep' => \true, 'offset' => 3])->let($result->next())->array($result->current())->isEqualTo(['token' => 'abc', 'value' => 'abc', 'length' => 3, 'namespace' => 'default', 'keep' => \true, 'offset' => 6])->let($result->next())->array($result->current())->isEqualTo(['token' => 'EOF', 'value' => 'EOF', 'length' => 0, 'namespace' => 'default', 'keep' => \true, 'offset' => 9])->let($result->next())->variable($result->current())->isNull(); } public function case_unrecognized_token() { $this->given($lexer = new SUT(), $datum = 'abczdef', $tokens = ['default' => ['abc' => 'abc', 'def' => 'def']])->when($result = $lexer->lexMe($datum, $tokens))->then->array($result->current())->isEqualTo(['token' => 'abc', 'value' => 'abc', 'length' => 3, 'namespace' => 'default', 'keep' => \true, 'offset' => 0])->exception(function () use ($result) { $result->next(); })->isInstanceOf(LUT\Exception\UnrecognizedToken::class)->hasMessage('Unrecognized token "z" at line 1 and column 4:' . "\n" . 'abczdef' . "\n" . ' ↑'); } public function case_namespace() { $this->given($lexer = new SUT(), $datum = 'abcdefghiabc', $tokens = ['default' => ['abc:one' => 'abc'], 'one' => ['def:two' => 'def'], 'two' => ['ghi:default' => 'ghi']])->when($result = $lexer->lexMe($datum, $tokens))->then->array(iterator_to_array($result))->isEqualTo([['token' => 'abc', 'value' => 'abc', 'length' => 3, 'namespace' => 'default', 'keep' => \true, 'offset' => 0], ['token' => 'def', 'value' => 'def', 'length' => 3, 'namespace' => 'one', 'keep' => \true, 'offset' => 3], ['token' => 'ghi', 'value' => 'ghi', 'length' => 3, 'namespace' => 'two', 'keep' => \true, 'offset' => 6], ['token' => 'abc', 'value' => 'abc', 'length' => 3, 'namespace' => 'default', 'keep' => \true, 'offset' => 9], ['token' => 'EOF', 'value' => 'EOF', 'length' => 0, 'namespace' => 'default', 'keep' => \true, 'offset' => 12]]); } public function case_namespace_with_shift() { $this->given($lexer = new SUT(), $datum = 'abcdefghiabc', $tokens = ['default' => ['abc:one' => 'abc'], 'one' => ['def:two' => 'def'], 'two' => ['ghi:__shift__ * 2' => 'ghi']])->when($result = $lexer->lexMe($datum, $tokens))->then->array(iterator_to_array($result))->isEqualTo([['token' => 'abc', 'value' => 'abc', 'length' => 3, 'namespace' => 'default', 'keep' => \true, 'offset' => 0], ['token' => 'def', 'value' => 'def', 'length' => 3, 'namespace' => 'one', 'keep' => \true, 'offset' => 3], ['token' => 'ghi', 'value' => 'ghi', 'length' => 3, 'namespace' => 'two', 'keep' => \true, 'offset' => 6], ['token' => 'abc', 'value' => 'abc', 'length' => 3, 'namespace' => 'default', 'keep' => \true, 'offset' => 9], ['token' => 'EOF', 'value' => 'EOF', 'length' => 0, 'namespace' => 'default', 'keep' => \true, 'offset' => 12]]); } public function case_namespace_shift_too_much() { $this->given($lexer = new SUT(), $datum = 'abcdefghiabc', $tokens = ['default' => ['abc:__shift__' => 'abc']])->when($result = $lexer->lexMe($datum, $tokens))->then->exception(function () use ($result) { $result->next(); })->isInstanceOf(LUT\Exception\Lexer::class)->hasMessage('Cannot shift namespace 1-times, from token abc ' . 'in namespace default, because the stack contains ' . 'only 0 namespaces.'); } public function case_namespace_does_not_exist() { $this->given($lexer = new SUT(), $datum = 'abcdef', $tokens = ['default' => ['abc:foo' => 'abc', 'def' => 'def']])->when($result = $lexer->lexMe($datum, $tokens))->then->exception(function () use ($result) { $result->next(); })->isInstanceOf(LUT\Exception\Lexer::class)->hasMessage('Namespace foo does not exist, called by token abc ' . 'in namespace default.'); } public function case_skip() { $this->given($lexer = new SUT(), $datum = 'abc def ghi abc', $tokens = ['default' => ['skip' => '\s+', 'abc' => 'abc', 'def' => 'def', 'ghi' => 'ghi']])->when($result = $lexer->lexMe($datum, $tokens))->then->array(iterator_to_array($result))->isEqualTo([['token' => 'abc', 'value' => 'abc', 'length' => 3, 'namespace' => 'default', 'keep' => \true, 'offset' => 0], ['token' => 'def', 'value' => 'def', 'length' => 3, 'namespace' => 'default', 'keep' => \true, 'offset' => 4], ['token' => 'ghi', 'value' => 'ghi', 'length' => 3, 'namespace' => 'default', 'keep' => \true, 'offset' => 10], ['token' => 'abc', 'value' => 'abc', 'length' => 3, 'namespace' => 'default', 'keep' => \true, 'offset' => 15], ['token' => 'EOF', 'value' => 'EOF', 'length' => 0, 'namespace' => 'default', 'keep' => \true, 'offset' => 18]]); } public function case_match_empty_lexeme() { $this->given($lexer = new SUT(), $datum = 'abcdef', $tokens = ['default' => ['abc' => '\d?', 'def' => 'def']])->when($result = $lexer->lexMe($datum, $tokens))->then->exception(function () use ($result) { $result->next(); })->isInstanceOf(LUT\Exception\Lexer::class)->hasMessage('A lexeme must not match an empty value, which is ' . 'the case of "abc" (\d?).'); } public function case_unicode_enabled_by_default() { $this->given($lexer = new SUT(), $datum = '…ß', $tokens = ['default' => ['foo' => '…', 'bar' => '\w']])->when($result = $lexer->lexMe($datum, $tokens))->then->array(iterator_to_array($result))->isEqualTo([['token' => 'foo', 'value' => '…', 'length' => 1, 'namespace' => 'default', 'keep' => \true, 'offset' => 0], ['token' => 'bar', 'value' => 'ß', 'length' => 1, 'namespace' => 'default', 'keep' => \true, 'offset' => 3], ['token' => 'EOF', 'value' => 'EOF', 'length' => 0, 'namespace' => 'default', 'keep' => \true, 'offset' => 5]]); } public function case_unicode_disabled() { $this->given($lexer = new SUT(['lexer.unicode' => \false]), $datum = '…ß', $tokens = ['default' => ['foo' => '…', 'bar' => '\w']])->when($result = $lexer->lexMe($datum, $tokens))->then->array($result->current())->isEqualTo(['token' => 'foo', 'value' => '…', 'length' => 1, 'namespace' => 'default', 'keep' => \true, 'offset' => 0])->exception(function () use ($result) { $result->next(); })->isInstanceOf(LUT\Exception\UnrecognizedToken::class)->hasMessage('Unrecognized token "ß" at line 1 and column 4:' . "\n" . '…ß' . "\n" . ' ↑'); } } given($stream = new File\ReadWrite('hoa://Test/Vfs/Empty.pp?type=file'))->exception(function () use ($stream) { SUT::load($stream); })->isInstanceOf(LUT\Exception::class)->hasMessage('The grammar is empty: Nothing to read on the stream ' . 'hoa://Test/Vfs/Empty.pp?type=file.'); } public function case_load() { $this->given($stream = new File\ReadWrite('hoa://Test/Vfs/Grammar.pp?type=file'), $stream->writeAll('%pragma hello world' . "\n" . '%token foobar bazqux' . "\n" . 'ruleA:' . "\n" . ' '), $_ruleA = new LUT\Llk\Rule\Token('ruleA', 'foobar', null, -1, \true), $_ruleA->setPPRepresentation(' '))->when($result = SUT::load($stream))->then->object($result)->isInstanceOf(LUT\Llk\Parser::class)->array($result->getPragmas())->isEqualTo(['hello' => 'world'])->array($result->getTokens())->isEqualTo(['default' => ['foobar' => 'bazqux']])->array($result->getRules())->isEqualTo(['ruleA' => $_ruleA]); } public function case_save() { $this->given($stream = new File\Read('hoa://Library/Compiler/Llk/Llk.pp'), $parser = SUT::load($stream))->when($result = SUT::save($parser, 'Foobar'))->then->string($result)->isEqualTo(<<<'OUTPUT' class Foobar extends \Hoa\Compiler\Llk\Parser { public function __construct() { parent::__construct( [ 'default' => [ 'skip' => '\s', 'or' => '\|', 'zero_or_one' => '\?', 'one_or_more' => '\+', 'zero_or_more' => '\*', 'n_to_m' => '\{[0-9]+,[0-9]+\}', 'zero_to_m' => '\{,[0-9]+\}', 'n_or_more' => '\{[0-9]+,\}', 'exactly_n' => '\{[0-9]+\}', 'token' => '[a-zA-Z_][a-zA-Z0-9_]*', 'skipped' => '::', 'kept_' => '<', '_kept' => '>', 'named' => '\(\)', 'node' => '#[a-zA-Z_][a-zA-Z0-9_]*(:[mM])?', 'capturing_' => '\(', '_capturing' => '\)', 'unification_' => '\[', 'unification' => '[0-9]+', '_unification' => '\]', ], ], [ 0 => new \Hoa\Compiler\Llk\Rule\Concatenation(0, ['choice'], null), 'rule' => new \Hoa\Compiler\Llk\Rule\Concatenation('rule', [0], '#rule'), 2 => new \Hoa\Compiler\Llk\Rule\Token(2, 'or', null, -1, false), 3 => new \Hoa\Compiler\Llk\Rule\Concatenation(3, [2, 'concatenation'], '#choice'), 4 => new \Hoa\Compiler\Llk\Rule\Repetition(4, 0, -1, 3, null), 'choice' => new \Hoa\Compiler\Llk\Rule\Concatenation('choice', ['concatenation', 4], null), 6 => new \Hoa\Compiler\Llk\Rule\Concatenation(6, ['repetition'], '#concatenation'), 7 => new \Hoa\Compiler\Llk\Rule\Repetition(7, 0, -1, 6, null), 'concatenation' => new \Hoa\Compiler\Llk\Rule\Concatenation('concatenation', ['repetition', 7], null), 9 => new \Hoa\Compiler\Llk\Rule\Concatenation(9, ['quantifier'], '#repetition'), 10 => new \Hoa\Compiler\Llk\Rule\Repetition(10, 0, 1, 9, null), 11 => new \Hoa\Compiler\Llk\Rule\Token(11, 'node', null, -1, true), 12 => new \Hoa\Compiler\Llk\Rule\Repetition(12, 0, 1, 11, null), 'repetition' => new \Hoa\Compiler\Llk\Rule\Concatenation('repetition', ['simple', 10, 12], null), 14 => new \Hoa\Compiler\Llk\Rule\Token(14, 'capturing_', null, -1, false), 15 => new \Hoa\Compiler\Llk\Rule\Token(15, '_capturing', null, -1, false), 16 => new \Hoa\Compiler\Llk\Rule\Concatenation(16, [14, 'choice', 15], null), 17 => new \Hoa\Compiler\Llk\Rule\Token(17, 'skipped', null, -1, false), 18 => new \Hoa\Compiler\Llk\Rule\Token(18, 'token', null, -1, true), 19 => new \Hoa\Compiler\Llk\Rule\Token(19, 'unification_', null, -1, false), 20 => new \Hoa\Compiler\Llk\Rule\Token(20, 'unification', null, -1, true), 21 => new \Hoa\Compiler\Llk\Rule\Token(21, '_unification', null, -1, false), 22 => new \Hoa\Compiler\Llk\Rule\Concatenation(22, [19, 20, 21], null), 23 => new \Hoa\Compiler\Llk\Rule\Repetition(23, 0, 1, 22, null), 24 => new \Hoa\Compiler\Llk\Rule\Token(24, 'skipped', null, -1, false), 25 => new \Hoa\Compiler\Llk\Rule\Concatenation(25, [17, 18, 23, 24], '#skipped'), 26 => new \Hoa\Compiler\Llk\Rule\Token(26, 'kept_', null, -1, false), 27 => new \Hoa\Compiler\Llk\Rule\Token(27, 'token', null, -1, true), 28 => new \Hoa\Compiler\Llk\Rule\Token(28, 'unification_', null, -1, false), 29 => new \Hoa\Compiler\Llk\Rule\Token(29, 'unification', null, -1, true), 30 => new \Hoa\Compiler\Llk\Rule\Token(30, '_unification', null, -1, false), 31 => new \Hoa\Compiler\Llk\Rule\Concatenation(31, [28, 29, 30], null), 32 => new \Hoa\Compiler\Llk\Rule\Repetition(32, 0, 1, 31, null), 33 => new \Hoa\Compiler\Llk\Rule\Token(33, '_kept', null, -1, false), 34 => new \Hoa\Compiler\Llk\Rule\Concatenation(34, [26, 27, 32, 33], '#kept'), 35 => new \Hoa\Compiler\Llk\Rule\Token(35, 'token', null, -1, true), 36 => new \Hoa\Compiler\Llk\Rule\Token(36, 'named', null, -1, false), 37 => new \Hoa\Compiler\Llk\Rule\Concatenation(37, [35, 36], null), 'simple' => new \Hoa\Compiler\Llk\Rule\Choice('simple', [16, 25, 34, 37], null), 39 => new \Hoa\Compiler\Llk\Rule\Token(39, 'zero_or_one', null, -1, true), 40 => new \Hoa\Compiler\Llk\Rule\Token(40, 'one_or_more', null, -1, true), 41 => new \Hoa\Compiler\Llk\Rule\Token(41, 'zero_or_more', null, -1, true), 42 => new \Hoa\Compiler\Llk\Rule\Token(42, 'n_to_m', null, -1, true), 43 => new \Hoa\Compiler\Llk\Rule\Token(43, 'n_or_more', null, -1, true), 44 => new \Hoa\Compiler\Llk\Rule\Token(44, 'exactly_n', null, -1, true), 'quantifier' => new \Hoa\Compiler\Llk\Rule\Choice('quantifier', [39, 40, 41, 42, 43, 44], null), ], [ ] ); $this->getRule('rule')->setDefaultId('#rule'); $this->getRule('rule')->setPPRepresentation(' choice()'); $this->getRule('choice')->setPPRepresentation(' concatenation() ( ::or:: concatenation() #choice )*'); $this->getRule('concatenation')->setPPRepresentation(' repetition() ( repetition() #concatenation )*'); $this->getRule('repetition')->setPPRepresentation(' simple() ( quantifier() #repetition )? ?'); $this->getRule('simple')->setPPRepresentation(' ::capturing_:: choice() ::_capturing:: | ::skipped:: ( ::unification_:: ::_unification:: )? ::skipped:: #skipped | ::kept_:: ( ::unification_:: ::_unification:: )? ::_kept:: #kept | ::named::'); $this->getRule('quantifier')->setPPRepresentation(' | | | | | '); } } OUTPUT ); } public function case_parse_tokens() { $this->given($pp = '%token foobar1 bazqux1' . "\n" . '%token sourceNS1:foobar2 bazqux2' . "\n" . '%token sourceNS2:foobar3 bazqux3 -> destinationNS' . "\n" . '%token foobar4 barqux4 -> destinationNS')->when($result = SUT::parsePP($pp, $tokens, $rules, $pragmas, 'streamFoo'))->then->variable($result)->isNull()->array($tokens)->isEqualTo(['default' => ['foobar1' => 'bazqux1', 'foobar4:destinationNS' => 'barqux4'], 'sourceNS1' => ['foobar2' => 'bazqux2'], 'sourceNS2' => ['foobar3:destinationNS' => 'bazqux3']])->array($rules)->isEmpty()->array($pragmas)->isEmpty(); } public function case_parse_skip_tokens() { $this->given($pp = '%skip foobar1 bazqux1' . "\n" . '%skip foobar2 bazqux2' . "\n" . '%skip foobar3 bazqux3' . "\n" . '%skip sourceNS1:foobar4 bazqux4' . "\n" . '%skip sourceNS1:foobar5 bazqux5' . "\n" . '%skip sourceNS2:foobar6 bazqux6' . "\n")->when($result = SUT::parsePP($pp, $tokens, $rules, $pragmas, 'streamFoo'))->then->variable($result)->isNull()->array($tokens)->isEqualTo(['default' => ['skip' => '(?:(?:bazqux1|bazqux2)|bazqux3)'], 'sourceNS1' => ['skip' => '(?:bazqux4|bazqux5)'], 'sourceNS2' => ['skip' => 'bazqux6']])->array($rules)->isEmpty()->array($pragmas)->isEmpty(); } public function case_parse_pragmas() { $this->given($pp = '%pragma truly true' . "\n" . '%pragma falsy false' . "\n" . '%pragma numby 42' . "\n" . '%pragma foobar hello' . "\n" . '%pragma bazqux "world!" ' . "\n")->when($result = SUT::parsePP($pp, $tokens, $rules, $pragmas, 'streamFoo'))->then->variable($result)->isNull()->array($tokens)->isEqualTo(['default' => []])->array($rules)->isEmpty()->array($pragmas)->isIdenticalTo(['truly' => \true, 'falsy' => \false, 'numby' => 42, 'foobar' => 'hello', 'bazqux' => '"world!"']); } public function case_unrecognized_instructions() { $this->given($pp = '// shift line' . "\n" . '%foobar baz qux' . "\n")->exception(function () use ($pp) { SUT::parsePP($pp, $tokens, $rules, $pragmas, 'streamFoo'); })->isInstanceOf(LUT\Exception::class)->hasMessage('Unrecognized instructions:' . "\n" . ' %foobar baz qux' . "\n" . 'in file streamFoo at line 2.'); } public function case_parse_rules() { $this->given($pp = 'ruleA:' . "\n" . ' single space' . "\n" . ' single space' . "\n" . 'ruleB:' . "\n" . ' many spaces' . "\n" . "\t" . 'single tab' . "\n" . 'ruleC:' . "\n" . "\t\t" . 'many tabs' . "\n")->when($result = SUT::parsePP($pp, $tokens, $rules, $pragmas, 'streamFoo'))->then->variable($result)->isNull()->array($tokens)->isEqualTo(['default' => []])->array($rules)->isEqualTo(['ruleA' => ' single space single space', 'ruleB' => ' many spaces single tab', 'ruleC' => ' many tabs'])->array($pragmas)->isEmpty(); } public function case_parse_skip_comments() { $this->given($pp = '// Hello,' . "\n" . '// World!')->when($result = SUT::parsePP($pp, $tokens, $rules, $pragmas, 'streamFoo'))->then->variable($result)->isNull()->array($tokens)->isEqualTo(['default' => []])->array($rules)->isEmpty()->array($pragmas)->isEmpty(); } } when($result = new SUT('foo', ['bar']))->then->object($result)->isInstanceOf(LUT\Llk\Rule::class); } } when($result = new SUT('foo', ['bar']))->then->object($result)->isInstanceOf(LUT\Llk\Rule::class); } } when($result = new SUT('foo', ['bar']))->then->object($result)->isInstanceOf(LUT\Llk\Rule\Invocation::class); } } when($result = new SUT('foo', ['bar']))->then->object($result)->isInstanceOf(LUT\Llk\Rule\Invocation::class); } } given($rule = 'foo', $data = 'bar')->when($result = new SUT($rule, $data))->then->string($result->getRule())->isEqualTo($rule)->string($result->getData())->isEqualTo($data)->variable($result->getTodo())->isNull()->integer($result->getDepth())->isEqualTo(-1)->boolean($result->isTransitional())->isFalse(); } public function case_constructor_with_todo() { $this->given($rule = 'foo', $data = 'bar', $todo = ['baz', 'qux'])->when($result = new SUT($rule, $data, $todo))->then->string($result->getRule())->isEqualTo($rule)->string($result->getData())->isEqualTo($data)->array($result->getTodo())->isEqualTo($todo)->integer($result->getDepth())->isEqualTo(-1)->boolean($result->isTransitional())->isFalse(); } public function case_constructor_with_todo_and_depth() { $this->given($rule = 'foo', $data = 'bar', $todo = ['baz', 'qux'], $depth = 42)->when($result = new SUT($rule, $data, $todo, $depth))->then->string($result->getRule())->isEqualTo($rule)->string($result->getData())->isEqualTo($data)->array($result->getTodo())->isEqualTo($todo)->integer($result->getDepth())->isEqualTo($depth)->boolean($result->isTransitional())->isFalse(); } public function case_set_depth() { $this->given($rule = 42, $data = 'bar', $todo = ['baz', 'qux'], $depth = 42, $invocation = new SUT($rule, $data))->when($result = $invocation->setDepth($depth))->then->integer($result)->isEqualTo(-1); } public function case_get_depth() { $this->given($rule = 42, $data = 'bar', $todo = ['baz', 'qux'], $depth = 42, $invocation = new SUT($rule, $data), $invocation->setDepth($depth))->when($result = $invocation->getDepth())->then->integer($result)->isEqualTo($depth); } public function case_is_transitional() { $this->given($rule = 42, $data = 'bar', $invocation = new SUT($rule, $data))->when($result = $invocation->isTransitional())->then->boolean($result)->isTrue(); } } when($result = new SUT('foo', 7, 42, [], 'bar'))->then->object($result)->isInstanceOf(LUT\Llk\Rule::class); } public function case_constructor() { $this->given($name = 'foo', $min = 7, $max = 42, $children = [], $id = 'bar')->when($result = new SUT($name, $min, $max, $children, $id))->then->string($result->getName())->isEqualTo($name)->integer($result->getMin())->isEqualTo($min)->integer($result->getMax())->isEqualTo($max)->array($result->getChildren())->isEqualTo($children)->string($result->getNodeId())->isEqualTo($id)->boolean($result->isInfinite())->isFalse(); } public function case_constructor_min_and_max_are_casted_and_bounded() { $this->given($name = 'foo', $min = '-7', $max = '42', $children = [], $id = 'bar')->when($result = new SUT($name, $min, $max, $children, $id))->then->integer($result->getMin())->isEqualTo(0)->integer($result->getMax())->isEqualTo(42)->boolean($result->isInfinite())->isFalse(); } public function case_constructor_min_is_greater_than_max() { $this->given($name = 'foo', $min = 2, $max = 1, $children = [], $id = 'bar')->exception(function () use ($name, $min, $max, $children, $id) { new SUT($name, $min, $max, $children, $id); })->isInstanceOf(LUT\Exception\Rule::class)->hasMessage('Cannot repeat with a min (2) greater than max (1).'); } public function case_constructor_infinite_max() { $this->given($name = 'foo', $min = 2, $max = -1, $children = [], $id = 'bar')->when($result = new SUT($name, $min, $max, $children, $id))->then->integer($result->getMin())->isEqualTo(2)->integer($result->getMax())->isEqualTo(-1)->boolean($result->isInfinite())->isTrue(); } public function case_get_min() { return $this->case_constructor(); } public function case_get_max() { return $this->case_constructor(); } } given($name = 'foo', $children = ['bar'])->when($result = new SUT($name, $children))->then->string($result->getName())->isEqualTo($name)->array($result->getChildren())->isEqualTo($children)->variable($result->getNodeId())->isNull()->boolean($result->isTransitional())->isTrue(); } public function case_constructor_with_node_id() { $this->given($name = 'foo', $children = ['bar'], $nodeId = 'baz')->when($result = new SUT($name, $children, $nodeId))->then->string($result->getName())->isEqualTo($name)->array($result->getChildren())->isEqualTo($children)->string($result->getNodeId())->isEqualTo($nodeId)->boolean($result->isTransitional())->isTrue(); } public function case_set_name() { $this->given($name = 'foo', $children = ['bar'], $rule = new SUT($name, $children))->when($result = $rule->setName('baz'))->then->string($result)->isEqualTo($name); } public function case_get_name() { $this->given($name = 'baz', $children = ['bar'], $rule = new SUT('foo', $children), $rule->setName($name))->when($result = $rule->getName())->then->string($result)->isEqualTo($name); } public function case_set_children() { $this->given($name = 'foo', $children = ['bar'], $rule = new SUT($name, $children))->when($result = $this->invoke($rule)->setChildren(['baz']))->then->array($result)->isEqualTo($children); } public function case_get_children() { $this->given($name = 'foo', $children = ['baz'], $rule = new SUT($name, ['bar']), $this->invoke($rule)->setChildren($children))->when($result = $rule->getChildren())->then->array($result)->isEqualTo($children); } public function case_set_node_id() { $this->given($name = 'foo', $children = ['bar'], $nodeId = 'id', $rule = new SUT($name, $children, $nodeId))->when($result = $rule->setNodeId('baz:qux'))->then->string($result)->isEqualTo($nodeId); } public function case_get_node_id() { $this->given($name = 'foo', $children = ['bar'], $rule = new SUT($name, $children), $rule->setNodeId('baz'))->when($result = $rule->getNodeId())->then->string($result)->isEqualTo('baz'); } public function case_get_node_id_with_options() { $this->given($name = 'foo', $children = ['bar'], $rule = new SUT($name, $children), $rule->setNodeId('baz:qux'))->when($result = $rule->getNodeId())->then->string($result)->isEqualTo('baz'); } public function case_get_node_options_empty() { $this->given($name = 'foo', $children = ['bar'], $rule = new SUT($name, $children), $rule->setNodeId('baz'))->when($result = $rule->getNodeOptions())->then->array($result)->isEmpty(); } public function case_get_node_options() { $this->given($name = 'foo', $children = ['bar'], $rule = new SUT($name, $children), $rule->setNodeId('baz:qux'))->when($result = $rule->getNodeOptions())->then->array($result)->isEqualTo(['q', 'u', 'x']); } public function case_set_default_id() { $this->given($name = 'foo', $children = ['bar'], $nodeId = 'id', $rule = new SUT($name, $children, $nodeId))->when($result = $rule->setDefaultId('baz:qux'))->then->variable($result)->isNull(); } public function case_get_default_id() { $this->given($name = 'foo', $children = ['bar'], $rule = new SUT($name, $children), $rule->setDefaultId('baz'))->when($result = $rule->getDefaultId())->then->string($result)->isEqualTo('baz'); } public function case_get_default_id_with_options() { $this->given($name = 'foo', $children = ['bar'], $rule = new SUT($name, $children), $rule->setDefaultId('baz:qux'))->when($result = $rule->getDefaultId())->then->string($result)->isEqualTo('baz'); } public function case_get_default_options_empty() { $this->given($name = 'foo', $children = ['bar'], $rule = new SUT($name, $children), $rule->setDefaultId('baz'))->when($result = $rule->getDefaultOptions())->then->array($result)->isEmpty(); } public function case_get_default_options() { $this->given($name = 'foo', $children = ['bar'], $rule = new SUT($name, $children), $rule->setDefaultId('baz:qux'))->when($result = $rule->getDefaultOptions())->then->array($result)->isEqualTo(['q', 'u', 'x']); } public function case_set_pp_representation() { $this->given($name = 'foo', $children = ['bar'], $pp = ' ::b:: c()?', $rule = new SUT($name, $children), $oldIsTransitional = $rule->isTransitional())->when($result = $rule->setPPRepresentation($pp))->then->variable($result)->isNull()->boolean($oldIsTransitional)->isTrue()->boolean($rule->isTransitional())->isFalse(); } public function case_get_pp_representation() { $this->given($name = 'foo', $children = ['bar'], $pp = ' ::b:: c()?', $rule = new SUT($name, $children), $rule->setPPRepresentation($pp))->when($result = $rule->getPPRepresentation())->then->string($result)->isEqualTo($pp); } public function case_is_transitional() { $this->given($name = 'foo', $children = ['bar'], $pp = ' ::b:: c()?', $rule = new SUT($name, $children), $oldIsTransitional = $rule->isTransitional(), $rule->setPPRepresentation($pp))->when($result = $rule->isTransitional())->then->boolean($oldIsTransitional)->isTrue()->boolean($result)->isFalse(); } } when($result = new SUT('name', 'tokenName', 'nodeId', 0))->then->object($result)->isInstanceOf(LUT\Llk\Rule::class); } public function case_constructor() { $this->given($name = 'foo', $tokenName = 'bar', $nodeId = 'baz', $unification = 0)->when($result = new SUT($name, $tokenName, $nodeId, $unification))->then->string($result->getName())->isEqualTo($name)->string($result->getTokenName())->isEqualTo($tokenName)->string($result->getNodeId())->isEqualTo($nodeId)->integer($result->getUnificationIndex())->isEqualTo($unification)->boolean($result->isKept())->isFalse(); } public function case_constructor_with_kept_flag() { $this->given($name = 'foo', $tokenName = 'bar', $nodeId = 'baz', $unification = 0, $kept = \true)->when($result = new SUT($name, $tokenName, $nodeId, $unification, $kept))->then->string($result->getName())->isEqualTo($name)->string($result->getTokenName())->isEqualTo($tokenName)->string($result->getNodeId())->isEqualTo($nodeId)->integer($result->getUnificationIndex())->isEqualTo($unification)->boolean($result->isKept())->isTrue(); } public function case_get_token_name() { $this->given($name = 'foo', $tokenName = 'bar', $nodeId = 'baz', $unification = 0, $token = new SUT($name, $tokenName, $nodeId, $unification))->when($result = $token->getTokenName())->then->string($result)->isEqualTo($tokenName); } public function case_set_namespace() { $this->given($name = 'foo', $tokenName = 'bar', $nodeId = 'baz', $unification = 0, $namespace = 'qux', $token = new SUT($name, $tokenName, $nodeId, $unification))->when($result = $token->setNamespace($namespace))->then->variable($result)->isNull(); } public function case_get_namespace() { $this->given($name = 'foo', $tokenName = 'bar', $nodeId = 'baz', $unification = 0, $namespace = 'qux', $token = new SUT($name, $tokenName, $nodeId, $unification), $token->setNamespace($namespace))->when($result = $token->getNamespace())->then->string($result)->isEqualTo($namespace); } public function case_set_representation() { $this->given($name = 'foo', $tokenName = 'bar', $nodeId = 'baz', $unification = 0, $representation = 'qux', $token = new SUT($name, $tokenName, $nodeId, $unification))->when($result = $token->setRepresentation($representation))->then->variable($result)->isNull(); } public function case_get_representation() { $this->given($name = 'foo', $tokenName = 'bar', $nodeId = 'baz', $unification = 0, $representation = 'qux', $token = new SUT($name, $tokenName, $nodeId, $unification), $token->setRepresentation($representation))->when($result = $token->getRepresentation())->then->string($result)->isEqualTo($representation); } public function case_get_ast() { $this->given($name = 'foo', $tokenName = 'bar', $nodeId = 'baz', $unification = 0, $representation = 'qux', $token = new SUT($name, $tokenName, $nodeId, $unification), $token->setRepresentation($representation))->when($result = $token->getAST())->then->object($result)->isInstanceOf(LUT\Llk\TreeNode::class)->let($dumper = new LUT\Visitor\Dump())->string($dumper->visit($result))->isEqualTo('> #expression' . "\n" . '> > #concatenation' . "\n" . '> > > token(literal, q)' . "\n" . '> > > token(literal, u)' . "\n" . '> > > token(literal, x)' . "\n"); } public function case_set_value() { $this->given($name = 'foo', $tokenName = 'bar', $nodeId = 'baz', $unification = 0, $value = 'qux', $token = new SUT($name, $tokenName, $nodeId, $unification))->when($result = $token->setValue($value))->then->variable($result)->isNull(); } public function case_get_value() { $this->given($name = 'foo', $tokenName = 'bar', $nodeId = 'baz', $unification = 0, $value = 'qux', $token = new SUT($name, $tokenName, $nodeId, $unification), $token->setValue($value))->when($result = $token->getValue())->then->string($result)->isEqualTo($value); } public function case_set_kept() { $this->given($name = 'foo', $tokenName = 'bar', $nodeId = 'baz', $unification = 0, $kept = \true, $token = new SUT($name, $tokenName, $nodeId, $unification))->when($result = $token->setKept($kept))->then->boolean($result)->isFalse(); } public function case_is_kept() { $this->given($name = 'foo', $tokenName = 'bar', $nodeId = 'baz', $unification = 0, $kept = \true, $token = new SUT($name, $tokenName, $nodeId, $unification), $token->setKept($kept))->when($result = $token->isKept())->then->boolean($result)->isTrue(); } public function case_get_unification_index() { $this->given($name = 'foo', $tokenName = 'bar', $nodeId = 'baz', $unification = 42, $token = new SUT($name, $tokenName, $nodeId, $unification))->when($result = $token->getUnificationIndex())->then->integer($result)->isEqualTo($unification); } } when($result = new SUT('foo', 0))->then->object($result)->isInstanceOf(LUT\Exception::class); } } when($node = new SUT('foo'))->then->object($node)->isInstanceOf(Visitor\Element::class); } public function case_constructor() { $this->given($id = 'foo')->when($node = new SUT($id))->then->string($node->getId())->isEqualTo($id)->variable($node->getValue())->isNull()->integer($node->getChildrenNumber())->isEqualTo(0)->array($node->getChildren())->isEmpty()->variable($node->getParent())->isNull(); } public function case_constructor_with_a_value() { $this->given($id = 'foo', $value = ['bar'])->when($node = new SUT($id, $value))->then->string($node->getId())->isEqualTo($id)->array($node->getValue())->isEqualTo($value)->integer($node->getChildrenNumber())->isEqualTo(0)->array($node->getChildren())->isEmpty()->variable($node->getParent())->isNull(); } public function case_constructor_with_a_value_and_children() { $this->given($id = 'foo', $value = ['bar'], $children = [new SUT('baz'), new SUT('qux')])->when($node = new SUT($id, $value, $children))->then->string($node->getId())->isEqualTo($id)->array($node->getValue())->isEqualTo($value)->integer($node->getChildrenNumber())->isEqualTo(2)->array($node->getChildren())->isEqualTo($children)->variable($node->getParent())->isNull(); } public function case_constructor_with_a_value_and_children_and_a_parent() { $this->given($id = 'foo', $value = ['bar'], $children = [new SUT('baz'), new SUT('qux')], $parent = new SUT('root'))->when($node = new SUT($id, $value, $children, $parent))->then->string($node->getId())->isEqualTo($id)->array($node->getValue())->isEqualTo($value)->integer($node->getChildrenNumber())->isEqualTo(2)->array($node->getChildren())->isEqualTo($children)->object($node->getParent())->isIdenticalTo($parent); } public function case_set_id() { $this->given($node = new SUT('foo'))->when($result = $node->setId('bar'))->then->string($result)->isEqualTo('foo'); } public function case_get_id() { $this->given($node = new SUT('foo'), $node->setId('bar'))->when($result = $node->getId())->then->string($result)->isEqualTo('bar'); } public function case_set_value() { $this->given($node = new SUT('foo', ['bar']))->when($result = $node->setValue(['baz']))->then->array($result)->isEqualTo(['bar']); } public function case_get_value() { $this->given($node = new SUT('foo', ['bar']), $node->setValue(['baz']))->when($result = $node->getValue())->then->array($result)->isEqualTo(['baz']); } public function case_get_value_token() { $this->given($node = new SUT('foo', ['token' => 'bar']))->when($result = $node->getValueToken())->then->string($result)->isEqualTo('bar'); } public function case_get_value_token_undefined() { $this->given($node = new SUT('foo', ['bar']))->when($result = $node->getValueToken())->then->variable($result)->isNull(); } public function case_get_value_value() { $this->given($node = new SUT('foo', ['value' => 'bar']))->when($result = $node->getValueValue())->then->string($result)->isEqualTo('bar'); } public function case_get_value_value_undefined() { $this->given($node = new SUT('foo', ['bar']))->when($result = $node->getValueValue())->then->variable($result)->isNull(); } public function case_is_token() { $this->given($node = new SUT('foo', ['bar']))->when($result = $node->isToken())->then->boolean($result)->isTrue(); } public function case_is_not_token() { $this->given($node = new SUT('foo'))->when($result = $node->isToken())->then->boolean($result)->isFalse(); } public function case_prepend_child() { $this->given($childA = new SUT('baz'), $childB = new SUT('qux'), $node = new SUT('foo', ['bar'], [$childA]))->when($result = $node->prependChild($childB))->then->object($result)->isIdenticalTo($node)->integer($result->getChildrenNumber())->isEqualTo(2)->array($result->getChildren())->isEqualTo([$childB, $childA]); } public function case_append_child() { $this->given($childA = new SUT('baz'), $childB = new SUT('qux'), $node = new SUT('foo', ['bar'], [$childA]))->when($result = $node->appendChild($childB))->then->object($result)->isIdenticalTo($node)->integer($result->getChildrenNumber())->isEqualTo(2)->array($result->getChildren())->isEqualTo([$childA, $childB]); } public function case_set_children() { $this->given($childA = new SUT('baz'), $childB = new SUT('qux'), $childC = new SUT('hello'), $node = new SUT('foo', ['bar'], [$childA]))->when($result = $node->setChildren([$childB, $childC]))->then->array($result)->isEqualTo([$childA])->integer($node->getChildrenNumber())->isEqualTo(2)->array($node->getChildren())->isEqualTo([$childB, $childC]); } public function case_get_child() { $this->given($childA = new SUT('baz'), $childB = new SUT('qux'), $node = new SUT('foo', ['bar'], [$childA, $childB]))->when($result = $node->getChild(0))->then->object($result)->isIdenticalTo($childA)->when($result = $node->getChild(1))->then->object($result)->isIdenticalTo($childB); } public function case_get_child_undefined() { $this->given($node = new SUT('foo', ['bar']))->when($result = $node->getChild(0))->then->variable($result)->isNull(); } public function case_get_children() { $this->given($childA = new SUT('baz'), $childB = new SUT('qux'), $node = new SUT('foo', ['bar'], [$childA, $childB]))->when($result = $node->getChildren())->then->array($result)->isEqualTo([$childA, $childB]); } public function case_get_children_number() { $this->given($childA = new SUT('baz'), $childB = new SUT('qux'), $node = new SUT('foo', ['bar']))->when($result = $node->getChildrenNumber())->then->integer($result)->isEqualTo(0)->when($node->setChildren([$childA, $childB]), $result = $node->getChildrenNumber())->then->integer($result)->isEqualTo(2); } public function case_child_exists() { $this->given($node = new SUT('foo', ['bar'], [new SUT('baz')]))->when($result = $node->childExists(0))->then->boolean($result)->isTrue(); } public function case_child_does_not_exist() { $this->given($node = new SUT('foo', ['bar']))->when($result = $node->childExists(0))->then->boolean($result)->isFalse(); } public function case_set_parent() { $this->given($parent = new SUT('baz'), $node = new SUT('foo', ['bar'], [], $parent))->when($result = $node->setParent(new SUT('qux')))->then->object($result)->isIdenticalTo($parent); } public function case_get_parent() { $this->given($parent = new SUT('qux'), $node = new SUT('foo', ['bar'], [], new SUT('baz')), $node->setParent($parent))->when($result = $node->getParent())->then->object($result)->isIdenticalTo($parent); } public function case_get_data() { $this->given($node = new SUT('foo'))->when($result = $node->getData())->then->array($result)->isEmpty()->when($result[] = 'bar', $result[] = 'baz', $result = $node->getData())->then->array($result)->isEmpty(); } public function case_get_data_by_reference() { $this->given($node = new SUT('foo'))->when($result =& $node->getData())->then->array($result)->isEmpty()->when($result[] = 'bar', $result[] = 'baz', $result = $node->getData())->then->array($result)->isEqualTo(['bar', 'baz']); } } ', self::$_i) . $element->getId(); if (null !== $value = $element->getValue()) { $out .= '(' . ('default' !== $value['namespace'] ? $value['namespace'] . ':' : '') . $value['token'] . ', ' . $value['value'] . ')'; } $data = $element->getData(); if (!empty($data)) { $out .= ' ' . $this->dumpData($data); } $out .= "\n"; foreach ($element->getChildren() as $child) { $out .= $child->accept($this, $handle, $eldnah); } --self::$_i; return $out; } /** * Dump data. * * @param mixed $data Data. * @return string */ protected function dumpData($data) { $out = null; if (!is_array($data)) { return $data; } foreach ($data as $key => $value) { $out .= '[' . $key . ' => ' . $this->dumpData($value) . ']'; } return $out; } } _namespacePrefixesToBaseDirectories[$prefix])) { $this->_namespacePrefixesToBaseDirectories[$prefix] = []; } if (\true === $prepend) { array_unshift($this->_namespacePrefixesToBaseDirectories[$prefix], $baseDirectory); } else { array_push($this->_namespacePrefixesToBaseDirectories[$prefix], $baseDirectory); } return; } /** * Try to load the entity file for a given entity name. * * @param string $entity Entity name to load. * @return bool */ public function load($entity) { $entityPrefix = $entity; $hasBaseDirectory = \false; while (\false !== $pos = strrpos($entityPrefix, '\\')) { $currentEntityPrefix = substr($entity, 0, $pos + 1); $entityPrefix = rtrim($currentEntityPrefix, '\\'); $entitySuffix = substr($entity, $pos + 1); $entitySuffixAsPath = str_replace('\\', '/', $entitySuffix); if (\false === $this->hasBaseDirectory($currentEntityPrefix)) { continue; } $hasBaseDirectory = \true; foreach ($this->getBaseDirectories($currentEntityPrefix) as $baseDirectory) { $file = $baseDirectory . $entitySuffixAsPath . '.php'; if (\false !== $this->requireFile($file)) { return $file; } } } if (\true === $hasBaseDirectory && $entity === \Hoa\Consistency\Consistency::getEntityShortestName($entity) && \false !== $pos = strrpos($entity, '\\')) { return $this->runAutoloaderStack($entity . '\\' . substr($entity, $pos + 1)); } return null; } /** * Require a file if exists. * * @param string $filename File name. * @return bool */ public function requireFile($filename) { if (\false === file_exists($filename)) { return \false; } require $filename; return \true; } /** * Check whether at least one base directory exists for a namespace prefix. * * @param string $namespacePrefix Namespace prefix. * @return bool */ public function hasBaseDirectory($namespacePrefix) { return isset($this->_namespacePrefixesToBaseDirectories[$namespacePrefix]); } /** * Get declared base directories for a namespace prefix. * * @param string $namespacePrefix Namespace prefix. * @return array */ public function getBaseDirectories($namespacePrefix) { if (\false === $this->hasBaseDirectory($namespacePrefix)) { return []; } return $this->_namespacePrefixesToBaseDirectories[$namespacePrefix]; } /** * Get loaded classes. * * @return array */ public static function getLoadedClasses() { return get_declared_classes(); } /** * Run the entire autoloader stack with a specific entity. * * @param string $entity Entity name to load. * @return void */ public function runAutoloaderStack($entity) { return spl_autoload_call($entity); } /** * Register the autoloader. * * @param bool $prepend Prepend this autoloader to the stack or not. * @return bool */ public function register($prepend = \false) { return spl_autoload_register([$this, 'load'], \true, $prepend); } /** * Unregister the autoloader. * * @return bool */ public function unregister() { return spl_autoload_unregister([$this, 'load']); } /** * Get all registered autoloaders (not only from this library). * * @return array */ public function getRegisteredAutoloaders() { return spl_autoload_functions(); } /** * Dynamic new, a simple factory. * It loads and constructs a class, with provided arguments. * * @param bool $classname Classname. * @param array $arguments Arguments for the constructor. * @return object */ public static function dnew($classname, array $arguments = []) { $classname = ltrim($classname, '\\'); if (\false === \Hoa\Consistency\Consistency::entityExists($classname, \false)) { spl_autoload_call($classname); } $class = new \ReflectionClass($classname); if (empty($arguments) || \false === $class->hasMethod('__construct')) { return $class->newInstance(); } return $class->newInstanceArgs($arguments); } } /** * Autoloader. */ $autoloader = new \Hoa\Consistency\Autoloader(); $autoloader->addNamespace('Hoa', dirname(__DIR__)); $autoloader->register(); = $count) { return $entityName; } if ($parts[$count - 2] === $parts[$count - 1]) { return implode('\\', array_slice($parts, 0, -1)); } return $entityName; } /** * Declare a flex entity (for nested library). * * @param string $entityName Entity name. * @return bool */ public static function flexEntity($entityName) { return class_alias($entityName, static::getEntityShortestName($entityName), \false); } /** * Whether a word is reserved or not. * * @param string $word Word. * @return bool */ public static function isKeyword($word) { static $_list = [ // PHP keywords. '__halt_compiler', 'abstract', 'and', 'array', 'as', 'bool', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'false', 'final', 'float', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'int', 'interface', 'isset', 'list', 'mixed', 'namespace', 'new', 'null', 'numeric', 'object', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'resource', 'return', 'static', 'string', 'switch', 'throw', 'trait', 'true', 'try', 'unset', 'use', 'var', 'void', 'while', 'xor', 'yield', // Compile-time constants. '__class__', '__dir__', '__file__', '__function__', '__line__', '__method__', '__namespace__', '__trait__', ]; return in_array(strtolower($word), $_list); } /** * Whether an ID is a valid PHP identifier. * * @param string $id ID. * @return bool */ public static function isIdentifier($id) { return 0 !== preg_match('#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x80-\xff]*$#', $id); } /** * Register a register shutdown function. * It may be analogous to a super static destructor. * * @param callable $callable Callable. * @return bool */ public static function registerShutdownFunction($callable) { return register_shutdown_function($callable); } /** * Get PHP executable. * * @return string */ public static function getPHPBinary() { if (defined('PHP_BINARY')) { return \PHP_BINARY; } if (isset($_SERVER['_'])) { return $_SERVER['_']; } foreach (['', '.exe'] as $extension) { if (file_exists($_ = \PHP_BINDIR . DS . 'php' . $extension)) { return realpath($_); } } return null; } /** * Generate an Universal Unique Identifier (UUID). * * @return string */ public static function uuid() { return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xfff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)); } } namespace _PHPStan_33c983f26; if (70000 > \PHP_VERSION_ID && \false === \interface_exists('Throwable', \false)) { /** * Implement a fake Throwable class, introduced in PHP7.0. */ interface Throwable { public function getMessage(); public function getCode(); public function getFile(); public function getLine(); public function getTrace(); public function getPrevious(); public function getTraceAsString(); public function __toString(); } /** * Implement a fake Throwable class, introduced in PHP7.0. */ \class_alias('_PHPStan_33c983f26\Throwable', 'Throwable', \false); } /** * Define TLSv* constants, introduced in PHP 5.5. */ if (50600 > \PHP_VERSION_ID) { $define = function ($constantName, $constantValue, $case = \false) { if (!\defined($constantName)) { return \define($constantName, $constantValue, $case); } return \false; }; $define('STREAM_CRYPTO_METHOD_TLSv1_0_SERVER', 8); $define('STREAM_CRYPTO_METHOD_TLSv1_1_SERVER', 16); $define('STREAM_CRYPTO_METHOD_TLSv1_2_SERVER', 32); $define('STREAM_CRYPTO_METHOD_ANY_SERVER', 62); $define('STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT', 9); $define('STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT', 17); $define('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT', 33); $define('STREAM_CRYPTO_METHOD_ANY_CLIENT', 63); } /** * Flex entity. */ \Hoa\Consistency\Consistency::flexEntity('Hoa\Consistency\Consistency'); given($autoloader = new SUT(), $prefix = 'Foo\Bar\\', $baseDirectoryA = 'Source/Foo/Bar/', $baseDirectoryB = 'Source/Foo/Bar/')->when($autoloader->addNamespace($prefix, $baseDirectoryA), $result = $autoloader->addNamespace($prefix, $baseDirectoryB))->then->boolean($autoloader->hasBaseDirectory($prefix))->isTrue()->array($autoloader->getBaseDirectories($prefix))->isEqualTo([$baseDirectoryB, $baseDirectoryA]); } public function case_add_namespace_append() { $this->given($autoloader = new SUT(), $prefix = 'Foo\Bar\\', $baseDirectoryA = 'Source/Foo/Bar/', $baseDirectoryB = 'Source/Foo/Bar/')->when($autoloader->addNamespace($prefix, $baseDirectoryA), $result = $autoloader->addNamespace($prefix, $baseDirectoryB))->then->boolean($autoloader->hasBaseDirectory($prefix))->isTrue()->array($autoloader->getBaseDirectories($prefix))->isEqualTo([$baseDirectoryA, $baseDirectoryB]); } public function case_add_namespace_with_invalid_prefix() { $this->given($autoloader = new SUT(), $prefix = '\\\\Foo\Bar', $baseDirectory = 'Source/Foo/Bar/')->when($result = $autoloader->addNamespace($prefix, $baseDirectory))->then->boolean($autoloader->hasBaseDirectory('Foo\Bar\\'))->isTrue()->array($autoloader->getBaseDirectories('Foo\Bar\\'))->isEqualTo([$baseDirectory]); } public function case_add_namespace_with_invalid_base_directory() { $this->given($autoloader = new SUT(), $prefix = 'Foo\Bar\\', $baseDirectory = 'Source/Foo/Bar')->when($result = $autoloader->addNamespace($prefix, $baseDirectory))->then->boolean($autoloader->hasBaseDirectory('Foo\Bar\\'))->isTrue()->array($autoloader->getBaseDirectories('Foo\Bar\\'))->isEqualTo(['Source/Foo/Bar/']); } public function case_add_namespace_with_crazy_invalid_base_directory() { $this->given($autoloader = new SUT(), $prefix = 'Foo\Bar\\', $baseDirectory = 'Source/Foo/Bar/////')->when($result = $autoloader->addNamespace($prefix, $baseDirectory))->then->boolean($autoloader->hasBaseDirectory('Foo\Bar\\'))->isTrue()->array($autoloader->getBaseDirectories('Foo\Bar\\'))->isEqualTo(['Source/Foo/Bar/']); } public function case_load() { $this->given($autoloader = new \Mock\Hoa\Consistency\Autoloader(), $autoloader->addNamespace('Foo\Bar\\', 'Source/Foo/Bar/'), $this->calling($autoloader)->requireFile = function ($file) { return $file; })->when($result = $autoloader->load('_PHPStan_33c983f26\Foo\Bar\Baz\Qux'))->then->string($result)->isEqualTo('Source/Foo/Bar/Baz/Qux.php'); } public function case_load_invalid_entity() { $this->given($autoloader = new SUT())->when($result = $autoloader->load('Foo'))->then->variable($result)->isNull(); } public function case_load_flex_entity() { $self = $this; $this->given($autoloader = new \Mock\Hoa\Consistency\Autoloader(), $autoloader->addNamespace('Foo\Bar\\', 'Source/Foo/'), $this->calling($autoloader)->runAutoloaderStack = function ($entity) use ($self, &$called) { $called = \true; $self->string($entity)->isEqualTo('_PHPStan_33c983f26\Foo\Bar\Baz\Baz'); return; }, $autoloader->register())->when($result = $autoloader->load('_PHPStan_33c983f26\Foo\Bar\Baz'))->then->variable($result)->isNull()->boolean($called)->isTrue(); } public function case_load_unmapped_flex_entity() { $self = $this; $this->given($autoloader = new \Mock\Hoa\Consistency\Autoloader(), $this->calling($autoloader)->runAutoloaderStack = function ($entity) use ($self, &$called) { $called = \true; return; }, $autoloader->register())->when($result = $autoloader->load('_PHPStan_33c983f26\Foo\Bar\Baz'))->then->variable($result)->isNull()->variable($called)->isNull(); } public function case_require_existing_file() { $this->given($autoloader = new SUT(), $this->function->file_exists = \true, $constantName = 'HOA_TEST_' . uniqid(), $filename = 'hoa://Test/Vfs/Foo?type=file', file_put_contents($filename, 'when($result = $autoloader->requireFile($filename))->then->boolean($result)->isTrue()->string(constant($constantName))->isEqualTo('BAR'); } public function case_require_not_existing_file() { $this->given($autoloader = new SUT(), $this->function->file_exists = \false)->when($result = $autoloader->requireFile('/hoa/flatland'))->then->boolean($result)->isFalse(); } public function case_has_not_base_directory() { $this->given($autoloader = new SUT())->when($result = $autoloader->hasBaseDirectory('foo'))->then->boolean($result)->isFalse(); } public function case_get_base_undeclared_namespace_prefix() { $this->given($autoloader = new SUT())->when($result = $autoloader->getBaseDirectories('foo'))->then->array($result)->isEmpty(); } public function case_dnew() { $this->given($classname = 'Hoa\Consistency\Autoloader')->when($result = SUT::dnew($classname))->then->object($result)->isInstanceOf($classname); } public function case_dnew_unknown_class() { $this->given($this->function->spl_autoload_call = null)->exception(function () { SUT::dnew('Foo'); })->isInstanceOf('ReflectionException'); } public function case_get_loaded_classes() { $this->given($declaredClasses = get_declared_classes(), $this->function->get_declared_classes = $declaredClasses)->when($result = SUT::getLoadedClasses())->then->array($result)->isEqualTo($declaredClasses); } public function case_register() { $self = $this; $this->given($autoloader = new SUT())->when($result = $autoloader->register())->then->boolean($result)->isTrue()->array($autoloader->getRegisteredAutoloaders())->isEqualTo(spl_autoload_functions()); } public function case_unregister() { $this->given($autoloader = new SUT(), $oldRegisteredAutoloaders = $autoloader->getRegisteredAutoloaders())->when($result = $autoloader->register())->then->boolean($result)->isTrue()->integer(count($autoloader->getRegisteredAutoloaders()))->isEqualTo(count($oldRegisteredAutoloaders) + 1)->when($result = $autoloader->unregister())->then->boolean($result)->isTrue()->array($autoloader->getRegisteredAutoloaders())->isEqualTo($oldRegisteredAutoloaders); } } given($this->function->class_exists = $class, $this->function->interface_exists = $interface, $this->function->trait_exists = $trait)->when($result = SUT::entityExists('foo'))->then->boolean($result)->isTrue(); } public function case_entity_exists_with_class() { return $this->_entity_exists_with_xxx(\true, \false, \false); } public function case_entity_exists_with_interface() { return $this->_entity_exists_with_xxx(\false, \true, \false); } public function case_entity_exists_with_trait() { return $this->_entity_exists_with_xxx(\false, \false, \true); } public function case_entity_does_not_exists() { $this->given($this->function->class_exists = \false, $this->function->interface_exists = \false, $this->function->trait_exists = \false)->when($result = SUT::entityExists('foo'))->then->boolean($result)->isFalse(); } public function case_get_entity_shortest_name() { $this->when($result = SUT::getEntityShortestName('_PHPStan_33c983f26\Foo\Bar\Bar'))->then->string($result)->isEqualTo('_PHPStan_33c983f26\Foo\Bar'); } public function case_get_entity_shortest_name_with_already_the_shortest() { $this->when($result = SUT::getEntityShortestName('_PHPStan_33c983f26\Foo\Bar'))->then->string($result)->isEqualTo('_PHPStan_33c983f26\Foo\Bar'); } public function case_get_entity_shortest_name_with_no_namespace() { $this->when($result = SUT::getEntityShortestName('Foo'))->then->string($result)->isEqualTo('Foo'); } public function case_is_keyword() { $this->given($keywords = ['__HALT_COMPILER', 'abstract', 'and', 'array', 'as', 'bool', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'false', 'final', 'float', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'int', 'interface', 'isset', 'list', 'mixed', 'namespace', 'new', 'null', 'numeric', 'object', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'resource', 'return', 'static', 'string', 'switch', 'throw', 'trait', 'true', 'try', 'unset', 'use', 'var', 'void', 'while', 'xor', 'yield', '__CLASS__', '__DIR__', '__FILE__', '__FUNCTION__', '__LINE__', '__METHOD__', '__NAMESPACE__', '__TRAIT__'])->when(function () use ($keywords) { foreach ($keywords as $keyword) { $this->boolean(SUT::isKeyword($keyword))->isTrue(); } }); } public function case_is_identifier() { $this->given($_identifier = $this->realdom->regex('#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x80-\xff]*$#'))->when(function () use ($_identifier) { foreach ($this->sampleMany($_identifier, 1000) as $identifier) { $this->boolean(SUT::isIdentifier($identifier))->isTrue(); } }); } public function case_register_shutdown_function() { $self = $this; $this->given($callable = function () { }, $this->function->register_shutdown_function = function ($_callable) use (&$called, $self, &$callable) { $called = \true; $self->variable($_callable)->isEqualTo($callable); return \true; })->when($result = SUT::registerShutdownFunction($callable))->then->boolean($result)->isTrue(); } public function case_get_php_binary_with_constant() { $this->given($this->constant->PHP_BINARY = '/foo/php')->when($result = SUT::getPHPBinary())->then->string($result)->isEqualTo('/foo/php'); } public function case_get_php_binary_with_server() { $this->given($this->function->defined = \false, $_SERVER['_'] = '/bar/php')->when($result = SUT::getPHPBinary())->then->string($result)->isEqualTo('/bar/php'); } public function case_get_php_binary_with_bin_directory() { unset($_SERVER['_']); $this->given($this->function->defined = \false, $this->function->file_exists = \true, $this->function->realpath = '/baz/php')->when($result = SUT::getPHPBinary())->then->string($result)->isEqualTo('/baz/php'); } public function case_uuid() { $this->given($this->function->mt_rand = 42)->when($result = SUT::uuid())->then->string($result)->isEqualTo('002a002a-002a-402a-802a-002a002a002a'); } public function case_uuid_all_differents() { $this->when(function () { $uuids = []; for ($i = 0; $i < 10000; ++$i) { $uuids[] = SUT::uuid(); } $this->integer(count($uuids))->isEqualTo(count(array_unique($uuids))); }); } } when($result = new SUT('foo', 0))->then->object($result)->isInstanceOf('Hoa\Exception\Exception'); } } when($result = new SUT('strtoupper'))->then->string($result('foo'))->isEqualTo('FOO')->string($result->getValidCallback())->isEqualTo('strtoupper')->string($result->getHash())->isEqualTo('function#strtoupper')->isEqualTo($result . '')->object($reflection = $result->getReflection())->isInstanceOf('ReflectionFunction')->string($reflection->getName())->isEqualTo('strtoupper'); } public function case_form_class___method() { $this->when($result = new SUT(__CLASS__ . '::strtoupper'))->then->string($result('foo'))->isEqualTo('FOO')->array($result->getValidCallback())->isEqualTo([__CLASS__, 'strtoupper'])->string($result->getHash())->isEqualTo('class#' . __CLASS__ . '::strtoupper')->isEqualTo($result . '')->object($reflection = $result->getReflection())->isInstanceOf('ReflectionMethod')->string($reflection->getName())->isEqualTo('strtoupper'); } public function case_form_class_method() { $this->when($result = new SUT(__CLASS__, 'strtoupper'))->then->string($result('foo'))->isEqualTo('FOO')->array($result->getValidCallback())->isEqualTo([__CLASS__, 'strtoupper'])->string($result->getHash())->isEqualTo('class#' . __CLASS__ . '::strtoupper')->isEqualTo($result . '')->object($reflection = $result->getReflection())->isInstanceOf('ReflectionMethod')->string($reflection->getName())->isEqualTo('strtoupper'); } public function case_form_object_method() { $this->when($result = new SUT($this, 'strtolower'))->then->string($result('FOO'))->isEqualTo('foo')->array($result->getValidCallback())->isEqualTo([$this, 'strtolower'])->string($result->getHash())->matches('/^object\([^:]+\)#' . preg_quote(__CLASS__) . '::strtolower$/')->isEqualTo($result . '')->object($reflection = $result->getReflection())->isInstanceOf('ReflectionMethod')->string($reflection->getName())->isEqualTo('strtolower'); } public function case_form_object_invoke() { $this->when($result = new SUT($this))->then->string($result('foo'))->isEqualTo('FOO')->array($result->getValidCallback())->isEqualTo([$this, '__invoke'])->string($result->getHash())->matches('/^object\([^:]+\)#' . preg_quote(__CLASS__) . '::__invoke$/')->isEqualTo($result . '')->object($reflection = $result->getReflection())->isInstanceOf('ReflectionMethod')->string($reflection->getName())->isEqualTo('__invoke'); } public function case_form_closure() { $this->given($closure = function ($string) { return strtoupper($string); })->when($result = new SUT($closure))->then->string($result('foo'))->isEqualTo('FOO')->object($result->getValidCallback())->isIdenticalTo($closure)->string($result->getHash())->matches('/^closure\([^:]+\)$/')->isEqualTo($result . '')->object($reflection = $result->getReflection())->isInstanceOf('ReflectionFunction')->string($reflection->getName())->isEqualTo('Hoa\Consistency\Test\Unit\{closure}'); } public function case_form_array_of_class_method() { $this->when($result = new SUT([__CLASS__, 'strtoupper']))->then->string($result('foo'))->isEqualTo('FOO')->array($result->getValidCallback())->isEqualTo([__CLASS__, 'strtoupper'])->string($result->getHash())->isEqualTo('class#' . __CLASS__ . '::strtoupper')->isEqualTo($result . '')->object($reflection = $result->getReflection())->isInstanceOf('ReflectionMethod')->string($reflection->getName())->isEqualTo('strtoupper'); } public function case_form_array_of_object_method() { $this->when($result = new SUT([$this, 'strtolower']))->then->string($result('FOO'))->isEqualTo('foo')->array($result->getValidCallback())->isEqualTo([$this, 'strtolower'])->string($result->getHash())->matches('/^object\([^:]+\)#' . preg_quote(__CLASS__) . '::strtolower$/')->isEqualTo($result . '')->object($reflection = $result->getReflection())->isInstanceOf('ReflectionMethod')->string($reflection->getName())->isEqualTo('strtolower'); } public function case_form_able_not_a_string() { $this->exception(function () { new SUT(__CLASS__, 123); })->isInstanceOf('Hoa\Consistency\Exception'); } public function case_form_function_not_defined() { $this->exception(function () { new SUT('__hoa_test_undefined_function__'); })->isInstanceOf('Hoa\Consistency\Exception'); } public function case_form_able_cannot_be_deduced() { $this->given($this->function->method_exists = \false)->exception(function () { new SUT($this); })->isInstanceOf('Hoa\Consistency\Exception'); } public function case_invoke() { $this->given($callable = new SUT(function ($x, $y, $z) { return [$x, $y, $z]; }))->when($result = $callable(7, [4.2], 'foo'))->then->array($result)->isEqualTo([7, [4.2], 'foo']); } public function case_distribute_arguments() { $this->given($callable = new SUT(function ($x, $y, $z) { return [$x, $y, $z]; }))->when($result = $callable->distributeArguments([7, [4.2], 'foo']))->then->array($result)->isEqualTo([7, [4.2], 'foo']); } protected function _get_valid_callback_stream_xxx($argument, $method) { $this->given($stream = new \Mock\Hoa\Stream\IStream\Out(), $arguments = [$argument], $xcallable = new SUT($stream))->when($result = $xcallable->getValidCallback($arguments))->then->array($result)->isEqualTo([$stream, $method]); } public function case_get_valid_callback_stream_character() { return $this->_get_valid_callback_stream_xxx('f', 'writeCharacter'); } public function case_get_valid_callback_stream_string() { return $this->_get_valid_callback_stream_xxx('foo', 'writeString'); } public function case_get_valid_callback_stream_boolean() { return $this->_get_valid_callback_stream_xxx(\true, 'writeBoolean'); } public function case_get_valid_callback_stream_integer() { return $this->_get_valid_callback_stream_xxx(7, 'writeInteger'); } public function case_get_valid_callback_stream_array() { return $this->_get_valid_callback_stream_xxx([4, 2], 'writeArray'); } public function case_get_valid_callback_stream_float() { return $this->_get_valid_callback_stream_xxx(4.2, 'writeFloat'); } public function case_get_valid_callback_stream_other() { return $this->_get_valid_callback_stream_xxx($this, 'writeAll'); } public static function strtoupper($string) { return strtoupper($string); } public function strtolower($string) { return strtolower($string); } public function __invoke($string) { return strtoupper($string); } public function __toString() { return 'hello'; } } method or * closure, they all have the same behaviour. This callable is an extension of * native PHP callable (aka callback) to integrate Hoa's structures. * * @copyright Copyright © 2007-2017 Hoa community * @license New BSD License */ class Xcallable { /** * Callback, with the PHP format. * * @var mixed */ protected $_callback = null; /** * Callable hash. * * @var string */ protected $_hash = null; /** * Build a callback. * Accepted forms: * * `'function'`, * * `'class::method'`, * * `'class', 'method'`, * * `$object, 'method'`, * * `$object, ''`, * * `function (…) { … }`, * * `['class', 'method']`, * * `[$object, 'method']`. * * @param mixed $call First callable part. * @param mixed $able Second callable part (if needed). */ public function __construct($call, $able = '') { if ($call instanceof \Closure) { $this->_callback = $call; return; } if (!is_string($able)) { throw new \Hoa\Consistency\Exception('Bad callback form; the able part must be a string.', 0); } if ('' === $able) { if (is_string($call)) { if (\false === strpos($call, '::')) { if (!function_exists($call)) { throw new \Hoa\Consistency\Exception('Bad callback form; function %s does not exist.', 1, $call); } $this->_callback = $call; return; } list($call, $able) = explode('::', $call); } elseif (is_object($call)) { if ($call instanceof Stream\IStream\Out) { $able = null; } elseif (method_exists($call, '__invoke')) { $able = '__invoke'; } else { throw new \Hoa\Consistency\Exception('Bad callback form; an object but without a known ' . 'method.', 2); } } elseif (is_array($call) && isset($call[0])) { if (!isset($call[1])) { return $this->__construct($call[0]); } return $this->__construct($call[0], $call[1]); } else { throw new \Hoa\Consistency\Exception('Bad callback form.', 3); } } $this->_callback = [$call, $able]; return; } /** * Call the callable. * * @param ... * @return mixed */ public function __invoke() { $arguments = func_get_args(); $valid = $this->getValidCallback($arguments); return call_user_func_array($valid, $arguments); } /** * Distribute arguments according to an array. * * @param array $arguments Arguments. * @return mixed */ public function distributeArguments(array $arguments) { return call_user_func_array([$this, '__invoke'], $arguments); } /** * Get a valid callback in the PHP meaning. * * @param array &$arguments Arguments (could determine method on an * object if not precised). * @return mixed */ public function getValidCallback(array &$arguments = []) { $callback = $this->_callback; $head = null; if (isset($arguments[0])) { $head =& $arguments[0]; } // If method is undetermined, we find it (we understand event bucket and // stream). if (null !== $head && is_array($callback) && null === $callback[1]) { if ($head instanceof Event\Bucket) { $head = $head->getData(); } switch ($type = gettype($head)) { case 'string': if (1 === strlen($head)) { $method = 'writeCharacter'; } else { $method = 'writeString'; } break; case 'boolean': case 'integer': case 'array': $method = 'write' . ucfirst($type); break; case 'double': $method = 'writeFloat'; break; default: $method = 'writeAll'; $head = $head . "\n"; } $callback[1] = $method; } return $callback; } /** * Get hash. * Will produce: * * function#…; * * class#…::…; * * object(…)#…::…; * * closure(…). * * @return string */ public function getHash() { if (null !== $this->_hash) { return $this->_hash; } $_ =& $this->_callback; if (is_string($_)) { return $this->_hash = 'function#' . $_; } if (is_array($_)) { return $this->_hash = (is_object($_[0]) ? 'object(' . spl_object_hash($_[0]) . ')' . '#' . get_class($_[0]) : 'class#' . $_[0]) . '::' . (null !== $_[1] ? $_[1] : '???'); } return $this->_hash = 'closure(' . spl_object_hash($_) . ')'; } /** * Get appropriated reflection instance. * * @param ... * @return \Reflector */ public function getReflection() { $arguments = func_get_args(); $valid = $this->getValidCallback($arguments); if (is_string($valid)) { return new \ReflectionFunction($valid); } if ($valid instanceof \Closure) { return new \ReflectionFunction($valid); } if (is_array($valid)) { if (is_string($valid[0])) { if (\false === method_exists($valid[0], $valid[1])) { return new \ReflectionClass($valid[0]); } return new \ReflectionMethod($valid[0], $valid[1]); } $object = new \ReflectionObject($valid[0]); if (null === $valid[1]) { return $object; } return $object->getMethod($valid[1]); } } /** * Return the hash. * * @return string */ public function __toString() { return $this->getHash(); } } setData($data); return; } /** * Send this object on the event channel. * * @param string $eventId Event ID. * @param \Hoa\Event\Source $source Source. * @return void */ public function send($eventId, \Hoa\Event\Source $source) { return \Hoa\Event\Event::notify($eventId, $source, $this); } /** * Set source. * * @param \Hoa\Event\Source $source Source. * @return \Hoa\Event\Source */ public function setSource(\Hoa\Event\Source $source) { $old = $this->_source; $this->_source = $source; return $old; } /** * Get source. * * @return \Hoa\Event\Source */ public function getSource() { return $this->_source; } /** * Set data. * * @param mixed $data Data. * @return mixed */ public function setData($data) { $old = $this->_data; $this->_data = $data; return $old; } /** * Get data. * * @return mixed */ public function getData() { return $this->_data; } } new self(), self::KEY_SOURCE => null]; } return self::$_register[$eventId][self::KEY_EVENT]; } /** * Declare a new object in the observable collection. * Note: Hoa's libraries use hoa://Event/AnID for their observable objects; * * @param string $eventId Event ID. * @param \Hoa\Event\Source|string $source Observable object or class. * @return void * @throws \Hoa\Event\Exception */ public static function register($eventId, $source) { if (\true === self::eventExists($eventId)) { throw new \Hoa\Event\Exception('Cannot redeclare an event with the same ID, i.e. the event ' . 'ID %s already exists.', 0, $eventId); } if (is_object($source) && !$source instanceof \Hoa\Event\Source) { throw new \Hoa\Event\Exception('The source must implement \Hoa\Event\Source ' . 'interface; given %s.', 1, get_class($source)); } else { $reflection = new \ReflectionClass($source); if (\false === $reflection->implementsInterface('\Hoa\Event\Source')) { throw new \Hoa\Event\Exception('The source must implement \Hoa\Event\Source ' . 'interface; given %s.', 2, $source); } } if (!isset(self::$_register[$eventId][self::KEY_EVENT])) { self::$_register[$eventId][self::KEY_EVENT] = new self(); } self::$_register[$eventId][self::KEY_SOURCE] = $source; return; } /** * Undeclare an object in the observable collection. * * @param string $eventId Event ID. * @param bool $hard If false, just delete the source, else, * delete source and attached callables. * @return void */ public static function unregister($eventId, $hard = \false) { if (\false !== $hard) { unset(self::$_register[$eventId]); } else { self::$_register[$eventId][self::KEY_SOURCE] = null; } return; } /** * Attach an object to an event. * It can be a callable or an accepted callable form (please, see the * \Hoa\Consistency\Xcallable class). * * @param mixed $callable Callable. * @return \Hoa\Event\Event */ public function attach($callable) { $callable = xcallable($callable); $this->_callable[$callable->getHash()] = $callable; return $this; } /** * Detach an object to an event. * Please see $this->attach() method. * * @param mixed $callable Callable. * @return \Hoa\Event\Event */ public function detach($callable) { unset($this->_callable[xcallable($callable)->getHash()]); return $this; } /** * Check if at least one callable is attached to an event. * * @return bool */ public function isListened() { return !empty($this->_callable); } /** * Notify, i.e. send data to observers. * * @param string $eventId Event ID. * @param \Hoa\Event\Source $source Source. * @param \Hoa\Event\Bucket $data Data. * @return void * @throws \Hoa\Event\Exception */ public static function notify($eventId, \Hoa\Event\Source $source, \Hoa\Event\Bucket $data) { if (\false === self::eventExists($eventId)) { throw new \Hoa\Event\Exception('Event ID %s does not exist, cannot send notification.', 3, $eventId); } $data->setSource($source); $event = self::getEvent($eventId); foreach ($event->_callable as $callable) { $callable($data); } return; } /** * Check whether an event exists. * * @param string $eventId Event ID. * @return bool */ public static function eventExists($eventId) { return array_key_exists($eventId, self::$_register) && self::$_register[$eventId][self::KEY_SOURCE] !== null; } } /** * Flex entity. */ Consistency::flexEntity('Hoa\Event\Event'); _source = $source; $this->addIds($ids); return; } /** * Add acceptable ID (or reset). * * @param array $ids Accepted ID. * @return void */ public function addIds(array $ids) { foreach ($ids as $id) { $this->_callables[$id] = []; } return; } /** * Attach a callable to a listenable component. * * @param string $listenerId Listener ID. * @param mixed $callable Callable. * @return \Hoa\Event\Listener * @throws \Hoa\Event\Exception */ public function attach($listenerId, $callable) { if (\false === $this->listenerExists($listenerId)) { throw new \Hoa\Event\Exception('Cannot listen %s because it is not defined.', 0, $listenerId); } $callable = xcallable($callable); $this->_callables[$listenerId][$callable->getHash()] = $callable; return $this; } /** * Detach a callable from a listenable component. * * @param string $listenerId Listener ID. * @param mixed $callable Callable. * @return \Hoa\Event\Listener */ public function detach($listenerId, $callable) { unset($this->_callables[$listenerId][xcallable($callable)->getHash()]); return $this; } /** * Detach all callables from a listenable component. * * @param string $listenerId Listener ID. * @return \Hoa\Event\Listener */ public function detachAll($listenerId) { unset($this->_callables[$listenerId]); return $this; } /** * Check if a listener exists. * * @param string $listenerId Listener ID. * @return bool */ public function listenerExists($listenerId) { return array_key_exists($listenerId, $this->_callables); } /** * Send/fire a bucket to a listener. * * @param string $listenerId Listener ID. * @param \Hoa\Event\Bucket $data Data. * @return array * @throws \Hoa\Event\Exception */ public function fire($listenerId, \Hoa\Event\Bucket $data) { if (\false === $this->listenerExists($listenerId)) { throw new \Hoa\Event\Exception('Cannot fire on %s because it is not defined.', 1, $listenerId); } $data->setSource($this->_source); $out = []; foreach ($this->_callables[$listenerId] as $callable) { $out[] = $callable($data); } return $out; } } getListener(); if (null === $listener) { throw new \Hoa\Event\Exception('Cannot attach a callable to the listener %s because ' . 'it has not been initialized yet.', 0, get_class($this)); } $listener->attach($listenerId, $callable); return $this; } /** * Set listener. * * @param \Hoa\Event\Listener $listener Listener. * @return \Hoa\Event\Listener */ protected function setListener(\Hoa\Event\Listener $listener) { $old = $this->_listener; $this->_listener = $listener; return $old; } /** * Get listener. * * @return \Hoa\Event\Listener */ protected function getListener() { return $this->_listener; } } when($result = new SUT('foo'))->then->object($result)->isInstanceOf('Hoa\Event\Bucket')->string($result->getData())->isEqualTo('foo'); } public function case_send() { $self = $this; $this->given($eventId = 'hoa://Event/Test', $source = new \Mock\Hoa\Event\Source(), LUT::register($eventId, $source), $bucket = new SUT('foo'), LUT::getEvent($eventId)->attach(function (SUT $receivedBucket) use ($self, $bucket, &$called) { $called = \true; $self->object($receivedBucket)->isIdenticalTo($bucket); }))->when($result = $bucket->send($eventId, $source))->then->variable($result)->isNull()->boolean($called)->isTrue(); } public function case_set_source() { $this->given($bucket = new SUT(), $sourceA = new \Mock\Hoa\Event\Source())->when($result = $bucket->setSource($sourceA))->then->variable($result)->isNull()->object($bucket->getSource())->isIdenticalTo($sourceA)->given($sourceB = new \Mock\Hoa\Event\Source())->when($result = $bucket->setSource($sourceB))->then->object($result)->isIdenticalTo($sourceA)->object($bucket->getSource())->isIdenticalTo($sourceB); } public function case_set_data() { $this->given($bucket = new SUT(), $datumA = 'foo')->when($result = $bucket->setData($datumA))->then->variable($result)->isNull()->string($bucket->getData())->isEqualTo($datumA)->given($datumB = 'bar')->when($result = $bucket->setData($datumB))->then->string($result)->isEqualTo($datumA)->string($bucket->getData())->isEqualTo($datumB); } } given($eventId = 'hoa://Event/Test')->when($result = SUT::getEvent($eventId))->then->object($result)->isInstanceOf('Hoa\Event\Event')->object(SUT::getEvent($eventId))->isIdenticalTo($result); } public function case_register_source_instance() { $this->given($eventId = 'hoa://Event/Test', $source = new \Mock\Hoa\Event\Source())->when($result = SUT::register($eventId, $source))->then->variable($result)->isNull()->boolean(SUT::eventExists($eventId))->isTrue(); } public function case_register_source_name() { $this->given($eventId = 'hoa://Event/Test', $source = 'Mock\Hoa\Event\Source')->when($result = SUT::register($eventId, $source))->then->variable($result)->isNull()->boolean(SUT::eventExists($eventId))->isTrue(); } public function case_register_redeclare() { $this->given($eventId = 'hoa://Event/Test', $source = new \Mock\Hoa\Event\Source(), SUT::register($eventId, $source))->exception(function () use ($eventId, $source) { SUT::register($eventId, $source); })->isInstanceOf('Hoa\Event\Exception'); } public function case_register_not_a_source_instance() { $this->given($eventId = 'hoa://Event/Test', $source = new \StdClass())->exception(function () use ($eventId, $source) { $result = SUT::register($eventId, $source); })->isInstanceOf('Hoa\Event\Exception'); } public function case_register_not_a_source_name() { $this->given($eventId = 'hoa://Event/Test', $source = 'StdClass')->exception(function () use ($eventId, $source) { $result = SUT::register($eventId, $source); })->isInstanceOf('Hoa\Event\Exception'); } public function case_unregister() { $this->given($eventId = 'hoa://Event/Test', $source = new \Mock\Hoa\Event\Source(), SUT::register($eventId, $source))->when($result = SUT::unregister($eventId))->then->boolean(SUT::eventExists($eventId))->isFalse(); } public function case_unregister_hard() { $this->given($eventId = 'hoa://Event/Test', $source = new \Mock\Hoa\Event\Source(), SUT::register($eventId, $source), $event = SUT::getEvent($eventId))->when($result = SUT::unregister($eventId, \true))->then->boolean(SUT::eventExists($eventId))->isFalse()->object(SUT::getEvent($eventId))->isNotIdenticalTo($event); } public function case_unregister_not_registered() { $this->given($eventId = 'hoa://Event/Test')->when($result = SUT::unregister($eventId))->then->variable($result)->isNull(); } public function case_attach() { $this->given($event = SUT::getEvent('hoa://Event/Test'), $callable = function () { })->when($result = $event->attach($callable))->then->object($result)->isIdenticalTo($event)->boolean($event->isListened())->isTrue(); } public function case_detach() { $this->given($event = SUT::getEvent('hoa://Event/Test'), $callable = function () { }, $event->attach($callable))->when($result = $event->detach($callable))->then->object($result)->isIdenticalTo($event)->boolean($event->isListened())->isFalse(); } public function case_detach_unattached() { $this->given($event = SUT::getEvent('hoa://Event/Test'), $callable = function () { })->when($result = $event->detach($callable))->then->object($result)->isIdenticalTo($event)->boolean($event->isListened())->isFalse(); } public function case_is_listened() { $this->given($event = SUT::getEvent('hoa://Event/Test'))->when($result = $event->isListened())->then->boolean($event->isListened())->isFalse(); } public function case_notify() { $self = $this; $this->given($eventId = 'hoa://Event/Test', $source = new \Mock\Hoa\Event\Source(), $bucket = new LUT\Bucket(), SUT::register($eventId, $source), SUT::getEvent($eventId)->attach(function (LUT\Bucket $receivedBucket) use ($self, $source, $bucket, &$called) { $called = \true; $this->object($receivedBucket)->isIdenticalTo($bucket)->object($receivedBucket->getSource())->isIdenticalTo($source); }))->when($result = SUT::notify($eventId, $source, $bucket))->then->variable($result)->isNull()->boolean($called)->isTrue(); } public function case_notify_unregistered_event_id() { $this->given($eventId = 'hoa://Event/Test', $source = new \Mock\Hoa\Event\Source(), $data = new LUT\Bucket())->exception(function () use ($eventId, $source, $data) { SUT::notify($eventId, $source, $data); })->isInstanceOf('Hoa\Event\Exception'); } public function case_event_exists() { $this->given($eventId = 'hoa://Event/Test', $source = new \Mock\Hoa\Event\Source(), SUT::register($eventId, $source))->when($result = SUT::eventExists($eventId))->then->boolean($result)->isTrue(); } public function case_event_not_exists() { $this->given($eventId = 'hoa://Event/Test')->when($result = SUT::eventExists($eventId))->then->boolean($result)->isFalse(); } } when($result = new SUT('foo', 0))->then->object($result)->isInstanceOf('Hoa\Exception\Exception'); } } when($result = new \Mock\Hoa\Event\Listenable())->then->object($result)->isInstanceOf('Hoa\Event\Listenable'); } } given($source = new \Mock\Hoa\Event\Listenable(), $ids = ['foo', 'bar', 'baz'])->when($result = new SUT($source, $ids))->then->object($result)->isInstanceOf('Hoa\Event\Listener')->boolean($result->listenerExists('foo'))->isTrue()->boolean($result->listenerExists('bar'))->isTrue()->boolean($result->listenerExists('baz'))->isTrue(); } public function case_attach() { $this->given($source = new \Mock\Hoa\Event\Listenable(), $listenerId = 'foo', $listener = new SUT($source, ['foo', 'bar']), $callable = function () { return 42; })->when($result = $listener->attach($listenerId, $callable))->then->object($result)->isIdenticalTo($listener)->array($listener->fire($listenerId, new LUT\Bucket()))->isEqualTo([42]); } public function case_attach_to_an_undefined_listener() { $this->given($source = new \Mock\Hoa\Event\Listenable(), $listenerId = 'bar', $listener = new SUT($source, ['foo', 'baz']), $callable = function () { })->exception(function () use ($listener, $listenerId, $callable) { $listener->attach($listenerId, $callable); })->isInstanceOf('Hoa\Event\Exception'); } public function case_detach() { $this->given($source = new \Mock\Hoa\Event\Listenable(), $listenerId = 'foo', $listener = new SUT($source, ['foo', 'bar']), $callable = function () { return 42; }, $listener->attach($listenerId, $callable))->when($result = $listener->detach($listenerId, $callable))->then->object($result)->isIdenticalTo($listener)->array($listener->fire($listenerId, new LUT\Bucket()))->isEmpty(); } public function case_detach_an_undefined_listener() { $this->given($source = new \Mock\Hoa\Event\Listenable(), $listenerId = 'bar', $listener = new SUT($source, ['foo', 'baz']), $callable = function () { })->when($result = $listener->detach($listenerId, $callable))->then->object($result)->isIdenticalTo($listener); } public function case_detach_all() { $this->given($source = new \Mock\Hoa\Event\Listenable(), $listenerId = 'foo', $listener = new SUT($source, ['foo', 'bar']))->when($result = $listener->detachAll($listenerId))->then->object($result)->isIdenticalTo($listener)->boolean($listener->listenerExists($listenerId))->isFalse(); } public function case_detach_all_with_an_undefined_listener() { $this->given($source = new \Mock\Hoa\Event\Listenable(), $listenerId = 'bar', $listener = new SUT($source, ['foo', 'baz']))->when($result = $listener->detachAll($listenerId))->then->object($result)->isIdenticalTo($listener); } public function case_listener_exists() { $this->given($source = new \Mock\Hoa\Event\Listenable(), $ids = [], $listener = new SUT($source, $ids))->when($listener->addIds(['foo']))->then->boolean($listener->listenerExists('foo'))->isTrue()->boolean($listener->listenerExists('bar'))->isFalse()->when($listener->addIds(['bar']))->then->boolean($listener->listenerExists('bar'))->isTrue(); } public function case_fire() { $self = $this; $this->given($source = new \Mock\Hoa\Event\Listenable(), $ids = ['foo', 'bar'], $listener = new SUT($source, $ids), $listenerId = 'foo', $bucket = new LUT\Bucket(), $listener->attach($listenerId, function (LUT\Bucket $receivedBucket) use ($self, $bucket, $source, &$called) { $called = \true; $self->object($receivedBucket)->isIdenticalTo($bucket)->object($receivedBucket->getSource())->isIdenticalTo($source); return 42; }))->when($result = $listener->fire($listenerId, $bucket))->then->array($result)->isEqualTo([42])->boolean($called)->isTrue(); } public function case_fire_an_undefined_listenerId() { $this->given($source = new \Mock\Hoa\Event\Listenable(), $ids = [], $listener = new SUT($source, $ids))->exception(function () use ($listener) { $listener->fire('foo', new LUT\Bucket()); })->isInstanceOf('Hoa\Event\Exception'); } } given($listenable = new \Hoa\Event\Test\Unit\_Listenable(), $listener = new LUT\Listener($listenable, ['foo']))->when($result = $listenable->_setListener($listener))->then->variable($result)->isNull(); } public function case_get_listener() { $this->given($listenable = new \Hoa\Event\Test\Unit\_Listenable(), $listener = new LUT\Listener($listenable, ['foo']), $listenable->_setListener($listener))->when($result = $listenable->_getListener())->then->object($result)->isIdenticalTo($listener); } public function case_on() { $this->given($listenable = new \Hoa\Event\Test\Unit\_Listenable(), $listener = new LUT\Listener($listenable, ['foo']), $listenable->_setListener($listener), $callable = function () use (&$called) { $called = \true; return 42; })->when($result = $listenable->on('foo', $callable))->then->object($result)->isIdenticalTo($listenable)->when($listenable->doSomethingThatFires())->then->boolean($called)->isTrue(); } public function case_on_unregistered_listener() { $this->given($listenable = new \Hoa\Event\Test\Unit\_Listenable(), $listener = new LUT\Listener($listenable, ['foo']), $listenable->_setListener($listener))->exception(function () use ($listenable) { $listenable->on('bar', null); })->isInstanceOf('Hoa\Event\Exception'); } } class _Listenable implements LUT\Listenable { use SUT; public function _setListener(LUT\Listener $listener) { return $this->setListener($listener); } public function _getListener() { return $this->getListener(); } public function doSomethingThatFires() { $this->getListener()->fire('foo', new LUT\Bucket('bar')); return; } } when($result = new \Mock\Hoa\Event\Source())->then->object($result)->isInstanceOf('Hoa\Event\Source'); } } file = $file; $this->line = $line; $this->_trace = $trace; parent::__construct($message, $code); return; } /** * Enable error handler: Transform PHP error into `\Hoa\Exception\Error`. * * @param bool $enable Enable. * @return mixed */ public static function enableErrorHandler($enable = \true) { if (\false === $enable) { return restore_error_handler(); } return set_error_handler(function ($no, $str, $file = null, $line = null, $ctx = null) { if (0 === ($no & error_reporting())) { return; } $trace = debug_backtrace(); array_shift($trace); array_shift($trace); throw new \Hoa\Exception\Error($str, $no, $file, $line, $trace); }); } } send(); return; } /** * Send the exception on hoa://Event/Exception. * * @return void */ public function send() { Event::notify('hoa://Event/Exception', $this, new Event\Bucket($this)); return; } } /** * Flex entity. */ Consistency::flexEntity('Hoa\Exception\Exception'); _group = new \SplStack(); $this->beginTransaction(); return; } /** * Raise an exception as a string. * * @param bool $previous Whether raise previous exception if exists. * @return string */ public function raise($previous = \false) { $out = parent::raise($previous); if (0 >= count($this)) { return $out; } $out .= "\n\n" . 'Contains the following exceptions:'; foreach ($this as $exception) { $out .= "\n\n" . ' • ' . str_replace("\n", "\n" . ' ', $exception->raise($previous)); } return $out; } /** * Begin a transaction. * * @return \Hoa\Exception\Group */ public function beginTransaction() { $this->_group->push(new \ArrayObject()); return $this; } /** * Rollback a transaction. * * @return \Hoa\Exception\Group */ public function rollbackTransaction() { if (1 >= count($this->_group)) { return $this; } $this->_group->pop(); return $this; } /** * Commit a transaction. * * @return \Hoa\Exception\Group */ public function commitTransaction() { if (\false === $this->hasUncommittedExceptions()) { $this->_group->pop(); return $this; } foreach ($this->_group->pop() as $index => $exception) { $this[$index] = $exception; } return $this; } /** * Check if there is uncommitted exceptions. * * @return bool */ public function hasUncommittedExceptions() { return 1 < count($this->_group) && 0 < count($this->_group->top()); } /** * Check if an index in the group exists. * * @param mixed $index Index. * @return bool */ public function offsetExists($index) { foreach ($this->_group as $group) { if (isset($group[$index])) { return \true; } } return \false; } /** * Get an exception from the group. * * @param mixed $index Index. * @return Exception */ public function offsetGet($index) { foreach ($this->_group as $group) { if (isset($group[$index])) { return $group[$index]; } } return null; } /** * Set an exception in the group. * * @param mixed $index Index. * @param Exception $exception Exception. * @return void */ public function offsetSet($index, $exception) { if (!$exception instanceof \Exception) { return null; } $group = $this->_group->top(); if (null === $index || \true === is_int($index)) { $group[] = $exception; } else { $group[$index] = $exception; } return; } /** * Remove an exception in the group. * * @param mixed $index Index. * @return void */ public function offsetUnset($index) { foreach ($this->_group as $group) { if (isset($group[$index])) { unset($group[$index]); } } return; } /** * Get committed exceptions in the group. * * @return \ArrayObject */ public function getExceptions() { return $this->_group->bottom(); } /** * Get an iterator over all exceptions (committed or not). * * @return \ArrayIterator */ public function getIterator() { return $this->getExceptions()->getIterator(); } /** * Count the number of committed exceptions. * * @return int */ public function count() { return count($this->getExceptions()); } /** * Count the stack size, i.e. the number of opened transactions. * * @return int */ public function getStackSize() { return count($this->_group); } } _tmpArguments = $arguments; parent::__construct($message, $code, $previous); $this->_rawMessage = $message; $this->message = @vsprintf($message, $this->getArguments()); return; } /** * Get the backtrace. * Do not use \Exception::getTrace() any more. * * @return array */ public function getBacktrace() { if (null === $this->_trace) { $this->_trace = $this->getTrace(); } return $this->_trace; } /** * Get previous. * Do not use \Exception::getPrevious() any more. * * @return \Exception */ public function getPreviousThrow() { if (null === $this->_previous) { $this->_previous = $this->getPrevious(); } return $this->_previous; } /** * Get arguments for the message. * * @return array */ public function getArguments() { if (null === $this->_arguments) { $arguments = $this->_tmpArguments; if (!is_array($arguments)) { $arguments = [$arguments]; } foreach ($arguments as &$value) { if (null === $value) { $value = '(null)'; } } $this->_arguments = $arguments; unset($this->_tmpArguments); } return $this->_arguments; } /** * Get the raw message. * * @return string */ public function getRawMessage() { return $this->_rawMessage; } /** * Get the message already formatted. * * @return string */ public function getFormattedMessage() { return $this->getMessage(); } /** * Get the source of the exception (class, method, function, main etc.). * * @return string */ public function getFrom() { $trace = $this->getBacktrace(); $from = '{main}'; if (!empty($trace)) { $t = $trace[0]; $from = ''; if (isset($t['class'])) { $from .= $t['class'] . '::'; } if (isset($t['function'])) { $from .= $t['function'] . '()'; } } return $from; } /** * Raise an exception as a string. * * @param bool $previous Whether raise previous exception if exists. * @return string */ public function raise($previous = \false) { $message = $this->getFormattedMessage(); $trace = $this->getBacktrace(); $file = '/dev/null'; $line = -1; $pre = $this->getFrom(); if (!empty($trace)) { $file = isset($trace['file']) ? $trace['file'] : null; $line = isset($trace['line']) ? $trace['line'] : null; } $pre .= ': '; try { $out = $pre . '(' . $this->getCode() . ') ' . $message . "\n" . 'in ' . $this->getFile() . ' at line ' . $this->getLine() . '.'; } catch (\Exception $e) { $out = $pre . '(' . $this->getCode() . ') ' . $message . "\n" . 'in ' . $file . ' around line ' . $line . '.'; } if (\true === $previous && null !== $previous = $this->getPreviousThrow()) { $out .= "\n\n" . ' ⬇' . "\n\n" . 'Nested exception (' . get_class($previous) . '):' . "\n" . ($previous instanceof self ? $previous->raise(\true) : $previous->getMessage()); } return $out; } /** * Catch uncaught exception (only \Hoa\Exception\Idle and children). * * @param \Throwable $exception The exception. * @return void * @throws \Throwable */ public static function uncaught($exception) { if (!$exception instanceof self) { throw $exception; } while (0 < ob_get_level()) { ob_end_flush(); } echo 'Uncaught exception (' . get_class($exception) . '):' . "\n" . $exception->raise(\true); return; } /** * String representation of object. * * @return string */ public function __toString() { return $this->raise(); } /** * Enable uncaught exception handler. * This is restricted to Hoa's exceptions only. * * @param bool $enable Enable. * @return mixed */ public static function enableUncaughtHandler($enable = \true) { if (\false === $enable) { return restore_exception_handler(); } return set_exception_handler(function ($exception) { return self::uncaught($exception); }); } } This file was automatically generated by Composer Patches (https://github.com/cweagans/composer-patches) Patches applied to this directory: 0 Source: patches/Idle.patch when($result = new SUT('foo', 42, '/hoa/flatland', 153))->then->object($result)->isInstanceOf('Hoa\Exception\Exception'); } public function case_get_message() { $this->given($exception = new SUT('foo', 42, '/hoa/flatland', 153))->when($result = $exception->raise())->then->string($result)->isEqualTo('{main}: (42) foo' . "\n" . 'in /hoa/flatland at line 153.'); } public function case_disable_error_handler() { $this->given($this->function->restore_error_handler = function () use (&$called) { $called = \true; return null; })->when($result = SUT::enableErrorHandler(\false))->then->variable($result)->isNull()->boolean($called)->isTrue(); } public function case_enable_error_handler() { $self = $this; $this->given($this->function->set_error_handler = function ($handler) use ($self, &$called) { $called = \true; $self->object($handler)->isInstanceOf('Closure')->let($reflection = new \ReflectionObject($handler))->array($invokeParameters = $reflection->getMethod('__invoke')->getParameters())->hasSize(5)->string($invokeParameters[0]->getName())->isEqualTo('no')->string($invokeParameters[1]->getName())->isEqualTo('str')->string($invokeParameters[2]->getName())->isEqualTo('file')->boolean($invokeParameters[2]->isOptional())->isTrue()->string($invokeParameters[3]->getName())->isEqualTo('line')->boolean($invokeParameters[3]->isOptional())->isTrue()->string($invokeParameters[4]->getName())->isEqualTo('ctx')->boolean($invokeParameters[4]->isOptional())->isTrue(); return null; })->when($result = SUT::enableErrorHandler())->then->variable($result)->isNull()->boolean($called)->isTrue(); } public function case_error_handler() { $this->given(SUT::enableErrorHandler())->exception(function () { ++$i; })->isInstanceOf('Hoa\Exception\Error')->hasMessage('Undefined variable: i'); } } when($result = new SUT('foo'))->then->object($result)->isInstanceOf('Hoa\Exception\Idle'); } public function case_event_is_registered() { $this->given(new SUT('foo'))->when($result = Event::eventExists('hoa://Event/Exception'))->then->boolean($result)->isTrue(); } public function case_event_is_sent() { $self = $this; $this->given(Event::getEvent('hoa://Event/Exception')->attach(function (Event\Bucket $bucket) use ($self, &$called) { $called = \true; $self->object($bucket->getSource())->isInstanceOf('Hoa\Exception\Exception')->string($bucket->getSource()->getMessage())->isEqualTo('foo')->object($bucket->getData())->isIdenticalTo($bucket->getSource()); }))->when(new SUT('foo'))->then->boolean($called)->isTrue(); } } when($result = new SUT('foo'))->then->object($result)->isInstanceOf('Hoa\Exception\Exception')->isInstanceOf('ArrayAccess')->isInstanceOf('IteratorAggregate')->isInstanceOf('Countable'); } public function case_constructor() { $this->given($message = 'foo %s %d %s', $code = 7, $arguments = ['arg', 42, null], $previous = new SUT('previous'))->when($result = new SUT($message, $code, $arguments, $previous), $line = __LINE__)->then->string($result->getMessage())->isEqualTo('foo arg 42 (null)')->integer($result->getCode())->isEqualTo(7)->array($result->getArguments())->isEqualTo(['arg', 42, '(null)'])->object($result->getPreviousThrow())->isIdenticalTo($previous)->boolean($result->hasUncommittedExceptions())->isFalse(); } public function case_raise_zero_exception() { $this->given($group = new SUT('foo'), $line = __LINE__)->when($result = $group->raise())->then->string($result)->isEqualTo(__METHOD__ . '(): (0) foo' . "\n" . 'in ' . __FILE__ . ' at line ' . $line . '.'); } public function case_raise_one_exception() { $this->given($exception1 = new SUT('bar'), $barLine = __LINE__, $group = new SUT('foo'), $fooLine = __LINE__, $group[] = $exception1)->when($result = $group->raise())->then->string($result)->isEqualTo(__METHOD__ . '(): (0) foo' . "\n" . 'in ' . __FILE__ . ' at line ' . $fooLine . '.' . "\n\n" . 'Contains the following exceptions:' . "\n\n" . ' • ' . __METHOD__ . '(): (0) bar' . "\n" . ' in ' . __FILE__ . ' at line ' . $barLine . '.'); } public function case_raise_more_exceptions() { $this->given($exception1 = new SUT('bar'), $barLine = __LINE__, $exception2 = new SUT('baz'), $bazLine = __LINE__, $group = new SUT('foo'), $fooLine = __LINE__, $group[] = $exception1, $group[] = $exception2)->when($result = $group->raise())->then->string($result)->isEqualTo(__METHOD__ . '(): (0) foo' . "\n" . 'in ' . __FILE__ . ' at line ' . $fooLine . '.' . "\n\n" . 'Contains the following exceptions:' . "\n\n" . ' • ' . __METHOD__ . '(): (0) bar' . "\n" . ' in ' . __FILE__ . ' at line ' . $barLine . '.' . "\n\n" . ' • ' . __METHOD__ . '(): (0) baz' . "\n" . ' in ' . __FILE__ . ' at line ' . $bazLine . '.'); } public function case_begin_transaction() { $this->given($group = new SUT('foo'), $oldStackSize = $group->getStackSize())->when($result = $group->beginTransaction(), $stackSize = $group->getStackSize())->then->integer($oldStackSize)->isEqualTo(1)->object($result)->isIdenticalTo($group)->integer($stackSize)->isEqualTo($oldStackSize + 1); } public function case_rollback_transaction_with_an_empty_stack() { $this->given($group = new SUT('foo'), $oldStackSize = $group->getStackSize())->when($result = $group->rollbackTransaction(), $stackSize = $group->getStackSize())->then->integer($oldStackSize)->isEqualTo(1)->object($result)->isIdenticalTo($group)->integer($stackSize)->isEqualTo($oldStackSize); } public function case_rollback_transaction() { $this->given($group = new SUT('foo'), $group->beginTransaction(), $group->beginTransaction(), $oldStackSize = $group->getStackSize(), $group->rollbackTransaction())->when($result = $group->rollbackTransaction(), $stackSize = $group->getStackSize())->then->integer($oldStackSize)->isEqualTo(3)->object($result)->isIdenticalTo($group)->integer($stackSize)->isEqualTo($oldStackSize - 2); } public function case_commit_transaction_with_an_empty_stack() { $this->given($group = new SUT('foo'), $group->beginTransaction(), $oldCount = count($group), $oldStackSize = $group->getStackSize())->when($result = $group->commitTransaction(), $count = count($group), $stackSize = $group->getStackSize())->then->integer($oldCount)->isEqualTo(0)->integer($oldStackSize)->isEqualTo(2)->object($result)->isIdenticalTo($group)->integer($count)->isEqualTo($oldCount)->integer($stackSize)->isEqualTo($oldStackSize - 1); } public function case_commit_transaction() { $this->given($group = new SUT('foo'), $group->beginTransaction(), $exception1 = new SUT('bar'), $exception2 = new SUT('baz'), $group[] = $exception1, $group[] = $exception2, $oldCount = count($group), $oldStackSize = $group->getStackSize())->when($result = $group->commitTransaction(), $count = count($group), $stackSize = $group->getStackSize())->then->integer($oldCount)->isEqualTo(0)->integer($oldStackSize)->isEqualTo(2)->object($result)->isIdenticalTo($group)->integer($count)->isEqualTo($oldCount + 2)->integer($stackSize)->isEqualTo($oldStackSize - 1)->array(iterator_to_array($group->getIterator()))->isEqualTo([0 => $exception1, 1 => $exception2]); } public function case_has_uncommitted_exceptions() { $this->given($group = new SUT('foo'), $group->beginTransaction(), $group[] = new SUT('bar'))->when($result = $group->hasUncommittedExceptions())->then->boolean($result)->isTrue(); } public function case_has_no_uncommitted_exceptions() { $this->given($group = new SUT('foo'), $group->beginTransaction())->when($result = $group->hasUncommittedExceptions())->then->boolean($result)->isFalse(); } public function case_has_no_uncommitted_exceptions_with_empty_stack() { $this->given($group = new SUT('foo'), $group[] = new SUT('bar'))->when($result = $group->hasUncommittedExceptions())->then->boolean($result)->isFalse(); } public function case_offset_exists_with_no_uncommited_exceptions() { $this->given($group = new SUT('foo'), $group['bar'] = new SUT('bar'))->when($result = $group->offsetExists('bar'))->then->boolean($result)->isTrue(); } public function case_offset_does_not_exist_with_no_uncommited_exceptions() { $this->given($group = new SUT('foo'), $group['bar'] = new SUT('bar'))->when($result = $group->offsetExists('baz'))->then->boolean($result)->isFalse(); } public function case_offset_exists() { $this->given($group = new SUT('foo'), $group->beginTransaction(), $group->beginTransaction(), $group['bar'] = new SUT('bar'))->when($result = $group->offsetExists('bar'))->then->boolean($result)->isTrue(); } public function case_offset_does_not_exist() { $this->given($group = new SUT('foo'), $group->beginTransaction(), $group->beginTransaction(), $group['bar'] = new SUT('bar'))->when($result = $group->offsetExists('baz'))->then->boolean($result)->isFalse(); } public function case_offset_get_with_no_uncommited_exceptions() { $this->given($group = new SUT('foo'), $exception1 = new SUT('bar'), $group['bar'] = $exception1)->when($result = $group->offsetGet('bar'))->then->object($result)->isIdenticalTo($exception1); } public function case_offset_get_does_not_exist_with_no_uncommited_exceptions() { $this->given($group = new SUT('foo'), $exception1 = new SUT('bar'), $group['bar'] = $exception1)->when($result = $group->offsetGet('baz'))->then->variable($result)->isNull(); } public function case_offset_get() { $this->given($group = new SUT('foo'), $group->beginTransaction(), $group->beginTransaction(), $exception1 = new SUT('bar'), $group['bar'] = $exception1)->when($result = $group->offsetGet('bar'))->then->object($result)->isIdenticalTo($exception1); } public function case_offset_get_does_not_exist() { $this->given($group = new SUT('foo'), $group->beginTransaction(), $group->beginTransaction(), $exception1 = new SUT('bar'), $group['bar'] = $exception1)->when($result = $group->offsetGet('baz'))->then->variable($result)->isNull(); } public function case_offset_set_not_an_exception() { $this->given($group = new SUT('foo'))->when($group->offsetSet('bar', new \StdClass()))->then->boolean($group->offsetExists('bar'))->isFalse(); } public function case_offset_set() { $this->given($group = new SUT('foo'), $exception1 = new SUT('bar'))->when($result = $group->offsetExists('bar'))->then->boolean($result)->isFalse()->when($group->offsetSet('bar', $exception1))->then->boolean($group->offsetExists('bar'))->isTrue()->object($group->offsetGet('bar'))->isIdenticalTo($exception1); } public function case_offset_set_with_a_null_index() { $this->given($group = new SUT('foo'), $exception1 = new SUT('bar'))->when($group->offsetSet(null, $exception1))->then->boolean($group->offsetExists(0))->isTrue()->object($group->offsetGet(0))->isIdenticalTo($exception1); } public function case_offset_set_with_an_integer_index() { $this->given($group = new SUT('foo'), $exception1 = new SUT('bar'))->when($group->offsetSet(42, $exception1))->then->boolean($group->offsetExists(42))->isFalse()->boolean($group->offsetExists(0))->isTrue()->object($group->offsetGet(0))->isIdenticalTo($exception1); } public function case_offset_unset_with_no_uncommited_exceptions() { $this->given($group = new SUT('foo'), $group['bar'] = new SUT('bar'))->when($group->offsetUnset('bar'))->then->boolean($group->offsetExists('bar'))->isFalse(); } public function case_offset_unset_does_not_exist_with_no_uncommited_exceptions() { $this->given($group = new SUT('foo'))->when($group->offsetUnset('bar'))->then->boolean($group->offsetExists('bar'))->isFalse(); } public function case_offset_unset() { $this->given($group = new SUT('foo'), $group->beginTransaction(), $group->beginTransaction(), $group['bar'] = new SUT('bar'))->when($result = $group->offsetUnset('bar'))->then->boolean($group->offsetExists('bar'))->isFalse(); } public function case_offset_unset_does_not_exist() { $this->given($group = new SUT('foo'), $group->beginTransaction(), $group->beginTransaction())->when($result = $group->offsetUnset('bar'))->then->boolean($group->offsetExists('bar'))->isFalse(); } public function case_get_exceptions() { $this->given($group = new SUT('foo'), $exception1 = new SUT('bar'), $exception2 = new SUT('baz'), $group['bar'] = $exception1, $group->beginTransaction(), $group['baz'] = $exception2)->when($result = $group->getExceptions())->then->object($result)->isInstanceOf('ArrayObject')->object($result['bar'])->isIdenticalTo($exception1); } public function case_get_iterator() { $this->given($group = new SUT('foo'), $exception1 = new SUT('bar'), $group['bar'] = $exception1)->when($result = $group->getIterator())->then->object($result)->isInstanceOf('ArrayIterator')->array(iterator_to_array($result))->isEqualTo(['bar' => $exception1]); } public function case_count() { $this->given($group = new SUT('foo'), $exception1 = new SUT('bar'), $exception2 = new SUT('baz'), $group['bar'] = $exception1, $group->beginTransaction(), $group['baz'] = $exception2)->when($result = count($group))->then->integer($result)->isEqualTo(1); } public function get_get_stack_size() { $this->given($group = new SUT('foo'), $exception1 = new SUT('bar'), $exception2 = new SUT('baz'), $group['bar'] = $exception1, $group->beginTransaction(), $group['baz'] = $exception2)->when($result = $group->getStackSize())->then->integer($result)->isEqualTo(2); } } when($result = new SUT('foo'))->then->object($result)->isInstanceOf('Exception'); } public function case_get_backtrace() { $this->given($exception = new SUT('foo'))->when($result = $exception->getBacktrace())->then->array($result)->hasKey(0)->array($result[0])->hasKey('file')->hasKey('line')->hasKey('function')->hasKey('class')->hasKey('type')->hasKey('args'); } public function case_get_previous_throw() { $this->given($previous = new SUT('previous'), $exception = new SUT('foo', 0, [], $previous))->when($result = $exception->getPreviousThrow())->then->object($result)->isIdenticalTo($previous); } public function case_get_arguments() { $this->given($exception = new SUT('foo', 0, ['arg', 42, null]))->when($result = $exception->getArguments())->then->array($result)->isEqualTo(['arg', 42, '(null)']); } public function case_get_arguments_from_a_string() { $this->given($exception = new SUT('foo', 0, 'arg'))->when($result = $exception->getArguments())->then->array($result)->isEqualTo(['arg']); } public function case_get_raw_message() { $this->given($message = 'foo %s', $exception = new SUT($message))->when($result = $exception->getRawMessage())->then->string($result)->isEqualTo($message); } public function case_get_formatted_message() { $this->given($message = 'foo %s', $exception = new SUT($message, 0, 'bar'))->when($result = $exception->getFormattedMessage())->then->string($result)->isEqualTo($exception->getMessage())->isEqualTo('foo bar'); } public function case_get_from_object() { $this->given($exception = new SUT('foo'))->when($result = $exception->getFrom())->then->string($result)->isEqualTo(__METHOD__ . '()'); } public function case_raise() { $this->given($exception = new SUT('foo'), $line = __LINE__)->when($result = $exception->raise())->then->string($result)->isEqualTo(__METHOD__ . '(): (0) foo' . "\n" . 'in ' . __FILE__ . ' at line ' . $line . '.'); } public function case_raise_with_previous() { $this->given($previous = new SUT('previous'), $previousLine = __LINE__, $exception = new SUT('foo', 0, [], $previous), $line = __LINE__)->when($result = $exception->raise(\true))->then->string($result)->isEqualTo(__METHOD__ . '(): (0) foo' . "\n" . 'in ' . __FILE__ . ' at line ' . $line . '.' . "\n\n" . ' ⬇' . "\n\n" . 'Nested exception (' . get_class($previous) . '):' . "\n" . __METHOD__ . '(): (0) previous' . "\n" . 'in ' . __FILE__ . ' at line ' . $previousLine . '.'); } public function case_uncaught() { $this->given($this->function->ob_get_level = 0, $exception = new SUT('foo'), $line = __LINE__)->when($result = SUT::uncaught($exception))->then->variable($result)->isNull()->output->isEqualTo('Uncaught exception (' . get_class($exception) . '):' . "\n" . __METHOD__ . '(): (0) foo' . "\n" . 'in ' . __FILE__ . ' at line ' . $line . '.'); } public function case_uncaught_not_Hoa() { $this->exception(function () { SUT::uncaught(new \Exception('foo')); })->isInstanceOf('Exception')->output->isEmpty(); } public function case_to_string() { $this->given($exception = new SUT('foo'))->when($result = $exception->__toString())->then->string($result)->isEqualTo($exception->raise()); } public function case_disable_uncaught_handler() { $this->given($this->function->restore_exception_handler = function () use (&$called) { $called = \true; return null; })->when($result = SUT::enableUncaughtHandler(\false))->then->variable($result)->isNull()->boolean($called)->isTrue(); } public function case_enable_uncaught_handler() { $self = $this; $this->given($this->function->set_exception_handler = function ($handler) use ($self, &$called) { $called = \true; $self->object($handler)->isInstanceOf('Closure')->let($reflection = new \ReflectionObject($handler))->array($invokeParameters = $reflection->getMethod('__invoke')->getParameters())->hasSize(1)->string($invokeParameters[0]->getName())->isEqualTo('exception'); return null; })->when($result = SUT::enableUncaughtHandler())->then->variable($result)->isNull()->boolean($called)->isTrue(); } } setMode($mode); parent::__construct($streamName, $context, $wait); return; } /** * Open the stream and return the associated resource. * * @param string $streamName Stream name (e.g. path or URL). * @param \Hoa\Stream\Context $context Context. * @return resource * @throws \Hoa\File\Exception\FileDoesNotExist * @throws \Hoa\File\Exception */ protected function &_open($streamName, Stream\Context $context = null) { if (\false === is_dir($streamName)) { if ($this->getMode() == self::MODE_READ) { throw new \Hoa\File\Exception\FileDoesNotExist('Directory %s does not exist.', 0, $streamName); } else { self::create($streamName, $this->getMode(), null !== $context ? $context->getContext() : null); } } $out = null; return $out; } /** * Close the current stream. * * @return bool */ protected function _close() { return \true; } /** * Recursive copy of a directory. * * @param string $to Destination path. * @param bool $force Force to copy if the file $to already exists. * Use the \Hoa\Stream\IStream\Touchable::*OVERWRITE * constants. * @return bool * @throws \Hoa\File\Exception */ public function copy($to, $force = Stream\IStream\Touchable::DO_NOT_OVERWRITE) { if (empty($to)) { throw new \Hoa\File\Exception('The destination path (to copy) is empty.', 1); } $from = $this->getStreamName(); $fromLength = strlen($from) + 1; $finder = new \Hoa\File\Finder(); $finder->in($from); self::create($to, self::MODE_CREATE_RECURSIVE); foreach ($finder as $file) { $relative = substr($file->getPathname(), $fromLength); $_to = $to . DS . $relative; if (\true === $file->isDir()) { self::create($_to, self::MODE_CREATE); continue; } // This is not possible to do `$file->open()->copy(); // $file->close();` because the file will be opened in read and // write mode. In a PHAR for instance, this operation is // forbidden. So a special care must be taken to open file in read // only mode. $handle = null; if (\true === $file->isFile()) { $handle = new \Hoa\File\Read($file->getPathname()); } elseif (\true === $file->isDir()) { $handle = new \Hoa\File\Directory($file->getPathName()); } elseif (\true === $file->isLink()) { $handle = new \Hoa\File\Link\Read($file->getPathName()); } if (null !== $handle) { $handle->copy($_to, $force); $handle->close(); } } return \true; } /** * Delete a directory. * * @return bool */ public function delete() { $from = $this->getStreamName(); $finder = new \Hoa\File\Finder(); $finder->in($from)->childFirst(); foreach ($finder as $file) { $file->open()->delete(); $file->close(); } if (null === $this->getStreamContext()) { return @rmdir($from); } return @rmdir($from, $this->getStreamContext()->getContext()); } /** * Create a directory. * * @param string $name Directory name. * @param string $mode Create mode. Please, see the self::MODE_CREATE* * constants. * @param string $context Context ID (please, see the * \Hoa\Stream\Context class). * @return bool * @throws \Hoa\File\Exception */ public static function create($name, $mode = self::MODE_CREATE_RECURSIVE, $context = null) { if (\true === is_dir($name)) { return \true; } if (empty($name)) { return \false; } if (null !== $context) { if (\false === Stream\Context::contextExists($context)) { throw new \Hoa\File\Exception('Context %s was not previously declared, cannot retrieve ' . 'this context.', 2, $context); } else { $context = Stream\Context::getInstance($context); } } if (null === $context) { return @mkdir($name, 0755, self::MODE_CREATE_RECURSIVE === $mode); } return @mkdir($name, 0755, self::MODE_CREATE_RECURSIVE === $mode, $context->getContext()); } } setMode($mode); switch ($streamName) { case '0': $streamName = 'php://stdin'; break; case '1': $streamName = 'php://stdout'; break; case '2': $streamName = 'php://stderr'; break; default: if (\true === ctype_digit($streamName)) { if (\PHP_VERSION_ID >= 50306) { $streamName = 'php://fd/' . $streamName; } else { throw new \Hoa\File\Exception('You need PHP5.3.6 to use a file descriptor ' . 'other than 0, 1 or 2 (tried %d with PHP%s).', 0, [$streamName, \PHP_VERSION]); } } } parent::__construct($streamName, $context, $wait); return; } /** * Open the stream and return the associated resource. * * @param string $streamName Stream name (e.g. path or URL). * @param \Hoa\Stream\Context $context Context. * @return resource * @throws \Hoa\File\Exception\FileDoesNotExist * @throws \Hoa\File\Exception */ protected function &_open($streamName, ?Stream\Context $context = null) { if (substr($streamName, 0, 4) == 'file' && \false === is_dir(dirname($streamName))) { throw new \Hoa\File\Exception('Directory %s does not exist. Could not open file %s.', 1, [dirname($streamName), basename($streamName)]); } if (null === $context) { if (\false === $out = @fopen($streamName, $this->getMode(), \true)) { throw new \Hoa\File\Exception('Failed to open stream %s.', 2, $streamName); } return $out; } $out = @fopen($streamName, $this->getMode(), \true, $context->getContext()); if (\false === $out) { throw new \Hoa\File\Exception('Failed to open stream %s.', 3, $streamName); } return $out; } /** * Close the current stream. * * @return bool */ protected function _close() { return @fclose($this->getStream()); } /** * Start a new buffer. * The callable acts like a light filter. * * @param mixed $callable Callable. * @param int $size Size. * @return int */ public function newBuffer($callable = null, $size = null) { $this->setStreamBuffer($size); //@TODO manage $callable as a filter? return 1; } /** * Flush the output to a stream. * * @return bool */ public function flush() { return fflush($this->getStream()); } /** * Delete buffer. * * @return bool */ public function deleteBuffer() { return $this->disableStreamBuffer(); } /** * Get bufffer level. * * @return int */ public function getBufferLevel() { return 1; } /** * Get buffer size. * * @return int */ public function getBufferSize() { return $this->getStreamBufferSize(); } /** * Portable advisory locking. * * @param int $operation Operation, use the * \Hoa\Stream\IStream\Lockable::LOCK_* constants. * @return bool */ public function lock($operation) { return flock($this->getStream(), $operation); } /** * Rewind the position of a stream pointer. * * @return bool */ public function rewind() { return rewind($this->getStream()); } /** * Seek on a stream pointer. * * @param int $offset Offset (negative value should be supported). * @param int $whence Whence, use the * \Hoa\Stream\IStream\Pointable::SEEK_* constants. * @return int */ public function seek($offset, $whence = Stream\IStream\Pointable::SEEK_SET) { return fseek($this->getStream(), $offset, $whence); } /** * Get the current position of the stream pointer. * * @return int */ public function tell() { $stream = $this->getStream(); if (null === $stream) { return 0; } return ftell($stream); } /** * Create a file. * * @param string $name File name. * @param mixed $dummy To be compatible with childs. * @return bool */ public static function create($name, $dummy) { if (file_exists($name)) { return \true; } return touch($name); } } /** * Flex entity. */ Consistency::flexEntity('Hoa\File\File'); _flags = Iterator\FileSystem::KEY_AS_PATHNAME | Iterator\FileSystem::CURRENT_AS_FILEINFO | Iterator\FileSystem::SKIP_DOTS; $this->_first = Iterator\Recursive\Iterator::SELF_FIRST; return; } /** * Select a directory to scan. * * @param string|array $paths One or more paths. * @return \Hoa\File\Finder */ public function in($paths) { if (!is_array($paths)) { $paths = [$paths]; } foreach ($paths as $path) { if (1 === preg_match('/[\*\?\[\]]/', $path)) { $iterator = new Iterator\CallbackFilter(new Iterator\Glob(rtrim($path, DS)), function ($current) { return $current->isDir(); }); foreach ($iterator as $fileInfo) { $this->_paths[] = $fileInfo->getPathname(); } } else { $this->_paths[] = $path; } } return $this; } /** * Set max depth for recursion. * * @param int $depth Depth. * @return \Hoa\File\Finder */ public function maxDepth($depth) { $this->_maxDepth = $depth; return $this; } /** * Include files in the result. * * @return \Hoa\File\Finder */ public function files() { $this->_types[] = 'file'; return $this; } /** * Include directories in the result. * * @return \Hoa\File\Finder */ public function directories() { $this->_types[] = 'dir'; return $this; } /** * Include links in the result. * * @return \Hoa\File\Finder */ public function links() { $this->_types[] = 'link'; return $this; } /** * Follow symbolink links. * * @param bool $flag Whether we follow or not. * @return \Hoa\File\Finder */ public function followSymlinks($flag = \true) { if (\true === $flag) { $this->_flags ^= Iterator\FileSystem::FOLLOW_SYMLINKS; } else { $this->_flags |= Iterator\FileSystem::FOLLOW_SYMLINKS; } return $this; } /** * Include files that match a regex. * Example: * $this->name('#\.php$#'); * * @param string $regex Regex. * @return \Hoa\File\Finder */ public function name($regex) { $this->_filters[] = function (\SplFileInfo $current) use ($regex) { return 0 !== preg_match($regex, $current->getBasename()); }; return $this; } /** * Exclude directories that match a regex. * Example: * $this->notIn('#^\.(git|hg)$#'); * * @param string $regex Regex. * @return \Hoa\File\Finder */ public function notIn($regex) { $this->_filters[] = function (\SplFileInfo $current) use ($regex) { foreach (explode(DS, $current->getPathname()) as $part) { if (0 !== preg_match($regex, $part)) { return \false; } } return \true; }; return $this; } /** * Include files that respect a certain size. * The size is a string of the form: * operator number unit * where * • operator could be: <, <=, >, >= or =; * • number is a positive integer; * • unit could be: b (default), Kb, Mb, Gb, Tb, Pb, Eb, Zb, Yb. * Example: * $this->size('>= 12Kb'); * * @param string $size Size. * @return \Hoa\File\Finder */ public function size($size) { if (0 === preg_match('#^(<|<=|>|>=|=)\s*(\d+)\s*((?:[KMGTPEZY])b)?$#', $size, $matches)) { return $this; } $number = floatval($matches[2]); $unit = isset($matches[3]) ? $matches[3] : 'b'; $operator = $matches[1]; switch ($unit) { case 'b': break; // kilo case 'Kb': $number <<= 10; break; // mega. case 'Mb': $number <<= 20; break; // giga. case 'Gb': $number <<= 30; break; // tera. case 'Tb': $number *= 1099511627776; break; // peta. case 'Pb': $number *= pow(1024, 5); break; // exa. case 'Eb': $number *= pow(1024, 6); break; // zetta. case 'Zb': $number *= pow(1024, 7); break; // yota. case 'Yb': $number *= pow(1024, 8); break; } $filter = null; switch ($operator) { case '<': $filter = function (\SplFileInfo $current) use ($number) { return $current->getSize() < $number; }; break; case '<=': $filter = function (\SplFileInfo $current) use ($number) { return $current->getSize() <= $number; }; break; case '>': $filter = function (\SplFileInfo $current) use ($number) { return $current->getSize() > $number; }; break; case '>=': $filter = function (\SplFileInfo $current) use ($number) { return $current->getSize() >= $number; }; break; case '=': $filter = function (\SplFileInfo $current) use ($number) { return $current->getSize() === $number; }; break; } $this->_filters[] = $filter; return $this; } /** * Whether we should include dots or not (respectively . and ..). * * @param bool $flag Include or not. * @return \Hoa\File\Finder */ public function dots($flag = \true) { if (\true === $flag) { $this->_flags ^= Iterator\FileSystem::SKIP_DOTS; } else { $this->_flags |= Iterator\FileSystem::SKIP_DOTS; } return $this; } /** * Include files that are owned by a certain owner. * * @param int $owner Owner. * @return \Hoa\File\Finder */ public function owner($owner) { $this->_filters[] = function (\SplFileInfo $current) use ($owner) { return $current->getOwner() === $owner; }; return $this; } /** * Format date. * Date can have the following syntax: * date * since date * until date * If the date does not have the “ago” keyword, it will be added. * Example: “42 hours” is equivalent to “since 42 hours” which is equivalent * to “since 42 hours ago”. * * @param string $date Date. * @param int &$operator Operator (-1 for since, 1 for until). * @return int */ protected function formatDate($date, &$operator) { $operator = -1; if (0 === preg_match('#\bago\b#', $date)) { $date .= ' ago'; } if (0 !== preg_match('#^(since|until)\b(.+)$#', $date, $matches)) { $time = strtotime($matches[2]); if ('until' === $matches[1]) { $operator = 1; } } else { $time = strtotime($date); } return $time; } /** * Include files that have been changed from a certain date. * Example: * $this->changed('since 13 days'); * * @param string $date Date. * @return \Hoa\File\Finder */ public function changed($date) { $time = $this->formatDate($date, $operator); if (-1 === $operator) { $this->_filters[] = function (\SplFileInfo $current) use ($time) { return $current->getCTime() >= $time; }; } else { $this->_filters[] = function (\SplFileInfo $current) use ($time) { return $current->getCTime() < $time; }; } return $this; } /** * Include files that have been modified from a certain date. * Example: * $this->modified('since 13 days'); * * @param string $date Date. * @return \Hoa\File\Finder */ public function modified($date) { $time = $this->formatDate($date, $operator); if (-1 === $operator) { $this->_filters[] = function (\SplFileInfo $current) use ($time) { return $current->getMTime() >= $time; }; } else { $this->_filters[] = function (\SplFileInfo $current) use ($time) { return $current->getMTime() < $time; }; } return $this; } /** * Add your own filter. * The callback will receive 3 arguments: $current, $key and $iterator. It * must return a boolean: true to include the file, false to exclude it. * Example: * // Include files that are readable * $this->filter(function ($current) { * return $current->isReadable(); * }); * * @param callable $callback Callback * @return \Hoa\File\Finder */ public function filter($callback) { $this->_filters[] = $callback; return $this; } /** * Sort result by name. * If \Collator exists (from ext/intl), the $locale argument will be used * for its constructor. Else, strcmp() will be used. * Example: * $this->sortByName('fr_FR'); * * @param string $locale Locale. * @return \Hoa\File\Finder */ public function sortByName($locale = 'root') { if (\true === class_exists('Collator', \false)) { $collator = new \Collator($locale); $this->_sorts[] = function (\SplFileInfo $a, \SplFileInfo $b) use ($collator) { return $collator->compare($a->getPathname(), $b->getPathname()); }; } else { $this->_sorts[] = function (\SplFileInfo $a, \SplFileInfo $b) { return strcmp($a->getPathname(), $b->getPathname()); }; } return $this; } /** * Sort result by size. * Example: * $this->sortBySize(); * * @return \Hoa\File\Finder */ public function sortBySize() { $this->_sorts[] = function (\SplFileInfo $a, \SplFileInfo $b) { return $a->getSize() < $b->getSize(); }; return $this; } /** * Add your own sort. * The callback will receive 2 arguments: $a and $b. Please see the uasort() * function. * Example: * // Sort files by their modified time. * $this->sort(function ($a, $b) { * return $a->getMTime() < $b->getMTime(); * }); * * @param callable $callable Callback. * @return \Hoa\File\Finder */ public function sort($callable) { $this->_sorts[] = $callable; return $this; } /** * Child comes first when iterating. * * @return \Hoa\File\Finder */ public function childFirst() { $this->_first = Iterator\Recursive\Iterator::CHILD_FIRST; return $this; } /** * Get the iterator. * * @return \Traversable */ public function getIterator() { $_iterator = new Iterator\Append(); $types = $this->getTypes(); if (!empty($types)) { $this->_filters[] = function (\SplFileInfo $current) use ($types) { return in_array($current->getType(), $types); }; } $maxDepth = $this->getMaxDepth(); $splFileInfo = $this->getSplFileInfo(); foreach ($this->getPaths() as $path) { if (1 == $maxDepth) { $iterator = new Iterator\IteratorIterator(new Iterator\Recursive\Directory($path, $this->getFlags(), $splFileInfo), $this->getFirst()); } else { $iterator = new Iterator\Recursive\Iterator(new Iterator\Recursive\Directory($path, $this->getFlags(), $splFileInfo), $this->getFirst()); if (1 < $maxDepth) { $iterator->setMaxDepth($maxDepth - 1); } } $_iterator->append($iterator); } foreach ($this->getFilters() as $filter) { $_iterator = new Iterator\CallbackFilter($_iterator, $filter); } $sorts = $this->getSorts(); if (empty($sorts)) { return $_iterator; } $array = iterator_to_array($_iterator); foreach ($sorts as $sort) { uasort($array, $sort); } return new Iterator\Map($array); } /** * Set SplFileInfo classname. * * @param string $splFileInfo SplFileInfo classname. * @return string */ public function setSplFileInfo($splFileInfo) { $old = $this->_splFileInfo; $this->_splFileInfo = $splFileInfo; return $old; } /** * Get SplFileInfo classname. * * @return string */ public function getSplFileInfo() { return $this->_splFileInfo; } /** * Get all paths. * * @return array */ protected function getPaths() { return $this->_paths; } /** * Get max depth. * * @return int */ public function getMaxDepth() { return $this->_maxDepth; } /** * Get types. * * @return array */ public function getTypes() { return $this->_types; } /** * Get filters. * * @return array */ protected function getFilters() { return $this->_filters; } /** * Get sorts. * * @return array */ protected function getSorts() { return $this->_sorts; } /** * Get flags. * * @return int */ public function getFlags() { return $this->_flags; } /** * Get first. * * @return int */ public function getFirst() { return $this->_first; } } getStreamName()); } /** * Get directory name component of path. * * @return string */ public function getDirname() { return dirname($this->getStreamName()); } /** * Get size. * * @return int */ public function getSize() { if (\false === $this->getStatistic()) { return \false; } return filesize($this->getStreamName()); } /** * Get informations about a file. * * @return array */ public function getStatistic() { return fstat($this->getStream()); } /** * Get last access time of file. * * @return int */ public function getATime() { return fileatime($this->getStreamName()); } /** * Get inode change time of file. * * @return int */ public function getCTime() { return filectime($this->getStreamName()); } /** * Get file modification time. * * @return int */ public function getMTime() { return filemtime($this->getStreamName()); } /** * Get file group. * * @return int */ public function getGroup() { return filegroup($this->getStreamName()); } /** * Get file owner. * * @return int */ public function getOwner() { return fileowner($this->getStreamName()); } /** * Get file permissions. * * @return int */ public function getPermissions() { return fileperms($this->getStreamName()); } /** * Get file permissions as a string. * Result sould be interpreted like this: * * s: socket; * * l: symbolic link; * * -: regular; * * b: block special; * * d: directory; * * c: character special; * * p: FIFO pipe; * * u: unknown. * * @return string */ public function getReadablePermissions() { $p = $this->getPermissions(); if (($p & 0xc000) == 0xc000) { $out = 's'; } elseif (($p & 0xa000) == 0xa000) { $out = 'l'; } elseif (($p & 0x8000) == 0x8000) { $out = '-'; } elseif (($p & 0x6000) == 0x6000) { $out = 'b'; } elseif (($p & 0x4000) == 0x4000) { $out = 'd'; } elseif (($p & 0x2000) == 0x2000) { $out = 'c'; } elseif (($p & 0x1000) == 0x1000) { $out = 'p'; } else { $out = 'u'; } $out .= ($p & 0x100 ? 'r' : '-') . ($p & 0x80 ? 'w' : '-') . ($p & 0x40 ? $p & 0x800 ? 's' : 'x' : ($p & 0x800 ? 'S' : '-')) . ($p & 0x20 ? 'r' : '-') . ($p & 0x10 ? 'w' : '-') . ($p & 0x8 ? $p & 0x400 ? 's' : 'x' : ($p & 0x400 ? 'S' : '-')) . ($p & 0x4 ? 'r' : '-') . ($p & 0x2 ? 'w' : '-') . ($p & 0x1 ? $p & 0x200 ? 't' : 'x' : ($p & 0x200 ? 'T' : '-')); return $out; } /** * Check if the file is readable. * * @return bool */ public function isReadable() { return is_readable($this->getStreamName()); } /** * Check if the file is writable. * * @return bool */ public function isWritable() { return is_writable($this->getStreamName()); } /** * Check if the file is executable. * * @return bool */ public function isExecutable() { return is_executable($this->getStreamName()); } /** * Clear file status cache. * * @return void */ public function clearStatisticCache() { clearstatcache(\true, $this->getStreamName()); return; } /** * Clear all files status cache. * * @return void */ public static function clearAllStatisticCaches() { clearstatcache(); return; } /** * Set access and modification time of file. * * @param int $time Time. If equals to -1, time() should be used. * @param int $atime Access time. If equals to -1, $time should be * used. * @return bool */ public function touch($time = -1, $atime = -1) { if ($time == -1) { $time = time(); } if ($atime == -1) { $atime = $time; } return touch($this->getStreamName(), $time, $atime); } /** * Copy file. * Return the destination file path if succeed, false otherwise. * * @param string $to Destination path. * @param bool $force Force to copy if the file $to already exists. * Use the \Hoa\Stream\IStream\Touchable::*OVERWRITE * constants. * @return bool */ public function copy($to, $force = Stream\IStream\Touchable::DO_NOT_OVERWRITE) { $from = $this->getStreamName(); if ($force === Stream\IStream\Touchable::DO_NOT_OVERWRITE && \true === file_exists($to)) { return \true; } if (null === $this->getStreamContext()) { return @copy($from, $to); } return @copy($from, $to, $this->getStreamContext()->getContext()); } /** * Move a file. * * @param string $name New name. * @param bool $force Force to move if the file $name already * exists. * Use the \Hoa\Stream\IStream\Touchable::*OVERWRITE * constants. * @param bool $mkdir Force to make directory if does not exist. * Use the \Hoa\Stream\IStream\Touchable::*DIRECTORY * constants. * @return bool */ public function move($name, $force = Stream\IStream\Touchable::DO_NOT_OVERWRITE, $mkdir = Stream\IStream\Touchable::DO_NOT_MAKE_DIRECTORY) { $from = $this->getStreamName(); if ($force === Stream\IStream\Touchable::DO_NOT_OVERWRITE && \true === file_exists($name)) { return \false; } if (Stream\IStream\Touchable::MAKE_DIRECTORY === $mkdir) { \Hoa\File\Directory::create(dirname($name), \Hoa\File\Directory::MODE_CREATE_RECURSIVE); } if (null === $this->getStreamContext()) { return @rename($from, $name); } return @rename($from, $name, $this->getStreamContext()->getContext()); } /** * Delete a file. * * @return bool */ public function delete() { if (null === $this->getStreamContext()) { return @unlink($this->getStreamName()); } return @unlink($this->getStreamName(), $this->getStreamContext()->getContext()); } /** * Change file group. * * @param mixed $group Group name or number. * @return bool */ public function changeGroup($group) { return chgrp($this->getStreamName(), $group); } /** * Change file mode. * * @param int $mode Mode (in octal!). * @return bool */ public function changeMode($mode) { return chmod($this->getStreamName(), $mode); } /** * Change file owner. * * @param mixed $user User. * @return bool */ public function changeOwner($user) { return chown($this->getStreamName(), $user); } /** * Change the current umask. * * @param int $umask Umask (in octal!). If null, given the current * umask value. * @return int */ public static function umask($umask = null) { if (null === $umask) { return umask(); } return umask($umask); } /** * Check if it is a file. * * @return bool */ public function isFile() { return is_file($this->getStreamName()); } /** * Check if it is a link. * * @return bool */ public function isLink() { return is_link($this->getStreamName()); } /** * Check if it is a directory. * * @return bool */ public function isDirectory() { return is_dir($this->getStreamName()); } /** * Check if it is a socket. * * @return bool */ public function isSocket() { return filetype($this->getStreamName()) == 'socket'; } /** * Check if it is a FIFO pipe. * * @return bool */ public function isFIFOPipe() { return filetype($this->getStreamName()) == 'fifo'; } /** * Check if it is character special file. * * @return bool */ public function isCharacterSpecial() { return filetype($this->getStreamName()) == 'char'; } /** * Check if it is block special. * * @return bool */ public function isBlockSpecial() { return filetype($this->getStreamName()) == 'block'; } /** * Check if it is an unknown type. * * @return bool */ public function isUnknown() { return filetype($this->getStreamName()) == 'unknown'; } /** * Set the open mode. * * @param string $mode Open mode. Please, see the child::MODE_* * constants. * @return string */ protected function setMode($mode) { $old = $this->_mode; $this->_mode = $mode; return $old; } /** * Get the open mode. * * @return string */ public function getMode() { return $this->_mode; } /** * Get inode. * * @return int */ public function getINode() { return fileinode($this->getStreamName()); } /** * Check if the system is case sensitive or not. * * @return bool */ public static function isCaseSensitive() { return !(file_exists(mb_strtolower(__FILE__)) && file_exists(mb_strtoupper(__FILE__))); } /** * Get a canonicalized absolute pathname. * * @return string */ public function getRealPath() { if (\false === $out = realpath($this->getStreamName())) { return $this->getStreamName(); } return $out; } /** * Get file extension (if exists). * * @return string */ public function getExtension() { return pathinfo($this->getStreamName(), \PATHINFO_EXTENSION); } /** * Get filename without extension. * * @return string */ public function getFilename() { $file = basename($this->getStreamName()); if (defined('PATHINFO_FILENAME')) { return pathinfo($file, \PATHINFO_FILENAME); } if (strstr($file, '.')) { return substr($file, 0, strrpos($file, '.')); } return $file; } } getStreamName()); } /** * Change file group. * * @param mixed $group Group name or number. * @return bool */ public function changeGroup($group) { return lchgrp($this->getStreamName(), $group); } /** * Change file owner. * * @param mixed $user User. * @return bool */ public function changeOwner($user) { return lchown($this->getStreamName(), $user); } /** * Get file permissions. * * @return int */ public function getPermissions() { return 41453; // i.e. lrwxr-xr-x } /** * Get the target of a symbolic link. * * @return \Hoa\File\Generic * @throws \Hoa\File\Exception */ public function getTarget() { $target = dirname($this->getStreamName()) . DS . $this->getTargetName(); $context = null !== $this->getStreamContext() ? $this->getStreamContext()->getCurrentId() : null; if (\true === is_link($target)) { return new \Hoa\File\Link\ReadWrite($target, File::MODE_APPEND_READ_WRITE, $context); } elseif (\true === is_file($target)) { return new File\ReadWrite($target, File::MODE_APPEND_READ_WRITE, $context); } elseif (\true === is_dir($target)) { return new File\Directory($target, File::MODE_READ, $context); } throw new File\Exception('Cannot find an appropriated object that matches with ' . 'path %s when defining it.', 1, $target); } /** * Get the target name of a symbolic link. * * @return string */ public function getTargetName() { return readlink($this->getStreamName()); } /** * Create a link. * * @param string $name Link name. * @param string $target Target name. * @return bool */ public static function create($name, $target) { if (\false != linkinfo($name)) { return \true; } return symlink($target, $name); } } /** * Flex entity. */ Consistency::flexEntity('Hoa\File\Link\Link'); getMode(), $createModes)) { throw new File\Exception('Open mode are not supported; given %d. Only %s are supported.', 0, [$this->getMode(), implode(', ', $createModes)]); } preg_match('#^(\w+)://#', $streamName, $match); if ((isset($match[1]) && $match[1] == 'file' || !isset($match[1])) && !file_exists($streamName)) { throw new File\Exception\FileDoesNotExist('File %s does not exist.', 1, $streamName); } $out = parent::_open($streamName, $context); return $out; } /** * Test for end-of-file. * * @return bool */ public function eof() { return feof($this->getStream()); } /** * Read n characters. * * @param int $length Length. * @return string * @throws \Hoa\File\Exception */ public function read($length) { if (0 > $length) { throw new File\Exception('Length must be greater than 0, given %d.', 2, $length); } return fread($this->getStream(), $length); } /** * Alias of $this->read(). * * @param int $length Length. * @return string */ public function readString($length) { return $this->read($length); } /** * Read a character. * * @return string */ public function readCharacter() { return fgetc($this->getStream()); } /** * Read a boolean. * * @return bool */ public function readBoolean() { return (bool) $this->read(1); } /** * Read an integer. * * @param int $length Length. * @return int */ public function readInteger($length = 1) { return (int) $this->read($length); } /** * Read a float. * * @param int $length Length. * @return float */ public function readFloat($length = 1) { return (float) $this->read($length); } /** * Read an array. * Alias of the $this->scanf() method. * * @param string $format Format (see printf's formats). * @return array */ public function readArray($format = null) { return $this->scanf($format); } /** * Read a line. * * @return string */ public function readLine() { return fgets($this->getStream()); } /** * Read all, i.e. read as much as possible. * * @param int $offset Offset. * @return string */ public function readAll($offset = 0) { return stream_get_contents($this->getStream(), -1, $offset); } /** * Parse input from a stream according to a format. * * @param string $format Format (see printf's formats). * @return array */ public function scanf($format) { return fscanf($this->getStream(), $format); } } getMode(), $createModes)) { throw new File\Exception('Open mode are not supported; given %d. Only %s are supported.', 0, [$this->getMode(), implode(', ', $createModes)]); } preg_match('#^(\w+)://#', $streamName, $match); if ((isset($match[1]) && $match[1] == 'file' || !isset($match[1])) && !file_exists($streamName) && parent::MODE_READ_WRITE == $this->getMode()) { throw new File\Exception\FileDoesNotExist('File %s does not exist.', 1, $streamName); } $out = parent::_open($streamName, $context); return $out; } /** * Test for end-of-file. * * @return bool */ public function eof() { return feof($this->getStream()); } /** * Read n characters. * * @param int $length Length. * @return string * @throws \Hoa\File\Exception */ public function read($length) { if (0 > $length) { throw new File\Exception('Length must be greater than 0, given %d.', 2, $length); } return fread($this->getStream(), $length); } /** * Alias of $this->read(). * * @param int $length Length. * @return string */ public function readString($length) { return $this->read($length); } /** * Read a character. * * @return string */ public function readCharacter() { return fgetc($this->getStream()); } /** * Read a boolean. * * @return bool */ public function readBoolean() { return (bool) $this->read(1); } /** * Read an integer. * * @param int $length Length. * @return int */ public function readInteger($length = 1) { return (int) $this->read($length); } /** * Read a float. * * @param int $length Length. * @return float */ public function readFloat($length = 1) { return (float) $this->read($length); } /** * Read an array. * Alias of the $this->scanf() method. * * @param string $format Format (see printf's formats). * @return array */ public function readArray($format = null) { return $this->scanf($format); } /** * Read a line. * * @return string */ public function readLine() { return fgets($this->getStream()); } /** * Read all, i.e. read as much as possible. * * @param int $offset Offset. * @return string */ public function readAll($offset = 0) { return stream_get_contents($this->getStream(), -1, $offset); } /** * Parse input from a stream according to a format. * * @param string $format Format (see printf's formats). * @return array */ public function scanf($format) { return fscanf($this->getStream(), $format); } /** * Write n characters. * * @param string $string String. * @param int $length Length. * @return mixed * @throws \Hoa\File\Exception */ public function write($string, $length) { if (0 > $length) { throw new File\Exception('Length must be greater than 0, given %d.', 3, $length); } return fwrite($this->getStream(), $string, $length); } /** * Write a string. * * @param string $string String. * @return mixed */ public function writeString($string) { $string = (string) $string; return $this->write($string, strlen($string)); } /** * Write a character. * * @param string $char Character. * @return mixed */ public function writeCharacter($char) { return $this->write((string) $char[0], 1); } /** * Write a boolean. * * @param bool $boolean Boolean. * @return mixed */ public function writeBoolean($boolean) { return $this->write((string) (bool) $boolean, 1); } /** * Write an integer. * * @param int $integer Integer. * @return mixed */ public function writeInteger($integer) { $integer = (string) (int) $integer; return $this->write($integer, strlen($integer)); } /** * Write a float. * * @param float $float Float. * @return mixed */ public function writeFloat($float) { $float = (string) (float) $float; return $this->write($float, strlen($float)); } /** * Write an array. * * @param array $array Array. * @return mixed */ public function writeArray(array $array) { $array = var_export($array, \true); return $this->write($array, strlen($array)); } /** * Write a line. * * @param string $line Line. * @return mixed */ public function writeLine($line) { if (\false === $n = strpos($line, "\n")) { return $this->write($line . "\n", strlen($line) + 1); } ++$n; return $this->write(substr($line, 0, $n), $n); } /** * Write all, i.e. as much as possible. * * @param string $string String. * @return mixed */ public function writeAll($string) { return $this->write($string, strlen($string)); } /** * Truncate a file to a given length. * * @param int $size Size. * @return bool */ public function truncate($size) { return ftruncate($this->getStream(), $size); } } getMode(), $createModes)) { throw new File\Exception('Open mode are not supported; given %d. Only %s are supported.', 0, [$this->getMode(), implode(', ', $createModes)]); } preg_match('#^(\w+)://#', $streamName, $match); if ((isset($match[1]) && $match[1] == 'file' || !isset($match[1])) && !file_exists($streamName)) { throw new File\Exception\FileDoesNotExist('File %s does not exist.', 1, $streamName); } $out = parent::_open($streamName, $context); return $out; } /** * Write n characters. * * @param string $string String. * @param int $length Length. * @return mixed * @throws \Hoa\File\Exception */ public function write($string, $length) { if (0 > $length) { throw new File\Exception('Length must be greater than 0, given %d.', 2, $length); } return fwrite($this->getStream(), $string, $length); } /** * Write a string. * * @param string $string String. * @return mixed */ public function writeString($string) { $string = (string) $string; return $this->write($string, strlen($string)); } /** * Write a character. * * @param string $char Character. * @return mixed */ public function writeCharacter($char) { return $this->write((string) $char[0], 1); } /** * Write a boolean. * * @param bool $boolean Boolean. * @return mixed */ public function writeBoolean($boolean) { return $this->write((string) (bool) $boolean, 1); } /** * Write an integer. * * @param int $integer Integer. * @return mixed */ public function writeInteger($integer) { $integer = (string) (int) $integer; return $this->write($integer, strlen($integer)); } /** * Write a float. * * @param float $float Float. * @return mixed */ public function writeFloat($float) { $float = (string) (float) $float; return $this->write($float, strlen($float)); } /** * Write an array. * * @param array $array Array. * @return mixed */ public function writeArray(array $array) { $array = var_export($array, \true); return $this->write($array, strlen($array)); } /** * Write a line. * * @param string $line Line. * @return mixed */ public function writeLine($line) { if (\false === $n = strpos($line, "\n")) { return $this->write($line . "\n", strlen($line) + 1); } ++$n; return $this->write(substr($line, 0, $n), $n); } /** * Write all, i.e. as much as possible. * * @param string $string String. * @return mixed */ public function writeAll($string) { return $this->write($string, strlen($string)); } /** * Truncate a file to a given length. * * @param int $size Size. * @return bool */ public function truncate($size) { return ftruncate($this->getStream(), $size); } } This file was automatically generated by Composer Patches (https://github.com/cweagans/composer-patches) Patches applied to this directory: 0 Source: patches/File.patch 1 Source: patches/Read.patch getMode(), $createModes)) { throw new \Hoa\File\Exception('Open mode are not supported; given %d. Only %s are supported.', 0, [$this->getMode(), implode(', ', $createModes)]); } preg_match('#^(\w+)://#', $streamName, $match); if ((isset($match[1]) && $match[1] == 'file' || !isset($match[1])) && !file_exists($streamName)) { throw new \Hoa\File\Exception\FileDoesNotExist('File %s does not exist.', 1, $streamName); } $out = parent::_open($streamName, $context); return $out; } /** * Test for end-of-file. * * @return bool */ public function eof() { return feof($this->getStream()); } /** * Read n characters. * * @param int $length Length. * @return string * @throws \Hoa\File\Exception */ public function read($length) { if (0 > $length) { throw new \Hoa\File\Exception('Length must be greater than 0, given %d.', 2, $length); } return fread($this->getStream(), $length); } /** * Alias of $this->read(). * * @param int $length Length. * @return string */ public function readString($length) { return $this->read($length); } /** * Read a character. * * @return string */ public function readCharacter() { return fgetc($this->getStream()); } /** * Read a boolean. * * @return bool */ public function readBoolean() { return (bool) $this->read(1); } /** * Read an integer. * * @param int $length Length. * @return int */ public function readInteger($length = 1) { return (int) $this->read($length); } /** * Read a float. * * @param int $length Length. * @return float */ public function readFloat($length = 1) { return (float) $this->read($length); } /** * Read an array. * Alias of the $this->scanf() method. * * @param string $format Format (see printf's formats). * @return array */ public function readArray($format = null) { return $this->scanf($format); } /** * Read a line. * * @return string */ public function readLine() { return fgets($this->getStream()); } /** * Read all, i.e. read as much as possible. * * @param int $offset Offset. * @return string */ public function readAll($offset = 0) { return stream_get_contents($this->getStream(), -1, $offset); } /** * Parse input from a stream according to a format. * * @param string $format Format (see printf's formats). * @return array */ public function scanf($format) { return fscanf($this->getStream(), $format); } } getMode(), $createModes)) { throw new \Hoa\File\Exception('Open mode are not supported; given %d. Only %s are supported.', 0, [$this->getMode(), implode(', ', $createModes)]); } preg_match('#^(\w+)://#', $streamName, $match); if ((isset($match[1]) && $match[1] == 'file' || !isset($match[1])) && !file_exists($streamName) && parent::MODE_READ_WRITE == $this->getMode()) { throw new \Hoa\File\Exception\FileDoesNotExist('File %s does not exist.', 1, $streamName); } $out = parent::_open($streamName, $context); return $out; } /** * Test for end-of-file. * * @return bool */ public function eof() { return feof($this->getStream()); } /** * Read n characters. * * @param int $length Length. * @return string * @throws \Hoa\File\Exception */ public function read($length) { if (0 > $length) { throw new \Hoa\File\Exception('Length must be greater than 0, given %d.', 2, $length); } return fread($this->getStream(), $length); } /** * Alias of $this->read(). * * @param int $length Length. * @return string */ public function readString($length) { return $this->read($length); } /** * Read a character. * * @return string */ public function readCharacter() { return fgetc($this->getStream()); } /** * Read a boolean. * * @return bool */ public function readBoolean() { return (bool) $this->read(1); } /** * Read an integer. * * @param int $length Length. * @return int */ public function readInteger($length = 1) { return (int) $this->read($length); } /** * Read a float. * * @param int $length Length. * @return float */ public function readFloat($length = 1) { return (float) $this->read($length); } /** * Read an array. * Alias of the $this->scanf() method. * * @param string $format Format (see printf's formats). * @return array */ public function readArray($format = null) { return $this->scanf($format); } /** * Read a line. * * @return string */ public function readLine() { return fgets($this->getStream()); } /** * Read all, i.e. read as much as possible. * * @param int $offset Offset. * @return string */ public function readAll($offset = 0) { return stream_get_contents($this->getStream(), -1, $offset); } /** * Parse input from a stream according to a format. * * @param string $format Format (see printf's formats). * @return array */ public function scanf($format) { return fscanf($this->getStream(), $format); } /** * Write n characters. * * @param string $string String. * @param int $length Length. * @return mixed * @throws \Hoa\File\Exception */ public function write($string, $length) { if (0 > $length) { throw new \Hoa\File\Exception('Length must be greater than 0, given %d.', 3, $length); } return fwrite($this->getStream(), $string, $length); } /** * Write a string. * * @param string $string String. * @return mixed */ public function writeString($string) { $string = (string) $string; return $this->write($string, strlen($string)); } /** * Write a character. * * @param string $char Character. * @return mixed */ public function writeCharacter($char) { return $this->write((string) $char[0], 1); } /** * Write a boolean. * * @param bool $boolean Boolean. * @return mixed */ public function writeBoolean($boolean) { return $this->write((string) (bool) $boolean, 1); } /** * Write an integer. * * @param int $integer Integer. * @return mixed */ public function writeInteger($integer) { $integer = (string) (int) $integer; return $this->write($integer, strlen($integer)); } /** * Write a float. * * @param float $float Float. * @return mixed */ public function writeFloat($float) { $float = (string) (float) $float; return $this->write($float, strlen($float)); } /** * Write an array. * * @param array $array Array. * @return mixed */ public function writeArray(array $array) { $array = var_export($array, \true); return $this->write($array, strlen($array)); } /** * Write a line. * * @param string $line Line. * @return mixed */ public function writeLine($line) { if (\false === $n = strpos($line, "\n")) { return $this->write($line . "\n", strlen($line) + 1); } ++$n; return $this->write(substr($line, 0, $n), $n); } /** * Write all, i.e. as much as possible. * * @param string $string String. * @return mixed */ public function writeAll($string) { return $this->write($string, strlen($string)); } /** * Truncate a file to a given length. * * @param int $size Size. * @return bool */ public function truncate($size) { return ftruncate($this->getStream(), $size); } } isFile()) { return $this->_stream = new \Hoa\File\ReadWrite($this->getPathname()); } elseif (\true === $this->isDir()) { return $this->_stream = new \Hoa\File\Directory($this->getPathname()); } elseif (\true === $this->isLink()) { return $this->_stream = new \Hoa\File\Link\ReadWrite($this->getPathname()); } throw new \Hoa\File\Exception('%s has an unknown type.', 0, $this->getPathname()); } /** * Close the opened stream. * * @return void */ public function close() { if (null === $this->_stream) { return; } return $this->_stream->close(); } /** * Destruct. * * @return void */ public function __destruct() { $this->close(); return; } } getMode(), $createModes)) { throw new File\Exception('Open mode are not supported; given %d. Only %s are supported.', 0, [$this->getMode(), implode(', ', $createModes)]); } preg_match('#^(\w+)://#', $streamName, $match); if ((isset($match[1]) && $match[1] == 'file' || !isset($match[1])) && !file_exists($streamName)) { throw new File\Exception\FileDoesNotExist('File %s does not exist.', 1, $streamName); } $out = parent::_open($streamName, $context); return $out; } /** * Test for end-of-file. * * @return bool */ public function eof() { return feof($this->getStream()); } /** * Read n characters. * * @param int $length Length. * @return string * @throws \Hoa\File\Exception */ public function read($length) { if (0 > $length) { throw new File\Exception('Length must be greater than 0, given %d.', 2, $length); } return fread($this->getStream(), $length); } /** * Alias of $this->read(). * * @param int $length Length. * @return string */ public function readString($length) { return $this->read($length); } /** * Read a character. * * @return string */ public function readCharacter() { return fgetc($this->getStream()); } /** * Read a boolean. * * @return bool */ public function readBoolean() { return (bool) $this->read(1); } /** * Read an integer. * * @param int $length Length. * @return int */ public function readInteger($length = 1) { return (int) $this->read($length); } /** * Read a float. * * @param int $length Length. * @return float */ public function readFloat($length = 1) { return (float) $this->read($length); } /** * Read an array. * Alias of the $this->scanf() method. * * @param string $format Format (see printf's formats). * @return array */ public function readArray($format = null) { return $this->scanf($format); } /** * Read a line. * * @return string */ public function readLine() { return fgets($this->getStream()); } /** * Read all, i.e. read as much as possible. * * @param int $offset Offset. * @return string */ public function readAll($offset = 0) { return stream_get_contents($this->getStream(), -1, $offset); } /** * Parse input from a stream according to a format. * * @param string $format Format (see printf's formats). * @return array */ public function scanf($format) { return fscanf($this->getStream(), $format); } } getMode(), $createModes)) { throw new File\Exception('Open mode are not supported; given %d. Only %s are supported.', 0, [$this->getMode(), implode(', ', $createModes)]); } preg_match('#^(\w+)://#', $streamName, $match); if ((isset($match[1]) && $match[1] == 'file' || !isset($match[1])) && !file_exists($streamName) && parent::MODE_READ_WRITE == $this->getMode()) { throw new File\Exception\FileDoesNotExist('File %s does not exist.', 1, $streamName); } $out = parent::_open($streamName, $context); return $out; } /** * Test for end-of-file. * * @return bool */ public function eof() { return feof($this->getStream()); } /** * Read n characters. * * @param int $length Length. * @return string * @throws \Hoa\File\Exception */ public function read($length) { if (0 > $length) { throw new File\Exception('Length must be greater than 0, given %d.', 2, $length); } return fread($this->getStream(), $length); } /** * Alias of $this->read(). * * @param int $length Length. * @return string */ public function readString($length) { return $this->read($length); } /** * Read a character. * * @return string */ public function readCharacter() { return fgetc($this->getStream()); } /** * Read a boolean. * * @return bool */ public function readBoolean() { return (bool) $this->read(1); } /** * Read an integer. * * @param int $length Length. * @return int */ public function readInteger($length = 1) { return (int) $this->read($length); } /** * Read a float. * * @param int $length Length. * @return float */ public function readFloat($length = 1) { return (float) $this->read($length); } /** * Read an array. * Alias of the $this->scanf() method. * * @param string $format Format (see printf's formats). * @return array */ public function readArray($format = null) { return $this->scanf($format); } /** * Read a line. * * @return string */ public function readLine() { return fgets($this->getStream()); } /** * Read all, i.e. read as much as possible. * * @param int $offset Offset. * @return string */ public function readAll($offset = 0) { return stream_get_contents($this->getStream(), -1, $offset); } /** * Parse input from a stream according to a format. * * @param string $format Format (see printf's formats). * @return array */ public function scanf($format) { return fscanf($this->getStream(), $format); } /** * Write n characters. * * @param string $string String. * @param int $length Length. * @return mixed * @throws \Hoa\File\Exception */ public function write($string, $length) { if (0 > $length) { throw new File\Exception('Length must be greater than 0, given %d.', 3, $length); } return fwrite($this->getStream(), $string, $length); } /** * Write a string. * * @param string $string String. * @return mixed */ public function writeString($string) { $string = (string) $string; return $this->write($string, strlen($string)); } /** * Write a character. * * @param string $char Character. * @return mixed */ public function writeCharacter($char) { return $this->write((string) $char[0], 1); } /** * Write a boolean. * * @param bool $boolean Boolean. * @return mixed */ public function writeBoolean($boolean) { return $this->write((string) (bool) $boolean, 1); } /** * Write an integer. * * @param int $integer Integer. * @return mixed */ public function writeInteger($integer) { $integer = (string) (int) $integer; return $this->write($integer, strlen($integer)); } /** * Write a float. * * @param float $float Float. * @return mixed */ public function writeFloat($float) { $float = (string) (float) $float; return $this->write($float, strlen($float)); } /** * Write an array. * * @param array $array Array. * @return mixed */ public function writeArray(array $array) { $array = var_export($array, \true); return $this->write($array, strlen($array)); } /** * Write a line. * * @param string $line Line. * @return mixed */ public function writeLine($line) { if (\false === $n = strpos($line, "\n")) { return $this->write($line . "\n", strlen($line) + 1); } ++$n; return $this->write(substr($line, 0, $n), $n); } /** * Write all, i.e. as much as possible. * * @param string $string String. * @return mixed */ public function writeAll($string) { return $this->write($string, strlen($string)); } /** * Truncate a file to a given length. * * @param int $size Size. * @return bool */ public function truncate($size) { return ftruncate($this->getStream(), $size); } } __construct() that will create a temporary * file that will be destroy when calling the $this->close() method. * * @param string $directory Directory where the temporary filename * will be created. If the directory does not * exist, it may generate a file in the * system's temporary directory. * @param string $prefix Prefix of the generated temporary * filename. * @return string */ public static function create($directory = null, $prefix = '__hoa_') { if (null === $directory || \false === is_dir($directory)) { $directory = static::getTemporaryDirectory(); } return tempnam($directory, $prefix); } /** * Get the directory path used for temporary files. * * @return string */ public static function getTemporaryDirectory() { return sys_get_temp_dir(); } } /** * Flex entity. */ Consistency::flexEntity('Hoa\File\Temporary\Temporary'); getMode(), $createModes)) { throw new File\Exception('Open mode are not supported; given %d. Only %s are supported.', 0, [$this->getMode(), implode(', ', $createModes)]); } preg_match('#^(\w+)://#', $streamName, $match); if ((isset($match[1]) && $match[1] == 'file' || !isset($match[1])) && !file_exists($streamName)) { throw new File\Exception\FileDoesNotExist('File %s does not exist.', 1, $streamName); } $out = parent::_open($streamName, $context); return $out; } /** * Write n characters. * * @param string $string String. * @param int $length Length. * @return mixed * @throws \Hoa\File\Exception */ public function write($string, $length) { if (0 > $length) { throw new File\Exception('Length must be greater than 0, given %d.', 2, $length); } return fwrite($this->getStream(), $string, $length); } /** * Write a string. * * @param string $string String. * @return mixed */ public function writeString($string) { $string = (string) $string; return $this->write($string, strlen($string)); } /** * Write a character. * * @param string $char Character. * @return mixed */ public function writeCharacter($char) { return $this->write((string) $char[0], 1); } /** * Write a boolean. * * @param bool $boolean Boolean. * @return mixed */ public function writeBoolean($boolean) { return $this->write((string) (bool) $boolean, 1); } /** * Write an integer. * * @param int $integer Integer. * @return mixed */ public function writeInteger($integer) { $integer = (string) (int) $integer; return $this->write($integer, strlen($integer)); } /** * Write a float. * * @param float $float Float. * @return mixed */ public function writeFloat($float) { $float = (string) (float) $float; return $this->write($float, strlen($float)); } /** * Write an array. * * @param array $array Array. * @return mixed */ public function writeArray(array $array) { $array = var_export($array, \true); return $this->write($array, strlen($array)); } /** * Write a line. * * @param string $line Line. * @return mixed */ public function writeLine($line) { if (\false === $n = strpos($line, "\n")) { return $this->write($line . "\n", strlen($line) + 1); } ++$n; return $this->write(substr($line, 0, $n), $n); } /** * Write all, i.e. as much as possible. * * @param string $string String. * @return mixed */ public function writeAll($string) { return $this->write($string, strlen($string)); } /** * Truncate a file to a given length. * * @param int $size Size. * @return bool */ public function truncate($size) { return ftruncate($this->getStream(), $size); } } setListener(new Event\Listener($this, ['new', 'modify', 'move'])); if (null !== $latency) { $this->setLatency($latency); } return; } /** * Run the watcher. * * Listenable events: * • new, when a file is new, i.e. found by the finder; * • modify, when a file has been modified; * • move, when a file has moved, i.e. no longer found by the finder. * * @return void */ public function run() { $iterator = $this->getIterator(); $previous = iterator_to_array($iterator); $current = $previous; while (\true) { foreach ($current as $name => $c) { if (!isset($previous[$name])) { $this->getListener()->fire('new', new Event\Bucket(['file' => $c])); continue; } if (null === $c->getHash()) { unset($current[$name]); continue; } if ($previous[$name]->getHash() != $c->getHash()) { $this->getListener()->fire('modify', new Event\Bucket(['file' => $c])); } unset($previous[$name]); } foreach ($previous as $p) { $this->getListener()->fire('move', new Event\Bucket(['file' => $p])); } usleep($this->getLatency() * 1000000); $previous = $current; $current = iterator_to_array($iterator); } return; } /** * Set latency. * * @param int $latency Latency (in seconds). * @return int */ public function setLatency($latency) { $old = $this->_latency; $this->_latency = $latency; return $old; } /** * Get latency. * * @return int */ public function getLatency() { return $this->_latency; } } getMode(), $createModes)) { throw new \Hoa\File\Exception('Open mode are not supported; given %d. Only %s are supported.', 0, [$this->getMode(), implode(', ', $createModes)]); } preg_match('#^(\w+)://#', $streamName, $match); if ((isset($match[1]) && $match[1] == 'file' || !isset($match[1])) && !file_exists($streamName) && parent::MODE_TRUNCATE_WRITE == $this->getMode()) { throw new \Hoa\File\Exception\FileDoesNotExist('File %s does not exist.', 1, $streamName); } $out = parent::_open($streamName, $context); return $out; } /** * Write n characters. * * @param string $string String. * @param int $length Length. * @return mixed * @throws \Hoa\File\Exception */ public function write($string, $length) { if (0 > $length) { throw new \Hoa\File\Exception('Length must be greater than 0, given %d.', 2, $length); } return fwrite($this->getStream(), $string, $length); } /** * Write a string. * * @param string $string String. * @return mixed */ public function writeString($string) { $string = (string) $string; return $this->write($string, strlen($string)); } /** * Write a character. * * @param string $char Character. * @return mixed */ public function writeCharacter($char) { return $this->write((string) $char[0], 1); } /** * Write a boolean. * * @param bool $boolean Boolean. * @return mixed */ public function writeBoolean($boolean) { return $this->write((string) (bool) $boolean, 1); } /** * Write an integer. * * @param int $integer Integer. * @return mixed */ public function writeInteger($integer) { $integer = (string) (int) $integer; return $this->write($integer, strlen($integer)); } /** * Write a float. * * @param float $float Float. * @return mixed */ public function writeFloat($float) { $float = (string) (float) $float; return $this->write($float, strlen($float)); } /** * Write an array. * * @param array $array Array. * @return mixed */ public function writeArray(array $array) { $array = var_export($array, \true); return $this->write($array, strlen($array)); } /** * Write a line. * * @param string $line Line. * @return mixed */ public function writeLine($line) { if (\false === $n = strpos($line, "\n")) { return $this->write($line . "\n", strlen($line) + 1); } ++$n; return $this->write(substr($line, 0, $n), $n); } /** * Write all, i.e. as much as possible. * * @param string $string String. * @return mixed */ public function writeAll($string) { return $this->write($string, strlen($string)); } /** * Truncate a file to a given length. * * @param int $size Size. * @return bool */ public function truncate($size) { return ftruncate($this->getStream(), $size); } } _iterator = $iterator; $this->_bufferSize = max($bufferSize, 1); $this->_buffer = new \SplDoublyLinkedList(); return; } /** * Get inner iterator. * * @return \Iterator */ public function getInnerIterator(): ?\Iterator { return $this->_iterator; } /** * Get buffer. * * @return \SplDoublyLinkedList */ protected function getBuffer() { return $this->_buffer; } /** * Get buffer size. * * @return int */ public function getBufferSize() { return $this->_bufferSize; } /** * Return the current element. * * @return mixed */ #[\ReturnTypeWillChange] public function current() { return $this->getBuffer()->current()[self::BUFFER_VALUE]; } /** * Return the key of the current element. * * @return mixed */ #[\ReturnTypeWillChange] public function key() { return $this->getBuffer()->current()[self::BUFFER_KEY]; } /** * Move forward to next element. * * @return void */ public function next(): void { $innerIterator = $this->getInnerIterator(); $buffer = $this->getBuffer(); $buffer->next(); // End of the buffer, need a new value. if (\false === $buffer->valid()) { for ($bufferSize = count($buffer), $maximumBufferSize = $this->getBufferSize(); $bufferSize >= $maximumBufferSize; --$bufferSize) { $buffer->shift(); } $innerIterator->next(); $buffer->push([self::BUFFER_KEY => $innerIterator->key(), self::BUFFER_VALUE => $innerIterator->current()]); // Seek to the end of the buffer. $buffer->setIteratorMode($buffer::IT_MODE_LIFO | $buffer::IT_MODE_KEEP); $buffer->rewind(); $buffer->setIteratorMode($buffer::IT_MODE_FIFO | $buffer::IT_MODE_KEEP); } return; } /** * Move backward to previous element. * * @return void */ public function previous() { $this->getBuffer()->prev(); return; } /** * Rewind the iterator to the first element. * * @return void */ public function rewind(): void { $innerIterator = $this->getInnerIterator(); $buffer = $this->getBuffer(); $innerIterator->rewind(); if (\true === $buffer->isEmpty()) { $buffer->push([self::BUFFER_KEY => $innerIterator->key(), self::BUFFER_VALUE => $innerIterator->current()]); } $buffer->rewind(); return; } /** * Check if current position is valid. * * @return bool */ public function valid(): bool { return $this->getBuffer()->valid() && $this->getInnerIterator()->valid(); } } _callback = $callback; return; } /** * Return the current element. * * @return mixed */ public function current() { $handle = $this->_callback; return $this->_current = $handle($this->_key); } /** * Return the key of the current element. * * @return mixed */ public function key() { return $this->_key; } /** * Move forward to next element. * * @return void */ public function next() { ++$this->_key; return; } /** * Rewind the iterator to the first element. * * @return void */ public function rewind() { $this->_key = 0; $this->_current = null; return; } /** * Check if current position is valid. * * @return bool */ public function valid() { return \true; } } _from = $from; $this->_to = $to; $this->_step = $step; return; } /** * Return the current element. * * @return int */ public function current() { return $this->_i; } /** * Return the key of the current element. * * @return int */ public function key() { return $this->_key; } /** * Move forward to next element. * * @return void */ public function next() { ++$this->_key; $this->_i += $this->_step; return; } /** * Rewind the iterator to the first element. * * @return void */ public function rewind() { $this->_key = 0; $this->_i = $this->_from; return; } /** * Check if current position is valid. * * @return bool */ public function valid() { return $this->_i < $this->_to; } } getIterator(); } $this->_iterator = $iterator; $this->_demuxer = $demuxer; return; } /** * Return the current element. * * @return mixed */ public function current() { if (null !== $this->_current) { return $this->_current; } $demuxer = $this->_demuxer; return $this->_current = $demuxer($this->_iterator->current()); } /** * Return the key of the current element. * * @return mixed */ public function key() { return $this->_iterator->key(); } /** * Move forward to next element. * * @return void */ public function next() { $this->_current = null; return $this->_iterator->next(); } /** * Rewind the iterator to the first element. * * @return void */ public function rewind() { return $this->_iterator->rewind(); } /** * Check if current position is valid. * * @return bool */ public function valid() { return $this->_iterator->valid(); } } _splFileInfoClass = $splFileInfoClass; parent::__construct($path); $this->setRelativePath($path); return; } /** * Current. * Please, see \DirectoryIterator::current() method. * * @return mixed */ public function current() { $out = parent::current(); if (null !== $this->_splFileInfoClass && $out instanceof \SplFileInfo) { $out->setInfoClass($this->_splFileInfoClass); $out = $out->getFileInfo(); if ($out instanceof \Hoa\Iterator\SplFileInfo) { $out->setRelativePath($this->getRelativePath()); } } return $out; } /** * Set relative path. * * @param string $relativePath Relative path. * @return string */ protected function setRelativePath($path) { $old = $this->_relativePath; $this->_relativePath = $path; return $old; } /** * Get relative path (if given). * * @return string */ public function getRelativePath() { return $this->_relativePath; } } _splFileInfoClass = $splFileInfoClass; if (null === $flags) { parent::__construct($path); } else { parent::__construct($path, $flags); } return; } /** * Current. * Please, see \FileSystemIterator::current() method. * * @return mixed */ public function current() { $out = parent::current(); if (null !== $this->_splFileInfoClass && $out instanceof \SplFileInfo) { $out->setInfoClass($this->_splFileInfoClass); $out = $out->getFileInfo(); } return $out; } } _iterator = $iterator; return; } /** * Get inner iterator. * * @return \Iterator */ public function getInnerIterator(): ?\Iterator { return $this->_iterator; } /** * Return the current element. * * @return mixed */ #[\ReturnTypeWillChange] public function current() { return $this->_current; } /** * Return the key of the current element. * * @return mixed */ #[\ReturnTypeWillChange] public function key() { return $this->_key; } /** * Move forward to next element. * * @return void */ #[\ReturnTypeWillChange] public function next() { $innerIterator = $this->getInnerIterator(); $this->_valid = $innerIterator->valid(); if (\false === $this->_valid) { return; } $this->_key = $innerIterator->key(); $this->_current = $innerIterator->current(); return $innerIterator->next(); } /** * Rewind the iterator to the first element. * * @return void */ #[\ReturnTypeWillChange] public function rewind() { $out = $this->getInnerIterator()->rewind(); $this->next(); return $out; } /** * Check if current position is valid. * * @return bool */ public function valid(): bool { return $this->_valid; } /** * Check whether there is a next element. * * @return bool */ public function hasNext() { return $this->getInnerIterator()->valid(); } /** * Get next value. * * @return mixed */ public function getNext() { return $this->getInnerIterator()->current(); } /** * Get next key. * * @return mixed */ public function getNextKey() { return $this->getInnerIterator()->key(); } } _iterator = $iterator; return; } /** * Get inner iterator. * * @return \Iterator */ public function getInnerIterator() { return $this->_iterator; } /** * Return the current element. * * @return mixed */ public function current() { return $this->getInnerIterator()->current(); } /** * Return the key of the current element. * * @return mixed */ public function key() { return $this->getInnerIterator()->key(); } /** * Move forward to next element. * * @return void */ public function next() { $this->_previousKey = $this->key(); $this->_previousCurrent = $this->current(); return $this->getInnerIterator()->next(); } /** * Rewind the iterator to the first element. * * @return void */ public function rewind() { $this->_previousKey = -1; $this->_previousCurrent = null; return $this->getInnerIterator()->rewind(); } /** * Check if current position is valid. * * @return bool */ public function valid() { return $this->getInnerIterator()->valid(); } /** * Check whether there is a previous element. * * @return bool */ public function hasPrevious() { return -1 !== $this->_previousKey; } /** * Get previous value. * * @return mixed */ public function getPrevious() { return $this->_previousCurrent; } /** * Get previous key. * * @return mixed */ public function getPreviousKey() { return $this->_previousKey; } } _infos[] = $default; } else { $this->_infos[$infos] = $default; } return $out; } /** * Get the registered iterator instances. * * @return array */ public function current() { $out = parent::current(); foreach ($out as $key => &$value) { if (null === $value) { $value = $this->_infos[$key]; } } return $out; } } _relativePath = self::$_handlePath; self::$_handlePath = null; } else { $this->_relativePath = $path; } $this->setSplFileInfoClass($splFileInfoClass); return; } /** * Current. * Please, see \RecursiveDirectoryIterator::current() method. * * @return mixed */ public function current() { $out = parent::current(); if (null !== $this->_splFileInfoClass && $out instanceof \SplFileInfo) { $out->setInfoClass($this->_splFileInfoClass); $out = $out->getFileInfo(); if ($out instanceof \Hoa\Iterator\SplFileInfo) { $out->setRelativePath($this->getRelativePath()); } } return $out; } /** * Get children. * Please, see \RecursiveDirectoryIterator::getChildren() method. * * @return mixed */ public function getChildren() { self::$_handlePath = $this->getRelativePath(); $out = parent::getChildren(); if ($out instanceof \RecursiveDirectoryIterator) { $out->setSplFileInfoClass($this->_splFileInfoClass); } return $out; } /** * Set SplFileInfo classname. * * @param string $splFileInfoClass SplFileInfo classname. * @return void */ public function setSplFileInfoClass($splFileInfoClass) { $this->_splFileInfoClass = $splFileInfoClass; return; } /** * Get relative path (if given). * * @return string */ public function getRelativePath() { return $this->_relativePath; } } getIterator(); } $this->_iterator = $iterator; return; } /** * Return the current element. * * @return mixed */ public function current() { return $this->_iterator->current(); } /** * Return the key of the current element. * * @return mixed */ public function key() { return $this->_iterator->key(); } /** * Move forward to next element. * * @return void */ public function next() { return $this->_iterator->next(); } /** * Rewind the iterator to the first element. * * @return void */ public function rewind() { return $this->_iterator->rewind(); } /** * Check if current position is valid. * * @return bool */ public function valid() { return $this->_iterator->valid(); } /** * Return an iterator for the current entry. * It's a fake, we return null. * * @return void */ public function getChildren() { return null; } /** * Return if an iterator can be created for the current entry. * It's a fake, we return false. * * @return bool */ public function hasChildren() { return \false; } } hasChildren() || \true === parent::accept(); } /** * Get an iterator for the current entry. * * @return \Hoa\Iterator\Recursive\RegularExpression */ public function getChildren() { return new static(\true === $this->hasChildren() ? $this->getInnerIterator()->getChildren() : null, $this->getRegex(), $this->getMode(), $this->getFlags(), $this->getPregFlags()); } /** * Check whether an iterator can be obtained for the current entry. * * @return bool */ public function hasChildren() { return $this->getInnerIterator()->hasChildren(); } } _regex = $regex; $this->setMode($mode); $this->setFlags($flags); $this->setPregFlags($pregFlags); $this->replacement = null; return; } /** * Get accept status. * * @return bool */ public function accept() { if (is_array(parent::current())) { return \false; } $this->_key = parent::key(); $this->_current = parent::current(); $matches = []; $useKey = $this->_flags & self::USE_KEY; $subject = $useKey ? $this->_key : $this->_current; $out = \false; switch ($this->_mode) { case self::MATCH: $out = 0 !== preg_match($this->_regex, $subject, $matches, $this->_pregFlags); break; case self::GET_MATCH: $this->_current = []; $out = 0 !== preg_match($this->_regex, $subject, $this->_current, $this->_pregFlags); break; case self::ALL_MATCHES: $this->_current = []; $out = 0 < preg_match_all($this->_regex, $subject, $this->_current, $this->_pregFlags); break; case self::SPLIT: $this->_current = preg_split($this->_regex, $subject, null, $this->_pregFlags); $out = is_array($this->_current) && 1 < count($this->_current); break; case self::REPLACE: $numberOfReplacement = 0; $result = preg_replace($this->_regex, $this->replacement, $subject, -1, $numberOfReplacement); if (null === $result || 0 === $numberOfReplacement) { $out = \false; break; } if (0 !== $useKey) { $this->_key = $result; $out = \true; break; } $this->_current = $result; $out = \true; break; default: $out = \false; break; } if (0 !== ($this->_flags & self::INVERT_MATCH)) { return \false === $out; } return $out; } /** * Get current key. * * @return int */ public function key() { return $this->_key; } /** * Get current value. * * @return string */ public function current() { return $this->_current; } /** * Set mode. * * @param int $mode Mode. * @return void */ public function setMode($mode) { if ($mode < self::MATCH || $mode > self::REPLACE) { throw new \InvalidArgumentException('Illegal mode ' . $mode . '.'); } $this->_mode = $mode; return; } /** * Set flags. * * @param int $flags Flags. * @return void */ public function setFlags($flags) { $this->_flags = $flags; return; } /** * Set preg flags. * * @param int $pregFlags Preg flags. * @return void */ public function setPregFlags($pregFlags) { $this->_pregFlags = $pregFlags; return; } /** * Get regular expression. * * @return string */ public function getRegex() { return $this->_regex; } /** * Get mode. * * @return int */ public function getMode() { return $this->_mode; } /** * Get flags. * * @return int */ public function getFlags() { return $this->_flags; } /** * Get preg flags. * * @return int */ public function getPregFlags() { return $this->_pregFlags; } } = $n) { throw new \Hoa\Iterator\Exception('n must be greater than 0, given %d.', 0, $n); } if ($iterator instanceof \IteratorAggregate) { $iterator = $iterator->getIterator(); } $this->_iterator = $iterator; $this->_n = $n; $this->_body = $body; return; } /** * Return the current element. * * @return mixed */ public function current() { return $this->_iterator->current(); } /** * Return the key of the current element. * * @return mixed */ public function key() { return $this->_iterator->key(); } /** * Move forward to next element. * * @return void */ public function next() { return $this->_iterator->next(); } /** * Rewind the iterator to the first element. * * @return void */ public function rewind() { return $this->_iterator->rewind(); } /** * Check if current position is valid. * * @return bool */ public function valid() { $valid = $this->_iterator->valid(); if (\true === $valid) { return \true; } if (null !== $this->_body) { $handle =& $this->_body; $handle($this->_i); } $this->rewind(); if ($this->_n <= $this->_i++) { $this->_i = 1; return \false; } return \true; } } getMTime()) { $this->_hash = md5($this->getPathname() . $mtime); } $this->_relativePath = $relativePath; return; } /** * Get the hash. * * @return string */ public function getHash() { return $this->_hash; } /** * Get the MTime. * * @return int */ public function getMTime() { try { return parent::getMTime(); } catch (\RuntimeException $e) { return -1; } } /** * Set relative path. * * @param string $relativePath Relative path. * @return string */ public function setRelativePath($relativePath) { $old = $this->_relativePath; $this->_relativePath = $relativePath; return $old; } /** * Get relative path (if given). * * @return string */ public function getRelativePath() { return $this->_relativePath; } /** * Get relative pathname (if possible). * * @return string */ public function getRelativePathname() { if (null === $relative = $this->getRelativePath()) { return $this->getPathname(); } return substr($this->getPathname(), strlen($relative)); } } given($counter1 = new LUT\Counter(0, 12, 3), $counter2 = new LUT\Counter(13, 23, 2), $append = new LUT\Append(), $append->append($counter1), $append->append($counter2))->when($result = iterator_to_array($append, \false))->then->array($result)->isEqualTo([0, 3, 6, 9, 13, 15, 17, 19, 21]); } public function case_singleton() { $this->given($counter1 = new LUT\Counter(0, 12, 3), $append = new LUT\Append(), $append->append($counter1))->when($result = iterator_to_array($append))->then->array($result)->isEqualTo([0, 3, 6, 9]); } public function case_empty() { $this->given($append = new LUT\Append())->when($result = iterator_to_array($append))->then->array($result)->isEmpty(); } } given($innerIterator = $this->getInnerIterator(), $bufferSize = 3)->when($result = new SUT($innerIterator, $bufferSize))->then->object($result->getInnerIterator())->isIdenticalTo($innerIterator)->integer($result->getBufferSize())->isEqualTo($bufferSize)->let($buffer = $this->invoke($result)->getBuffer())->object($buffer)->isInstanceOf(\SplDoublyLinkedList::class)->boolean($buffer->isEmpty())->isTrue(); } public function case_negative_buffer_size() { $this->given($innerIterator = $this->getInnerIterator(), $bufferSize = -42)->when($result = new SUT($innerIterator, $bufferSize))->then->integer($result->getBufferSize())->isEqualTo(1); } public function case_null_buffer_size() { $this->given($innerIterator = $this->getInnerIterator(), $bufferSize = 0)->when($result = new SUT($innerIterator, $bufferSize))->then->integer($result->getBufferSize())->isEqualTo(1); } public function case_fast_forward() { $this->given($iterator = new SUT($this->getInnerIterator(), 3))->when($result = iterator_to_array($iterator))->then->array($result)->isEqualTo(['a', 'b', 'c', 'd', 'e'])->array(iterator_to_array($this->invoke($iterator)->getBuffer()))->isEqualTo([0 => [$iterator::BUFFER_KEY => 3, $iterator::BUFFER_VALUE => 'd'], 1 => [$iterator::BUFFER_KEY => 4, $iterator::BUFFER_VALUE => 'e'], 2 => [$iterator::BUFFER_KEY => null, $iterator::BUFFER_VALUE => null]]); } public function case_fast_forward_with_too_big_buffer() { $this->given($iterator = new SUT($this->getInnerIterator(), 10))->when($result = iterator_to_array($iterator))->then->array($result)->isEqualTo(['a', 'b', 'c', 'd', 'e'])->array(iterator_to_array($this->invoke($iterator)->getBuffer()))->isEqualTo([0 => [$iterator::BUFFER_KEY => 0, $iterator::BUFFER_VALUE => 'a'], 1 => [$iterator::BUFFER_KEY => 1, $iterator::BUFFER_VALUE => 'b'], 2 => [$iterator::BUFFER_KEY => 2, $iterator::BUFFER_VALUE => 'c'], 3 => [$iterator::BUFFER_KEY => 3, $iterator::BUFFER_VALUE => 'd'], 4 => [$iterator::BUFFER_KEY => 4, $iterator::BUFFER_VALUE => 'e'], 5 => [$iterator::BUFFER_KEY => null, $iterator::BUFFER_VALUE => null]]); } public function case_fast_forward_with_smallest_buffer() { $this->given($iterator = new SUT($this->getInnerIterator(), 1))->when($result = iterator_to_array($iterator))->then->array($result)->isEqualTo(['a', 'b', 'c', 'd', 'e'])->array(iterator_to_array($this->invoke($iterator)->getBuffer()))->isEqualTo([0 => [$iterator::BUFFER_KEY => null, $iterator::BUFFER_VALUE => null]]); } public function case_forward_forward_forward() { $this->when($result = new SUT(new LUT\Map(['a', 'b', 'c']), 2))->then->variable($result->rewind())->isNull()->boolean($result->valid())->isTrue()->integer($result->key())->isEqualTo(0)->string($result->current())->isEqualTo('a')->variable($result->next())->isNull()->boolean($result->valid())->isTrue()->integer($result->key())->isEqualTo(1)->string($result->current())->isEqualTo('b')->variable($result->next())->isNull()->boolean($result->valid())->isTrue()->integer($result->key())->isEqualTo(2)->string($result->current())->isEqualTo('c')->variable($result->next())->isNull()->boolean($result->valid())->isFalse()->variable($result->key())->isNull()->variable($result->current())->isNull(); } public function case_forward_forward_backward_backward_forward_forward_forward_step_by_step() { $this->when($result = new SUT(new LUT\Map(['a', 'b', 'c']), 3))->then->variable($result->rewind())->isNull()->array(iterator_to_array($this->invoke($result)->getBuffer()))->isEqualTo([0 => [$result::BUFFER_KEY => 0, $result::BUFFER_VALUE => 'a']])->boolean($result->valid())->isTrue()->integer($result->key())->isEqualTo(0)->string($result->current())->isEqualTo('a')->variable($result->next())->isNull()->array(iterator_to_array($this->invoke($result)->getBuffer()))->isEqualTo([0 => [$result::BUFFER_KEY => 0, $result::BUFFER_VALUE => 'a'], 1 => [$result::BUFFER_KEY => 1, $result::BUFFER_VALUE => 'b']])->boolean($result->valid())->isTrue()->integer($result->key())->isEqualTo(1)->string($result->current())->isEqualTo('b')->variable($result->next())->isNull()->array(iterator_to_array($this->invoke($result)->getBuffer()))->isEqualTo([0 => [$result::BUFFER_KEY => 0, $result::BUFFER_VALUE => 'a'], 1 => [$result::BUFFER_KEY => 1, $result::BUFFER_VALUE => 'b'], 2 => [$result::BUFFER_KEY => 2, $result::BUFFER_VALUE => 'c']])->boolean($result->valid())->isTrue()->integer($result->key())->isEqualTo(2)->string($result->current())->isEqualTo('c')->variable($result->previous())->isNull()->array(iterator_to_array($this->invoke($result)->getBuffer()))->isEqualTo([0 => [$result::BUFFER_KEY => 0, $result::BUFFER_VALUE => 'a'], 1 => [$result::BUFFER_KEY => 1, $result::BUFFER_VALUE => 'b'], 2 => [$result::BUFFER_KEY => 2, $result::BUFFER_VALUE => 'c']])->boolean($result->valid())->isTrue()->integer($result->key())->isEqualTo(1)->string($result->current())->isEqualTo('b')->variable($result->previous())->isNull()->array(iterator_to_array($this->invoke($result)->getBuffer()))->isEqualTo([0 => [$result::BUFFER_KEY => 0, $result::BUFFER_VALUE => 'a'], 1 => [$result::BUFFER_KEY => 1, $result::BUFFER_VALUE => 'b'], 2 => [$result::BUFFER_KEY => 2, $result::BUFFER_VALUE => 'c']])->boolean($result->valid())->isTrue()->integer($result->key())->isEqualTo(0)->string($result->current())->isEqualTo('a')->variable($result->next())->isNull()->array(iterator_to_array($this->invoke($result)->getBuffer()))->isEqualTo([0 => [$result::BUFFER_KEY => 0, $result::BUFFER_VALUE => 'a'], 1 => [$result::BUFFER_KEY => 1, $result::BUFFER_VALUE => 'b'], 2 => [$result::BUFFER_KEY => 2, $result::BUFFER_VALUE => 'c']])->boolean($result->valid())->isTrue()->integer($result->key())->isEqualTo(1)->string($result->current())->isEqualTo('b')->variable($result->next())->isNull()->array(iterator_to_array($this->invoke($result)->getBuffer()))->isEqualTo([0 => [$result::BUFFER_KEY => 0, $result::BUFFER_VALUE => 'a'], 1 => [$result::BUFFER_KEY => 1, $result::BUFFER_VALUE => 'b'], 2 => [$result::BUFFER_KEY => 2, $result::BUFFER_VALUE => 'c']])->boolean($result->valid())->isTrue()->integer($result->key())->isEqualTo(2)->string($result->current())->isEqualTo('c')->variable($result->next())->isNull()->array(iterator_to_array($this->invoke($result)->getBuffer()))->isEqualTo([0 => [$result::BUFFER_KEY => 1, $result::BUFFER_VALUE => 'b'], 1 => [$result::BUFFER_KEY => 2, $result::BUFFER_VALUE => 'c'], 2 => [$result::BUFFER_KEY => null, $result::BUFFER_VALUE => null]])->boolean($result->valid())->isFalse()->variable($result->key())->isNull()->variable($result->current())->isNull(); } public function case_backward_out_of_buffer() { $this->when($result = new SUT(new LUT\Map(['a', 'b', 'c']), 1))->then->variable($result->rewind())->isNull()->boolean($result->valid())->isTrue()->integer($result->key())->isEqualTo(0)->string($result->current())->isEqualTo('a')->variable($result->next())->isNull()->boolean($result->valid())->isTrue()->integer($result->key())->isEqualTo(1)->string($result->current())->isEqualTo('b')->variable($result->previous())->isNull()->boolean($result->valid())->isFalse(); } public function case_rewind_rewind() { $this->when($result = new SUT(new LUT\Map(['a', 'b']), 3))->then->variable($result->rewind())->isNull()->boolean($result->valid())->isTrue()->integer($result->key())->isEqualTo(0)->string($result->current())->isEqualTo('a')->variable($result->next())->isNull()->variable($result->rewind())->isNull()->boolean($result->valid())->isTrue()->integer($result->key())->isEqualTo(0)->string($result->current())->isEqualTo('a')->variable($result->next())->isNull()->array(iterator_to_array($this->invoke($result)->getBuffer()))->isEqualTo([0 => [$result::BUFFER_KEY => 0, $result::BUFFER_VALUE => 'a'], 1 => [$result::BUFFER_KEY => 1, $result::BUFFER_VALUE => 'b']]); } protected function getInnerIterator() { return new LUT\Map(['a', 'b', 'c', 'd', 'e']); } } given($foobar = $this->getDummyIterator(), $filter = new LUT\CallbackFilter($foobar, function ($value) { return \false === in_array($value, ['a', 'e', 'i', 'o', 'u']); }))->when($result = iterator_to_array($filter))->then->array($result)->isEqualTo([0 => 'f', 3 => 'b', 5 => 'r']); } public function case_all_callback_parameters() { $self = $this; $this->given($foobar = $this->getDummyIterator(), $keys = [], $values = [], $filter = new LUT\CallbackFilter($foobar, function ($value, $key, $iterator) use ($self, $foobar, &$keys, &$values) { $self->object($iterator)->isIdenticalTo($foobar); $keys[] = $key; $values[] = $value; return \false === in_array($value, ['a', 'e', 'i', 'o', 'u']); }))->when($result = iterator_to_array($filter))->then->array($result)->isEqualTo([0 => 'f', 3 => 'b', 5 => 'r'])->array(array_combine($keys, $values))->isEqualTo(iterator_to_array($foobar)); } public function case_remove_all() { $this->given($foobar = $this->getDummyIterator(), $filter = new LUT\CallbackFilter($foobar, function () { return \false; }))->when($result = iterator_to_array($filter))->then->array($result)->isEmpty(); } public function case_remove_none() { $this->given($foobar = $this->getDummyIterator(), $filter = new LUT\CallbackFilter($foobar, function () { return \true; }))->when($foobarResult = iterator_to_array($foobar), $filterResult = iterator_to_array($filter))->then->array($foobarResult)->isEqualTo($filterResult); } public function case_recursive() { $this->given($foobar = $this->getDummyRecursiveIterator(), $filter = new LUT\Recursive\CallbackFilter($foobar, function ($value) { return \false === in_array($value, ['a', 'e', 'i', 'o', 'u']); }), $iterator = new LUT\Recursive\Iterator($filter))->when($result = iterator_to_array($iterator, \false))->then->array($result)->isEqualTo([0 => 'f', 1 => 'b', 2 => 'r']); } public function case_recursive_remove_all() { $this->given($foobar = $this->getDummyRecursiveIterator(), $filter = new LUT\Recursive\CallbackFilter($foobar, function () { return \false; }), $iterator = new LUT\Recursive\Iterator($filter))->when($result = iterator_to_array($iterator))->then->array($result)->isEmpty(); } public function case_recursive_remove_none() { $this->given($foobar = $this->getDummyRecursiveIterator(), $filter = new LUT\Recursive\CallbackFilter($foobar, function () { return \true; }), $foobarIterator = new LUT\Recursive\Iterator($foobar), $filterIterator = new LUT\Recursive\Iterator($filter))->when($foobarResult = iterator_to_array($foobarIterator), $filterResult = iterator_to_array($filterIterator))->then->array($foobarResult)->isEqualTo($filterResult); } protected function getDummyIterator() { return new LUT\Map(['f', 'o', 'o', 'b', 'a', 'r']); } protected function getDummyRecursiveIterator() { return new LUT\Recursive\Map([['f', 'o', 'o'], ['b', 'a', 'r']]); } } given($iterator = new LUT\CallbackGenerator(function ($key) { return $key * 2; }), $limit = new LUT\Limit($iterator, 0, 5))->when($result = iterator_to_array($limit))->then->array($result)->isEqualTo([0, 2, 4, 6, 8]); } } given($iterator = new LUT\Counter(0, 12, 3))->when($result = iterator_to_array($iterator))->then->array($result)->isEqualTo([0, 3, 6, 9]); } public function case_offset() { $this->given($iterator = new LUT\Counter(6, 12, 3))->when($result = iterator_to_array($iterator))->then->array($result)->isEqualTo([6, 9]); } public function case_too_small() { $this->exception(function () { new LUT\Counter(0, 0, 0); })->isInstanceOf(LUT\Exception::class); } public function case_too_big() { $this->given($iterator = new LUT\Counter(0, 12, 13))->when($result = iterator_to_array($iterator))->then->array($result)->isEqualTo([0]); } } given($counter = new LUT\Counter(0, 10, 1), $multiple = new LUT\Multiple(), $multiple->attachIterator($counter), $multiple->attachIterator(clone $counter), $demultiplexer = new LUT\Demultiplexer($multiple, function ($current) { return $current[0] * $current[1]; }))->when($result = iterator_to_array($demultiplexer, \false))->then->array($result)->isEqualTo([0, 1, 4, 9, 16, 25, 36, 49, 64, 81]); } public function case_associative_keys() { $this->given($counter = new LUT\Counter(0, 10, 1), $multiple = new LUT\Multiple(LUT\Multiple::MIT_NEED_ANY | LUT\Multiple::MIT_KEYS_ASSOC), $multiple->attachIterator($counter, 'one'), $multiple->attachIterator(clone $counter, 'two'), $demultiplexer = new LUT\Demultiplexer($multiple, function ($current) { return $current['one'] * $current['two']; }))->when($result = iterator_to_array($demultiplexer, \false))->then->array($result)->isEqualTo([0, 1, 4, 9, 16, 25, 36, 49, 64, 81]); } } given($root = resolve('hoa://Test/Vfs/Root?type=directory'), resolve('hoa://Test/Vfs/Root/A?type=file'), resolve('hoa://Test/Vfs/Root/Aa?type=file'), resolve('hoa://Test/Vfs/Root/Aaa?type=file'), $iterator = new LUT\Directory($root), $result = [])->when(function () use ($iterator, &$result) { foreach ($iterator as $key => $file) { $result[$key] = $file->getFilename(); $this->object($file)->isInstanceOf(LUT\Directory::class); } })->then->array($result)->isEqualTo([0 => 'A', 1 => 'Aa', 2 => 'Aaa']); } public function case_seek_and_dots() { $this->given($root = resolve('hoa://Test/Vfs/Root?type=directory'), resolve('hoa://Test/Vfs/Root/.?type=directory'), resolve('hoa://Test/Vfs/Root/..?type=directory'), resolve('hoa://Test/Vfs/Root/Skip?type=file'), resolve('hoa://Test/Vfs/Root/Gotcha?type=file'), $iterator = new LUT\Directory($root))->when($result = $iterator->current())->then->boolean($result->isDot())->isTrue()->when($iterator->next(), $result = $iterator->current())->then->boolean($result->isDot())->isTrue()->when($iterator->seek(3), $result = $iterator->current())->then->string($result->getFilename())->isEqualTo('Gotcha')->when($iterator->seek(2), $result = $iterator->current())->then->string($result->getFilename())->isEqualTo('Skip'); } public function case_recursive() { $this->given($root = resolve('hoa://Test/Vfs/Root?type=directory'), resolve('hoa://Test/Vfs/Root/A?type=file'), resolve('hoa://Test/Vfs/Root/Aa?type=file'), resolve('hoa://Test/Vfs/Root/Aaa?type=file'), resolve('hoa://Test/Vfs/Root/Foo?type=directory'), resolve('hoa://Test/Vfs/Root/Foo/Bar?type=directory'), resolve('hoa://Test/Vfs/Root/Foo/Bar/B?type=file'), resolve('hoa://Test/Vfs/Root/Foo/Bar/Bb?type=file'), resolve('hoa://Test/Vfs/Root/Foo/Bar/Bbb?type=file'), resolve('hoa://Test/Vfs/Root/Foo/C?type=file'), resolve('hoa://Test/Vfs/Root/Foo/Cc?type=file'), resolve('hoa://Test/Vfs/Root/Foo/Ccc?type=file'), $directory = new LUT\Recursive\Directory($root), $iterator = new LUT\Recursive\Iterator($directory), $result = [])->when(function () use ($iterator, &$result) { foreach ($iterator as $file) { $result[] = $file->getFilename(); } })->then->array($result)->isEqualTo(['A', 'Aa', 'Aaa', 'B', 'Bb', 'Bbb', 'C', 'Cc', 'Ccc']); } public function case_splFileClassInfo() { $this->given($splFileInfo = 'Hoa\Iterator\SplFileInfo', $root = resolve('hoa://Test/Vfs/Root?type=directory'), resolve('hoa://Test/Vfs/Root/a?type=file'), resolve('hoa://Test/Vfs/Root/b?type=file'), resolve('hoa://Test/Vfs/Root/c?type=file'), resolve('hoa://Test/Vfs/Root/d?type=file'), resolve('hoa://Test/Vfs/Root/e?type=file'), resolve('hoa://Test/Vfs/Root/f?type=file'), $iterator = new LUT\Directory($root, $splFileInfo), $result = [])->when(function () use ($iterator, $splFileInfo, &$result) { foreach ($iterator as $file) { $this->object($file)->isInstanceOf($splFileInfo); $result[] = $file->getFilename(); } })->then->array($result)->isEqualTo(['a', 'b', 'c', 'd', 'e', 'f']); } public function case_recursive_splFileClassInfo() { $this->given($splFileInfo = 'Hoa\Iterator\SplFileInfo', $root = resolve('hoa://Test/Vfs/Root?type=directory'), resolve('hoa://Test/Vfs/Root/A?type=directory'), resolve('hoa://Test/Vfs/Root/A/a?type=file'), resolve('hoa://Test/Vfs/Root/A/b?type=file'), resolve('hoa://Test/Vfs/Root/A/c?type=file'), resolve('hoa://Test/Vfs/Root/B?type=directory'), resolve('hoa://Test/Vfs/Root/B/d?type=file'), resolve('hoa://Test/Vfs/Root/B/e?type=file'), resolve('hoa://Test/Vfs/Root/B/c?type=directory'), resolve('hoa://Test/Vfs/Root/B/c/f?type=file'), $directory = new LUT\Recursive\Directory($root, LUT\FileSystem::CURRENT_AS_FILEINFO, $splFileInfo), $iterator = new LUT\Recursive\Iterator($directory), $result = [])->when(function () use ($iterator, $splFileInfo, &$result) { foreach ($iterator as $file) { $this->object($file)->isInstanceOf($splFileInfo); $result[] = $file->getFilename(); } })->then->array($result)->isEqualTo(['a', 'b', 'c', 'd', 'e', 'f']); } } given($root = resolve('hoa://Test/Vfs/Root?type=directory'), resolve('hoa://Test/Vfs/Root/.?type=directory'), resolve('hoa://Test/Vfs/Root/..?type=directory'), resolve('hoa://Test/Vfs/Root/A?type=file'), resolve('hoa://Test/Vfs/Root/B?type=file'), $iterator = new LUT\FileSystem($root), $result = [])->when(function () use ($iterator, &$result) { foreach ($iterator as $pathname => $file) { $this->object($file)->isInstanceOf('SplFileInfo'); $result[basename($pathname)] = $file->getFilename(); } })->array($result)->isEqualTo(['A' => 'A', 'B' => 'B']); } public function case_splFileClassInfo() { $this->given($splFileInfo = 'Hoa\Iterator\SplFileInfo', $root = resolve('hoa://Test/Vfs/Root?type=directory'), resolve('hoa://Test/Vfs/Root/a?type=file'), resolve('hoa://Test/Vfs/Root/b?type=file'), resolve('hoa://Test/Vfs/Root/c?type=file'), resolve('hoa://Test/Vfs/Root/d?type=file'), resolve('hoa://Test/Vfs/Root/e?type=file'), resolve('hoa://Test/Vfs/Root/f?type=file'), $iterator = new LUT\FileSystem($root, LUT\FileSystem::CURRENT_AS_FILEINFO, $splFileInfo), $result = [])->when(function () use ($iterator, $splFileInfo, &$result) { foreach ($iterator as $file) { $this->object($file)->isInstanceOf($splFileInfo); $result[] = $file->getFilename(); } })->then->array($result)->isEqualTo(['a', 'b', 'c', 'd', 'e', 'f']); } } given($foobar = $this->getDummyIterator(), $filter = new \Mock\Hoa\Iterator\Test\Unit\MyFilter($foobar), $this->calling($filter)->accept = function () { $value = $this->current(); return \false === in_array($value, ['a', 'e', 'i', 'o', 'u']); })->when($result = iterator_to_array($filter))->then->array($result)->isEqualTo([0 => 'f', 3 => 'b', 5 => 'r']); } public function case_remove_all() { $this->given($foobar = $this->getDummyIterator(), $filter = new \Mock\Hoa\Iterator\Test\Unit\MyFilter($foobar), $this->calling($filter)->accept = \false)->when($result = iterator_to_array($filter))->then->array($result)->isEmpty(); } public function case_remove_none() { $this->given($foobar = $this->getDummyIterator(), $filter = new \Hoa\Iterator\Test\Unit\MyFilter($foobar))->when($foobarResult = iterator_to_array($foobar), $filterResult = iterator_to_array($filter))->then->array($foobarResult)->isEqualTo($filterResult); } protected function getDummyIterator() { return new LUT\Map(['f', 'o', 'o', 'b', 'a', 'r']); } } given($iterator = new LUT\Map(['a']), $infinite = new LUT\Infinite($iterator), $limit = new LUT\Limit($infinite, 0, 100))->when($result = iterator_to_array($limit, \false))->then->array($result)->isEqualTo(array_fill(0, 100, 'a'))->size->isEqualTo(100); } } given($iterator = new LUT\Map([]), $iteratoriterator = new LUT\IteratorIterator($iterator))->when($result = $iteratoriterator->getInnerIterator())->then->object($result)->isIdenticalTo($iterator); } public function case_traverse() { $this->given($iterator = new LUT\Map(['a', 'b', 'c']), $iteratoriterator = new LUT\IteratorIterator($iterator))->when($result = iterator_to_array($iteratoriterator))->then->array($result)->isEqualTo(['a', 'b', 'c']); } public function case_recursive_leaves_only() { $this->given($array = ['a' => ['b', 'c', 'd'], 'e' => ['f', 'g', 'i']], $iterator = new LUT\Recursive\Map($array), $iteratoriterator = new LUT\Recursive\Iterator($iterator, LUT\Recursive\Iterator::LEAVES_ONLY))->when($result = iterator_to_array($iteratoriterator, \false))->then->array($result)->isEqualTo(['b', 'c', 'd', 'f', 'g', 'i']); } public function case_recursive_self_first() { $this->given($array = ['a' => ['b', 'c', 'd'], 'e' => ['f', 'g', 'i']], $iterator = new LUT\Recursive\Map($array), $iteratoriterator = new LUT\Recursive\Iterator($iterator, LUT\Recursive\Iterator::SELF_FIRST))->when($result = iterator_to_array($iteratoriterator, \false))->then->array($result)->isEqualTo([['b', 'c', 'd'], 'b', 'c', 'd', ['f', 'g', 'i'], 'f', 'g', 'i']); } public function case_recursive_child_first() { $this->given($array = ['a' => ['b', 'c', 'd'], 'e' => ['f', 'g', 'i']], $iterator = new LUT\Recursive\Map($array), $iteratoriterator = new LUT\Recursive\Iterator($iterator, LUT\Recursive\Iterator::CHILD_FIRST))->when($result = iterator_to_array($iteratoriterator, \false))->then->array($result)->isEqualTo(['b', 'c', 'd', ['b', 'c', 'd'], 'f', 'g', 'i', ['f', 'g', 'i']]); } } given($iterator = new LUT\Map(self::$_dummyArray), $limit = new LUT\Limit($iterator, 2, 3))->when($result = iterator_to_array($limit))->then->array($result)->isEqualTo([2 => 'o', 3 => 'b', 4 => 'a']); } public function case_negative_offset() { $this->given($iterator = new LUT\Map(self::$_dummyArray))->exception(function () use ($iterator) { new LUT\Limit($iterator, -2, 3); })->isInstanceOf(\OutOfRangeException::class); } public function case_empty() { $this->given($iterator = new LUT\Map(self::$_dummyArray), $limit = new LUT\Limit($iterator, 0, 0))->exception(function () use ($limit) { iterator_to_array($limit); })->isInstanceOf(\OutOfBoundsException::class); } } given($iterator = new LUT\Map(['a', 'b', 'c']), $lookahead = new LUT\Lookahead($iterator))->when($result = iterator_to_array($iterator))->then->array($result)->isEqualTo(['a', 'b', 'c']); } public function case_check_ahead() { $this->given($iterator = new LUT\Map(['a', 'b', 'c']), $lookahead = new LUT\Lookahead($iterator))->when($lookahead->rewind(), $key = $lookahead->key(), $current = $lookahead->current(), $hasNext = $lookahead->hasNext(), $next = $lookahead->getNext())->then->integer($key)->isEqualTo(0)->string($current)->isEqualTo('a')->boolean($hasNext)->isTrue()->string($next)->isEqualTo('b')->when($lookahead->next(), $key = $lookahead->key(), $current = $lookahead->current(), $hasNext = $lookahead->hasNext(), $next = $lookahead->getNext())->then->integer($key)->isEqualTo(1)->string($current)->isEqualTo('b')->boolean($hasNext)->isTrue()->string($next)->isEqualTo('c')->when($lookahead->next(), $key = $lookahead->key(), $current = $lookahead->current(), $hasNext = $lookahead->hasNext(), $next = $lookahead->getNext())->then->integer($key)->isEqualTo(2)->string($current)->isEqualTo('c')->boolean($hasNext)->isFalse()->variable($next)->isNull(); } public function case_double_rewind() { $this->given($iterator = new LUT\Map(['a', 'b', 'c']), $lookahead = new LUT\Lookahead($iterator))->when($lookahead->rewind(), $key = $lookahead->key(), $current = $lookahead->current(), $hasNext = $lookahead->hasNext(), $next = $lookahead->getNext())->then->integer($key)->isEqualTo(0)->string($current)->isEqualTo('a')->boolean($hasNext)->isTrue()->string($next)->isEqualTo('b')->when($lookahead->rewind(), $key = $lookahead->key(), $current = $lookahead->current(), $hasNext = $lookahead->hasNext(), $next = $lookahead->getNext())->then->integer($key)->isEqualTo(0)->string($current)->isEqualTo('a')->boolean($hasNext)->isTrue()->string($next)->isEqualTo('b'); } public function case_empty() { $this->given($iterator = new LUT\Mock(), $lookahead = new LUT\Lookahead($iterator))->when($lookahead->rewind(), $valid = $lookahead->valid())->then->boolean($valid)->isFalse(); } } given($iterator = new LUT\Map(['a', 'b', 'c']), $lookbehind = new LUT\Lookbehind($iterator))->when($result = iterator_to_array($iterator))->then->array($result)->isEqualTo(['a', 'b', 'c']); } public function case_check_behind() { $this->given($iterator = new LUT\Map(['a', 'b', 'c']), $lookbehind = new LUT\Lookbehind($iterator))->when($lookbehind->rewind(), $key = $lookbehind->key(), $current = $lookbehind->current(), $hasPrevious = $lookbehind->hasPrevious(), $previous = $lookbehind->getPrevious())->then->integer($key)->isEqualTo(0)->string($current)->isEqualTo('a')->boolean($hasPrevious)->isFalse()->variable($previous)->isNull()->when($lookbehind->next(), $key = $lookbehind->key(), $current = $lookbehind->current(), $hasPrevious = $lookbehind->hasPrevious(), $previous = $lookbehind->getPrevious())->then->integer($key)->isEqualTo(1)->string($current)->isEqualTo('b')->boolean($hasPrevious)->isTrue()->string($previous)->isEqualTo('a')->when($lookbehind->next(), $key = $lookbehind->key(), $current = $lookbehind->current(), $hasPrevious = $lookbehind->hasPrevious(), $previous = $lookbehind->getPrevious())->then->integer($key)->isEqualTo(2)->string($current)->isEqualTo('c')->boolean($hasPrevious)->isTrue()->string($previous)->isEqualTo('b'); } public function case_double_rewind() { $this->given($iterator = new LUT\Map(['a', 'b', 'c']), $lookbehind = new LUT\Lookbehind($iterator))->when($lookbehind->rewind(), $key = $lookbehind->key(), $current = $lookbehind->current(), $hasPrevious = $lookbehind->hasPrevious())->then->integer($key)->isEqualTo(0)->string($current)->isEqualTo('a')->boolean($hasPrevious)->isFalse()->when($lookbehind->rewind(), $key = $lookbehind->key(), $current = $lookbehind->current(), $hasPrevious = $lookbehind->hasPrevious())->then->integer($key)->isEqualTo(0)->string($current)->isEqualTo('a')->boolean($hasPrevious)->isFalse(); } public function case_empty() { $this->given($iterator = new LUT\Mock(), $lookbehind = new LUT\Lookbehind($iterator))->when($lookbehind->rewind(), $valid = $lookbehind->valid())->then->boolean($valid)->isFalse(); } } given($iterator = new LUT\Map(self::$_dummyArray))->when($result = iterator_to_array($iterator))->then->array($result)->isEqualTo(self::$_dummyArray); } public function case_empty() { $this->given($iterator = new LUT\Map())->when($result = iterator_to_array($iterator))->then->array($result)->isEmpty(); } public function case_recursive() { $this->given($array = ['a' => ['b', 'c', 'd'], 'e' => ['f', 'g', 'i'], 'k'], $iterator = new LUT\Recursive\Map($array))->when(function () use ($iterator) { foreach ($iterator as $key => $value) { if ('a' === $key) { $this->boolean($iterator->hasChildren())->isTrue()->object($children = $iterator->getChildren())->isInstanceOf(LUT\Recursive\Map::class)->array(iterator_to_array($children))->isEqualTo(['b', 'c', 'd']); } elseif ('e' === $key) { $this->boolean($iterator->hasChildren())->isTrue()->object($children = $iterator->getChildren())->isInstanceOf(LUT\Recursive\Map::class)->array(iterator_to_array($children))->isEqualTo(['f', 'g', 'i']); } elseif ('k' === $value) { $this->boolean($iterator->hasChildren())->isFalse(); } } }); } } given($iterator = new LUT\Mock())->when($result = iterator_to_array($iterator))->then->array($result)->isEmpty(); } public function case_recursive_mock_mock() { $this->when($iterator = new LUT\Recursive\Mock(new LUT\Mock()))->then->variable($iterator->getChildren())->isNull()->boolean($iterator->hasChildren())->isFalse(); } public function case_recursive() { $this->given($map = new LUT\Map(['a', 'b', 'c']), $mock = new LUT\Recursive\Mock($map), $iteratoriterator = new LUT\Recursive\Iterator($mock))->when($result = iterator_to_array($map, \false))->then->array($result)->isEqualTo(['a', 'b', 'c']); } } given($foo = new LUT\Map(['f', 'o', 'o']), $bar = new LUT\Map(['b', 'a', 'r']), $multiple = new LUT\Multiple(LUT\Multiple::MIT_NEED_ANY | LUT\Multiple::MIT_KEYS_ASSOC), $multiple->attachIterator($foo, 'one'), $multiple->attachIterator($bar, 'two'))->when($result = iterator_to_array($multiple, \false))->then->array($result)->isEqualTo([['one' => 'f', 'two' => 'b'], ['one' => 'o', 'two' => 'a'], ['one' => 'o', 'two' => 'r']]); } public function case_default_value() { $this->given($foobar = new LUT\Map(['f', 'o', 'o', 'b', 'a', 'r']), $baz = new LUT\Map(['b', 'a', 'z']), $multiple = new LUT\Multiple(LUT\Multiple::MIT_NEED_ANY | LUT\Multiple::MIT_KEYS_ASSOC), $multiple->attachIterator($foobar, 'one', '!'), $multiple->attachIterator($baz, 'two', '?'))->when($result = iterator_to_array($multiple, \false))->then->array($result)->isEqualTo([['one' => 'f', 'two' => 'b'], ['one' => 'o', 'two' => 'a'], ['one' => 'o', 'two' => 'z'], ['one' => 'b', 'two' => '?'], ['one' => 'a', 'two' => '?'], ['one' => 'r', 'two' => '?']]); } public function case_empty() { $this->given($multiple = new LUT\Multiple())->when($result = iterator_to_array($multiple))->then->array($result)->isEmpty(); } } given($dummyArray = ['f', 'o', 'o', 'b', 'a', 'r'], $iterator = new LUT\Map($dummyArray), $norewind = new LUT\NoRewind($iterator))->when($result = iterator_to_array($norewind))->then->array($result)->isEqualTo($dummyArray)->when($norewind->rewind())->boolean($norewind->valid())->isFalse()->when($result = iterator_to_array($norewind))->then->array($result)->isEmpty(); } } given($map = new LUT\Map(['abc', 'dea', 'fgh', 'iaj', 'klm']), $iterator = new LUT\RegularExpression($map, '/a/'))->when($result = iterator_to_array($iterator))->then->array($result)->isEqualTo([0 => 'abc', 1 => 'dea', 3 => 'iaj']); } public function case_recursive() { $this->given($map = new LUT\Recursive\Map([['abc', 'dea', 'fgh'], ['iaj', 'klm']]), $regex = new LUT\Recursive\RegularExpression($map, '/a/'), $iterator = new LUT\Recursive\Iterator($regex))->when($result = iterator_to_array($iterator, \false))->then->array($result)->isEqualTo([0 => 'abc', 1 => 'dea', 2 => 'iaj']); } public function case_recursive_children_flags() { $this->given($map = new LUT\Recursive\Map([['abc', 'dea', 'fgh'], ['iaj', 'klm']]), $mode = LUT\Recursive\RegularExpression::ALL_MATCHES, $flag = LUT\Recursive\RegularExpression::USE_KEY, $pregFlag = LUT\Recursive\RegularExpression::ALL_MATCHES, $iterator = new LUT\Recursive\RegularExpression($map, '/a/', $mode, $flag, $pregFlag))->when($result = $iterator->getChildren())->then->object($result)->isInstanceOf(LUT\Recursive\RegularExpression::class)->integer($result->getMode())->isEqualTo($mode)->integer($result->getFlags())->isEqualTo($flag)->integer($result->getPregFlags())->isEqualTo($pregFlag); } } given($iterator = new LUT\Map(self::$_dummyArray), $repeater = new LUT\Repeater($iterator, 3))->when($result = iterator_to_array($repeater))->then->array($result)->isEqualTo(self::$_dummyArray + self::$_dummyArray + self::$_dummyArray); } public function case_with_body() { $self = $this; $this->given($iterator = new LUT\Map(self::$_dummyArray), $count = 0, $repeater = new LUT\Repeater($iterator, 3, function ($repetition) use ($self, &$count) { $this->integer($repetition)->isEqualTo($count + 1); ++$count; }))->when($result = iterator_to_array($repeater))->then->array($result)->isEqualTo(self::$_dummyArray + self::$_dummyArray + self::$_dummyArray)->integer($count)->isEqualTo(3); } } given($pathname = 'hoa://Test/Vfs/Foo.bar?type=file')->when($result = new LUT\SplFileInfo($pathname))->then->boolean($result->isFile())->isTrue()->string($result->getType())->isEqualTo('file'); } public function case_directory() { $this->given($pathname = 'hoa://Test/Vfs/Foo?type=directory')->when($result = new LUT\SplFileInfo($pathname))->then->boolean($result->isDir())->isTrue()->string($result->getType())->isEqualTo('dir'); } public function case_path_informations() { $this->given($relativePath = 'hoa://Test/Vfs/A/B/', $relativePathname = 'C/Foo.bar', $pathname = $relativePath . $relativePathname)->when($result = new LUT\SplFileInfo($pathname . '?type=file', $relativePath))->then->boolean($result->isFile())->isTrue()->string($result->getBasename())->isEqualTo('Foo.bar?type=file')->string($result->getExtension())->isEqualTo('bar?type=file')->string($result->getRelativePath())->isEqualTo($relativePath)->string($result->getRelativePathname())->isEqualTo($relativePathname . '?type=file')->string($result->getPath())->isEqualTo('hoa://Test/Vfs/A/B/C')->string($result->getPathname())->isEqualTo($pathname . '?type=file'); } public function case_times() { $this->given($timestamp = $this->realdom->boundinteger($this->realdom->timestamp('yesterday'), $this->realdom->timestamp('tomorrow')), $atime = $this->sample($timestamp), $ctime = $this->sample($timestamp), $mtime = $this->sample($timestamp), $pathname = 'hoa://Test/Vfs/Foo.bar?' . http_build_query(['type' => 'file', 'atime' => $atime, 'ctime' => $ctime, 'mtime' => $mtime]))->when($result = new LUT\SplFileInfo($pathname))->then->integer($result->getATime())->isEqualTo($atime)->integer($result->getCTime())->isEqualTo($ctime)->integer($result->getMTime())->isEqualTo($mtime); } public function case_permissions() { $this->given($pathname = 'hoa://Test/Vfs/Fo.bar?type=file&permissions=0744')->when($result = new LUT\SplFileInfo($pathname))->then->boolean($result->isReadable())->isTrue()->boolean($result->isWritable())->isTrue()->boolean($result->isExecutable())->isTrue()->given($pathname = 'hoa://Test/Vfs/Foo.bar?type=file&permissions=0644')->when($result = new LUT\SplFileInfo($pathname))->then->boolean($result->isReadable())->isTrue()->boolean($result->isWritable())->isTrue()->boolean($result->isExecutable())->isFalse()->given($pathname = 'hoa://Test/Vfs/Fooo.bar?type=file&permissions=0444')->when($result = new LUT\SplFileInfo($pathname))->then->boolean($result->isReadable())->isTrue()->boolean($result->isWritable())->isFalse()->boolean($result->isExecutable())->isFalse()->given($pathname = 'hoa://Test/Vfs/Foooo.bar?type=file&permissions=0044')->when($result = new LUT\SplFileInfo($pathname))->then->boolean($result->isReadable())->isFalse()->boolean($result->isWritable())->isFalse()->boolean($result->isExecutable())->isFalse(); } } // // Hoa // // // @license // // New BSD License // // Copyright © 2007-2016, 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\Math\Arithmetic. // // Provide a grammar for arithmetic expressions. // // @copyright Copyright © 2007-2016 Hoa community. // @license New BSD License // %skip space [\x20\x09]+ %token bracket_ \( %token _bracket \) %token comma , %token number (0|[1-9]\d*)(\.\d+)?([eE][\+\-]?\d+)? %token plus \+ %token minus \-|− %token times \*|× %token div /|÷ %token constant [A-Z_]+[A-Z0-9_]* %token id \w+ expression: primary() ( ::plus:: #addition expression() )? primary: secondary() ( ::minus:: #substraction expression() )? secondary: ternary() ( ::times:: #multiplication expression() )? ternary: term() ( ::div:: #division expression() )? term: ( ::bracket_:: expression() ::_bracket:: #group ) | number() | constant() | variable() | ( ::minus:: #negative | ::plus:: ) term() | function() number: constant: #variable: #function: ::bracket_:: ( expression() ( ::comma:: expression() )* )? ::_bracket:: getOption($v)) { switch ($c) { case 'h': case '?': return $this->usage(); case '__ambiguous': $this->resolveOptionAmbiguity($v); break; } } $this->parser->listInputs($expression); $compiler = Compiler\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')); $visitor = new Math\Visitor\Arithmetic(); $dump = new Compiler\Visitor\Dump(); if (null !== $expression) { $ast = $compiler->parse($expression); echo $expression . ' = ' . $visitor->visit($ast), "\n"; return; } $readline = new Console\Readline(); $readline->setAutocompleter(new Console\Readline\Autocompleter\Word(array_merge(array_keys($visitor->getConstants()->getArrayCopy()), array_keys($visitor->getFunctions()->getArrayCopy())))); $handle = null; $expression = 'h'; do { switch ($expression) { case 'h': case 'help': echo 'Usage:', "\n", ' h[elp] to print this help;', "\n", ' c[onstants] to print available constants;', "\n", ' f[unctions] to print available functions;', "\n", ' e[xpression] to print the current expression;', "\n", ' d[ump] to dump the tree of the expression;', "\n", ' q[uit] to quit.', "\n"; break; case 'c': case 'constants': echo implode(', ', array_keys($visitor->getConstants()->getArrayCopy())), "\n"; break; case 'f': case 'functions': echo implode(', ', array_keys($visitor->getFunctions()->getArrayCopy())), "\n"; break; case 'e': case 'expression': echo $handle, "\n"; break; case 'd': case 'dump': if (null === $handle) { echo 'Type a valid expression before (“> 39 + 3”).', "\n"; } else { echo $dump->visit($compiler->parse($handle)), "\n"; } break; case 'q': case 'quit': break 2; default: if (null === $expression) { break; } try { echo $visitor->visit($compiler->parse($expression)), "\n"; } catch (Compiler\Exception $e) { echo $e->getMessage(), "\n"; break; } $handle = $expression; break; } } while (\false !== $expression = $readline->readLine('> ')); return; } /** * The command usage. * * @return int */ public function usage() { echo 'Usage : math:calc [expression]', "\n", 'Options :', "\n", $this->makeUsageOptionsList(['help' => 'This help.']), "\n"; return; } } __halt_compiler(); A simple calculator. _sets[] = $s; } $this->_max = count($this->_sets) - 1; $this->_break = empty($this->_sets); return; } /** * Get the current value. * * @return array */ public function current() { return $this->_current; } /** * Prepare the current value. * * @return void */ protected function _current() { $this->_current = []; foreach ($this->_sets as $set) { $this->_current[] = $set->current(); } return; } /** * Get the current key. * * @return int */ public function key() { return $this->_key; } /** * Advance the internal collection pointer, and return the current value. * * @return array */ public function next() { for ($i = 0; $i <= $this->_max; ++$i) { $this->_sets[$i]->next(); if (\false !== $this->_sets[$i]->valid()) { break; } $this->_sets[$i]->rewind(); if ($i === $this->_max) { $this->_break = \true; break; } } ++$this->_key; $this->_current(); return $this->current(); } /** * Rewind the internal collection pointer, and return the first collection. * * @return array */ public function rewind() { $this->_break = empty($this->_sets); $this->_key = 0; foreach ($this->_sets as $set) { $set->rewind(); } $this->_current(); return $this->current(); } /** * Check if there is a current element after calls to the rewind() or the * next() methods. * * @return bool */ public function valid() { return \false === $this->_break; } } _n = $n; $this->_k = $k; return; } /** * Get current γ. * * @return array */ public function current() { return $this->_current; } /** * Get current α. * * @return int */ public function key() { return $this->_key; } /** * Compute γ_{α + 1}. * * @return void */ public function next() { return; } /** * Rewind iterator. * * @return void */ public function rewind() { $this->_current = []; $this->_tmp = null; $this->_i = 0; $this->_o = 0 === $this->_n ? [0] : array_fill(0, $this->_n, 0); $this->_o[0] = $this->_k; $this->_last = \false; return; } /** * Compute γ_α. * * @return bool */ public function valid() { if (\true === $this->_last) { return \false; } if (0 === $this->_n) { return \false; } if ($this->_k == $this->_o[$this->_i = $this->_n - 1]) { $this->_last = \true; $this->_current = $this->_o; ++$this->_key; return \true; } $this->_current = $this->_o; ++$this->_key; $this->_tmp = $this->_o[$this->_i]; $this->_o[$this->_i] = 0; while ($this->_o[$this->_i] == 0) { --$this->_i; } --$this->_o[$this->_i]; $this->_o[$this->_i + 1] = $this->_tmp + 1; return \true; } } values as callable. * * @var \ArrayObject */ protected $_functions = null; /** * List of supported constants: identifier => values. * * @var \ArrayObject */ protected $_constants = null; /** * List of supported variables: identifier => values as callable. * * @var \ArrayObject */ protected $_variables = null; /** * Initialize constants and functions. * */ public function __construct() { $this->initializeConstants(); $this->initializeFunctions(); $this->initializeVariables(); return; } /** * Add a constant. * * @param string $name Constant name. * @param mixed $value Value. * @return void * @throws \Hoa\Math\Exception\AlreadyDefinedConstant */ public function addConstant($name, $value) { if (\true === $this->_constants->offsetExists($name)) { throw new \Hoa\Math\Exception\AlreadyDefinedConstant('Constant %s is already defined.', 0, $name); } $this->_constants[$name] = $value; return; } /** * Get a constant. * * @param string $name Constant name. * @return mixed * @throws \Hoa\Math\Exception\UnknownConstant */ public function getConstant($name) { if (\false === $this->_constants->offsetExists($name)) { throw new \Hoa\Math\Exception\UnknownConstant('Constant %s does not exist.', 1, $name); } return $this->_constants[$name]; } /** * Get constants. * * @return \ArrayObject */ public function getConstants() { return $this->_constants; } /** * Add a function. * * @param string $name Function name. * @param mixed $callable Callable. * @return void * @throws \Hoa\Math\Exception\UnknownFunction */ public function addFunction($name, $callable = null) { if (null === $callable) { if (\false === function_exists($name)) { throw new \Hoa\Math\Exception\UnknownFunction('Function %s does not exist, cannot add it.', 2, $name); } $callable = $name; } $this->_functions[$name] = xcallable($callable); return; } /** * Get a function. * * @param string $name Function name. * @return \Hoa\Consistency\Xcallable * @throws \Hoa\Math\Exception\UnknownFunction */ public function getFunction($name) { if (\false === $this->_functions->offsetExists($name)) { throw new \Hoa\Math\Exception\UnknownFunction('Function %s does not exist.', 3, $name); } return $this->_functions[$name]; } /** * Get functions. * * @return \ArrayObject */ public function getFunctions() { return $this->_functions; } /** * Add a variable. * * @param string $name Variable name. * @param callable $callable Callable. * @return void */ public function addVariable($name, callable $callable) { $this->_variables[$name] = xcallable($callable); return; } /** * Get a variable. * * @param string $name Variable name. * @return callable * @throws \Hoa\Math\Exception\UnknownVariable */ public function getVariable($name) { if (\false === $this->_variables->offsetExists($name)) { throw new \Hoa\Math\Exception\UnknownVariable('Variable %s does not exist.', 4, $name); } return $this->_variables[$name]($this); } /** * Get variables. * * @return \ArrayObject */ public function getVariables() { return $this->_variables; } /** * Initialize constants mapping. * * @return void */ protected function initializeConstants() { static $_constants = null; if (null === $_constants) { $_constants = new \ArrayObject(['PI' => \M_PI, 'PI_2' => \M_PI_2, 'PI_4' => \M_PI_4, 'E' => \M_E, 'SQRT_PI' => \M_SQRTPI, 'SQRT_2' => \M_SQRT2, 'SQRT_3' => \M_SQRT3, 'LN_PI' => \M_LNPI, 'LOG_2E' => \M_LOG2E, 'LOG_10E' => \M_LOG10E, 'LN_2' => \M_LN2, 'LN_10' => \M_LN10, 'ONE_OVER_PI' => \M_1_PI, 'TWO_OVER_PI' => \M_2_PI, 'TWO_OVER_SQRT_PI' => \M_2_SQRTPI, 'ONE_OVER_SQRT_2' => \M_SQRT1_2, 'EULER' => \M_EULER, 'INFINITE' => \INF]); } $this->_constants = $_constants; return; } /** * Initialize functions mapping. * * @return void */ protected function initializeFunctions() { static $_functions = null; if (null === $_functions) { $average = function () { $arguments = func_get_args(); return array_sum($arguments) / count($arguments); }; $_functions = new \ArrayObject(['abs' => xcallable('abs'), 'acos' => xcallable('acos'), 'asin' => xcallable('asin'), 'atan' => xcallable('atan'), 'average' => xcallable($average), 'avg' => xcallable($average), 'ceil' => xcallable('ceil'), 'cos' => xcallable('cos'), 'count' => xcallable(function () { return count(func_get_args()); }), 'deg2rad' => xcallable('deg2rad'), 'exp' => xcallable('exp'), 'floor' => xcallable('floor'), 'ln' => xcallable('log'), 'log' => xcallable(function ($value, $base = 10) { return log($value, $base); }), 'max' => xcallable('max'), 'min' => xcallable('min'), 'pow' => xcallable('pow'), 'rad2deg' => xcallable('rad2deg'), 'round' => xcallable(function ($value, $precision = 0) { return round($value, $precision); }), 'sin' => xcallable('sin'), 'sqrt' => xcallable('sqrt'), 'sum' => xcallable(function () { return array_sum(func_get_args()); }), 'tan' => xcallable('tan')]); } $this->_functions = $_functions; return; } /** * Initialize variables mapping. * * @return void */ protected function initializeVariables() { if (null === $this->_variables) { $this->_variables = new \ArrayObject(); } return; } } _parameters->getParameter('integer.min')) { $this->_parameters->setParameter('integer.min', max(-mt_getrandmax(), $this->_parameters->getParameter('integer.min'))); } if (null === $this->_parameters->getParameter('integer.max')) { $this->_parameters->setParameter('integer.max', min(mt_getrandmax(), $this->_parameters->getParameter('integer.max'))); } return; } /** * Generate a discrete uniform distribution. * * @param int $lower Lower bound value. * @param int $upper Upper bound value. * @return int */ protected function _getInteger($lower, $upper) { return mt_rand($lower, $upper); } /** * Generate a continuous uniform distribution. * * @param float $lower Lower bound value. * @param float $upper Upper bound value. * @return float */ protected function _getFloat($lower, $upper) { return $lower + lcg_value() * abs($upper - $lower); } } _parameters = new Zformat\Parameter(__CLASS__, [], ['integer.min' => -16, 'integer.max' => 15, 'float.min' => -128.0, 'float.max' => 127.0]); $this->_parameters->setParameters($parameters); if (null === $this->_parameters->getParameter('integer.min')) { $this->_parameters->setParameter('integer.min', \PHP_INT_MIN); } if (null === $this->_parameters->getParameter('integer.max')) { $this->_parameters->setParameter('integer.max', \PHP_INT_MAX); } if (null === $this->_parameters->getParameter('float.min')) { $this->_parameters->setParameter('float.min', \PHP_INT_MIN); } if (null === $this->_parameters->getParameter('float.max')) { $this->_parameters->setParameter('float.max', \PHP_INT_MAX); } $this->construct(); return; } /** * Construct. * * @return void */ public function construct() { return; } /** * Get parameters. * * @return \Hoa\Zformat\Parameter */ public function getParameters() { return $this->_parameters; } /** * Generate a discrete uniform distribution. * * @param int $lower Lower bound value. * @param int $upper Upper bound value. * @param array &$exclude Excluded values. * @return int */ public function getInteger($lower = null, $upper = null, array &$exclude = null) { if (null === $lower) { $lower = $this->_parameters->getParameter('integer.min'); } if (null === $upper) { $upper = $this->_parameters->getParameter('integer.max'); } if (null === $exclude) { if ($lower > $upper) { throw new Math\Exception('Unexpected values, integer %d should be lower than %d', 0, [$lower, $upper]); } return $this->_getInteger($lower, $upper); } sort($exclude); $upper -= count($exclude); if ($lower > $upper) { throw new Math\Exception('Unexpected values, integer %d should be lower than %d', 1, [$lower, $upper]); } $sampled = $this->_getInteger($lower, $upper); foreach ($exclude as $e) { if ($sampled >= $e) { ++$sampled; } else { break; } } return $sampled; } /** * Generate a discrete uniform distribution. * * @param int $lower Lower bound value. * @param int $upper Upper bound value. * @return int */ abstract protected function _getInteger($lower, $upper); /** * Generate a continuous uniform distribution. * * @param float $lower Lower bound value. * @param float $upper Upper bound value. * @return float */ public function getFloat($lower = null, $upper = null) { if (null === $lower) { $lower = $this->_parameters->getParameter('float.min'); } /* $lower = true === S_32\BITS ? -3.4028235e38 + 1 : -1.7976931348623157e308 + 1; */ if (null === $upper) { $upper = $this->_parameters->getParameter('float.max'); } /* $upper = true === S_32\BITS ? 3.4028235e38 - 1 : 1.7976931348623157e308 - 1; */ if ($lower > $upper) { throw new Math\Exception('Unexpected values, float %f should be lower than %f', 2, [$lower, $upper]); } return $this->_getFloat($lower, $upper); } /** * Generate a continuous uniform distribution. * * @param float $lower Lower bound value. * @param float $upper Upper bound value. * @return float */ abstract protected function _getFloat($lower, $upper); /** * Get an exclude set. * * @return array */ public function getExcludeSet() { return []; } } /** * Flex entity. */ Consistency::flexEntity('Hoa\Math\Sampler\Sampler'); // // Hoa // // // @license // // New BSD License // // Copyright © 2007-2016, 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\Math\Arithmetic. // // Provide a testable (i.e. easily generable) grammar for arithmetic // expressions. // // @copyright Copyright © 2007-2016 Hoa community. // @license New BSD License // %skip space [\x20\x09]+ %token bracket_ \( %token _bracket \) %token comma , %token number ([1-9]\d*)(\.\d+)? %token plus \+ %token minus \- %token times \* %token div / expression: primary() ( ::plus:: #addition expression() )? primary: secondary() ( ::minus:: #substraction expression() )? secondary: ternary() ( ::times:: #multiplication expression() )? ternary: term() ( ::div:: #division expression() )? term: ( ::bracket_:: expression() ::_bracket:: #group ) | number() | ( ::minus:: #negative | ::plus:: ) term() number: given($iterator = new CUT([]))->when($result = iterator_to_array($iterator))->then->array($result)->isEqualTo([[null]]); } public function case_X() { $this->given($iterator = new CUT([1, 2, 3]))->when($result = iterator_to_array($iterator))->then->array($result)->isEqualTo([[1], [2], [3]]); } public function case_X_Y() { $this->given($iterator = new CUT([1, 2, 3], [4, 5, 6]))->when($result = iterator_to_array($iterator))->then->array($result)->isEqualTo([[1, 4], [2, 4], [3, 4], [1, 5], [2, 5], [3, 5], [1, 6], [2, 6], [3, 6]]); } public function case_X_Y_Z() { $this->given($iterator = new CUT([1, 2, 3], [4, 5, 6], [7, 8, 9]))->when($result = iterator_to_array($iterator))->then->array($result)->isEqualTo([[1, 4, 7], [2, 4, 7], [3, 4, 7], [1, 5, 7], [2, 5, 7], [3, 5, 7], [1, 6, 7], [2, 6, 7], [3, 6, 7], [1, 4, 8], [2, 4, 8], [3, 4, 8], [1, 5, 8], [2, 5, 8], [3, 5, 8], [1, 6, 8], [2, 6, 8], [3, 6, 8], [1, 4, 9], [2, 4, 9], [3, 4, 9], [1, 5, 9], [2, 5, 9], [3, 5, 9], [1, 6, 9], [2, 6, 9], [3, 6, 9]]); } } given($n = 0, $k = 0, $withoutZero = \false)->when($result = CUT::Γ($n, $k, $withoutZero))->then->array($result)->isEmpty(); } public function case_n2_k3() { $this->given($n = 2, $k = 3, $withoutZero = \false)->when($result = CUT::Γ($n, $k, $withoutZero))->then->array($result)->isEqualTo([[3, 0], [2, 1], [1, 2], [0, 3]]); } public function case_n3_k2() { $this->given($n = 3, $k = 2, $withoutZero = \false)->when($result = CUT::Γ($n, $k, $withoutZero))->then->array($result)->isEqualTo([[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]]); } public function case_n2_k3_without_zero() { $this->given($n = 2, $k = 3, $withoutZero = \true)->when($result = CUT::Γ($n, $k, $withoutZero))->then->array($result)->isEqualTo([[2, 1], [1, 2]]); } public function case_n3_k2_without_zero() { $this->given($n = 3, $k = 2, $withoutZero = \true)->when($result = CUT::Γ($n, $k, $withoutZero))->then->array($result)->isEmpty(); } } given($n = 0, $k = 0, $iterator = new CUT($n, $k))->when($result = iterator_to_array($iterator))->then->array($result)->isEmpty(); } public function case_n2_k3() { $this->given($n = 2, $k = 3, $iterator = new CUT($n, $k))->when($result = iterator_to_array($iterator))->then->array($result)->isEqualTo([[3, 0], [2, 1], [1, 2], [0, 3]]); } public function case_n3_k2() { $this->given($n = 3, $k = 2, $iterator = new CUT($n, $k))->when($result = iterator_to_array($iterator))->then->array($result)->isEqualTo([[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]]); } } given($context = new CUT())->when($result = $context->getVariables())->then->object($result)->isInstanceOf('ArrayObject')->array(iterator_to_array($result))->isEmpty(); } public function case_context_exception_when_getting_unknown_variable() { $this->given($name = 'foo', $context = new CUT())->then->exception(function () use ($context, $name) { $context->getVariable($name); })->isInstanceOf('Hoa\Math\Exception\UnknownVariable'); } public function case_context_returns_variable_value() { $this->given($name = 'foo', $value = 42, $callable = function () use ($value) { return $value; }, $context = new CUT(), $context->addVariable($name, $callable))->when($result = $context->getVariable($name))->then->integer($result)->isEqualTo($value); } public function case_context_has_predefined_constants() { $this->given($context = new CUT())->when($result = $context->getConstants())->then->object($result)->isInstanceOf('ArrayObject')->array(iterator_to_array($result))->isEqualTo(['PI' => \M_PI, 'PI_2' => \M_PI_2, 'PI_4' => \M_PI_4, 'E' => \M_E, 'SQRT_PI' => \M_SQRTPI, 'SQRT_2' => \M_SQRT2, 'SQRT_3' => \M_SQRT3, 'LN_PI' => \M_LNPI, 'LOG_2E' => \M_LOG2E, 'LOG_10E' => \M_LOG10E, 'LN_2' => \M_LN2, 'LN_10' => \M_LN10, 'ONE_OVER_PI' => \M_1_PI, 'TWO_OVER_PI' => \M_2_PI, 'TWO_OVER_SQRT_PI' => \M_2_SQRTPI, 'ONE_OVER_SQRT_2' => \M_SQRT1_2, 'EULER' => \M_EULER, 'INFINITE' => \INF]); } public function case_context_exception_when_getting_unknown_constant() { $this->given($name = 'FOO', $context = new CUT())->then->exception(function () use ($context, $name) { $context->getConstant($name); })->isInstanceOf('Hoa\Math\Exception\UnknownConstant'); } public function case_context_exception_when_setting_already_defined_constant() { $this->given($name = 'PI', $context = new CUT())->then->exception(function () use ($context, $name) { $context->addConstant($name, 42); })->isInstanceOf('Hoa\Math\Exception\AlreadyDefinedConstant'); } public function case_context_returns_constant_value() { $this->given($name = 'FOO', $value = 42, $context = new CUT(), $context->addConstant($name, $value))->when($result = $context->getConstant($name))->then->variable($result)->isEqualTo($value); } public function case_context_has_predefined_functions() { $this->given($context = new CUT())->when($result = $context->getFunctions())->then->object($result)->isInstanceOf('ArrayObject')->array(iterator_to_array($result))->hasSize(23)->hasKey('abs')->hasKey('acos')->hasKey('asin')->hasKey('atan')->hasKey('average')->hasKey('avg')->hasKey('ceil')->hasKey('cos')->hasKey('count')->hasKey('deg2rad')->hasKey('exp')->hasKey('floor')->hasKey('ln')->hasKey('log')->hasKey('max')->hasKey('min')->hasKey('pow')->hasKey('rad2deg')->hasKey('round')->hasKey('round')->hasKey('sin')->hasKey('sqrt')->hasKey('sum')->hasKey('tan'); } public function case_context_exception_when_getting_unknown_function() { $this->given($name = 'foo', $context = new CUT())->then->exception(function () use ($context, $name) { $context->getFunction($name); })->isInstanceOf('Hoa\Math\Exception\UnknownFunction'); } public function case_context_exception_when_setting_unknown_function() { $this->given($name = 'foo', $context = new CUT())->then->exception(function () use ($context, $name) { $context->addFunction($name); })->isInstanceOf('Hoa\Math\Exception\UnknownFunction'); } public function case_context_returns_function_callable() { $this->given($name = 'foo', $callable = function () { }, $context = new CUT(), $context->addFunction($name, $callable))->when($result = $context->getFunction($name))->then->object($result)->isInstanceOf('Hoa\Consistency\Xcallable'); } public function case_context_returns_the_right_function_callable() { $this->given($name = 'foo', $value = 42, $callable = function () use ($value) { return $value; }, $context = new CUT(), $context->addFunction($name, $callable))->when($result = $context->getFunction($name))->then->integer($result())->isEqualTo($value); } } given($compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), $visitor = new CUT(), $ast = $compiler->parse('1 / 0'))->exception(function () use ($visitor, $ast) { $visitor->visit($ast); })->isInstanceOf(\RuntimeException::class); } public function case_github_43() { $this->given($compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), $visitor = new CUT(), $ast = $compiler->parse('1 / (1 / 0)'))->exception(function () use ($visitor, $ast) { $visitor->visit($ast); })->isInstanceOf(\RuntimeException::class); } public function case_github_47() { $this->given($compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), $visitor = new CUT())->when($ast = $compiler->parse('C'))->then->object($ast)->isInstanceOf(Compiler\Llk\TreeNode::class)->string($ast->getId())->isEqualTo('token')->string($ast->getValueToken())->isEqualTo('constant')->string($ast->getValueValue())->isEqualTo('C'); } } given($sampler = new CUT())->when($x = $sampler->getInteger())->then->integer($x); } public function case_bounded_integer() { $this->given($sampler = new CUT())->when($x = $sampler->getInteger(-5, 5))->then->integer($x)->isGreaterThanOrEqualTo(-5)->isLessThanOrEqualTo(5)->when($y = $sampler->getInteger(42, 42))->then->integer($y)->isIdenticalTo(42); } public function case_optional_bounds_integer() { $this->given($sampler = new CUT(['integer.min' => 42, 'integer.max' => 42]))->when($x = $sampler->getInteger())->then->integer($x)->isIdenticalTo(42); } public function case_excluded_integers() { $this->given($exclude = [], $sampler = new CUT())->when($x = $sampler->getInteger(0, 2, $exclude))->then->integer($x)->isGreaterThanOrEqualTo(0)->isLessThanOrEqualTo(2)->given($exclude[] = 2)->when($y = $sampler->getInteger(0, 2, $exclude))->then->integer($y)->isGreaterThanOrEqualTo(0)->isLessThanOrEqualTo(1)->given($exclude[] = 0)->when($z = $sampler->getInteger(0, 2, $exclude))->then->integer($z)->isIdenticalTo(1); } public function case_uniformity_integer() { $this->given($max = $this->sample($this->realdom()->boundinteger(1 << 18, 1 << 20)), $sum = 0, $upper = 1 << 10, $sampler = new CUT(['integer.min' => -$upper, 'integer.max' => $upper]))->when(function () use ($max, &$sum, &$sampler) { for ($i = 0; $i < $max; ++$i) { $sum += $sampler->getInteger(); } })->then->float($sum / $max)->isGreaterThanOrEqualTo(-1.5)->isLessThanOrEqualTo(1.5); } public function case_float() { $this->given($sampler = new CUT())->when($x = $sampler->getFloat())->then->float($x); } public function case_bounded_float() { $this->given($sampler = new CUT())->when($x = $sampler->getFloat(-5.5, 5.5))->then->float($x)->isGreaterThanOrEqualTo(-5.5)->isLessThanOrEqualTo(5.5)->when($y = $sampler->getFloat(4.2, 4.2))->float($y)->isIdenticalTo(4.2); } public function case_optional_bounds_float() { $this->given($sampler = new CUT(['float.min' => 4.2, 'float.max' => 4.2]))->when($x = $sampler->getFloat())->then->float($x)->isIdenticalTo(4.2); } public function case_uniformity_float() { $this->given($max = $this->sample($this->realdom()->boundinteger(1 << 18, 1 << 20)), $sum = 0, $upper = 1 << 10, $sampler = new CUT(['float.min' => -$upper, 'float.max' => $upper]))->when(function () use ($max, &$sum, &$sampler) { for ($i = 0; $i < $max; ++$i) { $sum += $sampler->getFloat(); } })->then->float($sum / $max)->isGreaterThanOrEqualTo(-1.5)->isLessThanOrEqualTo(1.5); } } given($sampler = new Compiler\Llk\Sampler\BoundedExhaustive(Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Test/Unit/Arithmetic.pp')), new Regex\Visitor\Isotropic(new LUT\Sampler\Random()), 9), $compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), $visitor = new CUT())->executeOnFailure(function () use (&$expression) { echo 'Failed expression: ', $expression, '.', "\n"; })->when(function () use (&$sampler, &$compiler, &$visitor) { foreach ($sampler as $i => $expression) { try { $x = (float) $visitor->visit($compiler->parse($expression)); } catch (\Exception $e) { continue; } eval('$y = (float) ' . $expression . ';'); if (is_nan($x) || is_nan($y)) { $this->boolean(\true); continue; } $this->float($x)->isNearlyEqualTo($y); } }); } public function case_visitor_unknown_variable() { $this->given($compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), $visitor = new CUT(), $variableName = 'unknown_variable')->then->object($compiler->parse($variableName . ' * 2'))->isInstanceOf('Hoa\Compiler\Llk\TreeNode')->exception(function () use ($variableName, $compiler, $visitor) { $visitor->visit($compiler->parse($variableName . ' * 2')); })->isInstanceOf('Hoa\Math\Exception\UnknownVariable'); } public function case_visitor_variable() { $this->given($compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), $visitor = new CUT(), $variableName = 'a_variable', $variableValue = 42)->when($visitor->addVariable($variableName, function () use ($variableValue) { return $variableValue; }))->then->float($visitor->visit($compiler->parse($variableName . ' * 2')))->isEqualTo($variableValue * 2); } public function case_visitor_unknown_constant() { $this->given($compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), $visitor = new CUT(), $constantName = 'UNKNOWN_CONSTANT')->then->object($compiler->parse($constantName . ' * 2'))->isInstanceOf('Hoa\Compiler\Llk\TreeNode')->exception(function () use ($constantName, $compiler, $visitor) { $visitor->visit($compiler->parse($constantName . ' * 2')); })->isInstanceOf('Hoa\Math\Exception\UnknownConstant'); } public function case_visitor_constant() { $this->given($compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), $visitor = new CUT(), $constantName = 'A_CONSTANT', $constantValue = 42)->when($visitor->addConstant($constantName, $constantValue))->then->float($visitor->visit($compiler->parse($constantName . ' * 2')))->isEqualTo($constantValue * 2); } public function case_visitor_unknown_function() { $this->given($compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), $visitor = new CUT(), $functionName = 'unknown_function')->then->object($compiler->parse($functionName . '() * 2'))->isInstanceOf('Hoa\Compiler\Llk\TreeNode')->exception(function () use ($functionName, $compiler, $visitor) { $visitor->visit($compiler->parse($functionName . '() * 2')); })->isInstanceOf('Hoa\Math\Exception\UnknownFunction'); } public function case_visitor_function() { $this->given($compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), $visitor = new CUT(), $functionName = 'a_function', $functionResult = 42)->when($visitor->addFunction($functionName, function () use ($functionResult) { return $functionResult; }))->then->float($visitor->visit($compiler->parse($functionName . '() * 2')))->isEqualTo($functionResult * 2); } public function case_change_default_context() { $this->given($compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), $visitor = new CUT(), $context = new \Mock\Hoa\Math\Context(), $variableName = 'a_variable', $variableValue = 42)->when($context->addVariable($variableName, function () use ($variableValue) { return $variableValue; }))->then->object($visitor->setContext($context))->isNotIdenticalTo($context)->object($visitor->getContext())->isIdenticalTo($context)->float($visitor->visit($compiler->parse('abs(' . $variableName . ' - PI)')))->isEqualTo(abs($variableValue - \M_PI))->mock($context)->call('getFunction')->withArguments('abs')->once->call('getVariable')->withArguments($variableName)->once->call('getConstant')->withArguments('PI')->once; } } initializeContext(); return; } /** * Set visitor's context * * @param \Hoa\Math\Context $context * @return \Hoa\Math\Context */ public function setContext(Math\Context $context) { $old = $this->_context; $this->_context = $context; return $old; } /** * Get visitor's context * * @return \Hoa\Math\Context */ public function getContext() { return $this->_context; } /** * Visit an element. * * @param \Hoa\Visitor\Element $element Element to visit. * @param mixed &$handle Handle (reference). * @param mixed $eldnah Handle (not reference). * @return float */ public function visit(Visitor\Element $element, &$handle = null, $eldnah = null) { $type = $element->getId(); $children = $element->getChildren(); if (null === $handle) { $handle = function ($x) { return $x; }; } $acc =& $handle; switch ($type) { case '#function': $name = array_shift($children)->accept($this, $_, $eldnah); $function = $this->getFunction($name); $arguments = []; foreach ($children as $child) { $child->accept($this, $_, $eldnah); $arguments[] = $_(); unset($_); } $acc = function () use ($function, $arguments, $acc) { return $acc($function->distributeArguments($arguments)); }; break; case '#negative': $children[0]->accept($this, $a, $eldnah); $acc = function () use ($a, $acc) { return $acc(-$a()); }; break; case '#addition': $children[0]->accept($this, $a, $eldnah); $acc = function ($b) use ($a, $acc) { return $acc($a() + $b); }; $children[1]->accept($this, $acc, $eldnah); break; case '#substraction': $children[0]->accept($this, $a, $eldnah); $acc = function ($b) use ($a, $acc) { return $acc($a()) - $b; }; $children[1]->accept($this, $acc, $eldnah); break; case '#multiplication': $children[0]->accept($this, $a, $eldnah); $acc = function ($b) use ($a, $acc) { return $acc($a() * $b); }; $children[1]->accept($this, $acc, $eldnah); break; case '#division': $children[0]->accept($this, $a, $eldnah); $parent = $element->getParent(); if (null === $parent || $type === $parent->getId()) { $acc = function ($b) use ($a, $acc) { if (0.0 === $b) { throw new \RuntimeException('Division by zero is not possible.'); } return $acc($a()) / $b; }; } else if ('#fakegroup' !== $parent->getId()) { $classname = get_class($element); $group = new $classname('#fakegroup', null, [$element], $parent); $element->setParent($group); $this->visit($group, $acc, $eldnah); break; } else { $acc = function ($b) use ($a, $acc) { if (0.0 === $b) { throw new \RuntimeException('Division by zero is not possible.'); } return $acc($a() / $b); }; } $children[1]->accept($this, $acc, $eldnah); break; case '#fakegroup': case '#group': $children[0]->accept($this, $a, $eldnah); $acc = function () use ($a, $acc) { return $acc($a()); }; break; case '#variable': $out = $this->getVariable($children[0]->getValueValue()); $acc = function () use ($out, $acc) { return $acc($out); }; break; case 'token': $value = $element->getValueValue(); $out = null; if ('constant' === $element->getValueToken()) { if (defined($value)) { $out = constant($value); } else { $out = $this->getConstant($value); } } elseif ('id' === $element->getValueToken()) { return $value; } else { $out = (float) $value; } $acc = function () use ($out, $acc) { return $acc($out); }; break; } if (null === $element->getParent()) { return $acc(); } } /** * Get functions. * * @return \ArrayObject */ public function getFunctions() { return $this->_context->getFunctions(); } /** * Get a function. * * @param string $name Function name. * @return \Hoa\Consistency\Xcallable * @throws \Hoa\Math\Exception\UnknownFunction */ public function getFunction($name) { return $this->_context->getFunction($name); } /** * Get constants. * * @return \ArrayObject */ public function getConstants() { return $this->_context->getConstants(); } /** * Get a constant. * * @param string $name Constant name. * @return mixed * @throws \Hoa\Math\Exception\UnknownFunction */ public function getConstant($name) { return $this->_context->getConstant($name); } /** * Get variables. * * @return \ArrayObject */ public function getVariables() { return $this->_context->getVariables(); } /** * Get a variable. * * @param string $name Variable name. * @return callable * @throws \Hoa\Math\Exception\UnknownVariable */ public function getVariable($name) { return $this->_context->getVariable($name); } protected function initializeContext() { if (null === $this->_context) { $this->_context = new Math\Context(); } return; } /** * Add a function. * * @param string $name Function name. * @param mixed $callable Callable. * @return void */ public function addFunction($name, $callable = null) { return $this->_context->addFunction($name, $callable); } /** * Add a constant. * * @param string $name Constant name. * @param mixed $value Value. * @return void */ public function addConstant($name, $value) { return $this->_context->addConstant($name, $value); } /** * Add a variable. * * @param string $name Variable name. * @param callable $callable Callable. * @return void */ public function addVariable($name, callable $callable) { return $this->_context->addVariable($name, $callable); } } getOption($v)) { switch ($c) { case 'E': $exists = \false; break; case 'u': $unfold = \true; break; case 't': $tree = \true; break; case 'V': $verbose = \false; break; case 'h': case '?': return $this->usage(); case '__ambiguous': $this->resolveOptionAmbiguity($v); break; } } $this->parser->listInputs($path); if (null === $path) { return $this->usage(); } if (\true === $tree) { $protocol = Protocol::getInstance(); $foo = substr($path, 0, 6); if ('hoa://' !== $foo) { return; } $path = substr($path, 6); $current = $protocol; foreach (explode('/', $path) as $component) { if (!isset($current[$component])) { break; } $current = $current[$component]; } echo $current; return; } if (\true === $verbose) { echo Console\Cursor::colorize('foreground(yellow)'), $path, Console\Cursor::colorize('normal'), ' is equivalent to:', "\n"; } $resolved = resolve($path, $exists, $unfold); foreach ((array) $resolved as $r) { echo $r, "\n"; } return; } /** * The command usage. * * @return int */ public function usage() { echo 'Usage : protocol:resolve path', "\n", 'Options :', "\n", $this->makeUsageOptionsList(['E' => 'Do not check if the resolution result exists.', 'u' => 'Unfold all possible results.', 't' => 'Print the tree from the path.', 'V' => 'No-verbose, i.e. be as quiet as possible, just print ' . 'essential information.', 'help' => 'This help.']), "\n"; return; } } __halt_compiler(); Resolve `hoa://` paths. _reach) as $part) { $out[] = "\r" . $part . strtolower($head) . $queue; } $out[] = "\r" . dirname(dirname(dirname(dirname(__DIR__)))) . $queue; return implode(RS, $out); } $out = []; foreach (explode(RS, $this->_reach) as $part) { $pos = strrpos(rtrim($part, \DIRECTORY_SEPARATOR), \DIRECTORY_SEPARATOR) + 1; $head = substr($part, 0, $pos); $tail = substr($part, $pos); $out[] = $head . strtolower($tail); } $this->_reach = implode(RS, $out); return parent::reach($queue); } } _name = $name; } if (null !== $reach) { $this->_reach = $reach; } foreach ($children as $child) { $this[] = $child; } return; } /** * Add a node. * * @param string $name Node's name. If null, will be * set to name of `$node`. * @param \Hoa\Protocol\Protocol $node Node to add. * @return \Hoa\Protocol\Protocol * @throws \Hoa\Protocol\Exception */ public function offsetSet($name, $node): void { if (!$node instanceof self) { throw new Protocol\Exception('Protocol node must extend %s.', 0, __CLASS__); } if (empty($name)) { $name = $node->getName(); } if (empty($name)) { throw new Protocol\Exception('Cannot add a node to the `hoa://` protocol without a name.', 1); } $this->_children[$name] = $node; return; } /** * Get a specific node. * * @param string $name Node's name. * @return \Hoa\Protocol\Protocol * @throws \Hoa\Protocol\Exception */ #[\ReturnTypeWillChange] public function offsetGet($name) { if (!isset($this[$name])) { throw new Protocol\Exception('Node %s does not exist.', 2, $name); } return $this->_children[$name]; } /** * Check if a node exists. * * @param string $name Node's name. * @return bool */ public function offsetExists($name): bool { return \true === array_key_exists($name, $this->_children); } /** * Remove a node. * * @param string $name Node's name to remove. * @return void */ public function offsetUnset($name): void { unset($this->_children[$name]); return; } /** * Resolve a path, i.e. iterate the nodes tree and reach the queue of * the path. * * @param string $path Path to resolve. * @param array &$accumulator Combination of all possibles paths. * @param string $id ID. * @return mixed */ protected function _resolve($path, &$accumulator, $id = null) { if (substr($path, 0, 6) == 'hoa://') { $path = substr($path, 6); } if (empty($path)) { return null; } if (null === $accumulator) { $accumulator = []; $posId = strpos($path, '#'); if (\false !== $posId) { $id = substr($path, $posId + 1); $path = substr($path, 0, $posId); } else { $id = null; } } $path = trim($path, '/'); $pos = strpos($path, '/'); if (\false !== $pos) { $next = substr($path, 0, $pos); } else { $next = $path; } if (isset($this[$next])) { if (\false === $pos) { if (null === $id) { $this->_resolveChoice($this[$next]->reach(), $accumulator); return \true; } $accumulator = null; return $this[$next]->reachId($id); } $tnext = $this[$next]; $this->_resolveChoice($tnext->reach(), $accumulator); return $tnext->_resolve(substr($path, $pos + 1), $accumulator, $id); } $this->_resolveChoice($this->reach($path), $accumulator); return \true; } /** * Resolve choices, i.e. a reach value has a “;”. * * @param string $reach Reach value. * @param array &$accumulator Combination of all possibles paths. * @return void */ protected function _resolveChoice($reach, array &$accumulator) { if (empty($accumulator)) { $accumulator = explode(RS, $reach); return; } if (\false === strpos($reach, RS)) { if (\false !== $pos = strrpos($reach, "\r")) { $reach = substr($reach, $pos + 1); foreach ($accumulator as &$entry) { $entry = null; } } foreach ($accumulator as &$entry) { $entry .= $reach; } return; } $choices = explode(RS, $reach); $ref = $accumulator; $accumulator = []; foreach ($choices as $choice) { if (\false !== $pos = strrpos($choice, "\r")) { $choice = substr($choice, $pos + 1); foreach ($ref as $entry) { $accumulator[] = $choice; } } else { foreach ($ref as $entry) { $accumulator[] = $entry . $choice; } } } unset($ref); return; } /** * Queue of the node. * Generic one. Must be overrided in children classes. * * @param string $queue Queue of the node (generally a filename, * with probably a query). * @return mixed */ public function reach($queue = null) { return empty($queue) ? $this->_reach : $queue; } /** * ID of the component. * Generic one. Should be overrided in children classes. * * @param string $id ID of the component. * @return mixed * @throws \Hoa\Protocol\Exception */ public function reachId($id) { throw new Protocol\Exception('The node %s has no ID support (tried to reach #%s).', 4, [$this->getName(), $id]); } /** * Set a new reach value. * * @param string $reach Reach value. * @return string */ public function setReach($reach) { $old = $this->_reach; $this->_reach = $reach; return $old; } /** * Get node's name. * * @return string */ public function getName() { return $this->_name; } /** * Get reach's root. * * @return string */ protected function getReach() { return $this->_reach; } /** * Get an iterator. * * @return \ArrayIterator */ public function getIterator(): \Traversable { return new \ArrayIterator($this->_children); } /** * Get root the protocol. * * @return \Hoa\Protocol\Protocol */ public static function getRoot() { return Protocol::getInstance(); } /** * Print a tree of component. * * @return string */ public function __toString() { static $i = 0; $out = str_repeat(' ', $i) . $this->getName() . "\n"; foreach ($this as $node) { ++$i; $out .= $node; --$i; } return $out; } } /** * Flex entity. */ Consistency::flexEntity('Hoa\Protocol\Node\Node'); This file was automatically generated by Composer Patches (https://github.com/cweagans/composer-patches) Patches applied to this directory: 0 Source: patches/Node.patch 1 Source: patches/Wrapper.patch initialize(); return; } /** * Singleton. * To use the `hoa://` protocol shared by everyone. * * @return \Hoa\Protocol\Protocol */ public static function getInstance() { if (null === static::$_instance) { static::$_instance = new static(); } return static::$_instance; } /** * Initialize the protocol. * * @return void */ protected function initialize() { $root = dirname(dirname(__DIR__)); $cwd = 'cli' === \PHP_SAPI ? dirname(realpath($_SERVER['argv'][0])) : getcwd(); $this[] = new \Hoa\Protocol\Node('Application', $cwd . DS, [new \Hoa\Protocol\Node('Public', 'Public' . DS)]); $this[] = new \Hoa\Protocol\Node('Data', dirname($cwd) . DS, [new \Hoa\Protocol\Node('Etc', 'Etc' . DS, [new \Hoa\Protocol\Node('Configuration', 'Configuration' . DS), new \Hoa\Protocol\Node('Locale', 'Locale' . DS)]), new \Hoa\Protocol\Node('Lost+found', 'Lost+found' . DS), new \Hoa\Protocol\Node('Temporary', 'Temporary' . DS), new \Hoa\Protocol\Node('Variable', 'Variable' . DS, [new \Hoa\Protocol\Node('Cache', 'Cache' . DS), new \Hoa\Protocol\Node('Database', 'Database' . DS), new \Hoa\Protocol\Node('Log', 'Log' . DS), new \Hoa\Protocol\Node('Private', 'Private' . DS), new \Hoa\Protocol\Node('Run', 'Run' . DS), new \Hoa\Protocol\Node('Test', 'Test' . DS)])]); $this[] = new \Hoa\Protocol\Node\Library('Library', $root . DS . 'Hoathis' . DS . RS . $root . DS . 'Hoa' . DS); return; } /** * Resolve (unfold) an `hoa://` path to its real resource. * * @param string $path Path to resolve. * @param bool $exists If `true`, try to find the first that exists, * else return the first solution. * @param bool $unfold Return all solutions instead of one. * @return mixed */ public function resolve($path, $exists = \true, $unfold = \false) { if (substr($path, 0, 6) !== 'hoa://') { if (\true === is_dir($path)) { $path = rtrim($path, '/\\'); if (0 === strlen($path)) { $path = '/'; } } return $path; } if (isset(self::$_cache[$path])) { $handle = self::$_cache[$path]; } else { $out = $this->_resolve($path, $handle); // Not a path but a resource. if (!is_array($handle)) { return $out; } $handle = array_values(array_unique($handle, \SORT_REGULAR)); foreach ($handle as &$entry) { if (\true === is_dir($entry)) { $entry = rtrim($entry, '/\\'); if (0 === strlen($entry)) { $entry = '/'; } } } self::$_cache[$path] = $handle; } if (\true === $unfold) { if (\true !== $exists) { return $handle; } $out = []; foreach ($handle as $solution) { if (file_exists($solution)) { $out[] = $solution; } } return $out; } if (\true !== $exists) { return $handle[0]; } foreach ($handle as $solution) { if (file_exists($solution)) { return $solution; } } return static::NO_RESOLUTION; } /** * Clear the cache. * * @return void */ public static function clearCache() { self::$_cache = []; return; } } /** * Flex entity. */ Consistency::flexEntity('Hoa\Protocol\Protocol'); when($result = new SUT('foo', 0))->then->object($result)->isInstanceOf('Hoa\Exception\Exception'); } } given($this->constant->WITH_COMPOSER = \false, $node = new SUT('foo', 'bar'))->when($result = $node->reach())->then->string($result)->isEqualTo('bar'); } public function case_reach_without_composer_with_a_queue() { $this->given($this->constant->WITH_COMPOSER = \false, $node = new SUT('foo', 'bar'))->when($result = $node->reach('baz'))->then->string($result)->isEqualTo('baz'); } public function case_reach_with_composer_without_a_queue_and_a_single_reach() { $this->given($this->constant->WITH_COMPOSER = \true, $node = new SUT('foo', 'Bar' . DS . 'Baz' . DS . 'Qux' . DS))->when($result = $node->reach())->then->string($result)->isEqualTo('Bar' . DS . 'Baz' . DS . 'qux' . DS); } public function case_reach_with_composer_without_a_queue_and_a_multiple_reaches() { $this->given($this->constant->WITH_COMPOSER = \true, $node = new SUT('foo', 'Bar' . DS . 'Baz' . DS . 'Qux' . DS . RS . 'Hello' . DS . 'Mister' . DS . 'Anderson' . DS))->when($result = $node->reach())->then->string($result)->isEqualTo('Bar' . DS . 'Baz' . DS . 'qux' . DS . RS . 'Hello' . DS . 'Mister' . DS . 'anderson' . DS); } public function case_reach_with_composer_with_a_simple_queue() { $this->given($this->constant->WITH_COMPOSER = \true, $node = new SUT('foo', 'Bar' . DS . 'Baz' . DS . 'Qux' . DS))->when($result = $node->reach('Hello'))->then->string($result)->isEqualTo("\r" . 'Bar' . DS . 'Baz' . DS . 'Qux' . DS . 'hello' . RS . "\r" . dirname(dirname(dirname(dirname(dirname(dirname(__DIR__))))))); } public function case_reach_with_composer_with_a_queue() { $this->given($this->constant->WITH_COMPOSER = \true, $node = new SUT('foo', 'Bar' . DS))->when($result = $node->reach('Hello/Mister/Anderson'))->then->string($result)->isEqualTo("\r" . 'Bar' . DS . 'hello' . DS . 'Mister' . DS . 'Anderson' . RS . "\r" . dirname(dirname(dirname(dirname(dirname(dirname(__DIR__)))))) . DS . 'Mister' . DS . 'Anderson'); } } when($result = new SUT())->then->object($result)->isInstanceOf('ArrayAccess')->isInstanceOf('IteratorAggregate'); } public function case_empty_constructor() { $this->when($result = new SUT())->then->variable($result->getName())->isNull()->array(iterator_to_array($result->getIterator()))->isEmpty(); } public function case_constructor_with_a_name() { $this->given($name = 'foo')->when($result = new SUT($name))->then->string($result->getName())->isEqualTo($name)->array(iterator_to_array($result->getIterator()))->isEmpty(); } public function case_constructor_with_a_name_and_children() { $this->given($name = 'foo', $children = [new SUT('bar'), new SUT('baz')])->when($result = new SUT($name, '', $children))->then->string($result->getName())->isEqualTo($name)->array(iterator_to_array($result->getIterator()))->hasSize(2); } public function case_offset_set() { $this->given($root = new SUT(), $name = 'foo', $node = new SUT(), $oldCountChildren = count(iterator_to_array($root->getIterator())))->when($result = $root->offsetSet($name, $node))->then->integer(count(iterator_to_array($root->getIterator())))->isEqualTo($oldCountChildren + 1)->object($root[$name])->isIdenticalTo($node); } public function case_offset_set_not_a_node() { $this->given($root = new SUT())->exception(function () use ($root) { $root->offsetSet('foo', null); })->isInstanceOf('Hoa\Protocol\Exception'); } public function case_offset_set_no_name() { $this->given($root = new SUT())->exception(function () use ($root) { $root->offsetSet(null, new SUT()); })->isInstanceOf('Hoa\Protocol\Exception'); } public function case_offset_get() { $this->given($root = new SUT(), $child = new SUT(), $root['foo'] = $child)->when($result = $root->offsetGet('foo'))->then->object($result)->isIdenticalTo($child); } public function case_offset_get_an_unknown_name() { $this->given($root = new SUT())->exception(function () use ($root) { $root->offsetGet('foo'); })->isInstanceOf('Hoa\Protocol\Exception'); } public function case_offset_exists() { $this->given($root = new SUT(), $child = new SUT(), $root['foo'] = $child)->when($result = $root->offsetExists('foo'))->then->boolean($result)->isTrue(); } public function case_offset_not_exists() { $this->given($root = new SUT())->when($result = $root->offsetExists('foo'))->then->boolean($result)->isFalse(); } public function case_offset_unset() { $this->given($root = new SUT(), $child = new SUT(), $root['foo'] = $child)->when($result = $root->offsetUnset('foo'))->then->boolean($root->offsetExists('foo'))->isFalse(); } public function case_reach() { $this->given($reach = 'bar', $node = new SUT('foo', $reach))->when($result = $node->reach())->then->string($result)->isEqualTo($reach); } public function case_reach_with_a_queue() { $this->given($queue = 'baz', $node = new SUT('foo', 'bar'))->when($result = $node->reach('baz'))->then->string($result)->isEqualTo($queue); } public function case_reach_id() { $this->given($node = new SUT())->exception(function () use ($node) { $node->reachId('foo'); })->isInstanceOf('Hoa\Protocol\Exception'); } public function case_set_reach() { $this->given($reach = 'bar', $node = new SUT('foo', $reach))->when($result = $node->setReach('baz'))->then->string($result)->isEqualTo($reach)->string($node->reach())->isEqualTo('baz'); } public function case_get_name() { $this->given($name = 'foo', $node = new SUT($name))->when($result = $node->getName())->then->string($result)->isEqualTo($name); } public function case_get_iterator() { $this->given($childA = new SUT('bar'), $childB = new SUT('baz'), $children = [$childA, $childB])->when($result = new SUT('foo', '', $children))->then->object($result->getIterator())->isInstanceOf('ArrayIterator')->array(iterator_to_array($result->getIterator()))->isEqualTo(['bar' => $childA, 'baz' => $childB]); } public function case_get_root() { $this->when($result = SUT::getRoot())->then->object($result)->isIdenticalTo(LUT::getInstance()); } public function case_to_string_as_leaf() { $this->given($node = new SUT('foo'))->when($result = $node->__toString())->then->string($result)->isEqualTo('foo' . "\n"); } public function case_to_string_as_node() { $this->given($node = new SUT('foo'), $node[] = new SUT('bar'), $node[] = new SUT('baz'))->when($result = $node->__toString())->then->string($result)->isEqualTo('foo' . "\n" . ' bar' . "\n" . ' baz' . "\n"); } } when($result = SUT::getInstance())->then->object($result)->isInstanceOf('Hoa\Protocol\Node'); } public function case_default_tree() { $this->when($result = SUT::getInstance())->then->object($result['Application'])->isInstanceOf('Hoa\Protocol\Node\Node')->object($result['Application']['Public'])->isInstanceOf('Hoa\Protocol\Node\Node')->object($result['Data'])->isInstanceOf('Hoa\Protocol\Node\Node')->object($result['Data']['Etc'])->isInstanceOf('Hoa\Protocol\Node\Node')->object($result['Data']['Etc']['Configuration'])->isInstanceOf('Hoa\Protocol\Node\Node')->object($result['Data']['Etc']['Locale'])->isInstanceOf('Hoa\Protocol\Node\Node')->object($result['Data']['Lost+found'])->isInstanceOf('Hoa\Protocol\Node\Node')->object($result['Data']['Temporary'])->isInstanceOf('Hoa\Protocol\Node\Node')->object($result['Data']['Variable'])->isInstanceOf('Hoa\Protocol\Node\Node')->object($result['Data']['Variable']['Cache'])->isInstanceOf('Hoa\Protocol\Node\Node')->object($result['Data']['Variable']['Database'])->isInstanceOf('Hoa\Protocol\Node\Node')->object($result['Data']['Variable']['Log'])->isInstanceOf('Hoa\Protocol\Node\Node')->object($result['Data']['Variable']['Private'])->isInstanceOf('Hoa\Protocol\Node\Node')->object($result['Data']['Variable']['Run'])->isInstanceOf('Hoa\Protocol\Node\Node')->object($result['Data']['Variable']['Test'])->isInstanceOf('Hoa\Protocol\Node\Node')->object($result['Library'])->isInstanceOf('Hoa\Protocol\Node\Library')->string($result['Library']->reach())->isEqualTo(dirname(dirname(dirname(dirname(__DIR__)))) . DS . 'hoathis' . DS . RS . dirname(dirname(dirname(dirname(__DIR__)))) . DS . 'hoa' . DS); } public function case_resolve_not_a_hoa_path() { $this->given($protocol = SUT::getInstance())->when($result = $protocol->resolve('/foo/bar'))->then->string($result)->isEqualTo('/foo/bar'); } public function case_resolve_to_non_existing_resource() { $this->given($protocol = SUT::getInstance())->when($result = $protocol->resolve('hoa://Application/Foo/Bar'))->then->string($result)->isEqualTo(SUT::NO_RESOLUTION); } public function case_resolve_does_not_test_if_exists() { $this->given($protocol = SUT::getInstance())->when($result = $protocol->resolve('hoa://Application/Foo/Bar', \false))->then->string($result)->isEqualTo('/Foo/Bar'); } public function case_resolve_unfold_to_existing_resources() { $this->given($protocol = SUT::getInstance())->when($result = $protocol->resolve('hoa://Library', \true, \true))->then->array($result)->contains(dirname(dirname(dirname(dirname(__DIR__)))) . DS . 'hoa'); } public function case_resolve_unfold_to_non_existing_resources() { $this->given($parentHoaDirectory = dirname(dirname(dirname(dirname(__DIR__)))), $protocol = SUT::getInstance())->when($result = $protocol->resolve('hoa://Library', \false, \true))->then->array($result)->isEqualTo([$parentHoaDirectory . DS . 'hoathis', $parentHoaDirectory . DS . 'hoa']); } } given($wrapper = new SUT())->when($result = $wrapper->stream_cast(\STREAM_CAST_FOR_SELECT))->then->boolean($result)->isFalse(); } public function case_stream_cast_as_stream() { $this->given($wrapper = new SUT())->when($result = $wrapper->stream_cast(\STREAM_CAST_AS_STREAM))->then->boolean($result)->isFalse(); } public function case_stream_close() { $this->given($wrapper = new SUT(), $this->openFile($wrapper))->when($result = $wrapper->stream_close())->then->variable($result)->isNull()->variable($wrapper->getStream())->isNull()->variable($wrapper->getStreamName())->isNull(); } public function case_stream_not_eof() { $this->given($wrapper = new SUT(), $this->openFile($wrapper, 'foo'), fseek($wrapper->getStream(), 0, \SEEK_SET))->when($result = $wrapper->stream_eof())->then->boolean($result)->isFalse(); } public function case_stream_eof() { $this->given($this->function->feof = \true, $wrapper = new SUT())->when($result = $wrapper->stream_eof())->then->boolean($result)->isTrue(); } public function case_stream_flush() { $this->given($wrapper = new SUT(), $this->openFile($wrapper))->when($result = $wrapper->stream_flush())->then->boolean($result)->isTrue(); } public function _case_stream_xxx_lock($operation) { $this->given($this->function->flock = function ($resource, $operation) use (&$_resource, &$_operation) { $_resource = $resource; $_operation = $operation; if ($operation === \LOCK_NB) { return \true; } return flock($resource, $operation); }, $wrapper = new SUT(), $this->openFile($wrapper))->when($result = $wrapper->stream_lock($operation))->then->boolean($result)->isTrue()->resource($_resource)->isStream()->isIdenticalTo($wrapper->getStream())->integer($_operation)->isEqualTo($operation); } public function case_stream_shared_lock() { return $this->_case_stream_xxx_lock(\LOCK_SH); } public function case_stream_exclusive_lock() { return $this->_case_stream_xxx_lock(\LOCK_EX); } public function case_stream_release_lock() { return $this->_case_stream_xxx_lock(\LOCK_UN); } public function case_stream_not_blocking_lock() { return $this->_case_stream_xxx_lock(\LOCK_NB); } public function _case_metadata_touch_with_xxx_arguments($arguments, $path, $time, $atime) { $this->given($this->function->touch = function ($path, $time, $atime) use (&$_path, &$_time, &$_atime) { $_path = $path; $_time = $time; $_atime = $atime; return \true; }, $wrapper = new SUT())->when($result = $wrapper->stream_metadata($path, \STREAM_META_TOUCH, $arguments))->then->boolean($result)->isTrue()->string($_path)->isEqualTo($path)->variable($_time)->isEqualTo($time)->variable($_atime)->isEqualTo($atime); } public function case_metadata_touch_with_no_argument() { return $this->_case_metadata_touch_with_xxx_arguments([], 'foo', null, null); } public function case_metadata_touch_with_time() { return $this->_case_metadata_touch_with_xxx_arguments([42], 'foo', 42, null); } public function case_metadata_touch_with_time_and_atime() { return $this->_case_metadata_touch_with_xxx_arguments([42, 777], 'foo', 42, 777); } public function _case_metadata_owner_xxx($owner) { $this->given($this->function->chown = function ($path, $user) use (&$_path, &$_user) { $_path = $path; $_user = $user; return \true; }, $path = 'foo', $user = 'gordon', $wrapper = new SUT())->when($result = $wrapper->stream_metadata('foo', $owner, $user))->then->boolean($result)->isTrue()->string($path)->isEqualTo($_path)->string($user)->isEqualTo($_user); } public function case_metadata_owner() { return $this->_case_metadata_owner_xxx(\STREAM_META_OWNER); } public function case_metadata_owner_name() { return $this->_case_metadata_owner_xxx(\STREAM_META_OWNER_NAME); } public function _case_metadata_group_xxx($grp) { $this->given($this->function->chgrp = function ($path, $group) use (&$_path, &$_group) { $_path = $path; $_group = $group; return \true; }, $path = 'foo', $group = 'root', $wrapper = new SUT())->when($result = $wrapper->stream_metadata('foo', $grp, $group))->then->boolean($result)->isTrue()->string($path)->isEqualTo($_path)->string($group)->isEqualTo($_group); } public function case_metadata_group() { return $this->_case_metadata_group_xxx(\STREAM_META_GROUP); } public function case_metadata_group_name() { return $this->_case_metadata_group_xxx(\STREAM_META_GROUP_NAME); } public function case_metadata_access() { $this->given($this->function->chmod = function ($path, $mode) use (&$_path, &$_mode) { $_path = $path; $_mode = $mode; return \true; }, $path = 'foo', $mode = 0755, $wrapper = new SUT())->when($result = $wrapper->stream_metadata('foo', \STREAM_META_ACCESS, $mode))->then->boolean($result)->isTrue()->string($path)->isEqualTo($_path)->integer($mode)->isEqualTo($_mode); } public function case_metadata_default() { $this->given($option = 0, $mode = 0, $wrapper = new SUT())->when($result = $wrapper->stream_metadata('foo', $option, $mode))->then->boolean($result)->isFalse(); } public function case_stream_open() { $this->given($this->function->fopen = function ($path, $mode, $options) use (&$_path, &$_mode, &$_options, &$_openedPath) { $_path = $path; $_mode = $mode; $_options = $options; return fopen($path, $mode, $options); }, $wrapper = new SUT(), $path = 'hoa://Test/Vfs/Foo?type=file', $mode = 'r', $options = \STREAM_USE_PATH)->when($result = $wrapper->stream_open($path, $mode, $options, $openedPath))->then->boolean($result)->isTrue()->string(SUT::realPath($path, \true))->isEqualTo($_path)->string($mode)->isEqualTo($_mode)->integer($options)->isEqualTo($_options & \STREAM_USE_PATH)->resource($openedPath)->isStream()->isIdenticalTo($wrapper->getStream())->string($wrapper->getStreamName())->isEqualTo('atoum://Foo'); } public function case_stream_open_not_hoa_protocol() { $this->given($wrapper = new SUT(), $path = LUT::NO_RESOLUTION, $mode = 'r', $options = \STREAM_USE_PATH)->when($result = $wrapper->stream_open($path, $mode, $options, $openedPath))->then->boolean($result)->isFalse(); } public function case_stream_open_not_a_resource() { $this->given($this->function->fopen = function ($path, $mode, $options) use (&$_path, &$_mode, &$_options, &$_openedPath) { $_path = $path; $_mode = $mode; $_options = $options; return fopen($path, $mode, $options); }, $this->function->is_resource = \false, $wrapper = new SUT(), $path = 'hoa://Test/Vfs/Foo?type=file', $mode = 'r', $options = \STREAM_USE_PATH)->when($result = $wrapper->stream_open($path, $mode, $options, $openedPath))->then->boolean($result)->isFalse()->string(SUT::realPath($path, \true))->isEqualTo($_path)->string($mode)->isEqualTo($_mode)->integer($options)->isEqualTo($_options & \STREAM_USE_PATH)->resource($openedPath)->isStream(); } public function case_stream_read() { $this->given($this->function->fread = function ($resource, $count) use (&$_resource, &$_count) { $_resource = $resource; $_count = $count; return fread($resource, $count); }, $wrapper = new SUT(), $count = 42, $this->openFile($wrapper, str_repeat('@', $count)))->when($result = $wrapper->stream_read($count))->then->string($result)->hasLength($count)->resource($_resource)->isStream()->isIdenticalTo($wrapper->getStream())->integer($_count)->isEqualTo($count); } public function _case_stream_seek_xxx($offset, $whence) { return $this->given($this->function->fseek = function ($resource, $offset, $whence) use (&$_resource, &$_offset, &$_whence) { $_resource = $resource; $_offset = $offset; $_whence = $whence; return fseek($resource, $offset, $whence); }, $wrapper = new SUT(), $this->openFile($wrapper, 'foobar'))->when($result = $wrapper->stream_seek($offset, $whence))->then->boolean($result)->isTrue()->resource($_resource)->isStream()->isIdenticalTo($wrapper->getStream())->integer($offset)->isEqualTo($_offset)->integer($whence)->isEqualTo($_whence)->integer(ftell($wrapper->getStream())); } public function case_stream_seek_set() { return $this->_case_stream_seek_xxx(3, \SEEK_SET)->isEqualTo(3); } public function case_stream_seek_current() { return $this->_case_stream_seek_xxx(4, \SEEK_CUR)->isEqualTo(4); } public function case_stream_seek_end() { return $this->_case_stream_seek_xxx(-4, \SEEK_END)->isEqualTo(2); } public function case_stream_stat() { $this->given($this->function->fstat = function ($resource) use (&$_resource) { $_resource = $resource; return fstat($resource); }, $wrapper = new SUT(), $this->openFile($wrapper))->when($result = $wrapper->stream_stat())->then->array($result)->resource($_resource)->isStream()->isIdenticalTo($wrapper->getStream()); } public function case_stream_tell() { $this->given($this->function->ftell = function ($resource) use (&$_resource) { $_resource = $resource; return ftell($resource); }, $wrapper = new SUT(), $this->openFile($wrapper, 'foo'), $wrapper->stream_seek(2))->when($result = $wrapper->stream_tell())->then->integer($result)->isEqualTo(2)->resource($_resource)->isStream()->isIdenticalTo($wrapper->getStream()); } public function case_stream_truncate() { $this->given($this->function->ftruncate = function ($resource, $size) use (&$_resource, &$_size) { $_resource = $resource; $_size = $size; return ftruncate($resource, $size); }, $wrapper = new SUT(), $this->openFile($wrapper, 'foobar'), $size = 3)->when($result = $wrapper->stream_truncate($size))->then->boolean($result)->isTrue()->resource($_resource)->isStream()->isIdenticalTo($wrapper->getStream())->integer($size)->isEqualTo($_size)->integer($wrapper->stream_tell())->isEqualTo(0)->let($wrapper->stream_seek(0, \SEEK_END))->integer($wrapper->stream_tell())->isEqualTo(3); } public function case_stream_write() { $this->given($this->function->fwrite = function ($resource, $data) use (&$_resource, &$_data) { $_resource = $resource; $_data = $data; return fwrite($resource, $data); }, $wrapper = new SUT(), $wrapper->stream_open('hoa://Test/Vfs/Foo?type=file', 'wb+', \STREAM_USE_PATH, $openedPath), $data = 'foo')->when($result = $wrapper->stream_write($data))->then->integer($result)->isEqualTo(strlen($data))->resource($_resource)->isStream()->isIdenticalTo($wrapper->getStream())->string($_data)->isEqualTo($data)->let($wrapper->stream_seek(0))->string($wrapper->stream_read(3))->isEqualTo($data); } public function case_dir_closedir() { $this->given($wrapper = new SUT(), $this->openDirectory($wrapper))->when($result = $wrapper->dir_closedir())->then->variable($result)->isNull()->variable($wrapper->getStream())->isNull()->variable($wrapper->getStreamName())->isNull(); } public function case_dir_opendir() { $this->given($this->function->opendir = function ($path) use (&$_path) { $_path = $path; return opendir($path); }, $wrapper = new SUT(), $path = 'hoa://Test/Vfs/Bar?type=directory', $options = 0)->when($result = $wrapper->dir_opendir($path, $options))->then->boolean($result)->isTrue()->string(SUT::realPath($path, \true))->isEqualTo($_path)->resource($wrapper->getStream())->isStream()->string($wrapper->getStreamName())->isEqualTo('atoum://Bar'); } public function case_dir_opendir_not_a_resource() { $this->given($this->function->opendir = function ($path) use (&$_path) { $_path = $path; return \false; }, $wrapper = new SUT(), $path = 'hoa://Test/Vfs/Bar?type=directory', $options = 0)->when($result = $wrapper->dir_opendir($path, $options))->then->boolean($result)->isFalse()->string(SUT::realPath($path, \true))->isEqualTo($_path)->variable($wrapper->getStream())->isNull()->variable($wrapper->getStreamName())->isNull(); } public function case_dir_readdir() { $this->given($this->function->readdir = function ($resource) use (&$_resource) { $_resource = $resource; return readdir($resource); }, $wrapper = new SUT(), $this->openDirectory($wrapper, ['Baz', 'Qux']))->when($result = $wrapper->dir_readdir())->then->string($result)->isEqualTo('Baz')->resource($_resource)->isIdenticalTo($wrapper->getStream()); } public function case_dir_readdir_until_eod() { $this->given($this->function->readdir = function ($resource) use (&$_resource) { $_resource = $resource; return readdir($resource); }, $wrapper = new SUT(), $this->openDirectory($wrapper, ['Baz', 'Qux']))->when($result = $wrapper->dir_readdir())->then->string($result)->isEqualTo('Baz')->resource($_resource)->isIdenticalTo($wrapper->getStream())->when($result = $wrapper->dir_readdir())->then->string($result)->isEqualTo('Qux')->when($result = $wrapper->dir_readdir())->then->boolean($result)->isFalse(); } public function case_dir_rewinddir() { $this->given($this->function->rewinddir = function ($resource) use (&$_resource) { $_resource = $resource; return rewinddir($resource); }, $wrapper = new SUT(), $this->openDirectory($wrapper, ['Baz']), $wrapper->dir_readdir())->when($result = $wrapper->dir_rewinddir())->then->variable($result)->isNull()->when($result = $wrapper->dir_readdir())->then->string($result)->isEqualTo('Baz')->resource($_resource)->isIdenticalTo($wrapper->getStream()); } public function case_dir_mkdir() { $this->given($this->function->mkdir = function ($path, $mode, $options) use (&$_path, &$_mode, &$_options) { $_path = $path; $_mode = $mode; $_options = $options; return \true; }, $wrapper = new SUT(), $this->openDirectory($wrapper), $path = 'Baz', $mode = 0755, $options = \STREAM_MKDIR_RECURSIVE)->when($result = $wrapper->mkdir($path, $mode, $options))->then->boolean($result)->isTrue()->string($_path)->isEqualTo($path)->integer($_mode)->isEqualTo($_mode)->integer($_options)->isEqualTo($options | \STREAM_MKDIR_RECURSIVE); } public function case_rename() { $this->given($this->function->rename = function ($from, $to) use (&$_from, &$_to) { $_to = $to; $_from = $from; return rename($from, $to); }, $wrapper = new SUT(), $this->openFile($wrapper), $from = 'hoa://Test/Vfs/Foo?type=file', $to = 'hoa://Test/Vfs/Oof?type=file')->when($result = $wrapper->rename($from, $to))->then->boolean($result)->isTrue()->string($_from)->isEqualTo(SUT::realPath($from))->string($_to)->isEqualTo(SUT::realPath($_to, \false)); } public function case_rmdir() { $this->given($this->function->rmdir = function ($path) use (&$_path) { $_path = $path; return rmdir($path); }, $wrapper = new SUT(), $this->openDirectory($wrapper))->when($result = $wrapper->rmdir('hoa://Test/Vfs/Bar?type=directory', 0))->then->boolean($result)->isTrue(); } public function case_rmdir_a_file() { $this->given($wrapper = new SUT(), $this->openFile($wrapper))->when($result = $wrapper->rmdir('hoa://Test/Vfs/Foo?type=file', 0))->then->boolean($result)->isFalse(); } public function case_unlink() { $this->given($wrapper = new SUT(), $this->openFile($wrapper))->when($result = $wrapper->unlink('hoa://Test/Vfs/Foo?type=file'))->then->boolean($result)->isTrue(); } public function case_rmdir_a_directory() { $this->given($wrapper = new SUT(), $this->openDirectory($wrapper))->when($result = $wrapper->unlink('hoa://Test/Vfs/Bar?type=directory'))->then->boolean($result)->isFalse(); } public function case_url_stat() { $this->given($this->function->stat = function ($path) use (&$_path) { $_path = $path; return stat($path); }, $wrapper = new SUT(), $this->openFile($wrapper), $path = 'hoa://Test/Vfs/Foo?type=file')->when($result = $wrapper->url_stat($path, 0))->then->let($keys = ['dev', 'ino', 'mode', 'nlink', 'uid', 'gid', 'rdev', 'size', 'atime', 'mtime', 'ctime', 'blksize', 'blocks'])->array($result)->hasSize(26)->hasKeys($keys)->hasKeys(array_keys($keys))->string($_path)->isEqualTo(SUT::realPath($path)); } public function case_url_stat_not_hoa_protocol() { $this->given($wrapper = new SUT(), $path = LUT::NO_RESOLUTION)->when(function () use ($wrapper, $path) { $wrapper->url_stat($path, 0); })->then->error()->exists(); } protected function openFile(SUT $wrapper, $content = '') { $wrapper->stream_open('hoa://Test/Vfs/Foo?type=file', 'wb+', \STREAM_USE_PATH, $openedPath); fwrite($openedPath, $content, strlen($content)); fseek($openedPath, 0, \SEEK_SET); return $wrapper; } protected function openDirectory(SUT $wrapper, array $children = []) { $wrapper->dir_opendir('hoa://Test/Vfs/Bar?type=directory', 0); foreach ($children as $child) { resolve('hoa://Test/Vfs/Bar/' . $child . '?type=file'); } return $wrapper; } } resolve($path, $exists); } /** * Retrieve the underlying resource. * * @param int $castAs Can be STREAM_CAST_FOR_SELECT when * stream_select() is calling stream_cast() or * STREAM_CAST_AS_STREAM when stream_cast() is * called for other uses. * @return resource */ public function stream_cast($castAs) { return \false; } /** * Close a resource. * This method is called in response to fclose(). * All resources that were locked, or allocated, by the wrapper should be * released. * * @return void */ public function stream_close() { if (\true === @fclose($this->getStream())) { $this->_stream = null; $this->_streamName = null; } return; } /** * Tests for end-of-file on a file pointer. * This method is called in response to feof(). * * access public * @return bool */ public function stream_eof() { return feof($this->getStream()); } /** * Flush the output. * This method is called in respond to fflush(). * If we have cached data in our stream but not yet stored it into the * underlying storage, we should do so now. * * @return bool */ public function stream_flush() { return fflush($this->getStream()); } /** * Advisory file locking. * This method is called in response to flock(), when file_put_contents() * (when flags contains LOCK_EX), stream_set_blocking() and when closing the * stream (LOCK_UN). * * @param int $operation Operation is one the following: * * LOCK_SH to acquire a shared lock (reader) ; * * LOCK_EX to acquire an exclusive lock (writer) ; * * LOCK_UN to release a lock (shared or exclusive) ; * * LOCK_NB if we don't want flock() to * block while locking (not supported on * Windows). * @return bool */ public function stream_lock($operation) { return flock($this->getStream(), $operation); } /** * Change stream options. * This method is called to set metadata on the stream. It is called when * one of the following functions is called on a stream URL: touch, chmod, * chown or chgrp. * * @param string $path The file path or URL to set metadata. * @param int $option One of the following constant: * * STREAM_META_TOUCH, * * STREAM_META_OWNER_NAME, * * STREAM_META_OWNER, * * STREAM_META_GROUP_NAME, * * STREAM_META_GROUP, * * STREAM_META_ACCESS. * @param mixed $values Arguments of touch, chmod, chown and chgrp. * @return bool */ public function stream_metadata($path, $option, $values) { $path = static::realPath($path, \false); switch ($option) { case \STREAM_META_TOUCH: $arity = count($values); if (0 === $arity) { $out = touch($path); } elseif (1 === $arity) { $out = touch($path, $values[0]); } else { $out = touch($path, $values[0], $values[1]); } break; case \STREAM_META_OWNER_NAME: case \STREAM_META_OWNER: $out = chown($path, $values); break; case \STREAM_META_GROUP_NAME: case \STREAM_META_GROUP: $out = chgrp($path, $values); break; case \STREAM_META_ACCESS: $out = chmod($path, $values); break; default: $out = \false; } return $out; } /** * Open file or URL. * This method is called immediately after the wrapper is initialized (f.e. * by fopen() and file_get_contents()). * * @param string $path Specifies the URL that was passed to the * original function. * @param string $mode The mode used to open the file, as * detailed for fopen(). * @param int $options Holds additional flags set by the * streams API. It can hold one or more of * the following values OR'd together: * * STREAM_USE_PATH, if path is relative, * search for the resource using the * include_path; * * STREAM_REPORT_ERRORS, if this is * set, you are responsible for raising * errors using trigger_error during * opening the stream. If this is not * set, you should not raise any errors. * @param string &$openedPath If the $path is opened successfully, and * STREAM_USE_PATH is set in $options, * $openedPath should be set to the full * path of the file/resource that was * actually opened. * @return bool */ public function stream_open($path, $mode, $options, &$openedPath) { $path = static::realPath($path, 'r' === $mode[0]); if (\Hoa\Protocol\Protocol::NO_RESOLUTION === $path) { return \false; } if (null === $this->context) { $openedPath = fopen($path, $mode, $options & \STREAM_USE_PATH); } else { $openedPath = fopen($path, $mode, $options & \STREAM_USE_PATH, $this->context); } if (\false === is_resource($openedPath)) { return \false; } $this->_stream = $openedPath; $this->_streamName = $path; return \true; } /** * Read from stream. * This method is called in response to fread() and fgets(). * * @param int $count How many bytes of data from the current * position should be returned. * @return string */ public function stream_read($count) { return fread($this->getStream(), $count); } /** * Seek to specific location in a stream. * This method is called in response to fseek(). * The read/write position of the stream should be updated according to the * $offset and $whence. * * @param int $offset The stream offset to seek to. * @param int $whence Possible values: * * SEEK_SET to set position equal to $offset * bytes ; * * SEEK_CUR to set position to current * location plus $offsete ; * * SEEK_END to set position to end-of-file * plus $offset. * @return bool */ public function stream_seek($offset, $whence = \SEEK_SET) { return 0 === fseek($this->getStream(), $offset, $whence); } /** * Retrieve information about a file resource. * This method is called in response to fstat(). * * @return array */ public function stream_stat() { return fstat($this->getStream()); } /** * Retrieve the current position of a stream. * This method is called in response to ftell(). * * @return int */ public function stream_tell() { return ftell($this->getStream()); } /** * Truncate a stream to a given length. * * @param int $size Size. * @return bool */ public function stream_truncate($size) { return ftruncate($this->getStream(), $size); } /** * Write to stream. * This method is called in response to fwrite(). * * @param string $data Should be stored into the underlying stream. * @return int */ public function stream_write($data) { return fwrite($this->getStream(), $data); } /** * Close directory handle. * This method is called in to closedir(). * Any resources which were locked, or allocated, during opening and use of * the directory stream should be released. * * @return void */ public function dir_closedir() { closedir($this->getStream()); $this->_stream = null; $this->_streamName = null; return; } /** * Open directory handle. * This method is called in response to opendir(). * * @param string $path Specifies the URL that was passed to opendir(). * @param int $options Whether or not to enforce safe_mode (0x04). * It is not used here. * @return bool */ public function dir_opendir($path, $options) { $path = static::realPath($path); $handle = null; if (null === $this->context) { $handle = @opendir($path); } else { $handle = @opendir($path, $this->context); } if (\false === $handle) { return \false; } $this->_stream = $handle; $this->_streamName = $path; return \true; } /** * Read entry from directory handle. * This method is called in response to readdir(). * * @return mixed */ public function dir_readdir() { return readdir($this->getStream()); } /** * Rewind directory handle. * This method is called in response to rewinddir(). * Should reset the output generated by self::dir_readdir, i.e. the next * call to self::dir_readdir should return the first entry in the location * returned by self::dir_opendir. * * @return void */ public function dir_rewinddir() { return rewinddir($this->getStream()); } /** * Create a directory. * This method is called in response to mkdir(). * * @param string $path Directory which should be created. * @param int $mode The value passed to mkdir(). * @param int $options A bitwise mask of values. * @return bool */ public function mkdir($path, $mode, $options) { if (null === $this->context) { return mkdir(static::realPath($path, \false), $mode, $options | \STREAM_MKDIR_RECURSIVE); } return mkdir(static::realPath($path, \false), $mode, $options | \STREAM_MKDIR_RECURSIVE, $this->context); } /** * Rename a file or directory. * This method is called in response to rename(). * Should attempt to rename $from to $to. * * @param string $from The URL to current file. * @param string $to The URL which $from should be renamed to. * @return bool */ public function rename($from, $to) { if (null === $this->context) { return rename(static::realPath($from), static::realPath($to, \false)); } return rename(static::realPath($from), static::realPath($to, \false), $this->context); } /** * Remove a directory. * This method is called in response to rmdir(). * * @param string $path The directory URL which should be removed. * @param int $options A bitwise mask of values. It is not used * here. * @return bool */ public function rmdir($path, $options) { if (null === $this->context) { return rmdir(static::realPath($path)); } return rmdir(static::realPath($path), $this->context); } /** * Delete a file. * This method is called in response to unlink(). * * @param string $path The file URL which should be deleted. * @return bool */ public function unlink($path) { if (null === $this->context) { return unlink(static::realPath($path)); } return unlink(static::realPath($path), $this->context); } /** * Retrieve information about a file. * This method is called in response to all stat() related functions. * * @param string $path The file URL which should be retrieve * information about. * @param int $flags Holds additional flags set by the streams API. * It can hold one or more of the following * values OR'd together. * STREAM_URL_STAT_LINK: for resource with the * ability to link to other resource (such as an * HTTP location: forward, or a filesystem * symlink). This flag specified that only * information about the link itself should be * returned, not the resource pointed to by the * link. This flag is set in response to calls to * lstat(), is_link(), or filetype(). * STREAM_URL_STAT_QUIET: if this flag is set, * our wrapper should not raise any errors. If * this flag is not set, we are responsible for * reporting errors using the trigger_error() * function during stating of the path. * @return array */ public function url_stat($path, $flags) { $path = static::realPath($path); if (\Hoa\Protocol\Protocol::NO_RESOLUTION === $path) { if ($flags & \STREAM_URL_STAT_QUIET) { return 0; } else { return trigger_error('Path ' . $path . ' cannot be resolved.', \E_WARNING); } } if ($flags & \STREAM_URL_STAT_LINK) { return @lstat($path); } return @stat($path); } /** * Get stream resource. * * @return resource */ public function getStream() { return $this->_stream; } /** * Get stream name. * * @return resource */ public function getStreamName() { return $this->_streamName; } } /** * Register the `hoa://` protocol. */ stream_wrapper_register('hoa', \Hoa\Protocol\Wrapper::class); 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 .*?(?=(? nc %token nc:_named_capturing > -> default %token nc:capturing_name .+?(?=(?) %token non_capturing_ \(\?: %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 \\.|. // Rules. #expression: alternation() alternation: concatenation() ( ::alternation:: 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:: concatenation()? ( ::alternation:: concatenation()? )? ::_capturing:: assertion: ( ::lookahead_:: #lookahead | ::negative_lookahead_:: #negativelookahead | ::lookbehind_:: #lookbehind | ::negative_lookbehind_:: #negativelookbehind ) alternation() ::_capturing:: quantification: ( class() | simple() ) ( quantifier() #quantification )? quantifier: | | | | | | | | | | | | | | | #class: ( ::negative_class_:: #negativeclass | ::class_:: ) ( range() | literal() )+ ::_class:: #range: literal() ::range:: literal() simple: capturing() | literal() capturing: ::comment_:: ? ::_comment:: #comment | ( ::named_capturing_:: ::_named_capturing:: #namedcapturing | ::non_capturing_:: #noncapturing | ::non_capturing_reset_:: #noncapturingreset | ::atomic_group_:: #atomicgroup | ::capturing_:: ) alternation() ::_capturing:: literal: | | | | | _sampler = $sampler; return; } /** * Visit an element. * * @param \Hoa\Visitor\Element $element Element to visit. * @param mixed &$handle Handle (reference). * @param mixed $eldnah Handle (not reference). * @return mixed * @throws \Hoa\Regex\Exception */ public function visit(Visitor\Element $element, &$handle = null, $eldnah = null) { switch ($element->getId()) { case '#expression': case '#capturing': case '#noncapturing': case '#namedcapturing': return $element->getChild(0)->accept($this, $handle, $eldnah); case '#alternation': case '#class': return $element->getChild($this->_sampler->getInteger(0, $element->getChildrenNumber() - 1))->accept($this, $handle, $eldnah); case '#concatenation': $out = null; foreach ($element->getChildren() as $child) { $out .= $child->accept($this, $handle, $eldnah); } return $out; case '#quantification': $out = null; $xy = $element->getChild(1)->getValueValue(); $x = 0; $y = 0; switch ($element->getChild(1)->getValueToken()) { case 'zero_or_one': $y = 1; break; case 'zero_or_more': $y = mt_rand(5, 8); // why not? break; case 'one_or_more': $x = 1; $y = mt_rand(5, 8); // why not? break; case 'exactly_n': $x = $y = (int) substr($xy, 1, -1); break; case 'n_to_m': $xy = explode(',', substr($xy, 1, -1)); $x = (int) trim($xy[0]); $y = (int) trim($xy[1]); break; case 'n_or_more': $xy = explode(',', substr($xy, 1, -1)); $x = (int) trim($xy[0]); $y = mt_rand($x + 5, $x + 8); // why not? break; } for ($i = 0, $max = $this->_sampler->getInteger($x, $y); $i < $max; ++$i) { $out .= $element->getChild(0)->accept($this, $handle, $eldnah); } return $out; case '#negativeclass': $c = []; foreach ($element->getChildren() as $child) { $c[Ustring::toCode($child->accept($this, $handle, $eldnah))] = \true; } do { // all printable ASCII. $i = $this->_sampler->getInteger(32, 126); } while (isset($c[$i])); return Ustring::fromCode($i); case '#range': $out = null; $left = $element->getChild(0)->accept($this, $handle, $eldnah); $right = $element->getChild(1)->accept($this, $handle, $eldnah); return Ustring::fromCode($this->_sampler->getInteger(Ustring::toCode($left), Ustring::toCode($right))); case 'token': $value = $element->getValueValue(); switch ($element->getValueToken()) { case 'character': $value = ltrim($value, '\\'); switch ($value) { case 'a': return "\\a"; case 'e': return "\x1b"; case 'f': return "\f"; case 'n': return "\n"; case 'r': return "\r"; case 't': return "\t"; default: return Ustring::fromCode(intval(substr($value, 1))); } break; case 'dynamic_character': $value = ltrim($value, '\\'); switch ($value[0]) { case 'x': $value = trim($value, 'x{}'); return Ustring::fromCode(hexdec($value)); default: return Ustring::fromCode(octdec($value)); } break; case 'character_type': $value = ltrim($value, '\\'); if ('s' === $value) { $value = $this->_sampler->getInteger(0, 1) ? 'h' : 'v'; } switch ($value) { case 'C': return $this->_sampler->getInteger(0, 127); case 'd': return $this->_sampler->getInteger(0, 9); case 'h': $h = [Ustring::fromCode(0x9), Ustring::fromCode(0x20), Ustring::fromCode(0xa0)]; return $h[$this->_sampler->getInteger(0, count($h) - 1)]; case 'v': $v = [Ustring::fromCode(0xa), Ustring::fromCode(0xb), Ustring::fromCode(0xc), Ustring::fromCode(0xd)]; return $v[$this->_sampler->getInteger(0, count($v) - 1)]; case 'w': $w = array_merge(range(0x41, 0x5a), range(0x61, 0x7a), [0x5f]); return Ustring::fromCode($w[$this->_sampler->getInteger(0, count($w) - 1)]); default: return '?'; } break; case 'literal': if ('.' === $value) { $w = array_merge(range(0x41, 0x5a), range(0x61, 0x7a), [0x5f]); return Ustring::fromCode($w[$this->_sampler->getInteger(0, count($w) - 1)]); } return str_replace('\\\\', '\\', preg_replace('#\\\\(?!\\\\)#', '', $value)); } break; case '#internal_options': break; default: throw new Regex\Exception('Unsupported node: %s.', 0, $element->getId()); } return; } } setType($is); if (self::IS_A_BRIGADE === $this->getType()) { $this->setBrigade($brigade); } else { $this->setBucket(stream_bucket_new($brigade, $buffer)); $bucket = $this->getBucket(); $this->setBrigade($bucket); } return; } /** * Test the end-of-bucket. * When testing, set the new bucket object. * * @return bool */ public function eob() { $this->_bucket = null; return \false == $this->getBucket(); } /** * Append bucket to the brigade. * * @param \Hoa\Stream\Bucket $bucket Bucket to add. * @return void */ public function append(\Hoa\Stream\Bucket $bucket) { stream_bucket_append($this->getBrigade(), $bucket->getBucket()); return; } /** * Prepend bucket to the brigade. * * @param \Hoa\Stream\Bucket $bucket Bucket to add. * @return void */ public function prepend(\Hoa\Stream\Bucket $bucket) { stream_bucket_prepend($this->getBrigade(), $bucket->getBucket()); return; } /** * Set type. * * @param bool $type Type. Please, see self::IS_A_* constants. * @return bool */ protected function setType($type) { $old = $this->_type; $this->_type = $type; return $old; } /** * Get type. * * @return bool */ public function getType() { return $this->_type; } /** * Set bucket data. * * @param string $data Data to set. * @return string */ public function setData($data) { $old = $this->getBucket()->data; $this->getBucket()->data = $data; $this->getBucket()->datalen = strlen($this->getBucket()->data); return $old; } /** * Get bucket data. * * @return string */ public function getData() { if (null === $this->getBucket()) { return null; } return $this->getBucket()->data; } /** * Get bucket length. * * @return int */ public function getLength() { if (null === $this->getBucket()) { return 0; } return $this->getBucket()->datalen; } /** * Set the brigade. * * @param resource &$brigade Brigade to add. * @return resource */ protected function setBrigade(&$brigade) { $old = $this->_brigade; $this->_brigade = $brigade; return $old; } /** * Get the brigade. * * @return resource */ public function getBrigade() { return $this->_brigade; } /** * Set bucket. * * @param resource $bucket Bucket. * @return resource */ protected function setBucket($bucket) { $old = $this->_bucket; $this->_bucket = $bucket; return $old; } /** * Get the current bucket. * * @return mixed */ protected function getBucket() { if (null === $this->_bucket && self::IS_A_BRIGADE === $this->getType()) { $this->_bucket = stream_bucket_make_writeable($this->getBrigade()); } return $this->_bucket; } } _stream; $this->_stream = $stream; return $old; } /** * Get current stream. * * @return object */ public function getStream() { return $this->_stream; } /** * Set inner stream. * * @param \Hoa\Stream $innerStream Inner stream. * @return \Hoa\Stream */ protected function setInnerStream(\Hoa\Stream\Stream $innerStream) { $old = $this->_innerStream; $this->_innerStream = $innerStream; return $old; } /** * Get inner stream. * * @return \Hoa\Stream */ public function getInnerStream() { return $this->_innerStream; } } _id = $id; $this->_context = stream_context_create(); return; } /** * Multiton. * * @param string $id ID. * @return \Hoa\Stream\Context * @throws \Hoa\Stream\Exception */ public static function getInstance($id) { if (empty($id)) { throw new \Hoa\Stream\Exception('Context ID must not be null.', 0); } if (\false === static::contextExists($id)) { static::$_instances[$id] = new static($id); } return static::$_instances[$id]; } /** * Get context ID. * * @return string */ public function getId() { return $this->_id; } /** * Check if a context exists. * * @param string $id ID. * @return bool */ public static function contextExists($id) { return array_key_exists($id, static::$_instances); } /** * Set options. * Please, see http://php.net/context. * * @param array $options Options. * @return bool */ public function setOptions(array $options) { return stream_context_set_option($this->getContext(), $options); } /** * Set parameters. * Please, see http://php.net/context.params. * * @param array $parameters Parameters. * @return bool */ public function setParameters(array $parameters) { return stream_context_set_params($this->getContext(), $parameters); } /** * Get options. * * @return array */ public function getOptions() { return stream_context_get_options($this->getContext()); } /** * Get parameters. * . * @return array */ public function getParameters() { return stream_context_get_params($this->getContext()); } /** * Get context as a resource. * * @return resource */ public function getContext() { return $this->_context; } } eob()) { $consumed += $iBucket->getLength(); $oBucket->append($iBucket); } unset($iBucket); unset($oBucket); return self::PASS_ON; } /** * Called during instanciation of the filter class object. * * @return bool */ public function onCreate() { return \true; } /** * Called upon filter shutdown (typically, this is also during stream * shutdown), and is executed after the flush method is called. * * @return void */ public function onClose() { return; } /** * Set the filter name. * * @param string $name Filter name. * @return string */ public function setName($name) { $old = $this->filtername; $this->filtername = $name; return $old; } /** * Set the filter parameters. * * @param mixed $parameters Filter parameters. * @return mixed */ public function setParameters($parameters) { $old = $this->params; $this->params = $parameters; return $old; } /** * Get the filter name. * * @return string */ public function getName() { return $this->filtername; } /** * Get the filter parameters. * * @return mixed */ public function getParameters() { return $this->params; } /** * Get the stream resource being filtered. * Maybe available only during **filter** calls when the closing parameter * is set to false. * * @return resource */ public function getStream() { return isset($this->stream) ? $this->stream : null; } } getStream(); } if (null === $parameters) { return self::$_resources[$name] = stream_filter_append($stream, $name, $mode); } return self::$_resources[$name] = stream_filter_append($stream, $name, $mode, $parameters); } /** * Prepend a filter to the list of filters. * * @param mixed $stream Stream which received the filter. * Should be resource or an object * \Hoa\Stream. * @param string $name Filter name. * @param int $mode self::READ, self::WRITE or * self::READ_AND_WRITE. * @param mixed $parameters Parameters. * @return resource */ public static function prepend($stream, $name, $mode = self::READ, $parameters = null) { if ($stream instanceof Stream) { $stream = $stream->getStream(); } if (null === $parameters) { return self::$_resources[$name] = stream_filter_prepend($stream, $name, $mode); } return self::$_resources[$name] = stream_filter_prepend($stream, $name, $mode, $parameters); } /** * Delete a filter. * * @param mixed $streamFilter Stream filter resource or name. * @return bool * @throws \Hoa\Stream\Filter\Exception */ public static function remove($streamFilter) { if (!is_resource($streamFilter)) { if (isset(self::$_resources[$streamFilter])) { $streamFilter = self::$_resources[$streamFilter]; } else { throw new \Hoa\Stream\Filter\Exception('Cannot remove the stream filter %s because no resource was ' . 'found with this name.', 3, $streamFilter); } } return stream_filter_remove($streamFilter); } /** * Check if a filter is already registered or not. * * @param string $name Filter name. * @return bool */ public static function isRegistered($name) { return in_array($name, self::getRegistered()); } /** * Get all registered filer names. * * @return array */ public static function getRegistered() { return stream_get_filters(); } } /** * Flex entity. */ Consistency::flexEntity('Hoa\Stream\Filter\Filter'); eob()) { $this->_buffer .= $iBucket->getData(); $consumed += $iBucket->getLength(); } if (null !== $consumed) { $return = self::PASS_ON; } if (\true === $closing) { $stream = $this->getStream(); $this->compute(); $bucket = new Stream\Bucket($stream, Stream\Bucket::IS_A_STREAM, $this->_buffer); $oBucket = new Stream\Bucket($out); $oBucket->append($bucket); $return = self::PASS_ON; $this->_buffer = null; } return $return; } /** * Compute the whole data (stored in $this->_buffer). * * @return string */ abstract protected function compute(); } read(). * * @param int $length Length. * @return string */ public function readString($length); /** * Read a character. * It could be equivalent to $this->read(1). * * @return string */ public function readCharacter(); /** * Read a boolean. * * @return bool */ public function readBoolean(); /** * Read an integer. * * @param int $length Length. * @return int */ public function readInteger($length = 1); /** * Read a float. * * @param int $length Length. * @return float */ public function readFloat($length = 1); /** * Read an array. * In most cases, it could be an alias to the $this->scanf() method. * * @param mixed $argument Argument (because the behavior is very * different according to the implementation). * @return array */ public function readArray($argument = null); /** * Read a line. * * @return string */ public function readLine(); /** * Read all, i.e. read as much as possible. * * @param int $offset Offset. * @return string */ public function readAll($offset = 0); /** * Parse input from a stream according to a format. * * @param string $format Format (see printf's formats). * @return array */ public function scanf($format); } lock() to block while locking. * * @const int */ const LOCK_NO_BLOCK = \LOCK_NB; /** * Portable advisory locking. * Should take a look at stream_supports_lock(). * * @param int $operation Operation, use the self::LOCK_* constants. * @return bool */ public function lock($operation); } F. * * @param string $F Element F. * @return array */ public function selectChildElements($F = null); /** * Select an F element immediately preceded by an E element: E + F. * * @param string $F Element F. * @return \Hoa\Stream\IStream\Structural */ public function selectAdjacentSiblingElement($F); /** * Select F elements preceded by an E element: E ~ F. * * @param string $F Element F. * @return array */ public function selectSiblingElements($F = null); /** * Execute a query selector and return the first result. * * @param string $query Query. * @return \Hoa\Stream\IStream\Structural */ public function querySelector($query); /** * Execute a query selector and return one or many results. * * @param string $query Query. * @return array */ public function querySelectorAll($query); } _open()` method. Please, see the `self::_getStream()` method. * * @param string $streamName Stream name (e.g. path or URL). * @param string $context Context ID (please, see the * `Hoa\Stream\Context` class). * @param bool $wait Differ opening or not. */ public function __construct($streamName, $context = null, $wait = \false) { $this->_streamName = $streamName; $this->_context = $context; $this->_hasBeenDeferred = $wait; $this->setListener(new Event\Listener($this, ['authrequire', 'authresult', 'complete', 'connect', 'failure', 'mimetype', 'progress', 'redirect', 'resolve', 'size'])); if (\true === $wait) { return; } $this->open(); return; } /** * Get a stream in the register. * If the stream does not exist, try to open it by calling the * $handler->_open() method. * * @param string $streamName Stream name. * @param \Hoa\Stream $handler Stream handler. * @param string $context Context ID (please, see the * \Hoa\Stream\Context class). * @return array * @throws \Hoa\Stream\Exception */ private static function &_getStream($streamName, \Hoa\Stream\Stream $handler, $context = null) { $name = md5($streamName); if (null !== $context) { if (\false === \Hoa\Stream\Context::contextExists($context)) { throw new \Hoa\Stream\Exception('Context %s was not previously declared, cannot retrieve ' . 'this context.', 0, $context); } $context = \Hoa\Stream\Context::getInstance($context); } if (!isset(self::$_register[$name])) { self::$_register[$name] = [self::NAME => $streamName, self::HANDLER => $handler, self::RESOURCE => $handler->_open($streamName, $context), self::CONTEXT => $context]; Event::register('hoa://Event/Stream/' . $streamName, $handler); // Add :open-ready? Event::register('hoa://Event/Stream/' . $streamName . ':close-before', $handler); } else { $handler->_borrowing = \true; } if (null === self::$_register[$name][self::RESOURCE]) { self::$_register[$name][self::RESOURCE] = $handler->_open($streamName, $context); } return self::$_register[$name]; } /** * Open the stream and return the associated resource. * Note: This method is protected, but do not forget that it could be * overloaded into a public context. * * @param string $streamName Stream name (e.g. path or URL). * @param \Hoa\Stream\Context $context Context. * @return resource * @throws \Hoa\Exception\Exception */ abstract protected function &_open($streamName, ?\Hoa\Stream\Context $context = null); /** * Close the current stream. * Note: this method is protected, but do not forget that it could be * overloaded into a public context. * * @return bool */ abstract protected function _close(); /** * Open the stream. * * @return \Hoa\Stream * @throws \Hoa\Stream\Exception */ final public function open() { $context = $this->_context; if (\true === $this->hasBeenDeferred()) { if (null === $context) { $handle = \Hoa\Stream\Context::getInstance(uniqid()); $handle->setParameters(['notification' => [$this, '_notify']]); $context = $handle->getId(); } elseif (\true === \Hoa\Stream\Context::contextExists($context)) { $handle = \Hoa\Stream\Context::getInstance($context); $parameters = $handle->getParameters(); if (!isset($parameters['notification'])) { $handle->setParameters(['notification' => [$this, '_notify']]); } } } $this->_bufferSize = self::DEFAULT_BUFFER_SIZE; $this->_bucket = self::_getStream($this->_streamName, $this, $context); return $this; } /** * Close the current stream. * * @return void */ final public function close() { $streamName = $this->getStreamName(); $name = md5($streamName); if (!isset(self::$_register[$name])) { return; } Event::notify('hoa://Event/Stream/' . $streamName . ':close-before', $this, new Event\Bucket()); if (\false === $this->_close()) { return; } unset(self::$_register[$name]); $this->_bucket[self::HANDLER] = null; Event::unregister('hoa://Event/Stream/' . $streamName); Event::unregister('hoa://Event/Stream/' . $streamName . ':close-before'); return; } /** * Get the current stream name. * * @return string */ public function getStreamName() { if (empty($this->_bucket)) { return null; } return $this->_bucket[self::NAME]; } /** * Get the current stream. * * @return resource */ public function getStream() { if (empty($this->_bucket)) { return null; } return $this->_bucket[self::RESOURCE]; } /** * Get the current stream context. * * @return \Hoa\Stream\Context */ public function getStreamContext() { if (empty($this->_bucket)) { return null; } return $this->_bucket[self::CONTEXT]; } /** * Get stream handler according to its name. * * @param string $streamName Stream name. * @return \Hoa\Stream */ public static function getStreamHandler($streamName) { $name = md5($streamName); if (!isset(self::$_register[$name])) { return null; } return self::$_register[$name][self::HANDLER]; } /** * Set the current stream. Useful to manage a stack of streams (e.g. socket * and select). Notice that it could be unsafe to use this method without * taking time to think about it two minutes. Resource of type “Unknown” is * considered as valid. * * @return resource * @throws \Hoa\Stream\Exception */ public function _setStream($stream) { if (\false === is_resource($stream) && ('resource' !== gettype($stream) || 'Unknown' !== get_resource_type($stream))) { throw new \Hoa\Stream\Exception('Try to change the stream resource with an invalid one; ' . 'given %s.', 1, gettype($stream)); } $old = $this->_bucket[self::RESOURCE]; $this->_bucket[self::RESOURCE] = $stream; return $old; } /** * Check if the stream is opened. * * @return bool */ public function isOpened() { return is_resource($this->getStream()); } /** * Set the timeout period. * * @param int $seconds Timeout period in seconds. * @param int $microseconds Timeout period in microseconds. * @return bool */ public function setStreamTimeout($seconds, $microseconds = 0) { return stream_set_timeout($this->getStream(), $seconds, $microseconds); } /** * Whether the opening of the stream has been deferred */ protected function hasBeenDeferred() { return $this->_hasBeenDeferred; } /** * Check whether the connection has timed out or not. * This is basically a shortcut of `getStreamMetaData` + the `timed_out` * index, but the resulting code is more readable. * * @return bool */ public function hasTimedOut() { $metaData = $this->getStreamMetaData(); return \true === $metaData['timed_out']; } /** * Set blocking/non-blocking mode. * * @param bool $mode Blocking mode. * @return bool */ public function setStreamBlocking($mode) { return stream_set_blocking($this->getStream(), (int) $mode); } /** * Set stream buffer. * Output using fwrite() (or similar function) is normally buffered at 8 Ko. * This means that if there are two processes wanting to write to the same * output stream, each is paused after 8 Ko of data to allow the other to * write. * * @param int $buffer Number of bytes to buffer. If zero, write * operations are unbuffered. This ensures that * all writes are completed before other * processes are allowed to write to that output * stream. * @return bool */ public function setStreamBuffer($buffer) { // Zero means success. $out = 0 === stream_set_write_buffer($this->getStream(), $buffer); if (\true === $out) { $this->_bufferSize = $buffer; } return $out; } /** * Disable stream buffering. * Alias of $this->setBuffer(0). * * @return bool */ public function disableStreamBuffer() { return $this->setStreamBuffer(0); } /** * Get stream buffer size. * * @return int */ public function getStreamBufferSize() { return $this->_bufferSize; } /** * Get stream wrapper name. * * @return string */ public function getStreamWrapperName() { if (\false === $pos = strpos($this->getStreamName(), '://')) { return 'file'; } return substr($this->getStreamName(), 0, $pos); } /** * Get stream meta data. * * @return array */ public function getStreamMetaData() { return stream_get_meta_data($this->getStream()); } /** * Whether this stream is already opened by another handler. * * @return bool */ public function isBorrowing() { return $this->_borrowing; } /** * Notification callback. * * @param int $ncode Notification code. Please, see * STREAM_NOTIFY_* constants. * @param int $severity Severity. Please, see * STREAM_NOTIFY_SEVERITY_* constants. * @param string $message Message. * @param int $code Message code. * @param int $transferred If applicable, the number of transferred * bytes. * @param int $max If applicable, the number of max bytes. * @return void */ public function _notify($ncode, $severity, $message, $code, $transferred, $max) { static $_map = [\STREAM_NOTIFY_AUTH_REQUIRED => 'authrequire', \STREAM_NOTIFY_AUTH_RESULT => 'authresult', \STREAM_NOTIFY_COMPLETED => 'complete', \STREAM_NOTIFY_CONNECT => 'connect', \STREAM_NOTIFY_FAILURE => 'failure', \STREAM_NOTIFY_MIME_TYPE_IS => 'mimetype', \STREAM_NOTIFY_PROGRESS => 'progress', \STREAM_NOTIFY_REDIRECTED => 'redirect', \STREAM_NOTIFY_RESOLVE => 'resolve', \STREAM_NOTIFY_FILE_SIZE_IS => 'size']; $this->getListener()->fire($_map[$ncode], new Event\Bucket(['code' => $code, 'severity' => $severity, 'message' => $message, 'transferred' => $transferred, 'max' => $max])); return; } /** * Call the $handler->close() method on each stream in the static stream * register. * This method does not check the return value of $handler->close(). Thus, * if a stream is persistent, the $handler->close() should do anything. It * is a very generic method. * * @return void */ final public static function _Hoa_Stream() { foreach (self::$_register as $entry) { $entry[self::HANDLER]->close(); } return; } /** * Transform object to string. * * @return string */ public function __toString() { return $this->getStreamName(); } /** * Close the stream when destructing. * * @return void */ public function __destruct() { if (\false === $this->isOpened()) { return; } $this->close(); return; } } /** * Class \Hoa\Stream\_Protocol. * * The `hoa://Library/Stream` node. * * @copyright Copyright © 2007-2017 Hoa community * @license New BSD License */ class _Protocol extends Protocol\Node { /** * Component's name. * * @var string */ protected $_name = 'Stream'; /** * ID of the component. * * @param string $id ID of the component. * @return mixed */ public function reachId($id) { return \Hoa\Stream\Stream::getStreamHandler($id); } } /** * Flex entity. */ Consistency::flexEntity('Hoa\Stream\Stream'); /** * Add the `hoa://Library/Stream` node. Should be use to reach/get an entry * in the stream register. */ $protocol = Protocol::getInstance(); $protocol['Library'][] = new \Hoa\Stream\_Protocol(); Hello, World! given($filename = 'hoa://Test/Vfs/Foo?type=file', $content = 'Hello, World!', file_put_contents($filename, $content), $stream = fopen($filename, 'r'), $name = 'string.toupper')->when(SUT::append($stream, $name), $result = stream_get_contents($stream))->then->string($result)->isEqualTo(strtoupper($content)); } public function case_prepend() { $this->given($filename = 'hoa://Test/Vfs/Foo?type=file', $content = 'Hello, World!', file_put_contents($filename, $content), $stream = fopen($filename, 'r'), $name = 'string.toupper')->when(SUT::prepend($stream, $name), $result = stream_get_contents($stream))->then->string($result)->isEqualTo(strtoupper($content)); } public function case_append_append() { $this->given($filename = 'hoa://Test/Vfs/Foo?type=file', $content = 'Hello, World!', file_put_contents($filename, $content), $stream = fopen($filename, 'r'), $name1 = 'string.toupper', $name2 = 'string.tolower')->when(SUT::append($stream, $name1), SUT::append($stream, $name2), $result = stream_get_contents($stream))->then->string($result)->isEqualTo(strtolower($content)); } public function case_append_prepend() { $this->given($filename = 'hoa://Test/Vfs/Foo?type=file', $content = 'Hello, World!', file_put_contents($filename, $content), $stream = fopen($filename, 'r'), $name1 = 'string.toupper', $name2 = 'string.tolower')->when(SUT::append($stream, $name1), SUT::prepend($stream, $name2), $result = stream_get_contents($stream))->then->string($result)->isEqualTo(strtoupper($content)); } public function case_prepend_prepend() { $this->given($filename = 'hoa://Test/Vfs/Foo?type=file', $content = 'Hello, World!', file_put_contents($filename, $content), $stream = fopen($filename, 'r'), $name1 = 'string.toupper', $name2 = 'string.tolower')->when(SUT::prepend($stream, $name1), SUT::prepend($stream, $name2), $result = stream_get_contents($stream))->then->string($result)->isEqualTo(strtoupper($content)); } public function case_append_1000_filters() { $this->given($filename = 'hoa://Test/Vfs/Foo?type=file', $content = 'Hello, World!', file_put_contents($filename, $content), $stream = fopen($filename, 'r'), $name = 'string.toupper')->when(function () use ($stream, $name) { for ($i = 1000; $i >= 0; --$i) { $this->resource(SUT::prepend($stream, $name)); } })->when($result = stream_get_contents($stream))->then->string($result)->isEqualTo(strtoupper($content)); } } given($name = 'custom', SUT::register($name, \Hoa\Stream\Test\Integration\Filter\CustomFilter::class), $filename = 'hoa://Test/Vfs/Foo?type=file', $content = 'Hello, World!', file_put_contents($filename, $content), $stream = fopen($filename, 'r'))->when(SUT::append($stream, $name), $result = stream_get_contents($stream))->then->string($result)->isEqualTo(strtolower($content) . ' ' . strlen($content)); } } class CustomFilter extends LUT\Filter\LateComputed { protected function compute() { $this->_buffer = strtolower($this->_buffer) . ' ' . strlen($this->_buffer); // proof that the buffer contains all the data return; } } given($port = mt_rand(10000, 12000), exec(sprintf('php -S 127.0.0.1:%d -t %s > /dev/null 2>&1 & echo $! && sleep 0.2', $port, dirname(__DIR__) . DS . 'Fixtures'), $outputs), $pid = $outputs[0], $stream = new \Hoa\Stream\Test\Integration\SUT('http://127.0.0.1:' . $port, null, \true), $stream->on('connect', function (Event\Bucket $bucket) use ($self, &$connectCalled) { $connectCalled = \true; $data = $bucket->getData(); $self->array($data)->isEqualTo(['code' => 0, 'severity' => 0, 'message' => null, 'transferred' => 0, 'max' => 0]); }), $stream->on('mimetype', function (Event\Bucket $bucket) use ($self, &$mimetypeCalled) { $mimetypeCalled = \true; $data = $bucket->getData(); $self->array($data)->isEqualTo(['code' => 0, 'severity' => 0, 'message' => 'text/html; charset=UTF-8', 'transferred' => 0, 'max' => 0]); }), $stream->on('size', function (Event\Bucket $bucket) use ($self, &$sizeCalled) { $sizeCalled = \true; $data = $bucket->getData(); $self->array($data)->isEqualTo(['code' => 0, 'severity' => 0, 'message' => 'Content-Length: 14', 'transferred' => 0, 'max' => 14]); }), $stream->on('progress', function (Event\Bucket $bucket) use ($self, &$progressCalled) { $progressCalled = \true; $data = $bucket->getData(); $self->array($data)->isEqualTo(['code' => 0, 'severity' => 0, 'message' => null, 'transferred' => 0, 'max' => 14]); }))->when($stream->open())->then->boolean($connectCalled)->isTrue()->boolean($mimetypeCalled)->isTrue()->boolean($sizeCalled)->isTrue()->boolean($progressCalled)->isTrue()->let(!empty($pid) && exec('kill ' . $pid)); } } class SUT extends LUT\Stream { protected function &_open($streamName, LUT\Context $context = null) { if (null === $context) { $out = fopen($streamName, 'rb'); } else { $out = fopen($streamName, 'rb', \false, $context->getContext()); } return $out; } protected function _close() { return fclose($this->getStream()); } } boolean(SUT::IS_A_BRIGADE)->isTrue()->boolean(SUT::IS_A_STREAM)->isFalse(); } public function case_construct_a_brigade() { $this->given($brigade = 'foo')->when($result = new SUT($brigade, SUT::IS_A_BRIGADE))->then->boolean($result->getType())->isEqualTo(SUT::IS_A_BRIGADE)->variable($result->getBrigade())->isIdenticalTo($brigade)->isIdenticalTo('foo'); } public function case_construct_a_stream() { $this->given($stream = fopen(__FILE__, 'r'), $buffer = 'bar')->when($result = new SUT($stream, SUT::IS_A_STREAM, $buffer))->then->boolean($result->getType())->isEqualTo(SUT::IS_A_STREAM)->let($bucket = $this->invoke($result)->getBucket())->object($bucket)->isInstanceOf(\StdClass::class)->resource($bucket->bucket)->string($bucket->data)->isEqualTo($buffer)->integer($bucket->datalen)->isEqualTo(strlen($buffer))->object($result->getBrigade())->isIdenticalTo($bucket); } public function case_eob() { $this->given($stream = fopen(__FILE__, 'r'), $bucket = new SUT($stream, SUT::IS_A_STREAM))->when($result = $bucket->eob())->then->boolean($result)->isTrue(); } public function case_set_data() { $this->given($stream = fopen(__FILE__, 'r'), $oldBuffer = 'bar', $bucket = new SUT($stream, SUT::IS_A_STREAM, $oldBuffer), $buffer = 'bazqux')->when($result = $bucket->setData('bazqux'))->then->string($result)->isEqualTo($oldBuffer)->let($_bucket = $this->invoke($bucket)->getBucket())->object($_bucket)->isInstanceOf(\StdClass::class)->resource($_bucket->bucket)->string($_bucket->data)->isEqualTo($buffer)->integer($_bucket->datalen)->isEqualTo(strlen($buffer))->object($bucket->getBrigade())->isIdenticalTo($_bucket); } public function case_get_data() { $this->given($stream = fopen(__FILE__, 'r'), $buffer = 'bar', $bucket = new SUT($stream, SUT::IS_A_STREAM, $buffer))->when($result = $bucket->getData())->then->string($result)->isEqualTo($buffer)->isEqualTo($this->invoke($bucket)->getBucket()->data); } public function case_get_length() { $this->given($stream = fopen(__FILE__, 'r'), $buffer = 'bar', $bucket = new SUT($stream, SUT::IS_A_STREAM, $buffer))->when($result = $bucket->getLength())->then->integer($result)->isEqualTo(strlen($buffer))->isEqualTo($this->invoke($bucket)->getBucket()->datalen); } } given($stream = new \StdClass(), $composite = new SUT())->when($result = $this->invoke($composite)->setStream($stream))->then->variable($result)->isNull(); } public function case_get_stream() { $this->given($stream = new \StdClass(), $composite = new SUT(), $this->invoke($composite)->setStream($stream))->when($result = $composite->getStream())->then->object($result)->isIdenticalTo($stream); } public function case_set_inner_stream() { $this->given($innerStream = new \Mock\Hoa\Stream(__FILE__), $composite = new SUT())->when($result = $this->invoke($composite)->setInnerStream($innerStream))->then->variable($result)->isNull(); } public function case_get_inner_stream() { $this->given($innerStream = new \Mock\Hoa\Stream(__FILE__), $composite = new SUT(), $this->invoke($composite)->setInnerStream($innerStream))->when($result = $composite->getInnerStream())->then->object($result)->isIdenticalTo($innerStream); } } exception(function () { SUT::getInstance(null); })->isInstanceOf(LUT\Exception::class); } public function case_get_new_instance() { $this->when($result = SUT::getInstance('foo'))->then->object($result)->isInstanceOf(SUT::class); } public function case_get_new_instances() { $this->when($result = SUT::getInstance('foo'))->then->object($result)->isNotIdenticalTo(SUT::getInstance('bar')); } public function case_get_same_instance() { $this->when($result = SUT::getInstance('foo'))->then->object($result)->isIdenticalTo(SUT::getInstance('foo')); } public function case_get_id() { $this->given($id = 'foo', $context = SUT::getInstance($id))->when($result = $context->getId())->then->string($result)->isEqualTo($id); } public function case_context_exists() { $this->given($id = 'foo', SUT::getInstance($id))->when($result = SUT::contextExists($id))->then->boolean($result)->isTrue(); } public function case_context_does_not_exist() { $this->when($result = SUT::contextExists('foo'))->then->boolean($result)->isFalse(); } public function case_set_options() { $this->given($context = SUT::getInstance('foo'), $options = ['bar' => ['baz' => 'qux']])->when($result = $context->setOptions($options))->then->boolean($result)->isTrue(); } public function case_get_options() { $this->given($context = SUT::getInstance('foo'), $options = ['bar' => ['baz' => 'qux']], $context->setOptions($options))->when($result = $context->getOptions())->then->array($result)->isEqualTo($options); } public function case_set_parameters() { $this->given($context = SUT::getInstance('foo'), $parameters = ['notificaion' => 'callback', 'options' => ['bar' => ['baz' => 'qux']]])->when($result = $context->setParameters($parameters))->then->boolean($result)->isTrue(); } public function case_get_parameters() { $this->given($context = SUT::getInstance('foo'), $parameters = ['notification' => 'callback', 'options' => ['bar' => ['baz' => 'qux']]], $context->setParameters($parameters))->when($result = $context->getParameters())->then->array($result)->isEqualTo($parameters); } public function case_get_context() { $this->given($context = SUT::getInstance('foo'))->when($result = $context->getContext())->then->resource($result)->isStreamContext(); } } when($result = new SUT('foo', 0))->then->object($result)->isInstanceOf(HoaException::class); } } integer(SUT::PASS_ON)->isEqualTo(\PSFS_PASS_ON)->integer(SUT::FEED_ME)->isEqualTo(\PSFS_FEED_ME)->integer(SUT::FATAL_ERROR)->isEqualTo(\PSFS_ERR_FATAL)->integer(SUT::FLAG_NORMAL)->isEqualTo(\PSFS_FLAG_NORMAL)->integer(SUT::FLAG_FLUSH_INC)->isEqualTo(\PSFS_FLAG_FLUSH_INC)->integer(SUT::FLAG_FLUSH_CLOSE)->isEqualTo(\PSFS_FLAG_FLUSH_CLOSE); } public function case_is_a_php_filter() { $this->when($result = new SUT())->then->object($result)->isInstanceOf(\php_user_filter::class); } public function case_interfaces() { $this->when($result = new SUT())->then->object($result)->isInstanceOf(LUT\IStream\Stream::class); } public function case_set_name() { $this->given($filter = new SUT())->when($result = $filter->setName('foo'))->then->string($result)->isEqualTo(''); } public function case_get_name() { $this->given($filter = new SUT(), $name = 'foo', $filter->setName($name))->when($result = $filter->getName())->then->string($result)->isEqualTo($name); } public function case_set_parameters() { $this->given($filter = new SUT())->when($result = $filter->setParameters(['foo', 'bar', 'baz']))->then->string($result)->isEqualTo(''); } public function case_get_parameters() { $this->given($filter = new SUT(), $parameters = ['foo', 'bar', 'baz'], $filter->setParameters($parameters))->when($result = $filter->getParameters())->then->array($result)->isEqualTo($parameters); } public function case_get_stream() { $this->given($filter = new SUT())->when($result = $filter->getStream())->then->variable($result)->isNull(); // Only available when filtering, so `null` is valid. } } when($result = new SUT('foo', 0))->then->object($result)->isInstanceOf(LUT\Exception::class); } } boolean(SUT::OVERWRITE)->isTrue()->boolean(SUT::DO_NOT_OVERWRITE)->isFalse()->integer(SUT::READ)->isEqualTo(\STREAM_FILTER_READ)->integer(SUT::WRITE)->isEqualTo(\STREAM_FILTER_WRITE)->integer(SUT::READ_AND_WRITE)->isEqualTo(\STREAM_FILTER_ALL); } public function case_register() { $this->when($result = SUT::register('foo', \StdClass::class))->then->boolean($result)->isTrue(); } public function case_register_already_registered_do_not_overwrite() { $this->given($name = 'foo', $class = \StdClass::class, SUT::register($name, $class))->exception(function () use ($name, $class) { SUT::register($name, $class); })->isInstanceOf(LUT\Filter\Exception::class)->hasMessage('Filter foo is already registered.'); } public function case_register_already_registered_do_overwrite() { $this->given($name = 'foo', SUT::register($name, \StdClass::class), new \_PHPStan_33c983f26\Mock\StdClass())->when($result = SUT::register($name, \_PHPStan_33c983f26\Mock\StdClass::class, SUT::OVERWRITE))->then->boolean($result)->isFalse(); } public function case_register_empty_name() { $this->exception(function () { SUT::register('', \StdClass::class); })->isInstanceOf(LUT\Filter\Exception::class)->hasMessage('Filter name cannot be empty ' . '(implementation class is StdClass).'); } public function case_register_unknown_class() { $this->exception(function () { SUT::register('foo', '42Foo'); })->isInstanceOf(LUT\Filter\Exception::class)->hasMessage('Cannot register the 42Foo class for the filter foo ' . 'because it does not exist.'); } public function case_append() { $this->given($stream = fopen('hoa://Test/Vfs/Foo?type=file', 'r'), $name = 'string.toupper')->when($result = SUT::append($stream, $name))->then->resource($result)->isStreamFilter(); } public function case_prepend() { $this->given($stream = fopen('hoa://Test/Vfs/Foo?type=file', 'r'), $name = 'string.toupper')->when($result = SUT::prepend($stream, $name))->then->resource($result)->isStreamFilter(); } public function case_remove() { $this->given($stream = fopen('hoa://Test/Vfs/Foo?type=file', 'r'), $name = 'string.toupper', $filter = SUT::append($stream, $name))->when($result = SUT::remove($filter))->then->boolean($result)->isTrue(); } public function case_remove_by_name() { $this->given($stream = fopen('hoa://Test/Vfs/Foo?type=file', 'r'), $name = 'string.toupper', $filter = SUT::append($stream, $name))->when($result = SUT::remove($name))->then->boolean($result)->isTrue(); } public function case_remove_unknown() { $this->exception(function () { SUT::remove('foo'); })->isInstanceOf(LUT\Filter\Exception::class)->hasMessage('Cannot remove the stream filter foo ' . 'because no resource was found with this name.'); } public function case_is_registered() { $this->when($result = SUT::isRegistered('string.toupper'))->then->boolean($result)->isTrue(); } public function case_is_not_registered() { $this->when($result = SUT::isRegistered('foo'))->then->boolean($result)->isFalse(); } public function case_get_registered() { $this->when($result = SUT::getRegistered())->then->array($result)->containsValues(['string.rot13', 'string.toupper', 'string.tolower', 'string.strip_tags', 'consumed', 'dechunk']); } } when($result = new \Mock\Hoa\Stream\IStream\Bufferable())->then->object($result)->isInstanceOf(SUT::class)->isInstanceOf(LUT\IStream\Stream::class); } } when($result = new \Mock\Hoa\Stream\IStream\In())->then->object($result)->isInstanceOf(SUT::class)->isInstanceOf(LUT\IStream\Stream::class); } } when($result = new \Mock\Hoa\Stream\IStream\Lockable())->then->object($result)->isInstanceOf(SUT::class)->isInstanceOf(LUT\IStream\Stream::class); } public function case_constants() { $this->when($result = SUT::LOCK_SHARED)->then->integer($result)->isEqualTo(\LOCK_SH)->when($result = SUT::LOCK_EXCLUSIVE)->then->integer($result)->isEqualTo(\LOCK_EX)->when($result = SUT::LOCK_RELEASE)->then->integer($result)->isEqualTo(\LOCK_UN)->when($result = SUT::LOCK_NO_BLOCK)->then->integer($result)->isEqualTo(\LOCK_NB); } } when($result = new \Mock\Hoa\Stream\IStream\Out())->then->object($result)->isInstanceOf(SUT::class)->isInstanceOf(LUT\IStream\Stream::class); } } when($result = new \Mock\Hoa\Stream\IStream\Pathable())->then->object($result)->isInstanceOf(SUT::class)->isInstanceOf(LUT\IStream\Stream::class); } } when($result = new \Mock\Hoa\Stream\IStream\Pointable())->then->object($result)->isInstanceOf(SUT::class)->isInstanceOf(LUT\IStream\Stream::class); } public function case_constants() { $this->when($result = SUT::SEEK_SET)->then->integer($result)->isEqualTo(\SEEK_SET)->when($result = SUT::SEEK_CURRENT)->then->integer($result)->isEqualTo(\SEEK_CUR)->when($result = SUT::SEEK_END)->then->integer($result)->isEqualTo(\SEEK_END); } } when($result = new \Mock\Hoa\Stream\IStream\Statable())->then->object($result)->isInstanceOf(SUT::class)->isInstanceOf(LUT\IStream\Stream::class); } public function case_constants() { $this->when($result = SUT::SIZE_UNDEFINED)->then->integer($result)->isEqualTo(-1); } } when($result = new \Mock\Hoa\Stream\IStream\Stream())->then->object($result)->isInstanceOf(SUT::class); } } when($result = new \Mock\Hoa\Stream\IStream\Structural())->then->object($result)->isInstanceOf(SUT::class)->isInstanceOf(LUT\IStream\Stream::class); } } when($result = new \Mock\Hoa\Stream\IStream\Touchable())->then->object($result)->isInstanceOf(SUT::class)->isInstanceOf(LUT\IStream\Stream::class); } public function case_constants() { $this->when($result = SUT::OVERWRITE)->then->boolean($result)->isEqualTo(\true)->when($result = SUT::DO_NOT_OVERWRITE)->then->boolean($result)->isEqualTo(\false)->when($result = SUT::MAKE_DIRECTORY)->then->boolean($result)->isEqualTo(\true)->when($result = SUT::DO_NOT_MAKE_DIRECTORY)->then->boolean($result)->isEqualTo(\false); } } when($result = new \Hoa\Stream\Test\Unit\SUT(__FILE__))->then->object($result)->isInstanceOf(LUT\IStream\Stream::class)->isInstanceOf(Event\Listenable::class); } public function case_constants() { $this->integer(\Hoa\Stream\Test\Unit\SUT::NAME)->isEqualTo(0)->integer(\Hoa\Stream\Test\Unit\SUT::HANDLER)->isEqualTo(1)->integer(\Hoa\Stream\Test\Unit\SUT::RESOURCE)->isEqualTo(2)->integer(\Hoa\Stream\Test\Unit\SUT::CONTEXT)->isEqualTo(3); } public function case_construct() { $this->given($name = __FILE__)->when($result = new \Hoa\Stream\Test\Unit\SUT($name))->then->string($result->getStreamName())->isEqualTo($name)->boolean($this->invoke($result)->hasBeenDeferred())->isFalse()->let($listener = $this->invoke($result)->getListener())->object($listener)->isInstanceOf(Event\Listener::class)->boolean($listener->listenerExists('authrequire'))->isTrue()->boolean($listener->listenerExists('authresult'))->isTrue()->boolean($listener->listenerExists('complete'))->isTrue()->boolean($listener->listenerExists('connect'))->isTrue()->boolean($listener->listenerExists('failure'))->isTrue()->boolean($listener->listenerExists('mimetype'))->isTrue()->boolean($listener->listenerExists('progress'))->isTrue()->boolean($listener->listenerExists('redirect'))->isTrue()->boolean($listener->listenerExists('resolve'))->isTrue()->boolean($listener->listenerExists('size'))->isTrue()->boolean(Event::eventExists('hoa://Event/Stream/' . $name))->isTrue()->boolean(Event::eventExists('hoa://Event/Stream/' . $name . ':close-before'))->isTrue(); } public function case_construct_with_a_context() { $this->given($name = __FILE__, $contextName = 'foo', LUT\Context::getInstance($contextName))->when($result = new \Hoa\Stream\Test\Unit\SUT($name, $contextName))->then->string($result->getStreamName())->isEqualTo($name)->boolean($this->invoke($result)->hasBeenDeferred())->isFalse()->object($this->invoke($result)->getListener())->isInstanceOf(Event\Listener::class); } public function case_construct_with_deferred_opening() { $this->given($name = __FILE__)->when($result = new \Hoa\Stream\Test\Unit\SUT($name, null, \true))->then->boolean($this->invoke($result)->hasBeenDeferred())->isTrue()->boolean($result->isOpened())->isFalse()->variable($result->getStreamName())->isNull(); } public function case_open() { $this->given($name = __FILE__, $stream = new \Hoa\Stream\Test\Unit\SUT($name, null, \true))->when($result = $stream->open())->then->object($result)->isIdenticalTo($stream)->boolean($this->invoke($result)->hasBeenDeferred())->isTrue()->boolean($result->isOpened())->isTrue()->string($result->getStreamName())->isEqualTo($name)->integer($result->getStreamBufferSize())->isEqualTo(\Hoa\Stream\Test\Unit\SUT::DEFAULT_BUFFER_SIZE); } public function case_close() { $this->given($name = __FILE__, $stream = new \Hoa\Stream\Test\Unit\SUT($name), $resource = $stream->getStream(), $context = $stream->getStreamContext())->when($result = $stream->close())->then->variable($result)->isNull()->boolean($stream->isOpened())->isFalse()->variable(\Hoa\Stream\Test\Unit\SUT::getStreamHandler($stream))->isNull()->variable($stream->getStreamName())->isEqualTo($name)->variable($stream->getStream())->isEqualTo($resource)->variable($stream->getStreamContext())->isEqualTo($context)->boolean(Event::eventExists('hoa://Event/Stream/' . $name))->isFalse()->boolean(Event::eventExists('hoa://Event/Stream/' . $name . ':close-before'))->isFalse(); } public function case_close_more_than_once() { $this->given($name = __FILE__, $stream = new \Hoa\Stream\Test\Unit\SUT($name), $close1 = $stream->close())->when($result = $stream->close())->then->variable($result)->isIdenticalTo($close1); } public function case_open_close_open() { $this->given($name = __FILE__, $stream = new \Hoa\Stream\Test\Unit\SUT($name, null, \true), $stream->open(), $resource = $stream->getStream(), $context = $stream->getStreamContext(), $handler = \Hoa\Stream\Test\Unit\SUT::getStreamHandler($stream), $this->function->stream_set_write_buffer = 0, $stream->setStreamBuffer(42), $stream->close())->when($result = $stream->open())->then->string($result->getStreamName())->isEqualTo($name)->resource($result->getStream())->isNotEqualTo($resource)->object($handler)->isIdenticalTo($result)->object($this->invoke($stream)->getListener())->isInstanceOf(Event\Listener::class)->boolean(Event::eventExists('hoa://Event/Stream/' . $name))->isTrue()->boolean(Event::eventExists('hoa://Event/Stream/' . $name . ':close-before'))->isTrue()->integer($stream->getStreamBufferSize())->isEqualTo(\Hoa\Stream\Test\Unit\SUT::DEFAULT_BUFFER_SIZE); } public function case_close_event_close_before() { $self = $this; $this->given($name = 'hoa://Test/Vfs/Foo?type=file', $stream = new \Hoa\Stream\Test\Unit\SUT($name), Event::getEvent('hoa://Event/Stream/' . $name . ':close-before')->attach(function (Event\Bucket $bucket) use ($self, &$called) { $called = \true; $self->variable($bucket->getData())->isNull()->boolean($bucket->getSource()->isOpened())->isTrue(); }))->when($result = $stream->close())->then->boolean($called)->isTrue(); } public function case_get_stream_name() { $this->given($name = __FILE__, $stream = new \Hoa\Stream\Test\Unit\SUT($name))->when($result = $stream->getStreamName())->then->string($result)->isEqualTo($name); } public function case_get_stream() { $this->given($name = __FILE__, $stream = new \Hoa\Stream\Test\Unit\SUT($name))->when($result = $stream->getStream())->then->resource($result)->isStream($name); } public function case_get_stream_context() { $this->given($name = __FILE__, $contextName = 'foo', $context = LUT\Context::getInstance($contextName), $stream = new \Hoa\Stream\Test\Unit\SUT($name, $contextName))->when($result = $stream->getStreamContext())->then->object($result)->isIdenticalTo($context); } public function case_get_stream_context_with_no_context_given() { $this->given($name = __FILE__, $stream = new \Hoa\Stream\Test\Unit\SUT($name))->when($result = $stream->getStreamContext())->then->variable($result)->isNull(); } public function case_get_stream_handler() { $this->given($name = __FILE__, $stream = new \Hoa\Stream\Test\Unit\SUT($name))->when($result = \Hoa\Stream\Test\Unit\SUT::getStreamHandler($name))->then->object($result)->isIdenticalTo($result); } public function case_get_stream_handler_of_unknown_stream() { $this->when($result = \Hoa\Stream\Test\Unit\SUT::getStreamHandler('foo'))->then->variable($result)->isNull(); } public function case__set_stream() { $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__), $oldStream = $stream->getStream(), $newStream = fopen('php://memory', 'rb'))->when($result = $stream->_setStream($newStream))->then->resource($result)->isIdenticalTo($oldStream)->isStream()->resource($stream->getStream())->isStream()->isIdenticalTo($newStream); } public function case__set_stream_invalid_resource() { $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__))->exception(function () use ($stream) { $stream->_setStream(\true); })->isInstanceOf(LUT\Exception::class); } public function case__set_stream_unknown_resource() { $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__), $oldStream = $stream->getStream(), $newStream = fopen('php://memory', 'rb'), $this->function->is_resource = \false, $this->function->gettype = 'resource', $this->function->get_resource_type = 'Unknown')->when($result = $stream->_setStream($newStream))->then->resource($result)->isIdenticalTo($oldStream)->isStream()->resource($stream->getStream())->isStream()->isIdenticalTo($newStream); } public function case_is_opened() { $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__))->when($result = $stream->isOpened())->then->boolean($result)->isTrue(); } public function case_is_not_opened() { $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__, null, \true))->when($result = $stream->isOpened())->then->boolean($result)->isFalse()->when($stream->open(), $result = $stream->isOpened())->then->boolean($result)->isTrue(); } public function case_set_stream_timeout() { $self = $this; $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__), $this->function->stream_set_timeout = function ($_stream, $_seconds, $_microseconds) use ($self, $stream, &$called) { $called = \true; $self->resource($_stream)->isIdenticalTo($stream->getStream())->integer($_seconds)->isEqualTo(7)->integer($_microseconds)->isEqualTo(42); return \true; })->when($result = $stream->setStreamTimeout(7, 42))->then->boolean($result)->isTrue()->boolean($called)->isTrue(); } public function case_has_been_deferred() { $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__, null, \true))->when($result = $this->invoke($stream)->hasBeenDeferred())->then->boolean($result)->isTrue(); } public function case_has_not_been_deferred() { $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__))->when($result = $this->invoke($stream)->hasBeenDeferred())->then->boolean($result)->isFalse(); } public function case_has_timed_out() { $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__), $this->function->stream_get_meta_data = ['timed_out' => \true])->when($result = $stream->hasTimedOut())->then->boolean($result)->isTrue(); } public function case_has_not_timed_out() { $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__), $this->function->stream_get_meta_data = ['timed_out' => \false])->when($result = $stream->hasTimedOut())->then->boolean($result)->isFalse(); } public function case_set_stream_blocking() { $self = $this; $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__), $this->function->stream_set_blocking = function ($_stream, $_mode) use ($self, $stream, &$called) { $called = \true; $self->resource($_stream)->isIdenticalTo($stream->getStream())->integer($_mode)->isEqualTo(1); return \true; })->when($result = $stream->setStreamBlocking(\true))->then->boolean($result)->isTrue()->boolean($called)->isTrue(); } public function case_get_default_stream_buffer_size() { $self = $this; $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__))->when($result = $stream->getStreamBufferSize())->then->integer($result)->isEqualTo(8192); } public function case_set_stream_buffer() { $self = $this; $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__), $this->function->stream_set_write_buffer = function ($_stream, $_buffer) use ($self, $stream, &$called) { $called = \true; $self->resource($_stream)->isIdenticalTo($stream->getStream())->integer($_buffer)->isEqualTo(42); return 0; })->when($result = $stream->setStreamBuffer(42))->then->boolean($result)->isTrue()->boolean($called)->isTrue()->integer($stream->getStreamBufferSize())->isEqualTo(42); } public function case_set_stream_buffer_fail() { $self = $this; $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__), $oldStreamBufferSize = $stream->getStreamBufferSize(), $this->function->stream_set_write_buffer = function ($_stream, $_buffer) use ($self, $stream, &$called) { $called = \true; $self->resource($_stream)->isIdenticalTo($stream->getStream())->integer($_buffer)->isEqualTo(42); return 1; })->when($result = $stream->setStreamBuffer(42))->then->boolean($result)->isFalse()->boolean($called)->isTrue()->integer($stream->getStreamBufferSize())->isEqualTo($oldStreamBufferSize); } public function case_disable_stream_buffer() { $self = $this; $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__), $this->function->stream_set_write_buffer = function ($_stream, $_buffer) use ($self, $stream, &$called) { $called = \true; $self->resource($_stream)->isIdenticalTo($stream->getStream())->integer($_buffer)->isEqualTo(0); return 0; })->when($result = $stream->disableStreamBuffer())->then->boolean($result)->isTrue()->boolean($called)->isTrue()->integer($stream->getStreamBufferSize())->isEqualTo(0); } public function case_get_stream_wrapper_name_with_no_wrapper() { $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__))->when($result = $stream->getStreamWrapperName())->then->string($result)->isEqualTo('file'); } public function case_get_stream_wrapper_name() { $this->given($stream = new \Hoa\Stream\Test\Unit\SUT('hoa://Test/Vfs/Foo?type=file'))->when($result = $stream->getStreamWrapperName())->then->string($result)->isEqualTo('hoa'); } public function case_get_stream_meta_data() { $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__))->when($result = $stream->getStreamMetaData())->then->array($result)->isEqualTo(['timed_out' => \false, 'blocked' => \true, 'eof' => \false, 'wrapper_type' => 'plainfile', 'stream_type' => 'STDIO', 'mode' => 'rb', 'unread_bytes' => 0, 'seekable' => \true, 'uri' => __FILE__]); } public function case_is_borrowing() { $this->given($streamA1 = new \Hoa\Stream\Test\Unit\SUT(__FILE__), $streamA2 = new \Hoa\Stream\Test\Unit\SUT(__FILE__))->when($result = $streamA2->isBorrowing())->then->boolean($result)->isTrue()->boolean($streamA1->isBorrowing())->isFalse(); } public function case_is_not_borrowing() { $this->given($stream = new \Hoa\Stream\Test\Unit\SUT(__FILE__))->when($result = $stream->isBorrowing())->then->boolean($result)->isFalse(); } public function case_shutdown_destructor() { $this->given($stream = new \Mock\Hoa\Stream\Test\Unit\SUTWithPublicClose(__FILE__), $this->calling($stream)->_close = function () use (&$called) { $called = \true; })->when($result = \Hoa\Stream\Test\Unit\SUT::_Hoa_Stream())->then->boolean($called)->isTrue(); } public function case_destruct_an_opened_stream() { $this->given($stream = new \Mock\Hoa\Stream\Test\Unit\SUTWithPublicClose(__FILE__), $this->calling($stream)->_close = function () use (&$called) { $called = \true; })->when($result = $stream->__destruct())->then->boolean($called)->isTrue(); } public function case_destruct_a_deferred_stream() { $this->given($stream = new \Mock\Hoa\Stream\Test\Unit\SUTWithPublicClose(__FILE__, null, \true), $this->calling($stream)->_close = function () use (&$called) { $called = \true; })->when($result = $stream->__destruct())->then->variable($called)->isNull(); } public function case_protocol_reach_id() { $this->given($name = 'hoa://Test/Vfs/Foo?type=file', $stream = new \Hoa\Stream\Test\Unit\SUT($name))->when($result = resolve('hoa://Library/Stream#' . $name))->then->object($result)->isIdenticalTo($stream); } public function case_protocol_reach_unknown_id() { $this->given($name = 'hoa://Test/Vfs/Foo?type=file')->when($result = resolve('hoa://Library/Stream#' . $name))->then->variable($result)->isNull(); } } class SUT extends LUT\Stream { protected function &_open($streamName, LUT\Context $context = null) { if (null === $context) { $out = fopen($streamName, 'rb'); } else { $out = fopen($streamName, 'rb', \false, $context->getContext()); } return $out; } protected function _close() { return fclose($this->getStream()); } } class SUTWithPublicClose extends \Hoa\Stream\Test\Unit\SUT { public function _close() { return parent::_close(); } } when($result = new SUT('foo', 0))->then->object($result)->isInstanceOf(LUT\Exception::class); } } when($result = new \Mock\Hoa\Stream\Wrapper\IWrapper\File())->then->object($result)->isInstanceOf(SUT::class); } } when($result = new \Mock\Hoa\Stream\Wrapper\IWrapper\IWrapper())->then->object($result)->isInstanceOf(SUT::class)->isInstanceOf(LUT\Wrapper\IWrapper\File::class)->isInstanceOf(LUT\Wrapper\IWrapper\Stream::class); } } when($result = new \Mock\Hoa\Stream\Wrapper\IWrapper\Stream())->then->object($result)->isInstanceOf(SUT::class); } } given($oldIsRegistered = SUT::isRegistered('foo'))->when($result = SUT::register('foo', 'StdClass'))->then->boolean($result)->isTrue()->boolean($oldIsRegistered)->isFalse()->boolean(SUT::isRegistered('foo'))->isTrue(); } public function case_register_already_registered() { $this->exception(function () { SUT::register('php', 'ClassName'); })->isInstanceOf(LUT\Exception::class)->hasMessage('The protocol php is already registered.'); } public function case_register_implementation_does_not_exist() { $this->exception(function () { SUT::register('foo', 'ClassName'); })->isInstanceOf(LUT\Exception::class)->hasMessage('Cannot use the ClassName class for the implementation ' . 'of the foo protocol because it is not found.'); } public function case_unregister() { $this->given(SUT::register('foo', 'StdClass'), $oldIsRegistered = SUT::isRegistered('foo'))->when($result = SUT::unregister('foo'))->then->boolean($result)->isTrue()->boolean($oldIsRegistered)->isTrue()->boolean(SUT::isRegistered('foo'))->isFalse(); } public function case_unregister_unregistered_protocol() { $this->when($result = SUT::unregister('foo'))->then->boolean($result)->isFalse(); } public function case_restore_registered_protocol() { $this->when($result = SUT::restore('php'))->then->boolean($result)->isTrue(); } public function case_restore_unregistered_protocol() { $this->when($result = SUT::restore('foo'))->then->boolean($result)->isFalse(); } public function case_is_registered() { $this->when($result = SUT::isRegistered('php'))->then->boolean($result)->isTrue(); } public function case_is_not_registered() { $this->when($result = SUT::isRegistered('foo'))->then->boolean($result)->isFalse(); } public function case_get_registered() { $this->when($result = SUT::getRegistered())->then->array($result)->containsValues(['https', 'php', 'file', 'glob', 'data', 'http', 'hoa']); } public function case_get_registered_dynamically() { $this->given($oldCount = count(SUT::getRegistered()))->when(SUT::register('foo', \StdClass::class), $result = SUT::getRegistered())->then->integer(count($result))->isEqualTo($oldCount + 1)->when(SUT::unregister('foo'), $result = SUT::getRegistered())->then->integer(count($result))->isEqualTo($oldCount); } } getOption($v)) { switch ($c) { case 'b': $base = intval($v); break; case '__ambiguous': $this->resolveOptionAmbiguity($v); break; case 'h': case '?': default: return $this->usage(); } } $this->parser->listInputs($code); $char = Ustring::fromCode(base_convert($code, $base, 10)); echo $char; return; } /** * The command usage. * * @return int */ public function usage() { echo 'Usage : ustring:fromcode ', "\n", 'Options :', "\n", $this->makeUsageOptionsList(['b' => 'Specify the base of the code (16 by default).', 'help' => 'This help.']), "\n"; return; } } __halt_compiler(); Get a character from its code. getOption($v)) { switch ($c) { case 'b': $base = intval($v); break; case '__ambiguous': $this->resolveOptionAmbiguity($v); break; case 'h': case '?': default: return $this->usage(); } } $this->parser->listInputs($char); $code = base_convert((string) Ustring::toCode($char), 10, $base); echo $code, "\n"; return; } /** * The command usage. * * @return int */ public function usage() { echo 'Usage : ustring:tocode ', "\n", 'Options :', "\n", $this->makeUsageOptionsList(['b' => 'Get the code in a specific base (16 by default).', 'help' => 'This help.']), "\n"; return; } } __halt_compiler(); Transform a character into its code.

Strings can sometimes be complex, especially when they use the Unicode encoding format. The Hoa\Ustring library provides several operations on UTF-8 strings.

Table of contents

Introduction

When we manipulate strings, the Unicode format establishes itself because of its compatibility with historical formats (like ASCII) and its capacity to understand a large range of characters and symbols for all cultures and all regions in the world. PHP provides several tools to manipulate such strings, like the following extensions: mbstring, iconv or also the excellent intl which is based on ICU, the reference implementation of Unicode. Unfortunately, sometimes we have to mix these extensions to achieve our aims and at the cost of a certain complexity along with a regrettable verbosity.

The Hoa\Ustring library answers to these issues by providing a simple way to manipulate strings with performance and efficiency in minds. It also provides some evoluated algorithms to perform search operations on strings.

Unicode strings

The Hoa\Ustring\Ustring class represents a UTF-8 Unicode strings and allows to manipulate it easily. This class implements the ArrayAccess, Countable and IteratorAggregate interfaces. We are going to use three examples in three different languages: French, Arab and Japanese. Thus:

$french   = new Hoa\Ustring\Ustring('Je t\'aime');
$arabic   = new Hoa\Ustring\Ustring('أحبك');
$japanese = new Hoa\Ustring\Ustring('私はあなたを愛して');

Now, let's see what we can do on these three strings.

String manipulation

Let's start with elementary operations. If we would like to count the number of characters (not bytes), we will use the count function. Thus:

var_dump(
    count($french),
    count($arabic),
    count($japanese)
);

/**
 * Will output:
 *     int(9)
 *     int(4)
 *     int(9)
 */

When we speak about text position, it is not suitable to speak about the right or the left, but rather about a beginning or an end, and based on the direction of writing. We can know this direction thanks to the Hoa\Ustring\Ustring::getDirection method. It returns the value of one of the following constants:

  • Hoa\Ustring\Ustring::LTR, for left-to-right, if the text is written from the left to the right,
  • Hoa\Ustring\Ustring::RTL, for right-to-left, if the text is written from the right to the left.

Let's observe the result with our examples:

var_dump(
    $french->getDirection()   === Hoa\Ustring\Ustring::LTR, // is left-to-right?
    $arabic->getDirection()   === Hoa\Ustring\Ustring::RTL, // is right-to-left?
    $japanese->getDirection() === Hoa\Ustring\Ustring::LTR  // is left-to-right?
);

/**
 * Will output:
 *     bool(true)
 *     bool(true)
 *     bool(true)
 */

The result of this method is computed thanks to the Hoa\Ustring\Ustring::getCharDirection static method which computes the direction of only one character.

If we would like to concatenate another string to the end or to the beginning, we will respectively use the Hoa\Ustring\Ustring::append and Hoa\Ustring\Ustring::prepend methods. These methods, like most of the ones which modifies the string, return the object itself, in order to chain the calls. For instance:

echo $french->append('… et toi, m\'aimes-tu ?')->prepend('Mam\'zelle ! ');

/**
 * Will output:
 *     Mam'zelle ! Je t'aime… et toi, m'aimes-tu ?
 */

We also have the Hoa\Ustring\Ustring::toLowerCase and Hoa\Ustring\Ustring::toUpperCase methods to, respectively, set the case of the string to lower or upper. For instance:

echo $french->toUpperCase();

/**
 * Will output:
 *     MAM'ZELLE ! JE T'AIME… ET TOI, M'AIMES-TU ?
 */

We can also add characters to the beginning or to the end of the string to reach a minimum length. This operation is frequently called the padding (for historical reasons dating back to typewriters). That's why we have the Hoa\Ustring\Ustring::pad method which takes three arguments: the minimum length, characters to add and a constant indicating whether we have to add at the end or at the beginning of the string (respectively Hoa\Ustring\Ustring::END, by default, and Hoa\Ustring\Ustring::BEGINNING).

echo $arabic->pad(20, ' ');

/**
 * Will output:
 *                     أحبك
 */

A similar operation allows to remove, by default, spaces at the beginning and at the end of the string thanks to the Hoa\Ustring\Ustring::trim method. For example, to retreive our original Arabic string:

echo $arabic->trim();

/**
 * Will output:
 *     أحبك
 */

If we would like to remove other characters, we can use its first argument which must be a regular expression. Finally, its second argument allows to specify from what side we would like to remove character: at the beginning, at the end or both, still by using the Hoa\Ustring\Ustring::BEGINNING and Hoa\Ustring\Ustring::END constants.

If we would like to remove other characters, we can use its first argument which must be a regular expression. Finally, its second argument allows to specify the side where to remove characters: at the beginning, at the end or both, still by using the Hoa\Ustring\Ustring::BEGINNING and Hoa\Ustring\Ustring::END constants. We can combine these constants to express “both sides”, which is the default value: Hoa\Ustring\Ustring::BEGINNING | Hoa\Ustring\Ustring::END. For example, to remove all the numbers and the spaces only at the end, we will write:

$arabic->trim('\s|\d', Hoa\Ustring\Ustring::END);

We can also reduce the string to a sub-string by specifying the position of the first character followed by the length of the sub-string to the Hoa\Ustring\Ustring::reduce method:

echo $french->reduce(3, 6)->reduce(2, 4);

/**
 * Will output:
 *     aime
 */

If we would like to get a specific character, we can rely on the ArrayAccess interface. For instance, to get the first character of each of our examples (from their original definitions):

var_dump(
    $french[0],
    $arabic[0],
    $japanese[0]
);

/**
 * Will output:
 *     string(1) "J"
 *     string(2) "أ"
 *     string(3) "私"
 */

If we would like the last character, we will use the -1 index. The index is not bounded to the length of the string. If the index exceeds this length, then a modulo will be applied.

We can also modify or remove a specific character with this method. For example:

$french->append(' ?');
$french[-1] = '!';
echo $french;

/**
 * Will output:
 *     Je t'aime !
 */

Another very useful method is the ASCII transformation. Be careful, this is not always possible, according to your settings. For example:

$title = new Hoa\Ustring\Ustring('Un été brûlant sur la côte');
echo $title->toAscii();

/**
 * Will output:
 *     Un ete brulant sur la cote
 */

We can also transform from Arabic or Japanese to ASCII. Symbols, like Mathemeticals symbols or emojis, are also transformed:

$emoji = new Hoa\Ustring\Ustring('I ❤ Unicode');
$maths = new Hoa\Ustring\Ustring('∀ i ∈ ℕ');

echo
    $arabic->toAscii(), "\n",
    $japanese->toAscii(), "\n",
    $emoji->toAscii(), "\n",
    $maths->toAscii(), "\n";

/**
 * Will output:
 *     ahbk
 *     sihaanatawo aishite
 *     I (heavy black heart)️ Unicode
 *     (for all) i (element of) N
 */

In order this method to work correctly, the intl extension needs to be present, so that the Transliterator class is present. If it does not exist, the Normalizer class must exist. If this class does not exist neither, the Hoa\Ustring\Ustring::toAscii method can still try a transformation, but it is less efficient. To activate this last solution, true must be passed as a single argument. This tour de force is not recommended in most cases.

We also find the getTransliterator method which returns a Transliterator object, or null if this class does not exist. This method takes a transliteration identifier as argument. We suggest to read the documentation about the transliterator of ICU to understand this identifier. The transliterate method allows to transliterate the current string based on an identifier and a beginning index and an end one. This method works the same way than the Transliterator::transliterate method.

More generally, to change the encoding format, we can use the Hoa\Ustring\Ustring::transcode static method, with a string as first argument, the original encoding format as second argument and the expected encoding format as third argument (UTF-8 by default). The get the list of encoding formats, we have to refer to the iconv extension or to use the following command line in a terminal:

$ iconv --list

To know if a string is encoded in UTF-8, we can use the Hoa\Ustring\Ustring::isUtf8 static method; for instance:

var_dump(
    Hoa\Ustring\Ustring::isUtf8('a'),
    Hoa\Ustring\Ustring::isUtf8(Hoa\Ustring\Ustring::transcode('a', 'UTF-8', 'UTF-16'))
);

/**
 * Will output:
 *     bool(true)
 *     bool(false)
 */

We can split the string into several sub-strings by using the Hoa\Ustring\Ustring::split method. As first argument, we have a regular expression (of kind PCRE), then an integer representing the maximum number of elements to return and finally a combination of constants. These constants are the same as the ones of preg_split.

By default, the second argument is set to -1, which means infinity, and the last argument is set to PREG_SPLIT_NO_EMPTY. Thus, if we would like to get all the words of a string, we will write:

print_r($title->split('#\b|\s#'));

/**
 * Will output:
 *     Array
 *     (
 *         [0] => Un
 *         [1] => ete
 *         [2] => brulant
 *         [3] => sur
 *         [4] => la
 *         [5] => cote
 *     )
 */

If we would like to iterate over all the characters, it is recommended to use the IteratorAggregate method, being the Hoa\Ustring\Ustring::getIterator method. Let's see on the Arabic example:

foreach ($arabic as $letter) {
    echo $letter, "\n";
}

/**
 * Will output:
 *     أ
 *     ح
 *     ب
 *     ك
 */

We notice that the iteration is based on the text direction, it means that the first element of the iteration is the first letter of the string starting from the beginning.

Of course, if we would like to get an array of characters, we can use the iterator_to_array PHP function:

print_r(iterator_to_array($arabic));

/**
 * Will output:
 *     Array
 *     (
 *         [0] => أ
 *         [1] => ح
 *         [2] => ب
 *         [3] => ك
 *     )
 */

Strings can also be compared thanks to the Hoa\Ustring\Ustring::compare method:

$string = new Hoa\Ustring\Ustring('abc');
var_dump(
    $string->compare('wxyz')
);

/**
 * Will output:
 *     string(-1)
 */

This methods returns -1 if the initial string comes before (in the alphabetical order), 0 if it is identical and 1 if it comes after. If we would like to use all the power of the underlying mechanism, we can call the Hoa\Ustring\Ustring::getCollator static method (if the Collator class exists, else Hoa\Ustring\Ustring::compare will use a simple byte to bytes comparison without taking care of the other parameters). Thus, if we would like to sort an array of strings, we will write:

$strings = array('c', 'Σ', 'd', 'x', 'α', 'a');
Hoa\Ustring\Ustring::getCollator()->sort($strings);
print_r($strings);

/**
 * Could output:
 *     Array
 *     (
 *         [0] => a
 *         [1] => c
 *         [2] => d
 *         [3] => x
 *         [4] => α
 *         [5] => Σ
 *     )
 */

Comparison between two strings depends on the locale, it means of the localization of the system, like the language, the country, the region etc. We can use the Hoa\Locale library to modify these data, but it's not a dependence of Hoa\Ustring.

We can also know if a string matches a certain pattern, still expressed with a regular expression. To achieve that, we will use the Hoa\Ustring\Ustring::match method. This method relies on the preg_match and preg_match_all PHP functions, but by modifying the pattern's options to ensure the Unicode support. We have the following parameters: the pattern, a variable passed by reference to collect the matches, flags, an offset and finally a boolean indicating whether the search is global or not (respectively if we have to use preg_match_all or preg_match). By default, the search is not global.

Thus, we will check that our French example contains aime with a direct object complement:

$french->match('#(?:(?&lt;direct_object>\w)[\'\b])aime#', $matches);
var_dump($matches['direct_object']);

/**
 * Will output:
 *     string(1) "t"
 */

This method returns false if an error is raised (for example if the pattern is not correct), 0 if no match has been found, the number of matches else.

Similarly, we can search and replace sub-strings by other sub-strings based on a pattern, still expressed with a regular expression. To achieve that, we will use the Hoa\Ustring\Ustring::replace method. This method uses the preg_replace and preg_replace_callback PHP functions, but still by modifying the pattern's options to ensure the Unicode support. As first argument, we find one or more patterns, as second argument, one or more replacements and as last argument the limit of replacements to apply. If the replacement is a callable, then the preg_replace_callback function will be used.

Thus, we will modify our French example to be more polite:

$french->replace('#(?:\w[\'\b])(?&lt;verb>aime)#', function ($matches) {
    return 'vous ' . $matches['verb'];
});

echo $french;

/**
 * Will output:
 *     Je vous aime
 */

The Hoa\Ustring\Ustring class provides constants which are aliases of existing PHP constants and ensure a better readability of the code:

  • Hoa\Ustring\Ustring::WITHOUT_EMPTY, alias of PREG_SPLIT_NO_EMPTY,
  • Hoa\Ustring\Ustring::WITH_DELIMITERS, alias of PREG_SPLIT_DELIM_CAPTURE,
  • Hoa\Ustring\Ustring::WITH_OFFSET, alias of PREG_OFFSET_CAPTURE and PREG_SPLIT_OFFSET_CAPTURE,
  • Hoa\Ustring\Ustring::GROUP_BY_PATTERN, alias of PREG_PATTERN_ORDER,
  • Hoa\Ustring\Ustring::GROUP_BY_TUPLE, alias of PREG_SET_ORDER.

Because they are strict aliases, we can write:

$string = new Hoa\Ustring\Ustring('abc1 defg2 hikl3 xyz4');
$string->match(
    '#(\w+)(\d)#',
    $matches,
    Hoa\Ustring\Ustring::WITH_OFFSET
  | Hoa\Ustring\Ustring::GROUP_BY_TUPLE,
    0,
    true
);

Characters

The Hoa\Ustring\Ustring class offers static methods working on a single Unicode character. We have already mentionned the getCharDirection method which allows to know the direction of a character. We also have the getCharWidth which counts the number of columns necessary to print a single character. Thus:

var_dump(
    Hoa\Ustring\Ustring::getCharWidth(Hoa\Ustring\Ustring::fromCode(0x7f)),
    Hoa\Ustring\Ustring::getCharWidth('a'),
    Hoa\Ustring\Ustring::getCharWidth('㽠')
);

/**
 * Will output:
 *     int(-1)
 *     int(1)
 *     int(2)
 */

This method returns -1 or 0 if the character is not printable (for instance, if this is a control character, like 0x7f which corresponds to DELETE), 1 or more if this is a character that can be printed. In our example, requires 2 columns to be printed.

To get more semantics, we have the Hoa\Ustring\Ustring::isCharPrintable method which allows to know whether a character is printable or not.

If we would like to count the number of columns necessary for a whole string, we have to use the Hoa\Ustring\Ustring::getWidth method. Thus:

var_dump(
    $french->getWidth(),
    $arabic->getWidth(),
    $japanese->getWidth()
);

/**
 * Will output:
 *     int(9)
 *     int(4)
 *     int(18)
 */

Try this in your terminal with a monospaced font. You will observe that Japanese requires 18 columns to be printed. This measure is very useful if we would like to know the length of a string to position it efficiently.

The getCharWidth method is different of getWidth because it includes control characters. This method is intended to be used, for example, with terminals (please, see the Hoa\Console library).

Finally, if this time we are not interested by Unicode characters but rather by machine characters char (being 1 byte), we have an extra operation. The Hoa\Ustring\Ustring::getBytesLength method will count the length of the string in bytes:

var_dump(
    $arabic->getBytesLength(),
    $japanese->getBytesLength()
);

/**
 * Will output:
 *     int(8)
 *     int(27)
 */

If we compare these results with the ones of the Hoa\Ustring\Ustring::count method, we understand that the Arabic characters are encoded with 2 bytes whereas Japanese characteres are encoded with 3 bytes. We can also get a specific byte thanks to the Hoa\Ustring\Ustring::getByteAt method. Once again, the index is not bounded.

Code-point

Each character is represented by an integer, called a code-point. To get the code-point of a character, we can use the Hoa\Ustring\Ustring::toCode static method, and to get a character based on its code-point, we can use the Hoa\Ustring\Ustring::fromCode static method. We also have the Hoa\Ustring\Ustring::toBinaryCode method which returns the binary representation of a character. Let's take an example:

var_dump(
    Hoa\Ustring\Ustring::toCode('Σ'),
    Hoa\Ustring\Ustring::toBinaryCode('Σ'),
    Hoa\Ustring\Ustring::fromCode(0x1a9)
);

/**
 * Will output:
 *     int(931)
 *     string(32) "1100111010100011"
 *     string(2) "Σ"
 */

Search algorithms

The Hoa\Ustring library provides sophisticated search algorithms on strings through the Hoa\Ustring\Search class.

We will study the Hoa\Ustring\Search::approximated algorithm which searches a sub-string in a string up to k differences (a difference is an addition, a deletion or a modification). Let's take the classical example of a DNA representation: We will search all the sub-strings approximating GATAA with 1 difference (maximum) in CAGATAAGAGAA. So, we will write:

$x      = 'GATAA';
$y      = 'CAGATAAGAGAA';
$k      = 1;
$search = Hoa\Ustring\Search::approximated($y, $x, $k);
$n      = count($search);

echo 'Try to match ', $x, ' in ', $y, ' with at most ', $k, ' difference(s):', "\n";
echo $n, ' match(es) found:', "\n";

foreach ($search as $position) {
    echo '    • ', substr($y, $position['i'], $position['l'), "\n";
}

/**
 * Will output:
 *     Try to match GATAA in CAGATAAGAGAA with at most 1 difference(s):
 *     4 match(es) found:
 *         • AGATA
 *         • GATAA
 *         • ATAAG
 *         • GAGAA
 */

This methods returns an array of arrays. Each sub-array represents a result and contains three indexes: i for the position of the first character (byte) of the result, j for the position of the last character and l for the length of the result (simply j - i). Thus, we can compute the results by using our initial string (here $y) and its indexes.

With our example, we have four results. The first is AGATA, being GATAA with one moved character, and AGATA exists in CAGATAAGAGAA. The second result is GATAA, our sub-string, which well and truly exists in CAGATAAGAGAA. The third result is ATAAG, being GATAA with one moved character, and ATAAG exists in CAGATAAGAGAA. Finally, the last result is GAGAA, being GATAA with one modified character, and GAGAA exists in CAGATAAGAGAA.

Another example, more concrete this time. We will consider the --testIt --foobar --testThat --testAt string (which represents possible options of a command line), and we will search --testot, an option that should have been given by the user. This option does not exist as it is. We will then use our search algorithm with at most 1 difference. Let's see:

$x      = 'testot';
$y      = '--testIt --foobar --testThat --testAt';
$k      = 1;
$search = Hoa\Ustring\Search::approximated($y, $x, $k);
$n      = count($search);

// …

/**
 * Will output:
 *     Try to match testot in --testIt --foobar --testThat --testAt with at most 1 difference(s)
 *     2 match(es) found:
 *         • testIt
 *         • testAt
 */

The testIt and testAt results are true options, so we can suggest them to the user. This is a mechanism user by Hoa\Console to suggest corrections to the user in case of a mistyping.

Conclusion

The Hoa\Ustring library provides facilities to manipulate strings encoded with the Unicode format, but also to make sophisticated search on strings.

Les chaînes de caractères peuvent parfois être complexes, particulièrement lorsqu'elles utilisent l'encodage Unicode. La bibliothèque Hoa\Ustring propose plusieurs opérations sur des chaînes de caractères UTF-8.

Table des matières

Introduction

Lorsque nous manipulons des chaînes de caractères, le format Unicode s'impose par sa compatibilité avec les formats de base historiques (comme ASCII) et par sa grande capacité à comprendre une très large plage de caractères et de symboles, pour toutes les cultures et toutes les régions de notre monde. PHP propose plusieurs outils pour manipuler de telles chaînes, comme les extensions mbstring, iconv ou encore l'excellente intl qui se base sur ICU, l'implémentation de référence d'Unicode. Malheureusement, il faut parfois mélanger ces extensions pour arriver à nos fins et au prix d'une certaine complexité et d'une verbosité regrettable.

La bibliothèque Hoa\Ustring répond à ces problématiques en proposant une façon simple de manipuler des chaînes de caractères, de manière performante et efficace. Elle propose également des algorithmes évolués pour des opérations de recherche sur des chaînes de caractères.

Chaîne de caractères Unicode

La classe Hoa\Ustring\Ustring représente une chaîne de caractères Unicode UTF-8 et permet de la manipuler facilement. Elle implémente les interfaces ArrayAccess, Countable et IteratorAggregate. Nous allons utiliser trois exemples dans trois langues différentes : français, arabe et japonais. Ainsi :

$french   = new Hoa\Ustring\Ustring('Je t\'aime');
$arabic   = new Hoa\Ustring\Ustring('أحبك');
$japanese = new Hoa\Ustring\Ustring('私はあなたを愛して');

Maintenant, voyons les opérations possibles sur ces trois chaînes.

Manipulation de la chaîne

Commençons par les opérations élémentaires. Si nous voulons compter le nombre de caractères (et non pas d'octets), nous allons utiliser la fonction count de PHP. Ainsi :

var_dump(
    count($french),
    count($arabic),
    count($japanese)
);

/**
 * Will output:
 *     int(9)
 *     int(4)
 *     int(9)
 */

Quand nous parlons de position sur un texte, il n'est pas adéquat de parler de droite ou de gauche, mais plutôt de début ou de fin, et cela à partir de la direction (sens d'écriture) du texte. Nous pouvons connaître cette direction grâce à la méthode Hoa\Ustring\Ustring::getDirection. Elle retourne la valeur d'une des constantes suivantes :

  • Hoa\Ustring\Ustring::LTR, pour left-to-right, si le texte s'écrit de gauche à droite ;
  • Hoa\Ustring\Ustring::RTL, pour right-to-left, si le texte s'écrit de droite à gauche.

Observons le résultat sur nos exemples :

var_dump(
    $french->getDirection()   === Hoa\Ustring\Ustring::LTR, // is left-to-right?
    $arabic->getDirection()   === Hoa\Ustring\Ustring::RTL, // is right-to-left?
    $japanese->getDirection() === Hoa\Ustring\Ustring::LTR  // is left-to-right?
);

/**
 * Will output:
 *     bool(true)
 *     bool(true)
 *     bool(true)
 */

Le résultat de cette méthode est calculé grâce à la méthode statique Hoa\Ustring\Ustring::getCharDirection qui calcule la direction d'un seul caractère.

Si nous voulons concaténer une autre chaîne à la fin ou au début, nous utiliserons respectivement les méthodes Hoa\Ustring\Ustring::append et Hoa\Ustring\Ustring::prepend. Ces méthodes, comme la plupart de celles qui modifient la chaîne, retournent l'objet lui-même, ce afin de chaîner les appels. Par exemple :

echo $french->append('… et toi, m\'aimes-tu ?')->prepend('Mam\'zelle ! ');

/**
 * Will output:
 *     Mam'zelle ! Je t'aime… et toi, m'aimes-tu ?
 */

Nous avons également les méthodes Hoa\Ustring\Ustring::toLowerCase et Hoa\Ustring\Ustring::toUpperCase pour, respectivement, mettre la chaîne en minuscules ou en majuscules. Par exemple :

echo $french->toUpperCase();

/**
 * Will output:
 *     MAM'ZELLE ! JE T'AIME… ET TOI, M'AIMES-TU ?
 */

Nous pouvons aussi ajouter des caractères en début ou en fin de chaîne pour atteindre une taille minimum. Cette opération est plus couramment appelée le padding (pour des raisons historiques remontant aux machines à écrire). C'est pourquoi nous trouvons la méthode Hoa\Ustring\Ustring::pad qui prend trois arguments : la taille minimum, les caractères à ajouter et une constante indiquant si nous devons ajouter en fin ou en début de chaîne (respectivement Hoa\Ustring\Ustring::END, par défaut, et Hoa\Ustring\Ustring::BEGINNING).

echo $arabic->pad(20, ' ');

/**
 * Will output:
 *                     أحبك
 */

Une opération similairement inverse permet de supprimer, par défaut, les espaces en début et en fin de chaîne grâce à la méthode Hoa\Ustring\Ustring::trim. Par exemple, pour revenir à notre chaîne arabe originale :

echo $arabic->trim();

/**
 * Will output:
 *     أحبك
 */

Si nous voulons supprimer d'autres caractères, nous pouvons utiliser son premier argument qui doit être une expression régulière. Enfin, son second argument permet de préciser de quel côté nous voulons supprimer les caractères : en début, en fin ou les deux, toujours en utilisant les constantes Hoa\Ustring\Ustring::BEGINNING et Hoa\Ustring\Ustring::END. Nous pouvons combiner ces constantes pour exprimer « les deux côtés », ce qui est la valeur par défaut : Hoa\Ustring\Ustring::BEGINNING | Hoa\Ustring\Ustring::END. Par exemple, pour supprimer tous les nombres et les espaces uniquement à la fin, nous écrirons :

$arabic->trim('\s|\d', Hoa\Ustring\Ustring::END);

Nous pouvons également réduire la chaîne à une sous-chaîne en précisant la position du premier caractère puis la taille de la sous-chaîne à la méthode Hoa\Ustring\Ustring::reduce :

echo $french->reduce(3, 6)->reduce(2, 4);

/**
 * Will output:
 *     aime
 */

Si nous voulons obtenir un caractère en particulier, nous pouvons exploiter l'interface ArrayAccess. Par exemple, pour obtenir le premier caractère de chacun de nos exemples (en les reprenant depuis le début) :

var_dump(
    $french[0],
    $arabic[0],
    $japanese[0]
);

/**
 * Will output:
 *     string(1) "J"
 *     string(2) "أ"
 *     string(3) "私"
 */

Si nous voulons le dernier caractère, nous utiliserons l'index -1. L'index n'est pas borné à la taille de la chaîne. Si jamais l'index dépasse cette taille, alors un modulo sera appliqué.

Nous pouvons aussi modifier ou supprimer un caractère précis avec cette méthode. Par exemple :

$french->append(' ?');
$french[-1] = '!';
echo $french;

/**
 * Will output:
 *     Je t'aime !
 */

Une autre méthode fort utile est la transformation en ASCII. Attention, ce n'est pas toujours possible, selon votre installation. Par exemple :

$title = new Hoa\Ustring\Ustring('Un été brûlant sur la côte');
echo $title->toAscii();

/**
 * Will output:
 *     Un ete brulant sur la cote
 */

Nous pouvons aussi transformer de l'arabe ou du japonais vers de l'ASCII. Les symboles, comme les symboles Mathématiques ou les emojis, sont aussi transformés :

$emoji = new Hoa\Ustring\Ustring('I ❤ Unicode');
$maths = new Hoa\Ustring\Ustring('∀ i ∈ ℕ');

echo
    $arabic->toAscii(), "\n",
    $japanese->toAscii(), "\n",
    $emoji->toAscii(), "\n",
    $maths->toAscii(), "\n";

/**
 * Will output:
 *     ahbk
 *     sihaanatawo aishite
 *     I (heavy black heart)️ Unicode
 *     (for all) i (element of) N
 */

Pour que cette méthode fonctionne correctement, il faut que l'extension intl soit présente, pour que la classe Transliterator existe. Si elle n'existe pas, la classe Normalizer doit exister. Si cette classe n'existe pas non plus, la méthode Hoa\Ustring\Ustring::toAscii peut quand même essayer une transformation mais moins efficace. Pour cela, il faut passer true en seul argument. Ce tour de force est déconseillé dans la plupart des cas.

Nous trouvons également la méthode getTransliterator qui retourne un objet Transliterator, ou null si cette classe n'existe pas. Cette méthode prend en argument un identifiant de translitération. Nous conseillons de lire la documentation sur le translitérateur d'ICU pour comprendre cet identifiant. La méthode transliterate permet de translitérer la chaîne courante à partir d'un identifiant et d'un index de début et de fin. Elle fonctionne de la même façon que la méthode Transliterator::transliterate.

Plus généralement, pour des changements d'encodage brut, nous pouvons utiliser la méthode statique Hoa\Ustring\Ustring::transcode, avec en premier argument une chaîne de caractères, en deuxième argument l'encodage d'origine et en dernier argument l'encodage final souhaité (par défaut UTF-8). Pour la liste des encodages, il faut se reporter à l'extension iconv ou entrer la commande suivante dans un terminal :

$ iconv --list

Pour savoir si une chaîne est encodée en UTF-8, nous pouvons utiliser la méthode statique Hoa\Ustring\Ustring::isUtf8 ; par exemple :

var_dump(
    Hoa\Ustring\Ustring::isUtf8('a'),
    Hoa\Ustring\Ustring::isUtf8(Hoa\Ustring\Ustring::transcode('a', 'UTF-8', 'UTF-16'))
);

/**
 * Will output:
 *     bool(true)
 *     bool(false)
 */

Nous pouvons éclater la chaîne en plusieurs sous-chaînes en utilisant la méthode Hoa\Ustring\Ustring::split. En premier argument, nous avons une expression régulière (type PCRE), puis un entier représentant le nombre maximum d'éléments à retourner et enfin une combinaison de constantes. Ces constantes sont les mêmes que celles de preg_split.

Par défaut, le deuxième argument vaut -1, qui symbolise l'infini, et le dernier argument vaut PREG_SPLIT_NO_EMPTY. Ainsi, si nous voulons obtenir tous les mots d'une chaîne, nous écrirons :

print_r($title->split('#\b|\s#'));

/**
 * Will output:
 *     Array
 *     (
 *         [0] => Un
 *         [1] => ete
 *         [2] => brulant
 *         [3] => sur
 *         [4] => la
 *         [5] => cote
 *     )
 */

Si nous voulons itérer sur tous les caractères, il est préférable d'exploiter l'interface IteratorAggregate, soit la méthode Hoa\Ustring\Ustring::getIterator. Voyons plutôt sur l'exemple en arabe :

foreach ($arabic as $letter) {
    echo $letter, "\n";
}

/**
 * Will output:
 *     أ
 *     ح
 *     ب
 *     ك
 */

Nous remarquons que l'itération se fait suivant la direction du texte, c'est à dire que le premier élément de l'itération est la première lettre de la chaîne en partant du début.

Bien sûr, si nous voulons obtenir un tableau des caractères, nous pouvons utiliser la fonction iterator_to_array de PHP :

print_r(iterator_to_array($arabic));

/**
 * Will output:
 *     Array
 *     (
 *         [0] => أ
 *         [1] => ح
 *         [2] => ب
 *         [3] => ك
 *     )
 */

Les chaînes peuvent également être comparées entre elles grâce à la méthode Hoa\Ustring\Ustring::compare :

$string = new Hoa\Ustring\Ustring('abc');
var_dump(
    $string->compare('wxyz')
);

/**
 * Will output:
 *     string(-1)
 */

Cette méthode retourne -1 si la chaîne initiale vient avant (par ordre alphabétique), 0 si elle est identique et 1 si elle vient après. Si nous voulons utiliser la pleine puissance du mécanisme sous-jacent, nous pouvons appeler la méthode statique Hoa\Ustring\Ustring::getCollator (si la classe Collator existe, sinon Hoa\Ustring\Ustring::compare utilisera une comparaison simple octet par octets sans tenir compte d'autres paramètres). Ainsi, si nous voulons trier un tableau de chaînes, nous écrirons plutôt :

$strings = array('c', 'Σ', 'd', 'x', 'α', 'a');
Hoa\Ustring\Ustring::getCollator()->sort($strings);
print_r($strings);

/**
 * Could output:
 *     Array
 *     (
 *         [0] => a
 *         [1] => c
 *         [2] => d
 *         [3] => x
 *         [4] => α
 *         [5] => Σ
 *     )
 */

La comparaison entre deux chaînes dépend de la locale, c'est à dire de la régionalisation du système, comme la langue, le pays, la région etc. Nous pouvons utiliser la bibliothèque Hoa\Locale pour modifier ces données, mais ce n'est pas une dépendance de Hoa\Ustring pour autant.

Nous pouvons également savoir si une chaîne correspond à un certain motif, toujours exprimé avec une expression régulière. Pour cela, nous allons utiliser la méthode Hoa\Ustring\Ustring::match. Cette méthode repose sur les fonctions preg_match et preg_match_all de PHP, mais en modifiant les options du motif afin qu'il supporte Unicode. Nous avons les paramètres suivants : le motif, une variable par référence pour récupérer les captures, les flags, la position de début de recherche (offset) et enfin un booléen indiquant si la recherche est globale ou non (respectivement si nous devons utiliser preg_match_all ou preg_match). Par défaut, la recherche n'est pas globale.

Ainsi, nous allons vérifier que notre exemple en français contient bien aime avec son complément d'objet direct :

$french->match('#(?:(?&lt;direct_object>\w)[\'\b])aime#', $matches);
var_dump($matches['direct_object']);

/**
 * Will output:
 *     string(1) "t"
 */

Cette méthode retourne false si une erreur est survenue (par exemple si le motif n'est pas correct), 0 si aucune correspondance n'a été trouvée, le nombre de correspondances trouvées sinon.

Similairement, nous pouvons chercher et remplacer des sous-chaînes par d'autres sous-chaînes suivant un motif, toujours exprimé avec une expression régulière. Pour cela, nous allons utiliser la méthode Hoa\Ustring\Ustring::replace. Cette méthode repose sur les fonctions preg_replace et preg_replace_callback de PHP, mais toujours en modifiant les options du motif afin qu'il supporte Unicode. En premier argument, nous trouvons le ou les motifs, en deuxième argument, le ou les remplacements et en dernier argument la limite de remplacements à faire. Si le remplacement est un callable, alors la fonction preg_replace_callback sera utilisée.

Ainsi, nous allons modifier notre exemple français pour qu'il soit plus poli :

$french->replace('#(?:\w[\'\b])(?&lt;verb>aime)#', function ($matches) {
    return 'vous ' . $matches['verb'];
});

echo $french;

/**
 * Will output:
 *     Je vous aime
 */

La classe Hoa\Ustring\Ustring propose des constantes qui sont des aliases de constantes PHP et qui permettent une meilleure lecture du code:

  • Hoa\Ustring\Ustring::WITHOUT_EMPTY, alias de PREG_SPLIT_NO_EMPTY ;
  • Hoa\Ustring\Ustring::WITH_DELIMITERS, alias de PREG_SPLIT_DELIM_CAPTURE ;
  • Hoa\Ustring\Ustring::WITH_OFFSET, alias de PREG_OFFSET_CAPTURE et PREG_SPLIT_OFFSET_CAPTURE ;
  • Hoa\Ustring\Ustring::GROUP_BY_PATTERN, alias de PREG_PATTERN_ORDER ;
  • Hoa\Ustring\Ustring::GROUP_BY_TUPLE, alias de PREG_SET_ORDER.

Comme ce sont des aliases stricts, nous pouvons écrire :

$string = new Hoa\Ustring\Ustring('abc1 defg2 hikl3 xyz4');
$string->match(
    '#(\w+)(\d)#',
    $matches,
    Hoa\Ustring\Ustring::WITH_OFFSET
  | Hoa\Ustring\Ustring::GROUP_BY_TUPLE,
    0,
    true
);

Caractères

La classe Hoa\Ustring\Ustring offre des méthodes statiques travaillant sur un seul caractère Unicode. Nous avons déjà évoqué la méthode getCharDirection qui permet de connaître la direction d'un caractère. Nous trouvons aussi getCharWidth qui calcule le nombre de colonnes nécessaires pour l'affichage d'un seul caractère. Ainsi :

var_dump(
    Hoa\Ustring\Ustring::getCharWidth(Hoa\Ustring\Ustring::fromCode(0x7f)),
    Hoa\Ustring\Ustring::getCharWidth('a'),
    Hoa\Ustring\Ustring::getCharWidth('㽠')
);

/**
 * Will output:
 *     int(-1)
 *     int(1)
 *     int(2)
 */

Cette méthode retourne -1 ou 0 si le caractère n'est pas imprimable (par exemple si c'est un caractère de contrôle, comme 0x7f qui correspond à DELETE), 1 ou plus si c'est un caractère qui peut être imprimé. Dans notre exemple, s'imprime sur 2 colonnes.

Pour plus de sémantique, nous avons accès à la méthode Hoa\Ustring\Ustring::isCharPrintable qui permet de savoir si un caractère est imprimable ou pas.

Si nous voulons calculer le nombre de colonnes pour tout une chaîne, il faut utiliser la méthode Hoa\Ustring\Ustring::getWidth. Ainsi :

var_dump(
    $french->getWidth(),
    $arabic->getWidth(),
    $japanese->getWidth()
);

/**
 * Will output:
 *     int(9)
 *     int(4)
 *     int(18)
 */

Essayez dans un terminal avec une police mono-espacée. Vous verrez que le japonais demande 18 colonnes pour s'afficher. Cette mesure est très utile si nous voulons connaître la largeur d'une chaîne pour la positionner correctement.

La méthode getCharWidth est différente de getWidth car elle prend en compte des caractères de contrôles. Elle est destinée à être utilisée, par exemple, avec des terminaux (voir la bibliothèque Hoa\Console).

Enfin, si cette fois nous ne nous intéressons pas aux caractères Unicode mais aux caractères machines char (soit 1 octet), nous avons une opération supplémentaire. La méthode Hoa\Ustring\Ustring::getBytesLength va compter la taille de la chaîne en octets :

var_dump(
    $arabic->getBytesLength(),
    $japanese->getBytesLength()
);

/**
 * Will output:
 *     int(8)
 *     int(27)
 */

Si nous comparons ces résultats avec ceux de la méthode Hoa\Ustring\Ustring::count, nous comprenons que les caractères arabes sont encodés sur 2 octets alors que les caractères japonais sont encodés sur 3 octets. Nous pouvons également obtenir un octet précis à l'aide de la méthode Hoa\Ustring\Ustring::getByteAt. Encore une fois, l'index n'est pas borné.

Code-point

Chaque caractère est représenté en machine par un entier, appelé code-point. Pour obtenir le code-point d'un caractère, nous pouvons utiliser la méthode statique Hoa\Ustring\Ustring::toCode, et pour obtenir un caractère à partir d'un code, nous pouvons utiliser la méthode statique Hoa\Ustring\Ustring::fromCode. Nous avons aussi la méthode statique Hoa\Ustring\Ustring::toBinaryCode qui retourne la représentation sous forme binaire d'un caractère. Prenons un exemple :

var_dump(
    Hoa\Ustring\Ustring::toCode('Σ'),
    Hoa\Ustring\Ustring::toBinaryCode('Σ'),
    Hoa\Ustring\Ustring::fromCode(0x1a9)
);

/**
 * Will output:
 *     int(931)
 *     string(32) "1100111010100011"
 *     string(2) "Σ"
 */

Algorithmes de recherche

La bibliothèque Hoa\Ustring propose des algorithmes de recherches sophistiquées sur les chaînes de caractères à travers la classe Hoa\Ustring\Search.

Nous allons étudier l'algorithme Hoa\Ustring\Search::approximated qui fait une recherche d'une sous-chaîne dans une chaîne avec au maximum k différences (une différence étant une insertion, une délétion ou une modification). Prenons un exemple classique avec une représentation ADN : nous allons chercher toutes les sous-chaînes s'approchant de GATAA à 1 différence près (au maximum) dans CAGATAAGAGAA. Pour cela, nous allons donc écrire :

$x      = 'GATAA';
$y      = 'CAGATAAGAGAA';
$k      = 1;
$search = Hoa\Ustring\Search::approximated($y, $x, $k);
$n      = count($search);

echo 'Try to match ', $x, ' in ', $y, ' with at most ', $k, ' difference(s):', "\n";
echo $n, ' match(es) found:', "\n";

foreach ($search as $position) {
    echo '    • ', substr($y, $position['i'], $position['l'), "\n";
}

/**
 * Will output:
 *     Try to match GATAA in CAGATAAGAGAA with at most 1 difference(s):
 *     4 match(es) found:
 *         • AGATA
 *         • GATAA
 *         • ATAAG
 *         • GAGAA
 */

Cette méthode retourne un tableau de tableaux. Chaque sous-tableau représente un résultat et contient trois indexes : i pour la position du premier caractère (octet) du résultat, j pour la position du dernier caractère et l pour la taille du résultat (tout simplement j - i). Ainsi, nous pouvons calculer les résultats en utilisant notre chaîne initiale (ici $y) et ces indexes.

Avec notre exemple, nous avons quatre résultats. Le premier est AGATA, soit GATAA avec un caractère déplacé, et AGATA existe bien dans CAGATAAGAGAA. Le deuxième résultat est GATAA, notre sous-chaîne, qui existe bel et bien dans CAGATAAGAGAA. Le troisième résultat est ATAAG, soit GATAA avec un caractère déplacé, et ATAAG existe bien dans CAGATAAGAGAA. Enfin, le dernier résultat est GAGAA, soit GATAA avec un caractère modifié, et GAGAA existe bien dans CAGATAAGAGAA.

Prenons un autre exemple, plus concret cette fois-ci. Nous allons considérer la chaîne --testIt --foobar --testThat --testAt (qui représente les options possibles d'une ligne de commande), et nous allons chercher --testot, une option qu'aurait pu donner l'utilisateur. Cette option n'existe pas telle quelle. Nous allons donc utiliser notre algorithme de recherche avec 1 différence au maximum. Voyons plutôt :

$x      = 'testot';
$y      = '--testIt --foobar --testThat --testAt';
$k      = 1;
$search = Hoa\Ustring\Search::approximated($y, $x, $k);
$n      = count($search);

// …

/**
 * Will output:
 *     Try to match testot in --testIt --foobar --testThat --testAt with at most 1 difference(s)
 *     2 match(es) found:
 *         • testIt
 *         • testAt
 */

Les résultats testIt et testAt sont des vraies options, donc nous pouvons les proposer à l'utilisateur. C'est un mécanisme utilisé par Hoa\Console pour proposer des corrections à l'utilisateur s'il se trompe.

Conclusion

La bibliothèque Hoa\Ustring propose des facilités pour manipuler des chaînes encodées au format Unicode, mais aussi pour effectuer des recherches sophistiquées sur des chaînes.

array_fill(-1, $n - $m + $k + 3, -2)]; for ($q = 0, $max = $k - 1; $q <= $max; ++$q) { $L[$q][-$q - 1] = $L[$q][-$q - 2] = $q - 1; } for ($q = 0; $q <= $k; ++$q) { for ($d = -$q, $max = $n - $m + $k - $q; $d <= $max; ++$d) { $l = min(max($L[$q - 1][$d - 1], $L[$q - 1][$d] + 1, $L[$q - 1][$d + 1] + 1), $m - 1); $a = substr($x, $l + 1, $m - $l); $b = substr($y, $l + 1 + $d, $n - $l - $d); $L[$q][$d] = $l + static::lcp($a, $b); if ($L[$q][$d] == $m - 1 || $d + $L[$q][$d] == $n - 1) { $j = $m + $d; $i = max(0, $j - $m); $offset[$q][] = ['i' => $i, 'j' => $j, 'l' => $j - $i]; } } } return empty($offset) ? $offset : $offset[$k]; } /** * Length of the longest common prefixes. * * @param string $x Word. * @param string $y Word. * @return int */ public static function lcp($x, $y) { $max = min(strlen($x), strlen($y)); $i = 0; while ($i < $max && $x[$i] == $y[$i]) { ++$i; } return $i; } } when($result = LUT::toCode(chr(160)))->then->integer($result)->isEqualTo(0xa0); } } given($x = 'GATAA', $y = 'CAGATAAGAGAA', $k = 1)->when($result = LUT\Search::approximated($y, $x, $k))->then->array($result)->isEqualTo([0 => ['i' => 1, 'j' => 6, 'l' => 5], 1 => ['i' => 2, 'j' => 7, 'l' => 5], 2 => ['i' => 3, 'j' => 8, 'l' => 5], 3 => ['i' => 7, 'j' => 12, 'l' => 5]]); } } given($this->function->function_exists = \true)->then->boolean(LUT::checkMbString())->isTrue(); } public function case_check_no_mbstring() { $this->given($this->function->function_exists = function ($name) { return 'mb_substr' !== $name; })->exception(function () { new LUT(); })->isInstanceOf('Hoa\Ustring\Exception'); } public function case_append_ltr() { $this->given($string = new LUT('je'))->when($result = $string->append(' t\'aime'))->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('je t\'aime'); } public function case_append_rtl() { $this->given($string = new LUT('أ'))->when($result = $string->append('حبك'))->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('أحبك'); } public function case_prepend_ltr() { $this->given($string = new LUT(' t\'aime'))->when($result = $string->prepend('je'))->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('je t\'aime'); } public function case_prepend_rtl() { $this->given($string = new LUT('ك'))->when($result = $string->prepend('أحب'))->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('أحبك'); } public function case_pad_beginning_ltr() { $this->given($string = new LUT('je t\'aime'))->when($result = $string->pad(20, '👍 💩 😄 ❤️ ', LUT::BEGINNING))->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('👍 💩 😄 ❤️ 👍 je t\'aime'); } public function case_pad_beginning_rtl() { $this->given($string = new LUT('أحبك'))->when($result = $string->pad(20, '👍 💩 😄 ❤️ ', LUT::BEGINNING))->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('👍 💩 😄 ❤️ 👍 💩 😄 ❤أحبك'); } public function case_pad_end_ltr() { $this->given($string = new LUT('je t\'aime'))->when($result = $string->pad(20, '👍 💩 😄 ❤️ ', LUT::END))->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('je t\'aime👍 💩 😄 ❤️ 👍 '); } public function case_pad_end_rtl() { $this->given($string = new LUT('أحبك'))->when($result = $string->pad(20, '👍 💩 😄 ❤️ ', LUT::END))->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('أحبك👍 💩 😄 ❤️ 👍 💩 😄 ❤'); } public function case_compare_no_collator() { $this->given($this->function->class_exists = function ($name) { return 'Collator' !== $name; }, $string = new LUT('b'))->case_compare(); } public function case_compare() { $this->given($string = new LUT('b'))->when($result = $string->compare('a'))->then->integer($result)->isEqualTo(1)->when($result = $string->compare('b'))->then->integer($result)->isEqualTo(0)->when($result = $string->compare('c'))->then->integer($result)->isEqualTo(-1); } public function case_collator() { $this->given($this->function->setlocale = 'fr_FR', $collator = LUT::getCollator())->when($result = $collator->getLocale(\Locale::VALID_LOCALE))->then->string($result)->isEqualTo('fr'); } public function case_safe_unsafe_pattern() { $this->given($pattern = '/foo/i')->when($result = LUT::safePattern($pattern))->then->string($result)->isEqualto('/foo/iu'); } public function case_safe_safe_pattern() { $this->given($pattern = '/foo/ui')->when($result = LUT::safePattern($pattern))->then->string($result)->isEqualto('/foo/ui'); } public function case_match_default() { $this->given($pattern = '/💩/u', $string = new LUT('foo 💩 bar'))->when($result = $string->match($pattern, $matches))->then->integer($result)->isEqualTo(1)->array($matches)->isEqualTo([0 => '💩']); } public function case_match_offset() { $this->given($pattern = '/💩/u', $string = new LUT('foo 💩 bar'))->when($result = $string->match($pattern, $matches, 0, 0))->then->integer($result)->isEqualTo(1)->array($matches)->isEqualTo([0 => '💩'])->when($result = $string->match($pattern, $matches, 0, 4))->then->integer($result)->isEqualTo(1)->array($matches)->isEqualTo([0 => '💩'])->when($result = $string->match($pattern, $matches, 0, 5))->then->integer($result)->isEqualTo(0)->array($matches)->isEmpty(); } public function case_match_with_offset() { $this->given($pattern = '/💩/u', $string = new LUT('foo 💩 bar'))->when($result = $string->match($pattern, $matches, $string::WITH_OFFSET))->then->integer($result)->isEqualTo(1)->array($matches)->isEqualTo([0 => [0 => '💩', 1 => 4]]); } public function case_match_all_default() { $this->given($pattern = '/💩/u', $string = new LUT('foo 💩 bar 💩 baz'))->when($result = $string->match($pattern, $matches, 0, 0, \true))->then->integer($result)->isEqualTo(2)->array($matches)->isEqualTo([0 => [0 => '💩', 1 => '💩']]); } public function case_match_all_with_offset() { $this->given($pattern = '/💩/u', $string = new LUT('foo 💩 bar 💩 baz'))->when($result = $string->match($pattern, $matches, $string::WITH_OFFSET, 0, \true))->then->integer($result)->isEqualTo(2)->array($matches)->isEqualTo([0 => [0 => [0 => '💩', 1 => 4], 1 => [0 => '💩', 1 => 13]]]); } public function case_match_all_grouped_by_pattern() { $this->given($pattern = '/(💩)/u', $string = new LUT('foo 💩 bar 💩 baz'))->when($result = $string->match($pattern, $matches, $string::GROUP_BY_PATTERN, 0, \true))->then->integer($result)->isEqualTo(2)->array($matches)->isEqualTo([0 => [0 => '💩', 1 => '💩'], 1 => [0 => '💩', 1 => '💩']]); } public function case_match_all_grouped_by_tuple() { $this->given($pattern = '/(💩)/u', $string = new LUT('foo 💩 bar 💩 baz'))->when($result = $string->match($pattern, $matches, $string::GROUP_BY_TUPLE, 0, \true))->then->integer($result)->isEqualTo(2)->array($matches)->isEqualTo([0 => [0 => '💩', 1 => '💩'], 1 => [0 => '💩', 1 => '💩']]); } public function case_replace() { $this->given($string = new LUT('❤️ 💩 💩'))->when($result = $string->replace('/💩/u', '😄'))->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('❤️ 😄 😄'); } public function case_replace_limited() { $this->given($string = new LUT('❤️ 💩 💩'))->when($result = $string->replace('/💩/u', '😄', 1))->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('❤️ 😄 💩'); } public function case_split_default() { $this->given($string = new LUT('❤️💩❤️💩❤️'))->when($result = $string->split('/💩/'))->then->array($result)->isEqualTo([0 => '❤️', 1 => '❤️', 2 => '❤️']); } public function case_split_default_limited() { $this->given($string = new LUT('❤️💩❤️💩❤️'))->when($result = $string->split('/💩/', 1))->then->array($result)->isEqualTo([0 => '❤️💩❤️💩❤️']); } public function case_split_with_delimiters() { $this->given($string = new LUT('❤️💩❤️💩❤️'))->when($result = $string->split('/💩/', -1, $string::WITH_DELIMITERS))->then->array($result)->isEqualTo([0 => '❤️', 1 => '❤️', 2 => '❤️']); } public function case_split_with_offset() { $this->given($string = new LUT('❤️💩❤️💩❤️'))->when($result = $string->split('/💩/', -1, $string::WITH_OFFSET))->then->array($result)->isEqualTo([0 => [0 => '❤️', 1 => 0], 1 => [0 => '❤️', 1 => 10], 2 => [0 => '❤️', 1 => 20]]); } public function case_iterator_ltr() { $this->given($string = new LUT('je t\'aime'))->when($result = iterator_to_array($string))->then->array($result)->isEqualTo(['j', 'e', ' ', 't', '\'', 'a', 'i', 'm', 'e']); } public function case_iterator_rtl() { $this->given($string = new LUT('أحبك'))->when($result = iterator_to_array($string))->then->array($result)->isEqualTo(['أ', 'ح', 'ب', 'ك']); } public function case_to_lower() { $this->given($string = new LUT('Σ \'ΑΓΑΠΏ'))->when($result = $string->toLowerCase())->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('σ \'αγαπώ')->given($string = new LUT('JE T\'AIME'))->when($result = $string->toLowerCase())->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('je t\'aime'); } public function case_to_upper() { $this->given($string = new LUT('σ \'αγαπώ'))->when($result = $string->toUpperCase())->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('Σ \'ΑΓΑΠΏ')->given($string = new LUT('je t\'aime'))->when($result = $string->toUpperCase())->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('JE T\'AIME'); } public function case_trim_default() { $this->given($string = new LUT('💩💩❤️💩💩'))->when($result = $string->trim('💩'))->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('❤️'); } public function case_trim_beginning() { $this->given($string = new LUT('💩💩❤️💩💩'))->when($result = $string->trim('💩', $string::BEGINNING))->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('❤️💩💩'); } public function case_trim_end() { $this->given($string = new LUT('💩💩❤️💩💩'))->when($result = $string->trim('💩', $string::END))->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('💩💩❤️'); } public function case_offset_get_ltr() { $this->given($string = new LUT('je t\'aime'))->when($result = $string[0])->then->string($result)->isEqualTo('j')->when($result = $string[-1])->then->string($result)->isEqualTo('e'); } public function case_offset_get_rtl() { $this->given($string = new LUT('أحبك'))->when($result = $string[0])->then->string($result)->isEqualTo('أ')->when($result = $string[-1])->then->string($result)->isEqualTo('ك'); } public function case_offset_set() { $this->given($string = new LUT('أحبﻙ'))->when($string[-1] = 'ك')->then->string((string) $string)->isEqualTo('أحبك'); } public function case_offset_unset() { $this->given($string = new LUT('أحبك😄'))->when(function () use ($string) { unset($string[-1]); })->then->string((string) $string)->isEqualTo('أحبك'); } public function case_reduce() { $this->given($string = new LUT('أحبك'))->when($result = $string->reduce(0, 1))->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('أ'); } public function case_count() { $this->given($string = new LUT('je t\'aime'))->when($result = count($string))->then->integer($result)->isEqualTo(9)->given($string = new LUT('أحبك'))->when($result = count($string))->then->integer($result)->isEqualTo(4)->given($string = new LUT('💩'))->when($result = count($string))->then->integer($result)->isEqualTo(1); } public function case_byte_at() { $this->given($string = new LUT('💩'))->when($result = $string->getByteAt(0))->then->integer(ord($result))->isEqualTo(0xf0)->when($result = $string->getByteAt(1))->then->integer(ord($result))->isEqualTo(0x9f)->when($result = $string->getByteAt(2))->then->integer(ord($result))->isEqualTo(0x92)->when($result = $string->getByteAt(3))->then->integer(ord($result))->isEqualTo(0xa9)->when($result = $string->getByteAt(-1))->then->integer(ord($result))->isEqualTo(0xa9); } public function case_bytes_length() { $this->given($string = new LUT('💩'))->when($result = $string->getBytesLength())->then->integer($result)->isEqualTo(4); } public function case_get_width() { $this->given($string = new LUT('💩'))->when($result = $string->getWidth())->then->integer($result)->isEqualTo(1)->given($string = new LUT('習'))->when($result = $string->getWidth())->then->integer($result)->isEqualTo(2); } public function case_get_char_direction() { $this->when($result = LUT::getCharDirection('A'))->then->integer($result)->isEqualTo(LUT::LTR)->when($result = LUT::getCharDirection('ا'))->then->integer($result)->isEqualTo(LUT::RTL); } public function case_get_char_width() { $this->given($data = [ // 8-bit control character. [0x0, 0], [0x19, -1], [0x7f, -1], [0x9f, -1], // Regular. [0xa0, 1], // Non-spacing characters mark. [0x300, 0], // in Mn [0x488, 0], // in Me [0x600, 0], // in Cf [0xad, 1], // in Cf, but the only exception [0x1160, 0], [0x11ff, 0], [0x200b, 0], // To test the last return statement. [0x1100, 2], [0x2160, 1], [0x3f60, 2], [0x303f, 1], [0x2329, 2], [0xaed0, 2], [0x232a, 2], [0xffa4, 1], [0xfe10, 2], [0xfe30, 2], [0xff00, 2], [0xf900, 2], ])->when(function () use ($data) { foreach ($data as $datum) { list($code, $width) = $datum; $this->when($result = LUT::getCharWidth(LUT::fromCode($code)))->then->integer($result)->isEqualTo($width); } }); } public function case_is_char_printable() { $this->when($result = LUT::isCharPrintable(LUT::fromCode(0x7f)))->then->boolean($result)->isFalse()->when($result = LUT::isCharPrintable(LUT::fromCode(0xa0)))->then->boolean($result)->isTrue()->when($result = LUT::isCharPrintable(LUT::fromCode(0x1100)))->then->boolean($result)->isTrue(); } public function case_from_code() { $this->when($result = LUT::fromCode(0x7e))->then->string($result)->isEqualTo('~')->when($result = LUT::fromCode(0xa7))->then->string($result)->isEqualTo('§')->when($result = LUT::fromCode(0x1207))->then->string($result)->isEqualTo('ሇ')->when($result = LUT::fromCode(0x1f4a9))->then->string($result)->isEqualTo('💩'); } public function case_to_code() { $this->when($result = LUT::toCode('~'))->then->integer($result)->isEqualTo(0x7e)->when($result = LUT::toCode('§'))->then->integer($result)->isEqualTo(0xa7)->when($result = LUT::toCode('ሇ'))->then->integer($result)->isEqualTo(0x1207)->when($result = LUT::toCode('💩'))->then->integer($result)->isEqualTo(0x1f4a9); } public function case_to_binary_code() { $this->when($result = LUT::toBinaryCode('~'))->then->string($result)->isEqualTo('01111110')->when($result = LUT::toBinaryCode('§'))->then->string($result)->isEqualTo('1100001010100111')->when($result = LUT::toBinaryCode('ሇ'))->then->string($result)->isEqualTo('111000011000100010000111')->when($result = LUT::toBinaryCode('💩'))->then->string($result)->isEqualTo('11110000100111111001001010101001'); } public function case_transcode_no_iconv() { $this->given($this->function->function_exists = function ($name) { return 'iconv' !== $name; })->exception(function () { LUT::transcode('foo', 'UTF-8'); })->isInstanceOf('Hoa\Ustring\Exception'); } public function case_transcode_and_isUtf8() { $this->given($uΣ = 'Σ')->when($Σ = LUT::transcode($uΣ, 'UTF-8', 'UTF-16'))->then->string($Σ)->isNotEqualTo($uΣ)->boolean(LUT::isUtf8($Σ))->isFalse()->when($Σ = LUT::transcode($Σ, 'UTF-16', 'UTF-8'))->string($Σ)->isEqualTo($uΣ)->boolean(LUT::isUtf8($Σ))->isTrue()->boolean(LUT::isUtf8($uΣ))->isTrue(); } public function case_to_ascii_no_transliterator_no_normalizer() { $this->given($this->function->class_exists = function ($name) { return \false === in_array($name, ['Transliterator', 'Normalizer']); }, $string = new LUT('Un été brûlant sur la côte'))->exception(function () use ($string) { $string->toAscii(); })->isInstanceOf('Hoa\Ustring\Exception'); } public function case_to_ascii_no_transliterator_no_normalizer_try() { $this->given($this->function->class_exists = function ($name) { return \false === in_array($name, ['Transliterator', 'Normalizer']); }, $string = new LUT('Un été brûlant sur la côte'))->when($result = $string->toAscii(\true))->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('Un ete brulant sur la cote'); } public function case_to_ascii_no_transliterator() { $this->given($this->function->class_exists = function ($name) { return 'Transliterator' !== $name; }, $string = new LUT('Un été brûlant sur la côte'))->when($result = $string->toAscii())->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo('Un ete brulant sur la cote'); } public function case_to_ascii() { $this->given($strings = ['Un été brûlant sur la côte' => 'Un ete brulant sur la cote', 'Αυτή είναι μια δοκιμή' => 'Aute einai mia dokime', 'أحبك' => 'ahbk', 'キャンパス' => 'kyanpasu', 'биологическом' => 'biologiceskom', '정, 병호' => 'jeong, byeongho', 'ますだ, よしひこ' => 'masuda, yoshihiko', 'मोनिच' => 'monica', 'क्ष' => 'ksa', 'أحبك 😀' => 'ahbk (grinning face)', '∀ i ∈ ℕ' => '(for all) i (element of) N'])->when(function () use ($strings) { foreach ($strings as $original => $asciied) { $this->given($string = new LUT($original))->when($result = $string->toAscii())->then->object($result)->isIdenticalTo($string)->string((string) $result)->isEqualTo($asciied); } }); } public function case_copy() { $this->given($string = new LUT('foo'))->when($result = $string->copy())->then->object($result)->isEqualTo($string); } public function case_toString() { $this->given($datum = $this->sample($this->realdom->regex('/\w{7,42}/')))->when($result = new LUT($datum))->then->castToString($result)->isEqualTo($datum); } } append($string); } return; } /** * Check if ext/mbstring is available. * * @return bool */ public static function checkMbString() { return function_exists('mb_substr'); } /** * Check if ext/iconv is available. * * @return bool */ public static function checkIconv() { return function_exists('iconv'); } /** * Append a substring to the current string, i.e. add to the end. * * @param string $substring Substring to append. * @return \Hoa\Ustring */ public function append($substring) { $this->_string .= $substring; return $this; } /** * Prepend a substring to the current string, i.e. add to the start. * * @param string $substring Substring to append. * @return \Hoa\Ustring */ public function prepend($substring) { $this->_string = $substring . $this->_string; return $this; } /** * Pad the current string to a certain length with another piece, aka piece. * * @param int $length Length. * @param string $piece Piece. * @param int $side Whether we append at the end or the beginning * of the current string. * @return \Hoa\Ustring */ public function pad($length, $piece, $side = self::END) { $difference = $length - $this->count(); if (0 >= $difference) { return $this; } $handle = null; for ($i = $difference / mb_strlen($piece) - 1; $i >= 0; --$i) { $handle .= $piece; } $handle .= mb_substr($piece, 0, $difference - mb_strlen($handle)); return static::END === $side ? $this->append($handle) : $this->prepend($handle); } /** * Make a comparison with a string. * Return < 0 if current string is less than $string, > 0 if greater and 0 * if equal. * * @param mixed $string String. * @return int */ public function compare($string) { if (null === $collator = static::getCollator()) { return strcmp($this->_string, (string) $string); } return $collator->compare($this->_string, $string); } /** * Get collator. * * @return \Collator */ public static function getCollator() { if (\false === class_exists('Collator')) { return null; } if (null === static::$_collator) { static::$_collator = new \Collator(setlocale(\LC_COLLATE, null)); } return static::$_collator; } /** * Ensure that the pattern is safe for Unicode: add the “u” option. * * @param string $pattern Pattern. * @return string */ public static function safePattern($pattern) { $delimiter = mb_substr($pattern, 0, 1); $options = mb_substr(mb_strrchr($pattern, $delimiter, \false), mb_strlen($delimiter)); if (\false === strpos($options, 'u')) { $pattern .= 'u'; } return $pattern; } /** * Perform a regular expression (PCRE) match. * * @param string $pattern Pattern. * @param array $matches Matches. * @param int $flags Please, see constants self::WITH_OFFSET, * self::GROUP_BY_PATTERN and * self::GROUP_BY_TUPLE. * @param int $offset Alternate place from which to start the * search. * @param bool $global Whether the match is global or not. * @return int */ public function match($pattern, &$matches = null, $flags = 0, $offset = 0, $global = \false) { $pattern = static::safePattern($pattern); if (0 === $flags) { if (\true === $global) { $flags = static::GROUP_BY_PATTERN; } } else { $flags &= ~\PREG_SPLIT_OFFSET_CAPTURE; } $offset = strlen(mb_substr($this->_string, 0, $offset)); if (\true === $global) { return preg_match_all($pattern, $this->_string, $matches, $flags, $offset); } return preg_match($pattern, $this->_string, $matches, $flags, $offset); } /** * Perform a regular expression (PCRE) search and replace. * * @param mixed $pattern Pattern(s). * @param mixed $replacement Replacement(s) (please, see * preg_replace() documentation). * @param int $limit Maximum of replacements. -1 for unbound. * @return \Hoa\Ustring */ public function replace($pattern, $replacement, $limit = -1) { $pattern = static::safePattern($pattern); if (\false === is_callable($replacement)) { $this->_string = preg_replace($pattern, $replacement, $this->_string, $limit); } else { $this->_string = preg_replace_callback($pattern, $replacement, $this->_string, $limit); } return $this; } /** * Split the current string according to a given pattern (PCRE). * * @param string $pattern Pattern (as a regular expression). * @param int $limit Maximum of split. -1 for unbound. * @param int $flags Please, see constants self::WITHOUT_EMPTY, * self::WITH_DELIMITERS, self::WITH_OFFSET. * @return array */ public function split($pattern, $limit = -1, $flags = self::WITHOUT_EMPTY) { return preg_split(static::safePattern($pattern), $this->_string, $limit, $flags); } /** * Iterator over chars. * * @return \ArrayIterator */ public function getIterator() { return new \ArrayIterator(preg_split('#(?_string)); } /** * Perform a lowercase folding on the current string. * * @return \Hoa\Ustring */ public function toLowerCase() { $this->_string = mb_strtolower($this->_string); return $this; } /** * Perform an uppercase folding on the current string. * * @return \Hoa\Ustring */ public function toUpperCase() { $this->_string = mb_strtoupper($this->_string); return $this; } /** * Transform a UTF-8 string into an ASCII one. * First, try with a transliterator. If not available, will fallback to a * normalizer. If not available, will try something homemade. * * @param bool $try Try something if \Normalizer is not present. * @return \Hoa\Ustring * @throws \Hoa\Ustring\Exception */ public function toAscii($try = \false) { if (0 === preg_match('#[\x80-\xff]#', $this->_string)) { return $this; } $string = $this->_string; $transId = 'Any-Latin; ' . '[\p{S}] Name; ' . 'Latin-ASCII'; if (null !== $transliterator = static::getTransliterator($transId)) { $this->_string = preg_replace_callback('#\\\\N\{([A-Z ]+)\}#u', function (array $matches) { return '(' . strtolower($matches[1]) . ')'; }, $transliterator->transliterate($string)); return $this; } if (\false === class_exists('Normalizer')) { if (\false === $try) { throw new \Hoa\Ustring\Exception('%s needs the class Normalizer to work properly, ' . 'or you can force a try by using %1$s(true).', 0, __METHOD__); } $string = static::transcode($string, 'UTF-8', 'ASCII//IGNORE//TRANSLIT'); $this->_string = preg_replace('#(?:[\'"`^](\w))#u', '\1', $string); return $this; } $string = \Normalizer::normalize($string, \Normalizer::NFKD); $string = preg_replace('#\p{Mn}+#u', '', $string); $this->_string = static::transcode($string, 'UTF-8', 'ASCII//IGNORE//TRANSLIT'); return $this; } /** * Transliterate the string into another. * See self::getTransliterator for more information. * * @param string $identifier Identifier. * @param int $start Start. * @param int $end End. * @return \Hoa\Ustring * @throws \Hoa\Ustring\Exception */ public function transliterate($identifier, $start = 0, $end = null) { if (null === $transliterator = static::getTransliterator($identifier)) { throw new \Hoa\Ustring\Exception('%s needs the class Transliterator to work properly.', 1, __METHOD__); } $this->_string = $transliterator->transliterate($this->_string, $start, $end); return $this; } /** * Get transliterator. * See http://userguide.icu-project.org/transforms/general for $identifier. * * @param string $identifier Identifier. * @return \Transliterator */ public static function getTransliterator($identifier) { if (\false === class_exists('Transliterator')) { return null; } return \Transliterator::create($identifier); } /** * Strip characters (default \s) of the current string. * * @param string $regex Characters to remove. * @param int $side Whether we trim the beginning, the end or both * sides, of the current string. * @return \Hoa\Ustring */ public function trim($regex = '\s', $side = 3) { $regex = '(?:' . $regex . ')+'; $handle = null; if (0 !== ($side & static::BEGINNING)) { $handle .= '(^' . $regex . ')'; } if (0 !== ($side & static::END)) { if (null !== $handle) { $handle .= '|'; } $handle .= '(' . $regex . '$)'; } $this->_string = preg_replace('#' . $handle . '#u', '', $this->_string); $this->_direction = null; return $this; } /** * Compute offset (negative, unbound etc.). * * @param int $offset Offset. * @return int */ protected function computeOffset($offset) { $length = mb_strlen($this->_string); if (0 > $offset) { $offset = -$offset % $length; if (0 !== $offset) { $offset = $length - $offset; } } elseif ($offset >= $length) { $offset %= $length; } return $offset; } /** * Get a specific chars of the current string. * * @param int $offset Offset (can be negative and unbound). * @return string */ public function offsetGet($offset) { return mb_substr($this->_string, $this->computeOffset($offset), 1); } /** * Set a specific character of the current string. * * @param int $offset Offset (can be negative and unbound). * @param string $value Value. * @return \Hoa\Ustring */ public function offsetSet($offset, $value) { $head = null; $offset = $this->computeOffset($offset); if (0 < $offset) { $head = mb_substr($this->_string, 0, $offset); } $tail = mb_substr($this->_string, $offset + 1); $this->_string = $head . $value . $tail; $this->_direction = null; return $this; } /** * Delete a specific character of the current string. * * @param int $offset Offset (can be negative and unbound). * @return string */ public function offsetUnset($offset) { return $this->offsetSet($offset, null); } /** * Check if a specific offset exists. * * @return bool */ public function offsetExists($offset) { return \true; } /** * Reduce the strings. * * @param int $start Position of first character. * @param int $length Maximum number of characters. * @return \Hoa\Ustring */ public function reduce($start, $length = null) { $this->_string = mb_substr($this->_string, $start, $length); return $this; } /** * Count number of characters of the current string. * * @return int */ public function count() { return mb_strlen($this->_string); } /** * Get byte (not character) at a specific offset. * * @param int $offset Offset (can be negative and unbound). * @return string */ public function getByteAt($offset) { $length = strlen($this->_string); if (0 > $offset) { $offset = -$offset % $length; if (0 !== $offset) { $offset = $length - $offset; } } elseif ($offset >= $length) { $offset %= $length; } return $this->_string[$offset]; } /** * Count number of bytes (not characters) of the current string. * * @return int */ public function getBytesLength() { return strlen($this->_string); } /** * Get the width of the current string. * Useful when printing the string in monotype (some character need more * than one column to be printed). * * @return int */ public function getWidth() { return mb_strwidth($this->_string); } /** * Get direction of the current string. * Please, see the self::LTR and self::RTL constants. * It does not yet support embedding directions. * * @return int */ public function getDirection() { if (null === $this->_direction) { if (null === $this->_string) { $this->_direction = static::LTR; } else { $this->_direction = static::getCharDirection(mb_substr($this->_string, 0, 1)); } } return $this->_direction; } /** * Get character of a specific character. * Please, see the self::LTR and self::RTL constants. * * @param string $char Character. * @return int */ public static function getCharDirection($char) { $c = static::toCode($char); if (!(0x5be <= $c && 0x10b7f >= $c)) { return static::LTR; } if (0x85e >= $c) { if (0x5be === $c || 0x5c0 === $c || 0x5c3 === $c || 0x5c6 === $c || 0x5d0 <= $c && 0x5ea >= $c || 0x5f0 <= $c && 0x5f4 >= $c || 0x608 === $c || 0x60b === $c || 0x60d === $c || 0x61b === $c || 0x61e <= $c && 0x64a >= $c || 0x66d <= $c && 0x66f >= $c || 0x671 <= $c && 0x6d5 >= $c || 0x6e5 <= $c && 0x6e6 >= $c || 0x6ee <= $c && 0x6ef >= $c || 0x6fa <= $c && 0x70d >= $c || 0x710 === $c || 0x712 <= $c && 0x72f >= $c || 0x74d <= $c && 0x7a5 >= $c || 0x7b1 === $c || 0x7c0 <= $c && 0x7ea >= $c || 0x7f4 <= $c && 0x7f5 >= $c || 0x7fa === $c || 0x800 <= $c && 0x815 >= $c || 0x81a === $c || 0x824 === $c || 0x828 === $c || 0x830 <= $c && 0x83e >= $c || 0x840 <= $c && 0x858 >= $c || 0x85e === $c) { return static::RTL; } } elseif (0x200f === $c) { return static::RTL; } elseif (0xfb1d <= $c) { if (0xfb1d === $c || 0xfb1f <= $c && 0xfb28 >= $c || 0xfb2a <= $c && 0xfb36 >= $c || 0xfb38 <= $c && 0xfb3c >= $c || 0xfb3e === $c || 0xfb40 <= $c && 0xfb41 >= $c || 0xfb43 <= $c && 0xfb44 >= $c || 0xfb46 <= $c && 0xfbc1 >= $c || 0xfbd3 <= $c && 0xfd3d >= $c || 0xfd50 <= $c && 0xfd8f >= $c || 0xfd92 <= $c && 0xfdc7 >= $c || 0xfdf0 <= $c && 0xfdfc >= $c || 0xfe70 <= $c && 0xfe74 >= $c || 0xfe76 <= $c && 0xfefc >= $c || 0x10800 <= $c && 0x10805 >= $c || 0x10808 === $c || 0x1080a <= $c && 0x10835 >= $c || 0x10837 <= $c && 0x10838 >= $c || 0x1083c === $c || 0x1083f <= $c && 0x10855 >= $c || 0x10857 <= $c && 0x1085f >= $c || 0x10900 <= $c && 0x1091b >= $c || 0x10920 <= $c && 0x10939 >= $c || 0x1093f === $c || 0x10a00 === $c || 0x10a10 <= $c && 0x10a13 >= $c || 0x10a15 <= $c && 0x10a17 >= $c || 0x10a19 <= $c && 0x10a33 >= $c || 0x10a40 <= $c && 0x10a47 >= $c || 0x10a50 <= $c && 0x10a58 >= $c || 0x10a60 <= $c && 0x10a7f >= $c || 0x10b00 <= $c && 0x10b35 >= $c || 0x10b40 <= $c && 0x10b55 >= $c || 0x10b58 <= $c && 0x10b72 >= $c || 0x10b78 <= $c && 0x10b7f >= $c) { return static::RTL; } } return static::LTR; } /** * Get the number of column positions of a wide-character. * * This is a PHP implementation of wcwidth() and wcswidth() (defined in IEEE * Std 1002.1-2001) for Unicode, by Markus Kuhn. Please, see * http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c. * * The wcwidth(wc) function shall either return 0 (if wc is a null * wide-character code), or return the number of column positions to be * occupied by the wide-character code wc, or return -1 (if wc does not * correspond to a printable wide-character code). * * @param string $char Character. * @return int */ public static function getCharWidth($char) { $char = (string) $char; $c = static::toCode($char); // Test for 8-bit control characters. if (0x0 === $c) { return 0; } if (0x20 > $c || 0x7f <= $c && $c < 0xa0) { return -1; } // Non-spacing characters. if (0xad !== $c && 0 !== preg_match('#^[\p{Mn}\p{Me}\p{Cf}\x{1160}-\x{11ff}\x{200b}]#u', $char)) { return 0; } // If we arrive here, $c is not a combining C0/C1 control character. return 1 + (0x1100 <= $c && (0x115f >= $c || 0x2329 === $c || 0x232a === $c || 0x2e80 <= $c && 0xa4cf >= $c && 0x303f !== $c || 0xac00 <= $c && 0xd7a3 >= $c || 0xf900 <= $c && 0xfaff >= $c || 0xfe10 <= $c && 0xfe19 >= $c || 0xfe30 <= $c && 0xfe6f >= $c || 0xff00 <= $c && 0xff60 >= $c || 0xffe0 <= $c && 0xffe6 >= $c || 0x20000 <= $c && 0x2fffd >= $c || 0x30000 <= $c && 0x3fffd >= $c)); } /** * Check whether the character is printable or not. * * @param string $char Character. * @return bool */ public static function isCharPrintable($char) { return 1 <= static::getCharWidth($char); } /** * Get a UTF-8 character from its decimal code representation. * * @param int $code Code. * @return string */ public static function fromCode($code) { return mb_convert_encoding('&#x' . dechex($code) . ';', 'UTF-8', 'HTML-ENTITIES'); } /** * Get a decimal code representation of a specific character. * * @param string $char Character. * @return int */ public static function toCode($char) { $char = (string) $char; $code = ord($char[0]); $bytes = 1; if (!($code & 0x80)) { // 0xxxxxxx return $code; } if (($code & 0xe0) === 0xc0) { // 110xxxxx $bytes = 2; $code = $code & ~0xc0; } elseif (($code & 0xf0) == 0xe0) { // 1110xxxx $bytes = 3; $code = $code & ~0xe0; } elseif (($code & 0xf8) === 0xf0) { // 11110xxx $bytes = 4; $code = $code & ~0xf0; } for ($i = 2; $i <= $bytes; $i++) { // 10xxxxxx $code = ($code << 6) + (ord($char[$i - 1]) & ~0x80); } return $code; } /** * Get a binary representation of a specific character. * * @param string $char Character. * @return string */ public static function toBinaryCode($char) { $char = (string) $char; $out = null; for ($i = 0, $max = strlen($char); $i < $max; ++$i) { $out .= vsprintf('%08b', ord($char[$i])); } return $out; } /** * Transcode. * * @param string $string String. * @param string $from Original encoding. * @param string $to Final encoding. * @return string * @throws \Hoa\Ustring\Exception */ public static function transcode($string, $from, $to = 'UTF-8') { if (\false === static::checkIconv()) { throw new \Hoa\Ustring\Exception('%s needs the iconv extension.', 2, __CLASS__); } return iconv($from, $to, $string); } /** * Check if a string is encoded in UTF-8. * * @param string $string String. * @return bool */ public static function isUtf8($string) { return (bool) preg_match('##u', $string); } /** * Copy current object string * * @return \Hoa\Ustring */ public function copy() { return clone $this; } /** * Transform the object as a string. * * @return string */ public function __toString() { return $this->_string; } } /** * Flex entity. */ Consistency::flexEntity('Hoa\Ustring\Ustring'); if (\false === \Hoa\Ustring\Ustring::checkMbString()) { throw new \Hoa\Ustring\Exception('%s needs the mbstring extension.', 0, __NAMESPACE__ . '\Ustring'); } when($result = new \Mock\Hoa\Visitor\Element())->object($result)->isInstanceOf('Hoa\Visitor\Element'); } } when($result = new \Mock\Hoa\Visitor\Visit())->object($result)->isInstanceOf('Hoa\Visitor\Visit'); } } implementsInterface('\Hoa\Zformat\Parameterizable')) { throw new \Hoa\Zformat\Exception('Only parameterizable object can have parameter; ' . '%s does implement \Hoa\Zformat\Parameterizable.', 1, $owner); } } $this->_owner = $owner; $this->setKeywords($keywords); $this->setDefault($parameters); return; } /** * Initialize constants. * * @return void */ public static function initializeConstants() { $c = explode('…', date('d…j…N…w…z…W…m…n…Y…y…g…G…h…H…i…s…u…O…T…U')); self::$_constants = ['d' => $c[0], 'j' => $c[1], 'N' => $c[2], 'w' => $c[3], 'z' => $c[4], 'W' => $c[5], 'm' => $c[6], 'n' => $c[7], 'Y' => $c[8], 'y' => $c[9], 'g' => $c[10], 'G' => $c[11], 'h' => $c[12], 'H' => $c[13], 'i' => $c[14], 's' => $c[15], 'u' => $c[16], 'O' => $c[17], 'T' => $c[18], 'U' => $c[19]]; return; } /** * Get constants. * * @return array */ public static function getConstants() { return self::$_constants; } /** * Set default parameters to a class. * * @param array $parameters Parameters to set. * @return void * @throws \Hoa\Zformat\Exception */ private function setDefault(array $parameters) { $this->_parameters = $parameters; return; } /** * Set parameters. * * @param array $parameters Parameters. * @return void */ public function setParameters(array $parameters) { $this->resetCache(); foreach ($parameters as $key => $value) { $this->setParameter($key, $value); } return; } /** * Get parameters. * * @return array */ public function getParameters() { return $this->_parameters; } /** * Set a parameter. * * @param string $key Key. * @param mixed $value Value. * @return mixed */ public function setParameter($key, $value) { $this->resetCache(); $old = null; if (\true === array_key_exists($key, $this->_parameters)) { $old = $this->_parameters[$key]; } $this->_parameters[$key] = $value; return $old; } /** * Get a parameter. * * @param string $parameter Parameter. * @return mixed */ public function getParameter($parameter) { if (array_key_exists($parameter, $this->_parameters)) { return $this->_parameters[$parameter]; } return null; } /** * Get a formatted parameter (i.e. zFormatted). * * @param string $parameter Parameter. * @return mixed */ public function getFormattedParameter($parameter) { if (null === $value = $this->getParameter($parameter)) { return null; } return $this->zFormat($value); } /** * Check a branch exists. * * @param string $branch Branch. * @return bool */ public function branchExists($branch) { $qBranch = preg_quote($branch); foreach ($this->getParameters() as $key => $value) { if (0 !== preg_match('#^' . $qBranch . '(.*)?#', $key)) { return \true; } } return \false; } /** * Unlinearize a branch to an array. * * @param string $branch Branch. * @return array */ public function unlinearizeBranch($branch) { $parameters = $this->getParameters(); $out = []; $lBranch = strlen($branch); foreach ($parameters as $key => $value) { if ($branch !== substr($key, 0, $lBranch)) { continue; } $handle = []; $explode = preg_split('#((?= 0) { $explode[$i] = str_replace('\.', '.', $explode[$i]); if ($i != $end) { $handle = [$explode[$i] => $handle]; } else { $handle = [$explode[$i] => $this->zFormat($value)]; } --$i; } $out = array_merge_recursive($out, $handle); } return $out; } /** * Set keywords. * * @param array $keywords Keywords. * @return void * @throws \Hoa\Zformat\Exception */ public function setKeywords($keywords) { $this->resetCache(); foreach ($keywords as $key => $value) { $this->setKeyword($key, $value); } return; } /** * Get keywords. * * @return array */ public function getKeywords() { return $this->_keywords; } /** * Set a keyword. * * @param string $key Key. * @param mixed $value Value. * @return mixed */ public function setKeyword($key, $value) { $this->resetCache(); $old = null; if (\true === array_key_exists($key, $this->_keywords)) { $old = $this->_keywords[$key]; } $this->_keywords[$key] = $value; return $old; } /** * Get a keyword. * * @param string $keyword Keyword. * @return mixed */ public function getKeyword($keyword) { if (\true === array_key_exists($keyword, $this->_keywords)) { return $this->_keywords[$keyword]; } return null; } /** * zFormat a string. * zFormat is inspired from the famous Zsh (please, take a look at * http://zsh.org), and specifically from ZStyle. * * ZFormat has the following pattern: * (:subject[:format]:) * * where subject could be a: * • keyword, i.e. a simple string: foo; * • reference to an existing parameter, i.e. a simple string prefixed by * a %: %bar; * • constant, i.e. a combination of chars, first is prefixed by a _: _Ymd * will given the current year, followed by the current month and * finally the current day. * * and where the format is a combination of chars, that apply functions on * the subject: * • h: to get the head of a path (equivalent to dirname); * • t: to get the tail of a path (equivalent to basename); * • r: to get the path without extension; * • e: to get the extension; * • l: to get the result in lowercase; * • u: to get the result in uppercase; * • U: to get the result with the first letter in uppercase (understand * classname); * • s///: to replace all matches by (the last / is * optional, only if more options are given after); * • s%%%: to replace the prefix by (the last % is * also optional); * • s###: to replace the suffix by (the last # is * also optional). * * Known constants are: * • d: day of the month, 2 digits with leading zeros; * • j: day of the month without leading zeros; * • N: ISO-8601 numeric representation of the day of the week; * • w: numeric representation of the day of the week; * • z: the day of the year (starting from 0); * • W: ISO-8601 week number of year, weeks starting on Monday; * • m: numeric representation of a month, with leading zeros; * • n: numeric representation of a month, without leading zeros; * • Y: a full numeric representation of a year, 4 digits; * • y: a two digit representation of a year; * • g: 12-hour format of an hour without leading zeros; * • G: 24-hour format of an hour without leading zeros; * • h: 12-hour format of an hour with leading zeros; * • H: 24-hour format of an hour with leading zeros; * • i: minutes with leading zeros; * • s: seconds with leading zeros; * • u: microseconds; * • O: difference to Greenwich time (GMT) in hours; * • T: timezone abbreviation; * • U: seconds since the Unix Epoch (a timestamp). * They are very useful for dynamic cache paths for example. * * Examples: * Let keywords $k and parameters $p: * $k = [ * 'foo' => 'bar', * 'car' => 'DeLoReAN', * 'power' => 2.21, * 'answerTo' => 'life_universe_everything_else', * 'answerIs' => 42, * 'hello' => 'wor.l.d' * ]; * $p = [ * 'plpl' => '(:foo:U:)', * 'foo' => 'ar(:%plpl:)', * 'favoriteCar' => 'A (:car:l:)!', * 'truth' => 'To (:answerTo:ls/_/ /U:) is (:answerIs:).', * 'file' => '/a/file/(:_Ymd:)/(:hello:trr:).(:power:e:)', * 'recursion' => 'oof(:%foo:s#ar#az:)' * ]; * Then, after applying the zFormat, we get: * • plpl: 'Bar', put the first letter in uppercase; * • foo: 'arBar', call the parameter plpl; * • favoriteCar: 'A delorean!', all is in lowercase; * • truth: 'To Life universe everything else is 42', all is in * lowercase, then replace underscores by spaces, and * finally put the first letter in uppercase; and no * transformation for 42; * • file: '/a/file/20090505/wor.21', get date constants, then * get the tail of the path and remove extension twice, * and add the extension of power; * • recursion: 'oofarBaz', get 'arbar' first, and then, replace the * suffix 'ar' by 'az'. * * @param string $value Parameter value. * @return string * @throws \Hoa\Zformat\Exception */ public function zFormat($value) { if (!is_string($value)) { return $value; } if (isset($this->_cache[$value])) { return $this->_cache[$value]; } if (null === self::$_constants) { self::initializeConstants(); } $self = $this; $keywords = $this->getKeywords(); $parameters = $this->getParameters(); return $this->_cache[$value] = preg_replace_callback('#\(:(.*?):\)#', function ($match) use ($self, $value, &$keywords, &$parameters) { preg_match('#([^:]+)(?::(.*))?#', $match[1], $submatch); if (!isset($submatch[1])) { return ''; } $out = null; $key = $submatch[1]; $word = substr($key, 1); // Call a parameter. if ('%' == $key[0]) { if (\false === array_key_exists($word, $parameters)) { throw new \Hoa\Zformat\Exception('Parameter %s is not found in parameters.', 0, $word); } $handle = $parameters[$word]; $out = $self->zFormat($handle); } elseif ('_' == $key[0]) { $constants = \Hoa\Zformat\Parameter::getConstants(); foreach (str_split($word) as $k => $v) { if (!isset($constants[$v])) { throw new \Hoa\Zformat\Exception('Constant char %s is not supported in the ' . 'rule %s.', 1, [$v, $value]); } $out .= $constants[$v]; } } else { if (\false === array_key_exists($key, $keywords)) { throw new \Hoa\Zformat\Exception('Keyword %s is not found in the rule %s.', 2, [$key, $value]); } $out = $keywords[$key]; } if (!isset($submatch[2])) { return $out; } preg_match_all('#(h|t|r|e|l|u|U|s(/|%|\#)(.*?)(? $flag) { switch ($flag) { case 'h': $out = dirname($out); break; case 't': $out = basename($out); break; case 'r': if (\false !== $position = strrpos($out, '.', 1)) { $out = substr($out, 0, $position); } break; case 'e': if (\false !== $position = strrpos($out, '.', 1)) { $out = substr($out, $position + 1); } break; case 'l': $out = strtolower($out); break; case 'u': $out = strtoupper($out); break; case 'U': $handle = null; foreach (explode('\\', $out) as $part) { if (null === $handle) { $handle = ucfirst($part); } else { $handle .= '\\' . ucfirst($part); } } $out = $handle; break; default: if (!isset($flags[3]) && !isset($flags[4])) { throw new \Hoa\Zformat\Exception('Unrecognized format pattern in the rule %s.', 4, $value); } $l = preg_quote($flags[3][$i], '#'); $r = $flags[4][$i]; switch ($flags[2][$i]) { case '%': $l = '^' . $l; break; case '#': $l .= '$'; break; } $out = preg_replace('#' . $l . '#', $r, $out); } } return $out; }, $value); } /** * Reset zFormat cache. * * @return void */ private function resetCache() { unset($this->_cache); $this->_cache = []; return; } } * The argument offset. Function arguments are counted starting from * zero. *

* @return mixed|false the specified argument, or false on error. */ #[Pure] function func_get_arg(int $position): mixed {} /** * Returns an array comprising a function's argument list * @link https://php.net/manual/en/function.func-get-args.php * @return array an array in which each element is a copy of the corresponding * member of the current user-defined function's argument list. */ #[Pure] function func_get_args(): array {} /** * Get string length * @link https://php.net/manual/en/function.strlen.php * @param string $string

* The string being measured for length. *

* @return int<0,max> The length of the string on success, * and 0 if the string is empty. */ #[Pure] function strlen(string $string): int {} /** * Binary safe string comparison * @link https://php.net/manual/en/function.strcmp.php * @param string $string1

* The first string. *

* @param string $string2

* The second string. *

* @return int less 0 if str1 is less than * str2; > 0 if str1 * is greater than str2, and 0 if they are * equal. */ #[Pure] function strcmp(string $string1, string $string2): int {} /** * Binary safe string comparison of the first n characters * @link https://php.net/manual/en/function.strncmp.php * @param string $string1

* The first string. *

* @param string $string2

* The second string. *

* @param int $length

* Number of characters to use in the comparison. *

* @return int less 0 if str1 is less than * str2; > 0 if str1 * is greater than str2, and 0 if they are * equal. */ #[Pure] function strncmp(string $string1, string $string2, int $length): int {} /** * Binary safe case-insensitive string comparison * @link https://php.net/manual/en/function.strcasecmp.php * @param string $string1

* The first string *

* @param string $string2

* The second string *

* @return int less than 0 if str1 is less than * str2; > 0 if str1 * is greater than str2, and 0 if they are * equal. */ #[Pure] function strcasecmp(string $string1, string $string2): int {} /** * Binary safe case-insensitive string comparison of the first n characters * @link https://php.net/manual/en/function.strncasecmp.php * @param string $string1

* The first string. *

* @param string $string2

* The second string. *

* @param int $length

* The length of strings to be used in the comparison. *

* @return int less than 0 if str1 is less than * str2; > 0 if str1 is * greater than str2, and 0 if they are equal. */ #[Pure] function strncasecmp(string $string1, string $string2, int $length): int {} /** * The function returns {@see true} if the passed $haystack starts from the * $needle string or {@see false} otherwise. * * @param string $haystack * @param string $needle * @return bool * @since 8.0 */ #[Pure] function str_starts_with(string $haystack, string $needle): bool {} /** * The function returns {@see true} if the passed $haystack ends with the * $needle string or {@see false} otherwise. * * @param string $haystack * @param string $needle * @return bool * @since 8.0 */ #[Pure] function str_ends_with(string $haystack, string $needle): bool {} /** * Checks if $needle is found in $haystack and returns a boolean value * (true/false) whether or not the $needle was found. * * @param string $haystack * @param string $needle * @return bool * @since 8.0 */ #[Pure] function str_contains(string $haystack, string $needle): bool {} /** * @since 8.3 */ function str_decrement(string $string): string {} /** * @since 8.3 */ function str_increment(string $string): string {} /** * Return the current key and value pair from an array and advance the array cursor * @link https://php.net/manual/en/function.each.php * @param array|ArrayObject &$array

* The input array. *

* @return array the current key and value pair from the array * array. This pair is returned in a four-element * array, with the keys 0, 1, * key, and value. Elements * 0 and key contain the key name of * the array element, and 1 and value * contain the data. *

*

* If the internal pointer for the array points past the end of the * array contents, each returns * false. * @removed 8.0 */ #[Deprecated(reason: "Use a foreach loop instead", since: "7.2")] function each(&$array): array {} /** * Sets which PHP errors are reported * @link https://php.net/manual/en/function.error-reporting.php * @param int|null $error_level [optional]

* The new error_reporting * level. It takes on either a bitmask, or named constants. Using named * constants is strongly encouraged to ensure compatibility for future * versions. As error levels are added, the range of integers increases, * so older integer-based error levels will not always behave as expected. *

*

* The available error level constants and the actual * meanings of these error levels are described in the * predefined constants. * * error_reporting level constants and bit values * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
valueconstant
1 * E_ERROR *
2 * E_WARNING *
4 * E_PARSE *
8 * E_NOTICE *
16 * E_CORE_ERROR *
32 * E_CORE_WARNING *
64 * E_COMPILE_ERROR *
128 * E_COMPILE_WARNING *
256 * E_USER_ERROR *
512 * E_USER_WARNING *
1024 * E_USER_NOTICE *
32767 * E_ALL *
2048 * E_STRICT *
4096 * E_RECOVERABLE_ERROR *
8192 * E_DEPRECATED *
16384 * E_USER_DEPRECATED *
*

* @return int the old error_reporting * level or the current level if no level parameter is * given. */ function error_reporting(?int $error_level = null): int {} /** * Defines a named constant * @link https://php.net/manual/en/function.define.php * @param string $constant_name

* The name of the constant. *

* @param null|array|bool|int|float|string $value

* The value of the constant. * In PHP 5, value must be a scalar value (integer, float, string, boolean, or null). * In PHP 7, array values are also accepted. * It is possible to define resource constants, * however it is not recommended and may cause unpredictable behavior. *

* @param bool $case_insensitive [optional]

* If set to true, the constant will be defined case-insensitive. * The default behavior is case-sensitive; i.e. * CONSTANT and Constant represent * different values. * Defining case-insensitive constants is deprecated as of PHP 7.3.0. *

*

* Case-insensitive constants are stored as lower-case. *

* @return bool true on success or false on failure. */ function define( string $constant_name, #[LanguageLevelTypeAware(['8.1' => 'mixed'], default: 'null|array|bool|int|float|string')] $value, #[Deprecated(since: "7.3")] bool $case_insensitive = false ): bool {} /** * Checks whether a given named constant exists * @link https://php.net/manual/en/function.defined.php * @param string $constant_name

* The constant name. *

* @return bool true if the named constant given by name * has been defined, false otherwise. */ #[Pure(true)] function defined(string $constant_name): bool {} /** * Returns the name of the class of an object * @link https://php.net/manual/en/function.get-class.php * @param object $object [optional]

* The tested object. This parameter may be omitted when inside a class. *

* @return string

The name of the class of which object is an * instance. * If object is omitted when inside a class, the * name of that class is returned.

*/ #[Pure] function get_class(object $object): string {} /** * the "Late Static Binding" class name * @link https://php.net/manual/en/function.get-called-class.php * @return string */ #[Pure] function get_called_class(): string {} /** * Retrieves the parent class name for object or class * @link https://php.net/manual/en/function.get-parent-class.php * @param object|string $object_or_class [optional]

* The tested object or class name *

* @return string|false

The name of the parent class of the class of which * object is an instance or the name. *

*

* If the object does not have a parent false will be returned. *

*

* If called without parameter outside object, this function returns false.

*/ #[Pure] function get_parent_class(object|string $object_or_class): string|false {} /** * Checks if the class method exists * @link https://php.net/manual/en/function.method-exists.php * @param object|string $object_or_class

* An object instance or a class name *

* @param string $method

* The method name *

* @return bool true if the method given by method_name * has been defined for the given object, false * otherwise. */ #[Pure] function method_exists($object_or_class, string $method): bool {} /** * Checks if the object or class has a property * @link https://php.net/manual/en/function.property-exists.php * @param object|string $object_or_class

* The class name or an object of the class to test for *

* @param string $property

* The name of the property *

* @return bool true if the property exists, false otherwise */ #[Pure] function property_exists($object_or_class, string $property): bool {} /** * Checks if the trait exists * @param string $trait Name of the trait to check * @param bool $autoload [optional] Whether to autoload if not already loaded. * @return bool Returns true if trait exists, false otherwise * @link https://secure.php.net/manual/en/function.trait-exists.php * @since 5.4 */ function trait_exists(string $trait, bool $autoload = true): bool {} /** * Checks if the class has been defined * @link https://php.net/manual/en/function.class-exists.php * @param string $class

* The class name. The name is matched in a case-insensitive manner. *

* @param bool $autoload [optional]

* Whether or not to call autoload by default. *

* @return bool true if class_name is a defined class, * false otherwise. */ function class_exists(string $class, bool $autoload = true): bool {} /** * Checks if the interface has been defined * @link https://php.net/manual/en/function.interface-exists.php * @param string $interface

* The interface name *

* @param bool $autoload [optional]

* Whether to call autoload or not by default. *

* @return bool true if the interface given by * interface_name has been defined, false otherwise. * @since 5.0.2 */ function interface_exists(string $interface, bool $autoload = true): bool {} /** * Return true if the given function has been defined * @link https://php.net/manual/en/function.function-exists.php * @param string $function

* The function name, as a string. *

* @return bool true if function_name exists and is a * function, false otherwise. *

*

* This function will return false for constructs, such as * include_once and echo. */ #[Pure(true)] function function_exists(string $function): bool {} /** * Checks if the enum has been defined * @link https://php.net/manual/en/function.enum-exists.php * @param string $enum

* The enum name. The name is matched in a case-insensitive manner. *

* @param bool $autoload [optional]

* Whether or not to call autoload by default. *

* @return bool true if enum is a defined enum, * false otherwise. * @since 8.1 */ function enum_exists(string $enum, bool $autoload = true): bool {} /** * Creates an alias for a class * @link https://php.net/manual/en/function.class-alias.php * @param string $class The original class. * @param string $alias The alias name for the class. * @param bool $autoload [optional] Whether to autoload if the original class is not found. * @return bool true on success or false on failure. */ function class_alias(string $class, string $alias, bool $autoload = true): bool {} /** * Returns an array with the names of included or required files * @link https://php.net/manual/en/function.get-included-files.php * @return string[] an array of the names of all files. *

* The script originally called is considered an "included file," so it will * be listed together with the files referenced by * include and family. *

*

* Files that are included or required multiple times only show up once in * the returned array. *

*/ #[Pure(true)] function get_included_files(): array {} /** * Alias of get_included_files * @link https://php.net/manual/en/function.get-required-files.php * @return string[] */ #[Pure(true)] function get_required_files(): array {} /** * checks if the object has this class as one of its parents or implements it * @link https://php.net/manual/en/function.is-subclass-of.php * @param object|string $object_or_class

* A class name or an object instance *

* @param string $class

* The class name *

* @param bool $allow_string [optional]

* If this parameter set to false, string class name as object is not allowed. * This also prevents from calling autoloader if the class doesn't exist. *

* @return bool This function returns true if the object object, * belongs to a class which is a subclass of * class_name, false otherwise. */ #[Pure] function is_subclass_of(mixed $object_or_class, string $class, bool $allow_string = true): bool {} /** * Checks if the object is of this class or has this class as one of its parents * @link https://php.net/manual/en/function.is-a.php * @param object|string $object_or_class

* The tested object *

* @param string $class

* The class name *

* @param bool $allow_string [optional]

* If this parameter set to FALSE, string class name as object * is not allowed. This also prevents from calling autoloader if the class doesn't exist. *

* @return bool TRUE if the object is of this class or has this class as one of * its parents, FALSE otherwise. */ #[Pure] function is_a(mixed $object_or_class, string $class, bool $allow_string = false): bool {} /** * Get the default properties of the class * @link https://php.net/manual/en/function.get-class-vars.php * @param string $class

* The class name *

* @return array an associative array of declared properties visible from the * current scope, with their default value. * The resulting array elements are in the form of * varname => value. */ #[Pure] function get_class_vars(string $class): array {} /** * Gets the properties of the given object * @link https://php.net/manual/en/function.get-object-vars.php * @param object $object

* An object instance. *

* @return array an associative array of defined object accessible non-static properties * for the specified object in scope. If a property have * not been assigned a value, it will be returned with a null value. */ #[Pure(true)] function get_object_vars(object $object): array {} /** * Gets the class methods' names * @link https://php.net/manual/en/function.get-class-methods.php * @param object|string $object_or_class

* The class name or an object instance *

* @return string[] an array of method names defined for the class specified by * class_name. In case of an error, it returns null. */ #[Pure] function get_class_methods(object|string $object_or_class): array {} /** * Generates a user-level error/warning/notice message * @link https://php.net/manual/en/function.trigger-error.php * @param string $message

* The designated error message for this error. It's limited to 1024 * characters in length. Any additional characters beyond 1024 will be * truncated. *

* @param int $error_level [optional]

* The designated error type for this error. It only works with the E_USER * family of constants, and will default to E_USER_NOTICE. *

* @return bool This function returns false if wrong error_type is * specified, true otherwise. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] function trigger_error(string $message, int $error_level = E_USER_NOTICE) {} /** * Alias of trigger_error * @link https://php.net/manual/en/function.user-error.php * @param string $message * @param int $error_level [optional] * @return bool This function returns false if wrong error_type is * specified, true otherwise. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] function user_error(string $message, int $error_level = E_USER_NOTICE) {} /** * Sets a user-defined error handler function * @link https://php.net/manual/en/function.set-error-handler.php * @param callable|null $callback

* The user function needs to accept two parameters: the error code, and a * string describing the error. Then there are three optional parameters * that may be supplied: the filename in which the error occurred, the * line number in which the error occurred, and the context in which the * error occurred (an array that points to the active symbol table at the * point the error occurred). The function can be shown as: *

*

* handler * interrno * stringerrstr * stringerrfile * interrline * arrayerrcontext * errno * The first parameter, errno, contains the * level of the error raised, as an integer.

* The user function should stop execution if necessary by calling `exit()`. * If the function returns a value other than false, script execution will * continue with the next statement after the one that caused an error. * If the function returns false, the standard PHP error handler is called. * @param int $error_levels [optional]

* Can be used to mask the triggering of the * error_handler function just like the error_reporting ini setting * controls which errors are shown. Without this mask set the * error_handler will be called for every error * regardless to the setting of the error_reporting setting. *

* @return callable|null a string containing the previously defined error handler (if any). If * the built-in error handler is used null is returned. null is also returned * in case of an error such as an invalid callback. If the previous error handler * was a class method, this function will return an indexed array with the class * and the method name. * * Note that error_handler chaining is possible by passing the output value as a reference: * ``` * $previousErrorHandler = set_error_handler( * static function (int $errNo, string $errstr, string $errFile, int $errLine) use (&$previousErrorHandler): bool { * // Handle specific scenarios * * return $previousErrorHandler !== null ? (bool) $previousErrorHandler(...func_get_args()) : false; * } * ); * ``` */ function set_error_handler(?callable $callback, int $error_levels = E_ALL) {} /** * Restores the previous error handler function * @link https://php.net/manual/en/function.restore-error-handler.php * @return bool This function always returns true. */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function restore_error_handler(): bool {} /** * @since 8.5 */ function get_error_handler(): ?callable {} /** * Sets a user-defined exception handler function * @link https://php.net/manual/en/function.set-exception-handler.php * @param callable|null $callback

* Name of the function to be called when an uncaught exception occurs. * This function must be defined before calling * set_exception_handler. This handler function * needs to accept one parameter, which will be the exception object that * was thrown. * NULL may be passed instead, to reset this handler to its default state. *

* @return callable|null the name of the previously defined exception handler, or null on error. If * no previous handler was defined, null is also returned. */ function set_exception_handler(?callable $callback) {} /** * @since 8.5 */ function get_exception_handler(): ?callable {} /** * Restores the previously defined exception handler function * @link https://php.net/manual/en/function.restore-exception-handler.php * @return bool This function always returns true. */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function restore_exception_handler(): bool {} /** * Returns an array with the name of the defined classes * @link https://php.net/manual/en/function.get-declared-classes.php * @return string[] an array of the names of the declared classes in the current script. *

* Note that depending on what extensions you have compiled or * loaded into PHP, additional classes could be present. This means that * you will not be able to define your own classes using these * names. There is a list of predefined classes in the Predefined Classes section of * the appendices. *

*/ #[Pure(true)] function get_declared_classes(): array {} /** * Returns an array of all declared interfaces * @link https://php.net/manual/en/function.get-declared-interfaces.php * @return string[] an array of the names of the declared interfaces in the current * script. */ #[Pure(true)] function get_declared_interfaces(): array {} /** * Returns an array of all declared traits * @return array with names of all declared traits in values. Returns NULL in case of a failure. * @link https://secure.php.net/manual/en/function.get-declared-traits.php * @see class_uses() * @since 5.4 */ #[Pure(true)] function get_declared_traits(): array {} /** * Returns an array of all defined functions * @link https://php.net/manual/en/function.get-defined-functions.php * @param bool $exclude_disabled [optional] Whether disabled functions should be excluded from the return value. * @return array an multidimensional array containing a list of all defined * functions, both built-in (internal) and user-defined. The internal * functions will be accessible via $arr["internal"], and * the user defined ones using $arr["user"] (see example * below). */ #[Pure(true)] function get_defined_functions(#[PhpStormStubsElementAvailable(from: '7.1')] #[Deprecated('Deprecated: has no effect since PHP 8.0', since:'8.5')] bool $exclude_disabled = true): array {} /** * Returns an array of all defined variables * @link https://php.net/manual/en/function.get-defined-vars.php * @return array A multidimensional array with all the variables. */ #[Pure(true)] function get_defined_vars(): array {} /** * Create an anonymous (lambda-style) function * @link https://php.net/manual/en/function.create-function.php * @param string $args

* The function arguments. *

* @param string $code

* The function code. *

* @return string|false a unique function name as a string, or false on error. * @removed 8.0 */ #[Deprecated(reason: "Use anonymous functions instead", since: "7.2")] function create_function(string $args, string $code): false|string {} /** * Returns the resource type * @link https://php.net/manual/en/function.get-resource-type.php * @param resource $resource

* The evaluated resource handle. *

* @return string If the given handle is a resource, this function * will return a string representing its type. If the type is not identified * by this function, the return value will be the string * Unknown. */ #[Pure(true)] function get_resource_type($resource): string {} /** * Returns an array with the names of all modules compiled and loaded * @link https://php.net/manual/en/function.get-loaded-extensions.php * @param bool $zend_extensions [optional]

* Only return Zend extensions, if not then regular extensions, like * mysqli are listed. Defaults to false (return regular extensions). *

* @return string[] an indexed array of all the modules names. */ #[Pure] function get_loaded_extensions(bool $zend_extensions = false): array {} /** * Find out whether an extension is loaded * @link https://php.net/manual/en/function.extension-loaded.php * @param string $extension

* The extension name. *

*

* You can see the names of various extensions by using * phpinfo or if you're using the * CGI or CLI version of * PHP you can use the -m switch to * list all available extensions: *

 * $ php -m
 * [PHP Modules]
 * xml
 * tokenizer
 * standard
 * sockets
 * session
 * posix
 * pcre
 * overload
 * mysql
 * mbstring
 * ctype
 * [Zend Modules]
 * 
*

* @return bool true if the extension identified by name * is loaded, false otherwise. */ #[Pure] function extension_loaded(string $extension): bool {} /** * Returns an array with the names of the functions of a module * @link https://php.net/manual/en/function.get-extension-funcs.php * @param string $extension

* The module name. *

*

* This parameter must be in lowercase. *

* @return string[]|false an array with all the functions, or false if * module_name is not a valid extension. */ #[Pure] function get_extension_funcs(string $extension): array|false {} /** * Returns an associative array with the names of all the constants and their values * @link https://php.net/manual/en/function.get-defined-constants.php * @param bool $categorize [optional]

* Causing this function to return a multi-dimensional * array with categories in the keys of the first dimension and constants * and their values in the second dimension. * * define("MY_CONSTANT", 1); * print_r(get_defined_constants(true)); * * The above example will output something similar to: *

 * Array
 * (
 * [Core] => Array
 * (
 * [E_ERROR] => 1
 * [E_WARNING] => 2
 * [E_PARSE] => 4
 * [E_NOTICE] => 8
 * [E_CORE_ERROR] => 16
 * [E_CORE_WARNING] => 32
 * [E_COMPILE_ERROR] => 64
 * [E_COMPILE_WARNING] => 128
 * [E_USER_ERROR] => 256
 * [E_USER_WARNING] => 512
 * [E_USER_NOTICE] => 1024
 * [E_STRICT] => 2048
 * [E_RECOVERABLE_ERROR] => 4096
 * [E_DEPRECATED] => 8192
 * [E_USER_DEPRECATED] => 16384
 * [E_ALL] => 32767
 * [TRUE] => 1
 * )
 * [pcre] => Array
 * (
 * [PREG_PATTERN_ORDER] => 1
 * [PREG_SET_ORDER] => 2
 * [PREG_OFFSET_CAPTURE] => 256
 * [PREG_SPLIT_NO_EMPTY] => 1
 * [PREG_SPLIT_DELIM_CAPTURE] => 2
 * [PREG_SPLIT_OFFSET_CAPTURE] => 4
 * [PREG_GREP_INVERT] => 1
 * )
 * [user] => Array
 * (
 * [MY_CONSTANT] => 1
 * )
 * )
 * 
*

* @return array */ #[Pure(true)] function get_defined_constants(bool $categorize = false): array {} /** * Generates a backtrace * @link https://php.net/manual/en/function.debug-backtrace.php * @param int $options [optional]

* As of 5.3.6, this parameter is a bitmask for the following options:

* debug_backtrace options * * * * * * * * * *
DEBUG_BACKTRACE_PROVIDE_OBJECT * Whether or not to populate the "object" index. *
DEBUG_BACKTRACE_IGNORE_ARGS * Whether or not to omit the "args" index, and thus all the function/method arguments, * to save memory. *
*

* Before 5.3.6, the only values recognized are true or false, which are the same as * setting or not setting the DEBUG_BACKTRACE_PROVIDE_OBJECT option respectively. *

* @param int $limit [optional]

* As of 5.4.0, this parameter can be used to limit the number of stack frames returned. * By default (limit=0) it returns all stack frames. *

* @return array

an array of associative arrays. The possible returned elements * are as follows: *

*

* Possible returned elements from debug_backtrace *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
NameTypeDescription
functionstring * The current function name. See also * __FUNCTION__. *
lineinteger * The current line number. See also * __LINE__. *
filestring * The current file name. See also * __FILE__. *
classstring * The current class name. See also * __CLASS__ *
objectobject * The current object. *
typestring * The current call type. If a method call, "->" is returned. If a static * method call, "::" is returned. If a function call, nothing is returned. *
argsarray * If inside a function, this lists the functions arguments. If * inside an included file, this lists the included file name(s). *
*/ #[Pure(true)] function debug_backtrace(int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT, int $limit = 0): array {} /** * Prints a backtrace * @link https://php.net/manual/en/function.debug-print-backtrace.php * @param int $options [optional]

* As of 5.3.6, this parameter is a bitmask for the following options: * debug_print_backtrace options * * * * * *
DEBUG_BACKTRACE_IGNORE_ARGS * Whether or not to omit the "args" index, and thus all the function/method arguments, * to save memory. *
*

* @param int $limit [optional]

* As of 5.4.0, this parameter can be used to limit the number of stack frames printed. * By default (limit = 0) it prints all stack frames. *

* @return void */ function debug_print_backtrace( int $options = 0, #[PhpStormStubsElementAvailable(from: '7.0')] int $limit = 0 ): void {} /** * Forces collection of any existing garbage cycles * @link https://php.net/manual/en/function.gc-collect-cycles.php * @return int number of collected cycles. */ function gc_collect_cycles(): int {} /** * Returns status of the circular reference collector * @link https://php.net/manual/en/function.gc-enabled.php * @return bool true if the garbage collector is enabled, false otherwise. */ #[Pure(true)] function gc_enabled(): bool {} /** * Activates the circular reference collector * @link https://php.net/manual/en/function.gc-enable.php * @return void */ function gc_enable(): void {} /** * Deactivates the circular reference collector * @link https://php.net/manual/en/function.gc-disable.php * @return void */ function gc_disable(): void {} /** * Gets information about the garbage collector * @link https://php.net/manual/en/function.gc-status.php * @return int[] associative array with the following elements: *
    *
  • "runs"
  • *
  • "collected"
  • *
  • "threshold"
  • *
  • "roots"
  • *
* @since 7.3 */ #[ArrayShape(["runs" => "int", "collected" => "int", "threshold" => "int", "roots" => "int"])] #[Pure(true)] function gc_status(): array {} /** * Reclaims memory used by the Zend Engine memory manager * @link https://php.net/manual/en/function.gc-mem-caches.php * @return int Returns the number of bytes freed. * @since 7.0 */ function gc_mem_caches(): int {} /** * Returns active resources * @link https://php.net/manual/en/function.get-resources.php * @param string|null $type [optional]

* * If defined, this will cause get_resources() to only return resources of the given type. A list of resource types is available. * * If the string Unknown is provided as the type, then only resources that are of an unknown type will be returned. * * If omitted, all resources will be returned. *

* @return resource[] Returns an array of currently active resources, indexed by resource number. * @since 7.0 */ #[Pure(true)] function get_resources(?string $type = null): array {} /** * @since 8.4 */ function exit(string|int $status = 0): never {} /** * @since 8.4 */ function die(string|int $status = 0): never {} /** * @template TObject of object * @param TObject $object * @param array $withProperties [optional] * @return TObject * @since 8.5 */ function clone(object $object, array $withProperties = []): object {} */ interface Traversable extends iterable {} /** * Interface to create an external Iterator. * @link https://php.net/manual/en/class.iteratoraggregate.php * @template TKey * @template-covariant TValue * @template-extends Traversable */ interface IteratorAggregate extends Traversable { /** * Retrieve an external iterator * @link https://php.net/manual/en/iteratoraggregate.getiterator.php * @return Traversable|TValue[] An instance of an object implementing Iterator or * Traversable * @throws Exception on failure. */ #[TentativeType] public function getIterator(): Traversable; } /** * Interface for external iterators or objects that can be iterated * themselves internally. * @link https://php.net/manual/en/class.iterator.php * @template TKey * @template-covariant TValue * @template-extends Traversable */ interface Iterator extends Traversable { /** * Return the current element * @link https://php.net/manual/en/iterator.current.php * @return TValue Can return any type. */ #[TentativeType] public function current(): mixed; /** * 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 TKey|null TKey on success, or null on failure. */ #[TentativeType] public function key(): mixed; /** * 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] public function valid(): bool; /** * 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; } /** * Interface to provide accessing objects as arrays. * @link https://php.net/manual/en/class.arrayaccess.php * @template TKey * @template TValue */ interface ArrayAccess { /** * Whether a offset exists * @link https://php.net/manual/en/arrayaccess.offsetexists.php * @param TKey $offset

* An offset to check for. *

* @return bool true on success or false on failure. *

*

* The return value will be casted to boolean if non-boolean was returned. */ #[TentativeType] public function offsetExists(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $offset): bool; /** * Offset to retrieve * @link https://php.net/manual/en/arrayaccess.offsetget.php * @param TKey $offset

* The offset to retrieve. *

* @return TValue Can return all value types. */ #[TentativeType] public function offsetGet(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $offset): mixed; /** * Offset to set * @link https://php.net/manual/en/arrayaccess.offsetset.php * @param TKey $offset

* The offset to assign the value to. *

* @param TValue $value

* The value to set. *

* @return void */ #[TentativeType] public function offsetSet( #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $offset, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value ): void; /** * Offset to unset * @link https://php.net/manual/en/arrayaccess.offsetunset.php * @param TKey $offset

* The offset to unset. *

* @return void */ #[TentativeType] public function offsetUnset(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $offset): void; } /** * Interface for customized serializing.
* As of PHP 8.1.0, a class which implements Serializable without also implementing `__serialize()` and `__unserialize()` * will generate a deprecation warning. * @link https://php.net/manual/en/class.serializable.php */ interface Serializable { /** * String representation of object. * @link https://php.net/manual/en/serializable.serialize.php * @return string|null The string representation of the object or null * @throws Exception Returning other type than string or null */ public function serialize(); /** * Constructs the object. * @link https://php.net/manual/en/serializable.unserialize.php * @param string $data The string representation of the object. * @return void */ public function unserialize(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data); } /** * Throwable is the base interface for any object that can be thrown via a throw statement in PHP 7, * including Error and Exception. * @link https://php.net/manual/en/class.throwable.php * @since 7.0 */ interface Throwable extends Stringable { /** * Gets the message * @link https://php.net/manual/en/throwable.getmessage.php * @return string * @since 7.0 */ public function getMessage(): string; /** * Gets the exception code * @link https://php.net/manual/en/throwable.getcode.php * @return int

* Returns the exception code as integer in * {@see Exception} but possibly as other type in * {@see Exception} descendants (for example as * string in {@see PDOException}). *

* @since 7.0 */ public function getCode(); /** * Gets the file in which the exception occurred * @link https://php.net/manual/en/throwable.getfile.php * @return string Returns the name of the file from which the object was thrown. * @since 7.0 */ public function getFile(): string; /** * Gets the line on which the object was instantiated * @link https://php.net/manual/en/throwable.getline.php * @return int Returns the line number where the thrown object was instantiated. * @since 7.0 */ public function getLine(): int; /** * Gets the stack trace * @link https://php.net/manual/en/throwable.gettrace.php * @return array

* Returns the stack trace as an array in the same format as * {@see debug_backtrace()}. *

* @since 7.0 */ public function getTrace(): array; /** * Gets the stack trace as a string * @link https://php.net/manual/en/throwable.gettraceasstring.php * @return string Returns the stack trace as a string. * @since 7.0 */ public function getTraceAsString(): string; /** * Returns the previous Throwable * @link https://php.net/manual/en/throwable.getprevious.php * @return null|Throwable Returns the previous {@see Throwable} if available, or NULL otherwise. * @since 7.0 */ #[LanguageLevelTypeAware(['8.0' => 'Throwable|null'], default: '')] public function getPrevious(); /** * Gets a string representation of the thrown object * @link https://php.net/manual/en/throwable.tostring.php * @return string

Returns the string representation of the thrown object.

* @since 7.0 */ public function __toString(); } /** * Exception is the base class for * all Exceptions. * @link https://php.net/manual/en/class.exception.php */ class Exception implements Throwable { /** * The error message * @var string */ protected $message; /** The error code */ protected $code; /** The filename where the error happened */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] protected $file; /** The line where the error happened */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] protected $line; /** * Clone the exception * Tries to clone the Exception, which results in Fatal error. * @link https://php.net/manual/en/exception.clone.php * @return void */ #[PhpStormStubsElementAvailable(from: "5.4", to: "8.0")] final private function __clone(): void {} /** * Clone the exception * Tries to clone the Exception, which results in Fatal error. * @link https://php.net/manual/en/exception.clone.php * @return void */ #[PhpStormStubsElementAvailable("8.1")] private function __clone(): void {} /** * Construct the exception. Note: The message is NOT binary safe. * @link https://php.net/manual/en/exception.construct.php * @param string $message [optional] The Exception message to throw. * @param int $code [optional] The Exception code. * @param null|Throwable $previous [optional] The previous throwable used for the exception chaining. */ #[Pure] public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $message = "", #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $code = 0, #[LanguageLevelTypeAware(['8.0' => 'Throwable|null'], default: 'Throwable')] $previous = null ) {} /** * Gets the Exception message * @link https://php.net/manual/en/exception.getmessage.php * @return string the Exception message as a string. */ #[Pure] final public function getMessage(): string {} /** * Gets the Exception code * @link https://php.net/manual/en/exception.getcode.php * @return mixed|int the exception code as integer in * Exception but possibly as other type in * Exception descendants (for example as * string in PDOException). */ #[Pure] final public function getCode() {} /** * Gets the file in which the exception occurred * @link https://php.net/manual/en/exception.getfile.php * @return string the filename in which the exception was created. */ #[Pure] final public function getFile(): string {} /** * Gets the line in which the exception occurred * @link https://php.net/manual/en/exception.getline.php * @return int the line number where the exception was created. */ #[Pure] final public function getLine(): int {} /** * Gets the stack trace * @link https://php.net/manual/en/exception.gettrace.php * @return array the Exception stack trace as an array. */ #[Pure] final public function getTrace(): array {} /** * Returns previous Exception * @link https://php.net/manual/en/exception.getprevious.php * @return null|Throwable Returns the previous {@see Throwable} if available, or NULL otherwise. * or null otherwise. */ #[Pure] final public function getPrevious(): ?Throwable {} /** * Gets the stack trace as a string * @link https://php.net/manual/en/exception.gettraceasstring.php * @return string the Exception stack trace as a string. */ #[Pure] final public function getTraceAsString(): string {} /** * String representation of the exception * @link https://php.net/manual/en/exception.tostring.php * @return string the string representation of the exception. */ #[TentativeType] public function __toString(): string {} #[TentativeType] public function __wakeup(): void {} } /** * Error is the base class for all internal PHP error exceptions. * @link https://php.net/manual/en/class.error.php * @since 7.0 */ class Error implements Throwable { /** The error message */ protected $message; /** The error code */ protected $code; /** The filename where the error happened */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] protected $file; /** The line where the error happened */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] protected $line; /** * Construct the error object. * @link https://php.net/manual/en/error.construct.php * @param string $message [optional] The Error message to throw. * @param int $code [optional] The Error code. * @param null|Throwable $previous [optional] The previous throwable used for the exception chaining. */ #[Pure] public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $message = "", #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $code = 0, #[LanguageLevelTypeAware(['8.0' => 'Throwable|null'], default: 'Throwable')] $previous = null ) {} /*** * Gets the message * @link https://php.net/manual/en/throwable.getmessage.php * @return string * @since 7.0 */ final public function getMessage(): string {} /** * Gets the exception code * @link https://php.net/manual/en/throwable.getcode.php * @return int

* Returns the exception code as integer in * {@see Exception} but possibly as other type in * {@see Exception} descendants (for example as * string in {@see PDOException}). *

* @since 7.0 */ final public function getCode() {} /** * Gets the file in which the exception occurred * @link https://php.net/manual/en/throwable.getfile.php * @return string Returns the name of the file from which the object was thrown. * @since 7.0 */ final public function getFile(): string {} /** * Gets the line on which the object was instantiated * @link https://php.net/manual/en/throwable.getline.php * @return int Returns the line number where the thrown object was instantiated. * @since 7.0 */ final public function getLine(): int {} /** * Gets the stack trace * @link https://php.net/manual/en/throwable.gettrace.php * @return array

* Returns the stack trace as an array in the same format as * {@see debug_backtrace()}. *

* @since 7.0 */ final public function getTrace(): array {} /** * Gets the stack trace as a string * @link https://php.net/manual/en/throwable.gettraceasstring.php * @return string Returns the stack trace as a string. * @since 7.0 */ final public function getTraceAsString(): string {} /** * Returns the previous Throwable * @link https://php.net/manual/en/throwable.getprevious.php * @return null|Throwable Returns the previous {@see Throwable} if available, or NULL otherwise. * @since 7.0 */ final public function getPrevious(): ?Throwable {} /** * Gets a string representation of the thrown object * @link https://php.net/manual/en/throwable.tostring.php * @return string

Returns the string representation of the thrown object.

* @since 7.0 */ public function __toString(): string {} /** * Clone the error * Error can not be clone, so this method results in fatal error. * @return void * @link https://php.net/manual/en/error.clone.php */ #[PhpStormStubsElementAvailable(from: "7.0", to: "8.0")] final private function __clone(): void {} /** * Clone the error * Error can not be clone, so this method results in fatal error. * @return void * @link https://php.net/manual/en/error.clone.php */ #[PhpStormStubsElementAvailable('8.1')] private function __clone(): void {} #[TentativeType] public function __wakeup(): void {} } /** * Is thrown when the type of an argument is correct but the value of it is incorrect. For example, passing a negative * integer when the function expects a positive one, or passing an empty string/array when the function expects it to not be empty. * @link https://www.php.net/manual/en/class.valueerror.php * @since 8.0 */ class ValueError extends Error {} /** * There are three scenarios where a TypeError may be thrown. * The first is where the argument type being passed to a function does not match its corresponding declared * parameter type. The second is where a value being returned from a function does not match the declared function return type. The third is where an * invalid number of arguments are passed to a built-in PHP function (strict mode only). * @link https://php.net/manual/en/class.typeerror.php * @since 7.0 */ class TypeError extends Error {} /** * ParseError is thrown when an error occurs while parsing PHP code, such as when {@see eval()} is called. * @link https://php.net/manual/en/class.parseerror.php * @since 7.0 */ class ParseError extends CompileError {} /** * ArgumentCountError is thrown when too few arguments are passed to a user * defined routine. * * @since 7.1 * @see https://php.net/migration71.incompatible#migration71.incompatible.too-few-arguments-exception */ class ArgumentCountError extends TypeError {} /** * ArithmeticError is thrown when an error occurs while performing mathematical operations. * In PHP 7.0, these errors include attempting to perform a bitshift by a negative amount, * and any call to {@see intdiv()} that would result in a value outside the possible bounds of an integer. * @link https://php.net/manual/en/class.arithmeticerror.php * @since 7.0 */ class ArithmeticError extends Error {} /** * Class CompileError * @link https://secure.php.net/manual/en/class.compileerror.php * @since 7.3 */ class CompileError extends Error {} /** * DivisionByZeroError is thrown when an attempt is made to divide a number by zero. * @link https://php.net/manual/en/class.divisionbyzeroerror.php * @since 7.0 */ class DivisionByZeroError extends ArithmeticError {} /** * @since 8.0 */ class UnhandledMatchError extends Error {} /** * @since 8.4 */ class RequestParseBodyException extends Exception {} /** * An Error Exception. * @link https://php.net/manual/en/class.errorexception.php */ class ErrorException extends Exception { #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] protected $severity; /** * Constructs the exception * @link https://php.net/manual/en/errorexception.construct.php * @param string $message [optional] The Exception message to throw. * @param int $code [optional] The Exception code. * @param int $severity [optional] The severity level of the exception. * @param string $filename [optional] The filename where the exception is thrown. * @param int $line [optional] The line number where the exception is thrown. * @param Throwable $previous [optional] The previous exception used for the exception chaining. */ #[Pure] public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $message = "", #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $code = 0, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $severity = 1, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $filename = null, #[LanguageLevelTypeAware(['8.0' => 'int|null'], default: '')] $line = null, #[LanguageLevelTypeAware(['8.0' => 'Throwable|null'], default: 'Throwable')] $previous = null ) {} /** * Gets the exception severity * @link https://php.net/manual/en/errorexception.getseverity.php * @return int the severity level of the exception. */ final public function getSeverity(): int {} } /** * Class used to represent anonymous functions. *

Anonymous functions, implemented in PHP 5.3, yield objects of this type. * This fact used to be considered an implementation detail, but it can now be relied upon. * Starting with PHP 5.4, this class has methods that allow further control of the anonymous function after it has been created. *

Besides the methods listed here, this class also has an __invoke method. * This is for consistency with other classes that implement calling magic, as this method is not used for calling the function. * @link https://secure.php.net/manual/en/class.closure.php */ final class Closure { /** * This method exists only to disallow instantiation of the Closure class. * Objects of this class are created in the fashion described on the anonymous functions page. * @link https://secure.php.net/manual/en/closure.construct.php */ private function __construct() {} /** * This is for consistency with other classes that implement calling magic, * as this method is not used for calling the function. * @param mixed ...$_ [optional] * @return mixed * @link https://secure.php.net/manual/en/class.closure.php */ public function __invoke(...$_) {} /** * Duplicates the closure with a new bound object and class scope * @link https://secure.php.net/manual/en/closure.bindto.php * @param object|null $newThis The object to which the given anonymous function should be bound, or NULL for the closure to be unbound. * @param object|class-string|null $newScope The class scope to which associate the closure is to be associated, or 'static' to keep the current one. * If an object is given, the type of the object will be used instead. * This determines the visibility of protected and private methods of the bound object. * @return Closure|null Returns the newly created Closure object or null on failure */ #[Pure] public function bindTo(?object $newThis, object|string|null $newScope = 'static'): ?Closure {} /** * This method is a static version of Closure::bindTo(). * See the documentation of that method for more information. * @link https://secure.php.net/manual/en/closure.bind.php * @param Closure $closure The anonymous functions to bind. * @param object|null $newThis The object to which the given anonymous function should be bound, or NULL for the closure to be unbound. * @param object|class-string|null $newScope The class scope to which associate the closure is to be associated, or 'static' to keep the current one. * If an object is given, the type of the object will be used instead. * This determines the visibility of protected and private methods of the bound object. * @return Closure|null Returns the newly created Closure object or null on failure */ #[Pure] public static function bind(Closure $closure, ?object $newThis, object|string|null $newScope = 'static'): ?Closure {} /** * Temporarily binds the closure to newthis, and calls it with any given parameters. * @link https://php.net/manual/en/closure.call.php * @param object $newThis The object to bind the closure to for the duration of the call. * @param mixed $args [optional] Zero or more parameters, which will be given as parameters to the closure. * @return mixed * @since 7.0 */ public function call(object $newThis, mixed ...$args): mixed {} /** * @param callable $callback * @return Closure * @since 7.1 */ public static function fromCallable(callable $callback): Closure {} /** * @since 8.5 */ public static function getCurrent(): Closure {} } /** * Classes implementing Countable can be used with the * count function. * @link https://php.net/manual/en/class.countable.php */ interface Countable { /** * Count elements of an object * @link https://php.net/manual/en/countable.count.php * @return int<0,max> The custom count as an integer. *

* The return value is cast to an integer. *

*/ #[TentativeType] public function count(): int; } /** * Weak references allow the programmer to retain a reference to an * object which does not prevent the object from being destroyed. * They are useful for implementing cache like structures. * @template T of object * @link https://www.php.net/manual/en/class.weakreference.php * @since 7.4 */ final class WeakReference { /** * This method exists only to disallow instantiation of the WeakReference * class. Weak references are to be instantiated with the factory method * WeakReference::create(). */ public function __construct() {} /** * Create a new weak reference. * @link https://www.php.net/manual/en/weakreference.create.php * @template TIn of object * @param TIn $object Any object. * @return WeakReference The freshly instantiated object. * @since 7.4 */ #[Pure] public static function create(object $object): WeakReference {} /** * Gets a weakly referenced object. If the object has already been * destroyed, NULL is returned. * @link https://www.php.net/manual/en/weakreference.get.php * @return T|null * @since 7.4 */ #[Pure] public function get(): ?object {} } /** * Weak maps allow creating a map from objects to arbitrary values * (similar to SplObjectStorage) without preventing the objects that are used * as keys from being garbage collected. If an object key is garbage collected, * it will simply be removed from the map. * * @since 8.0 * * @template TKey of object * @template TValue * @template-implements IteratorAggregate * @template-implements ArrayAccess */ final class WeakMap implements ArrayAccess, Countable, IteratorAggregate { /** * Returns {@see true} if the value for the object is contained in * the {@see WeakMap} and {@see false} instead. * * @param TKey $object Any object * @return bool */ #[Pure] public function offsetExists($object): bool {} /** * Returns the existsing value by an object. * * @param TKey $object Any object * @return TValue Value associated with the key object */ #[Pure] public function offsetGet($object): mixed {} /** * Sets a new value for an object. * * @param TKey $object Any object * @param TValue $value Any value * @return void */ public function offsetSet($object, mixed $value): void {} /** * Force removes an object value from the {@see WeakMap} instance. * * @param TKey $object Any object * @return void */ public function offsetUnset($object): void {} /** * Returns an iterator in the "[object => mixed]" format. * * @return Iterator */ #[Pure] public function getIterator(): Iterator {} /** * Returns the number of items in the {@see WeakMap} instance. * * @return int<0,max> */ #[Pure] public function count(): int {} } /** * Stringable interface denotes a class as having a __toString() method. * * @since 8.0 */ interface Stringable { /** * Magic method {@see https://www.php.net/manual/en/language.oop5.magic.php#object.tostring} * allows a class to decide how it will react when it is treated like a string. * * @return string Returns string representation of the object that * implements this interface (and/or "__toString" magic method). */ public function __toString(): string; } /** * @since 8.0 */ #[Attribute(Attribute::TARGET_CLASS)] final class Attribute { public int $flags; /** * Marks that attribute declaration is allowed only in classes. */ public const TARGET_CLASS = 1; /** * Marks that attribute declaration is allowed only in functions. */ public const TARGET_FUNCTION = 2; /** * Marks that attribute declaration is allowed only in class methods. */ public const TARGET_METHOD = 4; /** * Marks that attribute declaration is allowed only in class properties. */ public const TARGET_PROPERTY = 8; /** * Marks that attribute declaration is allowed only in class constants. */ public const TARGET_CLASS_CONSTANT = 16; /** * Marks that attribute declaration is allowed only in function or method parameters. */ public const TARGET_PARAMETER = 32; /** * Marks that attribute declaration is allowed only in constants. * @since 8.5 */ public const TARGET_CONSTANT = 32; /** * Marks that attribute declaration is allowed anywhere. */ public const TARGET_ALL = 127; /** * Notes that an attribute declaration in the same place is * allowed multiple times. */ public const IS_REPEATABLE = 64; /** * @param int $flags A value in the form of a bitmask indicating the places * where attributes can be defined. */ public function __construct(#[ExpectedValues(flagsFromClass: Attribute::class)] int $flags = Attribute::TARGET_ALL) {} } /** * @since 8.0 */ final class InternalIterator implements Iterator { private function __construct() {} public function current(): mixed {} public function next(): void {} public function key(): mixed {} public function valid(): bool {} public function rewind(): void {} } /** * @since 8.1 */ interface UnitEnum { public readonly string $name; /** * @return static[] */ #[Pure] public static function cases(): array; } /** * @since 8.1 */ interface BackedEnum extends UnitEnum { public readonly int|string $value; /** * Translates a string or int into the corresponding Enum * case, if any. If there is no matching case defined, it will throw a * ValueError. * @param int|string $value * @throws ValueError if there is no matching case defined * @throws TypeError * @return static * @link https://www.php.net/manual/en/backedenum.from.php */ #[Pure] public static function from(int|string $value): static; /** * Translates a string or int into the corresponding Enum * case, if any. If there is no matching case defined, it will return null. * @param int|string $value * @return static|null A case instance of this enumeration, or null if not * found. * @link https://www.php.net/manual/en/backedenum.tryfrom.php */ #[Pure] public static function tryFrom(int|string $value): ?static; } /** * @since 8.1 * @internal * * Internal interface to ensure precise type inference */ interface IntBackedEnum extends BackedEnum { public readonly int $value; /** * Translates an int into the corresponding Enum * case, if any. If there is no matching case defined, it will throw a * ValueError. * @param int $value * @return static * @throws ValueError if there is no matching case defined * @link https://www.php.net/manual/en/backedenum.from.php */ #[Pure] public static function from(int $value): static; /** * Translates an int into the corresponding Enum * case, if any. If there is no matching case defined, it will return null. * @param int $value * @return static|null * @link https://www.php.net/manual/en/backedenum.tryfrom.php */ #[Pure] public static function tryFrom(int $value): ?static; } /** * @since 8.1 * @internal * * Internal interface to ensure precise type inference */ interface StringBackedEnum extends BackedEnum { public readonly string $value; /** * Translates a string into the corresponding Enum * case, if any. If there is no matching case defined, it will throw a * ValueError. * @param string $value * @return static * @throws ValueError if there is no matching case defined * @link https://www.php.net/manual/en/backedenum.from.php */ #[Pure] public static function from(string $value): static; /** * Translates a string or int into the corresponding Enum * case, if any. If there is no matching case defined, it will return null. * @param string $value * @return static|null * @link https://www.php.net/manual/en/backedenum.tryfrom.php */ #[Pure] public static function tryFrom(string $value): ?static; } /** * @since 8.1 * * @template TStart * @template TResume * @template TReturn * @template TSuspend */ final class Fiber { /** * @param callable $callback Function to invoke when starting the fiber. */ public function __construct(callable $callback) {} /** * Starts execution of the fiber. Returns when the fiber suspends or terminates. * * @param TStart ...$args Arguments passed to fiber function. * * @return TSuspend|null Value from the first suspension point or NULL if the fiber returns. * * @throws FiberError If the fiber has already been started. * @throws Throwable If the fiber callable throws an uncaught exception. */ public function start(mixed ...$args): mixed {} /** * Resumes the fiber, returning the given value from {@see Fiber::suspend()}. * Returns when the fiber suspends or terminates. * * @param TResume $value * * @return TSuspend|null Value from the next suspension point or NULL if the fiber returns. * * @throws FiberError If the fiber has not started, is running, or has terminated. * @throws Throwable If the fiber callable throws an uncaught exception. */ public function resume(mixed $value = null): mixed {} /** * Throws the given exception into the fiber from {@see Fiber::suspend()}. * Returns when the fiber suspends or terminates. * * @param Throwable $exception * * @return TSuspend|null Value from the next suspension point or NULL if the fiber returns. * * @throws FiberError If the fiber has not started, is running, or has terminated. * @throws Throwable If the fiber callable throws an uncaught exception. */ public function throw(Throwable $exception): mixed {} /** * @return bool True if the fiber has been started. */ public function isStarted(): bool {} /** * @return bool True if the fiber is suspended. */ public function isSuspended(): bool {} /** * @return bool True if the fiber is currently running. */ public function isRunning(): bool {} /** * @return bool True if the fiber has completed execution (returned or threw). */ public function isTerminated(): bool {} /** * @return TReturn Return value of the fiber callback. NULL is returned if the fiber does not have a return statement. * * @throws FiberError If the fiber has not terminated or the fiber threw an exception. */ public function getReturn(): mixed {} /** * @return Fiber|null Returns the currently executing fiber instance or NULL if in {main}. */ public static function getCurrent(): ?Fiber {} /** * Suspend execution of the fiber. The fiber may be resumed with {@see Fiber::resume()} or {@see Fiber::throw()}. * * Cannot be called from {main}. * * @param TSuspend $value Value to return from {@see Fiber::resume()} or {@see Fiber::throw()}. * * @return TResume Value provided to {@see Fiber::resume()}. * * @throws FiberError Thrown if not within a fiber (i.e., if called from {main}). * @throws Throwable Exception provided to {@see Fiber::throw()}. */ public static function suspend(mixed $value = null): mixed {} } /** * @since 8.1 */ final class FiberError extends Error { public function __construct() {} } /** * @since 8.1 */ #[Attribute(Attribute::TARGET_METHOD)] final class ReturnTypeWillChange { public function __construct() {} } /** * @since 8.2 */ #[Attribute(Attribute::TARGET_CLASS)] final class AllowDynamicProperties { public function __construct() {} } /** * @since 8.2 */ #[Attribute(Attribute::TARGET_PARAMETER)] final class SensitiveParameter { public function __construct() {} } /** * @since 8.2 */ final class SensitiveParameterValue { private readonly mixed $value; public function __construct(mixed $value) {} public function getValue(): mixed {} public function __debugInfo(): array {} } /** * @since 8.3 */ #[Attribute(Attribute::TARGET_METHOD|Attribute::TARGET_PROPERTY)] final class Override { public function __construct() {} } /** * @since 8.4 */ #[Attribute(Attribute::TARGET_METHOD|Attribute::TARGET_FUNCTION|Attribute::TARGET_CLASS_CONSTANT|Attribute::TARGET_CONSTANT|Attribute::TARGET_CLASS)] final class Deprecated { public readonly ?string $message; public readonly ?string $since; public function __construct(?string $message = null, ?string $since = null) {} } /** * @since 8.5 */ #[Attribute(Attribute::TARGET_METHOD|Attribute::TARGET_FUNCTION)] final class NoDiscard { public readonly ?string $message; public function __construct(?string $message = null) {} } /** * @since 8.5 */ #[Attribute(Attribute::TARGET_ALL)] final class DelayedTargetValidation {} set_error_handler), the application aborts as it * was an E_ERROR. * @link https://php.net/manual/en/errorfunc.constants.php */ define('E_RECOVERABLE_ERROR', 4096); /** * Run-time warnings (non-fatal errors). Execution of the script is not * halted. * @link https://php.net/manual/en/errorfunc.constants.php */ define('E_WARNING', 2); /** * Compile-time parse errors. Parse errors should only be generated by * the parser. * @link https://php.net/manual/en/errorfunc.constants.php */ define('E_PARSE', 4); /** * Run-time notices. Indicate that the script encountered something that * could indicate an error, but could also happen in the normal course of * running a script. * @link https://php.net/manual/en/errorfunc.constants.php */ define('E_NOTICE', 8); /** * Enable to have PHP suggest changes * to your code which will ensure the best interoperability * and forward compatibility of your code. * @link https://php.net/manual/en/errorfunc.constants.php * @deprecated 8.4 */ define('E_STRICT', 2048); /** * Run-time notices. Enable this to receive warnings about code * that will not work in future versions. * @link https://php.net/manual/en/errorfunc.constants.php */ define('E_DEPRECATED', 8192); /** * Fatal errors that occur during PHP's initial startup. This is like an * E_ERROR, except it is generated by the core of PHP. * @link https://php.net/manual/en/errorfunc.constants.php */ define('E_CORE_ERROR', 16); /** * Warnings (non-fatal errors) that occur during PHP's initial startup. * This is like an E_WARNING, except it is generated * by the core of PHP. * @link https://php.net/manual/en/errorfunc.constants.php */ define('E_CORE_WARNING', 32); /** * Fatal compile-time errors. This is like an E_ERROR, * except it is generated by the Zend Scripting Engine. * @link https://php.net/manual/en/errorfunc.constants.php */ define('E_COMPILE_ERROR', 64); /** * Compile-time warnings (non-fatal errors). This is like an * E_WARNING, except it is generated by the Zend * Scripting Engine. * @link https://php.net/manual/en/errorfunc.constants.php */ define('E_COMPILE_WARNING', 128); /** * User-generated error message. This is like an * E_ERROR, except it is generated in PHP code by * using the PHP function trigger_error. * @link https://php.net/manual/en/errorfunc.constants.php */ define('E_USER_ERROR', 256); /** * User-generated warning message. This is like an * E_WARNING, except it is generated in PHP code by * using the PHP function trigger_error. * @link https://php.net/manual/en/errorfunc.constants.php */ define('E_USER_WARNING', 512); /** * User-generated notice message. This is like an * E_NOTICE, except it is generated in PHP code by * using the PHP function trigger_error. * @link https://php.net/manual/en/errorfunc.constants.php */ define('E_USER_NOTICE', 1024); /** * User-generated warning message. This is like an * E_DEPRECATED, except it is generated in PHP code by * using the PHP function trigger_error. * @link https://php.net/manual/en/errorfunc.constants.php */ define('E_USER_DEPRECATED', 16384); /** * All errors and warnings, as supported, except of level * E_STRICT prior to PHP 5.4.0. * Value of E_ALL is 32767 since PHP 5.4.x, * 30719 in PHP 5.3.x, 6143 in PHP 5.2.x, 2047 previously * @link https://php.net/manual/en/errorfunc.constants.php */ define('E_ALL', 30719); define('DEBUG_BACKTRACE_PROVIDE_OBJECT', 1); define('DEBUG_BACKTRACE_IGNORE_ARGS', 2); define('S_MEMORY', 1); define('S_VARS', 4); define('S_FILES', 8); define('S_INCLUDE', 16); define('S_SQL', 32); define('S_EXECUTOR', 64); define('S_MAIL', 128); define('S_SESSION', 256); define('S_MISC', 2); define('S_INTERNAL', 536870912); define('S_ALL', 511); define('true', (bool)1, true); define('false', (bool)0, true); define('null', null, true); define('ZEND_THREAD_SAFE', false); define('ZEND_DEBUG_BUILD', false); define('ZEND_VM_KIND_HYBRID', 4); define('ZEND_VM_KIND', ZEND_VM_KIND_HYBRID); define('PHP_WINDOWS_VERSION_BUILD', 0); define('PHP_WINDOWS_VERSION_MAJOR', 0); define('PHP_WINDOWS_VERSION_MINOR', 0); define('PHP_WINDOWS_VERSION_PLATFORM', 0); define('PHP_WINDOWS_VERSION_PRODUCTTYPE', 0); define('PHP_WINDOWS_VERSION_SP_MAJOR', 0); define('PHP_WINDOWS_VERSION_SP_MINOR', 0); define('PHP_WINDOWS_VERSION_SUITEMASK', 0); define('PHP_WINDOWS_NT_DOMAIN_CONTROLLER', 2); define('PHP_WINDOWS_NT_SERVER', 3); define('PHP_WINDOWS_NT_WORKSTATION', 1); /** * @since 7.4 */ define('PHP_WINDOWS_EVENT_CTRL_C', 0); /** * @since 7.4 */ define('PHP_WINDOWS_EVENT_CTRL_BREAK', 1); define('PHP_VERSION', "5.3.6-13ubuntu3.2"); define('PHP_MAJOR_VERSION', 5); define('PHP_MINOR_VERSION', 3); define('PHP_RELEASE_VERSION', 6); define('PHP_EXTRA_VERSION', "-13ubuntu3.2"); define('PHP_VERSION_ID', 50306); define('PHP_ZTS', 0); define('PHP_DEBUG', 0); define('PHP_OS', "Linux"); /** * The operating system family PHP was built for. Either of 'Windows', 'BSD', 'Darwin', 'Solaris', 'Linux' or 'Unknown'. Available as of PHP 7.2.0. * @since 7.2 */ define('PHP_OS_FAMILY', "Linux"); define('PHP_SAPI', "cli"); /** * @since 7.4 */ define('PHP_CLI_PROCESS_TITLE', 1); define('DEFAULT_INCLUDE_PATH', ".:/usr/share/php:/usr/share/pear"); define('PEAR_INSTALL_DIR', "/usr/share/php"); define('PEAR_EXTENSION_DIR', "/usr/lib/php5/20090626"); define('PHP_EXTENSION_DIR', "/usr/lib/php5/20090626"); /** * Specifies where the binaries were installed into. * @link https://php.net/manual/en/reserved.constants.php */ define('PHP_BINARY', '/usr/local/php/bin/php'); define('PHP_PREFIX', "/usr"); define('PHP_BINDIR', "/usr/bin"); define('PHP_LIBDIR', "/usr/lib/php5"); define('PHP_DATADIR', "/usr/share"); define('PHP_SYSCONFDIR', "/etc"); define('PHP_LOCALSTATEDIR', "/var"); define('PHP_CONFIG_FILE_PATH', "/etc/php5/cli"); define('PHP_CONFIG_FILE_SCAN_DIR', "/etc/php5/cli/conf.d"); define('PHP_SHLIB_SUFFIX', "so"); define('PHP_EOL', "\n"); define('SUHOSIN_PATCH', 1); define('SUHOSIN_PATCH_VERSION', "0.9.10"); define('PHP_MAXPATHLEN', 4096); define('PHP_INT_MAX', 9223372036854775807); define('PHP_INT_MIN', -9223372036854775808); define('PHP_INT_SIZE', 8); /** * Number of decimal digits that can be rounded into a float and back without precision loss. Available as of PHP 7.2.0. * @since 7.2 */ define('PHP_FLOAT_DIG', 15); /** * Smallest representable positive number x, so that x + 1.0 != 1.0. Available as of PHP 7.2.0. * @since 7.2 */ define('PHP_FLOAT_EPSILON', 2.2204460492503e-16); /** * Largest representable floating point number. Available as of PHP 7.2.0. * @since 7.2 */ define('PHP_FLOAT_MAX', 1.7976931348623e+308); /** * Smallest representable floating point number. Available as of PHP 7.2.0. * @since 7.2 */ define('PHP_FLOAT_MIN', 2.2250738585072e-308); define('ZEND_MULTIBYTE', 0); define('PHP_OUTPUT_HANDLER_START', 1); define('PHP_OUTPUT_HANDLER_CONT', 2); define('PHP_OUTPUT_HANDLER_END', 4); define('UPLOAD_ERR_OK', 0); define('UPLOAD_ERR_INI_SIZE', 1); define('UPLOAD_ERR_FORM_SIZE', 2); define('UPLOAD_ERR_PARTIAL', 3); define('UPLOAD_ERR_NO_FILE', 4); define('UPLOAD_ERR_NO_TMP_DIR', 6); define('UPLOAD_ERR_CANT_WRITE', 7); define('UPLOAD_ERR_EXTENSION', 8); define('STDIN', fopen('php://stdin', 'r')); define('STDOUT', fopen('php://stdout', 'w')); define('STDERR', fopen('php://stderr', 'w')); define('PHP_FD_SETSIZE', 1024); /** @link https://php.net/manual/en/outcontrol.constants.php */ define('PHP_OUTPUT_HANDLER_WRITE', 0); /** @link https://php.net/manual/en/outcontrol.constants.php */ define('PHP_OUTPUT_HANDLER_FLUSH', 4); /** @link https://php.net/manual/en/outcontrol.constants.php */ define('PHP_OUTPUT_HANDLER_CLEAN', 2); /** @link https://php.net/manual/en/outcontrol.constants.php */ define('PHP_OUTPUT_HANDLER_FINAL', 8); /** @link https://php.net/manual/en/outcontrol.constants.php */ define('PHP_OUTPUT_HANDLER_CLEANABLE', 16); /** @link https://php.net/manual/en/outcontrol.constants.php */ define('PHP_OUTPUT_HANDLER_FLUSHABLE', 32); /** @link https://php.net/manual/en/outcontrol.constants.php */ define('PHP_OUTPUT_HANDLER_REMOVABLE', 64); /** @link https://php.net/manual/en/outcontrol.constants.php */ define('PHP_OUTPUT_HANDLER_STDFLAGS', 112); /** @link https://php.net/manual/en/outcontrol.constants.php */ define('PHP_OUTPUT_HANDLER_STARTED', 4096); /** @link https://php.net/manual/en/outcontrol.constants.php */ define('PHP_OUTPUT_HANDLER_DISABLED', 8192); /** * @since 8.4 */ const PHP_SBINDIR = '/usr/local/sbin', PHP_OUTPUT_HANDLER_PROCESSED = 16384; /** * Specifies where the manpages were installed into. * @since 5.3.7 * @link https://php.net/manual/en/reserved.constants.php */ define('PHP_MANDIR', '/usr/local/php/php/man'); define('PHP_BUILD_DATE', 'Aug 14 2025 22:21:58'); define('PHP_BUILD_PROVIDER', 'https://github.com/docker-library/php'); '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 = null, #[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 = null, 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 = null, $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 {} } printf("Hello world!\n"); * ``` * * @link https://www.php.net/manual/en/ffi.load.php * * @param string $filename The name of a C header file. C preprocessor * directives are not supported, i.e. `#include`, `#define` and * CPP macros do not work, except for special cases listed below. * The header file should contain a #define statement for the * `FFI_SCOPE` variable, e.g.: `#define FFI_SCOPE "MYLIB"`. Refer * to the class introduction for details. The header file may * contain a `#define` statement for the `FFI_LIB` variable to * specify the library it exposes. If it is a system library only * the file name is required, e.g.: `#define FFI_LIB "libc.so.6"`. * If it is a custom library, a relative path is required, * e.g.: `#define FFI_LIB "./mylib.so"`. * * @return FFI|null Returns the freshly created {@see FFI} object, * or {@see null} on failure. */ 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 * the WEB environment. However, it's possible to preload FFI * definitions and libraries at php startup, and instantiate FFI objects * when necessary. Header files may be extended with `FFI_SCOPE` define * (default preloading scope is "C"). This name is going to be * used as {@see FFI::scope()} argument. It's possible to preload a few * files into a single scope. * * ```c * #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 a file loaded by `opcache.preload` in the `php.ini` * directive. * * ```c * ffi.preload=/etc/php/ffi/printf.h * ``` * * Finally, FFI::scope() instantiates an FFI object that implements * all C definitions from the given scope. * * ```php * $ffi = FFI::scope("libc"); * $ffi->printf("Hello world!\n"); * ``` * * @link https://www.php.net/manual/en/ffi.scope.php * * @param string $name The scope name defined by a special `FFI_SCOPE` define. * * @return FFI Returns the freshly created {@see FFI} object. */ public static function scope(string $name): FFI {} /** * Method that creates an arbitrary C structure. * * Creates a native data structure of the given C type. Any type * declared for the instance is allowed. * * Note: Calling {@see FFI::new()} statically is deprecated since PHP 8.3. * * @link https://www.php.net/manual/en/ffi.new.php * * @param string|CType $type is a valid C declaration as {@see string}, * or an instance of {@see FFI\CType} which has already been created. * @param bool $owned Whether to create owned (i.e. managed) or unmanaged * data. Managed data lives together with the returned * {@see FFI\CData} object, and is released when the last * reference to that object is released by regular PHP * reference counting or GC. Unmanaged data should be released * by calling {@see FFI::free()}, when no longer needed. * @param bool $persistent Whether to allocate the C data structure * permanently on the system heap (using `malloc()`), or on * the PHP request heap (using `emalloc()`). * * @return CData|null Returns the freshly created {@see FFI\CData} * object, or {@see null} on failure. * @throws ParserException */ public function new(CType|string $type, bool $owned = true, bool $persistent = false): ?CData {} /** * Manually removes previously created "not-owned" data structure. * * @link https://www.php.net/manual/en/ffi.free.php * * @param CData $ptr The handle of the unmanaged pointer to a C data structure. */ public static function free(CData $ptr): void {} /** * Creates a new {@see FFI\CData} object, that references the same * C data structure, but is associated with a different type. The * resulting object does not own the C data, and the source ptr must * survive the result. The C type may be specified as a {@see string} * with any valid C type declaration or as {@see FFI\CType} object, * created before. Any type declared for the instance is allowed. * * Note: Calling {@see FFI::cast()} statically is deprecated since PHP 8.3. * * ```php * $ffi = FFI::cdef(); * * $int32Value = $ffi->new('int32_t'); * $int16Array = $ffi->cast('int16_t[2]', $int32Value); * ``` * * @link https://www.php.net/manual/en/ffi.free.php * * @param CType|string $type A valid C declaration as {@see string}, or * an instance of {@see FFI\CType} which has already been created. * @param CData|int|float|bool|null $ptr The handle of the pointer * to a C data structure. * * @return CData|null Returns the freshly created {@see FFI\CData} object. */ public function cast(CType|string $type, $ptr): ?CData {} /** * This function creates and returns a {@see FFI\CType} object for * the given string containing a C type declaration. Any type * declared for the instance is allowed. * * ```php * $ffi = FFI::cdef(); * * $type = $ffi->type('int[2][3]'); * ``` * * @link https://www.php.net/manual/en/ffi.type.php * * @param string $type A valid C declaration as {@see string}. * @return CType|null Returns the freshly created {@see FFI\CType} * object, or {@see null} on failure. */ public function type(string $type): ?CType {} /** * This function returns the FFI\CType object, representing the type of * the given {@see FFI\CData} object. * * @link https://www.php.net/manual/en/ffi.typeof.php * * @param CData $ptr The handle of the pointer to a C data structure. * @return CType Returns the {@see FFI\CType} object representing the * type of the given {@see FFI\CData} object. */ public static function typeof(CData $ptr): CType {} /** * Constructs a new C array type with elements of $type and * dimensions specified by `$dimensions`. * * ```php * $ffi = FFI::cdef(); * * $t1 = $ffi->type('int[2][3]'); * $t2 = FFI::arrayType($ffi->type('int'), [2, 3]); * ``` * * @link https://www.php.net/manual/en/ffi.arraytype.php * * @param CType $type A valid C declaration as string, or an instance * of {@see FFI\CType} which has already been created. * @param array> $dimensions The dimensions of * the type as {@see array}. * * @return CType Returns the freshly created {@see FFI\CType} object. */ public static function arrayType(CType $type, array $dimensions): CType {} /** * Returns a 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 the life-time of the source object, and this may * cause dangling pointer dereference (like in regular C). * * @link https://www.php.net/manual/en/ffi.addr.php * * @param CData $ptr The handle of the pointer to a C data structure. * * @return CData Returns the freshly created {@see FFI\CData} object. */ public static function addr(CData $ptr): CData {} /** * Returns the size of a C data type of the given {@see FFI\CData} * or {@see FFI\CType}. * * @link https://www.php.net/manual/en/ffi.sizeof.php * * @param CData|CType $ptr The handle of the C data or type. * * @return int<0, max> The size of the memory area pointed at by ptr. */ public static function sizeof(CData|CType $ptr): int {} /** * Returns the size of a C data type of the given {@see FFI\CData} or * {@see FFI\CType}. * * @link https://www.php.net/manual/en/ffi.alignof.php * * @param CData|CType $ptr The handle of the C data or type. * * @return int<0, max> Returns the alignment of the given * {@see FFI\CData} or {@see FFI\CType} object. */ public static function alignof(CData|CType $ptr): int {} /** * Copies `$size` bytes from the memory area `$from` to the memory area `$to`. * * @link https://www.php.net/manual/en/ffi.memcpy.php * * @param CData $to The start of the memory area to copy to. * @param CData|string $from The start of the memory area to copy from. * @param int<0, max> $size The number of bytes to copy. */ public static function memcpy(CData $to, $from, int $size): void {} /** * Compares `$size` bytes from the memory areas `$ptr1` and `$ptr2`. * Both `$ptr1` and `$ptr2` can be any native data structures * ({@see FFI\CData}) or PHP strings. * * @link https://www.php.net/manual/en/ffi.memcmp.php * * @param CData|string $ptr1 The start of one memory area. * @param CData|string $ptr2 The start of another memory area. * @param int<0, max> $size The number of bytes to compare. * * @return int<-1, 1> Returns a value less than 0 if the contents of the * memory area starting at `$ptr1` are considered less than the * contents of the memory area starting at `$ptr2`, a value * greater than 0 if the contents of the first memory area are * considered greater than the second, and 0 if they are equal. */ public static function memcmp($ptr1, $ptr2, int $size): int {} /** * Fills `$size` bytes of the memory area pointed to by `$ptr` with the * given byte `$value`. * * @link https://www.php.net/manual/en/ffi.memset.php * * @param CData $ptr The start of the memory area to fill. * @param int $value The byte to fill with. * @param int<0, max> $size The number of bytes to fill. */ public static function memset(CData $ptr, int $value, int $size): void {} /** * Creates a PHP string from `$size` bytes of the memory area pointed * by `$ptr`. If size is omitted, `$ptr` must be a zero-terminated * array of C chars. * * @link https://www.php.net/manual/en/ffi.string.php * * @param CData $ptr The start of the memory area from which to * create a PHP {@see string}. * @param int<0, max>|null $size The number of bytes to copy to the * PHP {@see string}. If `$size` is omitted or {@see null}, * `$ptr` must be a zero-terminated ("\0") array of C char. * * @return string The freshly created PHP {@see string}. */ public static function string(CData $ptr, ?int $size = null): string {} /** * Checks whether the FFI\CData is a null pointer. * * @link https://www.php.net/manual/en/ffi.isnull.php * * @param CData $ptr The handle of the pointer to a C data structure. * * @return bool Returns whether a {@see FFI\CData} is a null pointer. */ 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 {@see CData} is a wrapper over raw C data, it * contains an additional {@see CData::$cdata} property. * * - 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. * * - In the case that CData is a wrapper over an array, it is an * implementation of the {@see \Traversable}, {@see \Countable}, * and {@see \ArrayAccess} * * - In the case when CData is a wrapper over a function pointer, it can * be called. * * @link https://www.php.net/manual/en/class.ffi-cdata.php * * @template T of int|float|bool|null|string|CData = null * * @mixin \Countable * @mixin \Traversable, T> * @mixin \ArrayAccess, T> * * @property T $cdata * * @method mixed __get(string $name) * @method mixed __set(string $name, mixed $value) * @method mixed __invoke(mixed ...$args) * * @since 7.4 */ final class CData { /** * Note that this method does not physically exist and is only required * for correct type inference. * * @param int<0, max> $offset */ private function offsetExists(int $offset) {} /** * Note that this method does not physically exist and is only required * for correct type inference. * * @param int<0, max> $offset * @return T */ private function offsetGet(int $offset): mixed {} /** * Note that this method does not physically exist and is only required * for correct type inference. * * @param int<0, max> $offset * @param T $value */ private function offsetSet(int $offset, mixed $value): void {} /** * Note that this method does not physically exist and is only required * for correct type inference. * * @param int<0, max> $offset */ private function offsetUnset(int $offset): void {} /** * Note that this method does not physically exist and is only required * for correct type inference. * * @return int<0, max> */ private function count(): int {} } /** * Class containing C type information. * * @link https://www.php.net/manual/en/class.ffi-ctype.php * * @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 non-empty-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 (CType::TYPE_*) */ public function getKind(): int {} /** * Returns the size of the type in bytes. * * @since 8.1 * @return int<0, max> */ public function getSize(): int {} /** * Returns the alignment of the type in bytes. * * @since 8.1 * @return int<0, max> */ public function getAlignment(): int {} /** * Returns the bit-mask of type attributes. * * @since 8.1 * @return int-mask-of */ 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 (CType::TYPE_*) * @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<0, max> * @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<0, max> * @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 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 (CType::ABI_*) * @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<0, max> * @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<0, max> $index * @return CType * @throws Exception In the case that the type is not a function. */ public function getFuncParameterType(int $index): CType {} } } 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 2010-2023 JetBrains s.r.o. 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. LuaSandbox is an extension for PHP 5, PHP 7, and HHVM to allow safely running * untrusted Lua 5.1 code from within PHP.

* * @link https://www.php.net/manual/en/book.luasandbox.php * @package luasandbox * @version 3.0.3 */ /** * The LuaSandbox class creates a Lua environment and allows for execution of Lua code. * * @link https://www.php.net/manual/en/class.luasandbox.php * @since luasandbox >= 1.0.0 */ class LuaSandbox { /** * Used with LuaSandbox::getProfilerFunctionReport() * to return timings in samples. */ public const SAMPLES = 0; /** * Used with LuaSandbox::getProfilerFunctionReport() * to return timings in seconds. */ public const SECONDS = 1; /** * Used with LuaSandbox::getProfilerFunctionReport() * to return timings in percentages of the total. */ public const PERCENT = 2; /** * Call a function in a Lua global variable. * *

If the name contains "." characters, the function is located via recursive table accesses, * as if the name were a Lua expression.

* *

If the variable does not exist, or is not a function, * false will be returned and a warning issued.

* *

For more information about calling Lua functions and the return values, * see LuaSandboxFunction::call().

* * @link https://www.php.net/manual/en/luasandbox.callFunction.php * @param string $name

Lua variable name.

* @param mixed[] $arguments

Arguments to the function.

* @return array|bool

Returns an array of values returned by the Lua function, * which may be empty, or false in case of failure.

* @see LuaSandboxFunction::call() * @since luasandbox >= 1.0.0 */ public function callFunction($name, array $arguments) {} /** * Disable the profiler. * * @link https://www.php.net/manual/en/luasandbox.disableProfiler.php * @since luasandbox >= 1.1.0 * @see LuaSandbox::enableProfiler() * @see LuaSandbox::getProfilerFunctionReport() */ public function disableProfiler() {} /** * Enable the profiler. * *

The profiler periodically samples the Lua environment * to record the running function. Testing indicates that * at least on Linux, setting a period less than 1ms will * lead to a high overrun count but no performance problems.

* * @link https://www.php.net/manual/en/luasandbox.enableprofiler.php * @param float $period [optional]

Sampling period in seconds.

* @return bool

Returns a boolean indicating whether the profiler is enabled.

* @since luasandbox >= 1.1.0 * @see LuaSandbox::disableProfiler() * @see LuaSandbox::getProfilerFunctionReport() */ public function enableProfiler($period = 0.02) {} /** * Fetch the current CPU time usage of the Lua environment. * *

This includes time spent in PHP callbacks.

* *

Note: On Windows, this function always returns zero. * On operating systems that do not support CLOCK_THREAD_CPUTIME_ID, * such as FreeBSD and Mac OS X, this function will return the * elapsed wall-clock time, not CPU time.

* * @link https://www.php.net/manual/en/luasandbox.getcpuusage.php * @return float

Returns the current CPU time usage in seconds.

* @since luasandbox >= 1.0.0 * @see LuaSandbox::getMemoryUsage() * @see LuaSandbox::getPeakMemoryUsage() * @see LuaSandbox::setCPULimit() */ public function getCPUUsage() {} /** * Fetch the current memory usage of the Lua environment. * * @link https://www.php.net/manual/en/luasandbox.getmemoryusage.php * @return int * @since luasandbox >= 1.0.0 * @see LuaSandbox::getMemoryUsage() * @see LuaSandbox::getCPUUsage() * @see LuaSandbox::setMemoryLimit() */ public function getMemoryUsage() {} /** * Fetch the peak memory usage of the Lua environment. * * @link https://www.php.net/manual/en/luasandbox.getpeakmemoryusage.php * @return int

Returns the current memory usage in bytes.

* @since luasandbox >= 1.0.0 * @see LuaSandbox::getMemoryUsage() * @see LuaSandbox::getCPUUsage() * @see LuaSandbox::setMemoryLimit() */ public function getPeakMemoryUsage() {} /** * Fetch profiler data. * *

For a profiling instance previously started by LuaSandbox::enableProfiler(), * get a report of the cost of each function.

* *

The measurement unit used for the cost is determined by the $units parameter:

*
  • LuaSandbox::SAMPLES Measure in number of samples.
  • *
  • LuaSandbox::SECONDS Measure in seconds of CPU time.
  • *
  • LuaSandbox::PERCENT Measure percentage of CPU time.
  • * *

    Note: On Windows, this function always returns an empty array. * On operating systems that do not support CLOCK_THREAD_CPUTIME_ID, * such as FreeBSD and Mac OS X, this function will report the * elapsed wall-clock time, not CPU time.

    * * @link https://www.php.net/manual/en/luasandbox.getprofilerfunctionreport.php * @param int $units Measurement unit constant. * @return array

    Returns profiler measurements, sorted in descending order, as an associative array. * Keys are the Lua function names (with source file and line defined in angle brackets), values are the * measurements as integer or float.

    * @since luasandbox >= 1.1.0 * @see LuaSandbox::SAMPLES * @see LuaSandbox::SECONDS * @see LuaSandbox::PERCENT */ public function getProfilerFunctionReport($units = LuaSandbox::SECONDS) {} /** * Return the versions of LuaSandbox and Lua. * * @link https://www.php.net/manual/en/luasandbox.getversioninfo.php * @return array

    Returns an array with two keys:

    *
  • LuaSandbox (string), the version of the LuaSandbox extension.
  • *
  • Lua (string), the library name and version as defined by the LUA_RELEASE macro, for example, "Lua 5.1.5".
  • * @since luasandbox >= 1.6.0 */ public static function getVersionInfo() {} /** * Load a precompiled binary chunk into the Lua environment. * *

    Loads data generated by LuaSandboxFunction::dump().

    * * @link https://www.php.net/manual/en/luasandbox.loadbinary.php * @param string $code

    Data from LuaSandboxFunction::dump().

    * @param string $chunkName [optional]

    Name for the loaded function.

    * @return LuaSandboxFunction * @since luasandbox >= 1.0.0 * @see LuaSandbox::loadString() */ public function loadBinary($code, $chunkName = '') {} /** * Load Lua code into the Lua environment. * *

    This is the equivalent of standard Lua's loadstring() function.

    * * @link https://www.php.net/manual/en/luasandbox.loadString.php * @param string $code

    Lua code.

    * @param string $chunkName [optional]

    Name for the loaded chunk, for use in error traces.

    * @return LuaSandboxFunction

    Returns a LuaSandboxFunction which, when executed, * will execute the passed $code.

    * @since luasandbox >= 1.0.0 * @see LuaSandbox::registerLibrary() * @see LuaSandbox::wrapPhpFunction() */ public function loadString($code, $chunkName = '') {} /** * Pause the CPU usage timer. * *

    This only has effect when called from within a callback from Lua. * When execution returns to Lua, the timer will be automatically unpaused. * If a new call into Lua is made, the timer will be unpaused * for the duration of that call.

    * *

    If a PHP callback calls into Lua again with timer not paused, * and then that Lua function calls into PHP again, * the second PHP call will not be able to pause the timer. * The logic is that even though the second PHP call would * avoid counting the CPU usage against the limit, * the first call still counts it.

    * * @link https://www.php.net/manual/en/luasandbox.pauseusagetimer.php * @return bool

    Returns a boolean indicating whether the timer is now paused.

    * @since luasandbox >= 1.4.0 * @see LuaSandbox::setCPULimit() * @see LuaSandbox::unpauseUsageTimer() */ public function pauseUsageTimer() {} /** * Register a set of PHP functions as a Lua library. * *

    Registers a set of PHP functions as a Lua library, * so that Lua can call the relevant PHP code.

    * *

    For more information about calling Lua functions and the return values, * see LuaSandboxFunction::call().

    * * @link https://www.php.net/manual/en/luasandbox.registerlibrary.php * @param string $libname

    The name of the library. * In the Lua state, the global variable of this name will be set to the table of functions. * If the table already exists, the new functions will be added to it.

    * @param array $functions

    Returns an array, where each key is a function name, * and each value is a corresponding PHP callable.

    * @since luasandbox >= 1.0.0 * @see LuaSandbox::loadString() * @see LuaSandbox::wrapPhpFunction() */ public function registerLibrary($libname, $functions) {} /** * Set the CPU time limit for the Lua environment. * *

    If the total user and system time used by the environment after the call * to this method exceeds this limit, a LuaSandboxTimeoutError exception is thrown.

    * *

    Time used in PHP callbacks is included in the limit.

    * *

    Setting the time limit from a callback while Lua is running causes the timer to be reset, * or started if it was not already running.

    * *

    Note: On Windows, the CPU limit will be ignored. On operating systems * that do not support CLOCK_THREAD_CPUTIME_ID, such as FreeBSD and * Mac OS X, wall-clock time rather than CPU time will be limited.

    * * @link https://www.php.net/manual/en/luasandbox.setcpulimit.php * @param bool|float $limit

    Limit as a float in seconds, or false for no limit.

    * @since luasandbox >= 1.0.0 * @see LuaSandbox::getCPUUsage() * @see LuaSandbox::setMemoryLimit() */ public function setCPULimit($limit) {} /** * Set the memory limit for the Lua environment. * * @link https://www.php.net/manual/en/luasandbox.setmemorylimit.php * @param int $limit

    Memory limit in bytes.

    * @throws LuaSandboxMemoryError

    Exception is thrown if this limit is exceeded.

    * @since luasandbox >= 1.0.0 * @see LuaSandbox::getMemoryUsage() * @see LuaSandbox::getPeakMemoryUsage() * @see LuaSandbox::setCPULimit() */ public function setMemoryLimit($limit) {} /** * Unpause the timer paused by LuaSandbox::pauseUsageTimer(). * * @link https://www.php.net/manual/en/luasandbox.unpauseusagetimer.php * @since luasandbox >= 1.0.0 * @see LuaSandbox::setCPULimit() * @see LuaSandbox::unpauseUsageTimer() */ public function unpauseUsageTimer() {} /** * Wrap a PHP callable in a LuaSandboxFunction. * *

    Wraps a PHP callable in a LuaSandboxFunction, * so it can be passed into Lua as an anonymous function.

    * *

    The function must return either an array of values (which may be empty), * or NULL which is equivalent to returning the empty array.

    * *

    Exceptions will be raised as errors in Lua, however only LuaSandboxRuntimeError * exceptions may be caught inside Lua with pcall() or xpcall().

    * *

    For more information about calling Lua functions and the return values, * see LuaSandboxFunction::call().

    * * @link https://www.php.net/manual/en/luasandbox.wrapPhpFunction.php * @param callable $function

    Callable to wrap.

    * @return LuaSandboxFunction * @since luasandbox >= 1.2.0 * @see LuaSandbox::loadString() * @see LuaSandbox::registerLibrary() */ public function wrapPhpFunction($function) {} } /** * Represents a Lua function, allowing it to be called from PHP. * *

    A LuaSandboxFunction may be obtained as a return value from Lua, * as a parameter passed to a callback from Lua, * or by using LuaSandbox::wrapPhpFunction(), LuaSandbox::loadString(), * or LuaSandbox::loadBinary().

    * * @since luasandbox >= 1.0.0 */ class LuaSandboxFunction { /** * Call a Lua function. * *

    Errors considered to be the fault of the PHP code will result in the * function returning false and E_WARNING being raised, for example, * a resource type being used as an argument. Lua errors will result * in a LuaSandboxRuntimeError exception being thrown.

    * *

    PHP and Lua types are converted as follows:

    *
      *
    • PHP NULL is Lua nil, and vice versa.
    • *
    • PHP integers and floats are converted to Lua numbers. Infinity and NAN are supported.
    • *
    • Lua numbers without a fractional part between approximately -2**53 and 2**53 are * converted to PHP integers, with others being converted to PHP floats.
    • *
    • PHP booleans are Lua booleans, and vice versa.
    • *
    • PHP strings are Lua strings, and vice versa.
    • *
    • Lua functions are PHP LuaSandboxFunction objects, and vice versa. * General PHP callables are not supported.
    • *
    • PHP arrays are converted to Lua tables, and vice versa.
    • *
        *
      • Note that Lua typically indexes arrays from 1, while PHP indexes arrays from 0. * No adjustment is made for these differing conventions.
      • *
      • Self-referential arrays are not supported in either direction.
      • *
      • PHP references are dereferenced.
      • *
      • Lua __pairs and __ipairs are processed. __index is ignored.
      • *
      • When converting from PHP to Lua, integer keys between -2**53 and 2**53 are represented as Lua numbers. * All other keys are represented as Lua strings.
      • *
      • When converting from Lua to PHP, keys other than strings and numbers will result in an error, * as will collisions when converting numbers to strings or vice versa * (since PHP considers things like $a[0] and $a["0"] as being equivalent).
      • *
      *
    • All other types are unsupported and will raise an error/exception, * including general PHP objects and Lua userdata and thread types.
    • *
    * *

    Lua functions inherently return a list of results. So on success, * this method returns an array containing all of the values returned by Lua, * with integer keys starting from zero. * Lua may return no results, in which case an empty array is returned.

    * * @link https://www.php.net/manual/en/luasandboxfunction.call.php * @param string[] $arguments

    Arguments passed to the function.

    * @return array|bool

    Returns an array of values returned by the function, * which may be empty, or false on error.

    * @since luasandbox >= 1.0.0 */ public function call(string ...$args) {} /** * Dump the function as a binary blob. * * @link https://www.php.net/manual/en/luasandboxfunction.dump.php * @return string

    Returns a string that may be passed to LuaSandbox::loadBinary().

    * @since luasandbox >= 1.0.0 */ public function dump() {} } /** * Base class for LuaSandbox exceptions. * * @since luasandbox >= 1.0.0 */ class LuaSandboxError extends Exception { public const RUN = 2; public const SYNTAX = 3; public const MEM = 4; public const ERR = 5; } /** * Catchable LuaSandbox runtime exceptions. * *

    These may be caught inside Lua using pcall() or xpcall().

    * * @since luasandbox >= 1.0.0 */ class LuaSandboxRuntimeError extends LuaSandboxError {} /** * Uncatchable LuaSandbox exceptions. * *

    These may not be caught inside Lua using pcall() or xpcall().

    * * @since luasandbox >= 1.0.0 */ class LuaSandboxFatalError extends LuaSandboxError {} /** * Exception thrown when Lua encounters an error inside an error handler. * * @since luasandbox >= 1.0.0 */ class LuaSandboxErrorError extends LuaSandboxFatalError {} /** * Exception thrown when Lua cannot allocate memory. * * @since luasandbox >= 1.0.0 * @see LuaSandbox::setMemoryLimit() */ class LuaSandboxMemoryError extends LuaSandboxFatalError {} /** * Exception thrown when Lua code cannot be parsed. * * @since luasandbox >= 1.0.0 */ class LuaSandboxSyntaxError extends LuaSandboxFatalError {} /** * Exception thrown when the configured CPU time limit is exceeded. * * @since luasandbox >= 1.0.0 * @see LuaSandbox::setCPULimit() */ class LuaSandboxTimeoutError extends LuaSandboxFatalError {} This file was automatically generated by Composer Patches (https://github.com/cweagans/composer-patches) Patches applied to this directory: 0 Source: patches/PDO.patch 1 Source: patches/ReflectionProperty.patch 2 Source: patches/SessionHandler.patch 3 Source: patches/xmlreader.patch 4 Source: patches/dom_c.patch PDOException from your own code. * @see https://php.net/manual/en/language.exceptions.php Exceptions in PHP * @link https://php.net/manual/en/class.pdoexception.php */ class PDOException extends RuntimeException { #[LanguageLevelTypeAware(['8.1' => 'array|null'], default: '')] public $errorInfo; protected $code; } /** * Represents a connection between PHP and a database server. * @link https://php.net/manual/en/class.pdo.php */ class PDO { /** * Represents the SQL NULL data type. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.param-null */ public const PARAM_NULL = 0; /** * Represents the SQL INTEGER data type. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.param-int */ public const PARAM_INT = 1; /** * Represents the SQL CHAR, VARCHAR, or other string data type. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.param-str */ public const PARAM_STR = 2; /** * Represents the SQL large object data type. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.param-lob */ public const PARAM_LOB = 3; /** * Represents a recordset type. Not currently supported by any drivers. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.param-stmt */ public const PARAM_STMT = 4; /** * Represents a boolean data type. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.param-bool */ public const PARAM_BOOL = 5; /** * Flag to denote a string uses the national character set. * @since 7.2 * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.param-str-natl */ public const PARAM_STR_NATL = 1073741824; /** * Flag to denote a string uses the regular character set. * @since 7.2 * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.param-str-char */ public const PARAM_STR_CHAR = 536870912; /** * Sets the default string parameter type, this can be one of PDO::PARAM_STR_NATL and PDO::PARAM_STR_CHAR. * @since 7.2 * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-default-str-param */ public const ATTR_DEFAULT_STR_PARAM = 21; /** * Specifies that a function created with PDO::sqliteCreateFunction() is deterministic, i.e. it always returns the same result given the same inputs within a single SQL statement. * @since 7.1.4 * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.sqlite-deterministic */ #[Deprecated('use Pdo\Sqlite::DETERMINISTIC instead', since: '8.5')] public const SQLITE_DETERMINISTIC = 2048; /** * @since 7.3 */ #[Deprecated('use Pdo\Sqlite::OPEN_READONLY instead', since: '8.5')] public const SQLITE_OPEN_READONLY = 1; /** * @since 7.3 */ #[Deprecated('use Pdo\Sqlite::OPEN_READWRITE instead', since: '8.5')] public const SQLITE_OPEN_READWRITE = 2; /** * @since 7.3 */ #[Deprecated('use Pdo\Sqlite::OPEN_CREATE instead', since: '8.5')] public const SQLITE_OPEN_CREATE = 4; /** * @since 7.3 */ #[Deprecated('use Pdo\Sqlite::OPEN_FLAGS instead', since: '8.5')] public const SQLITE_ATTR_OPEN_FLAGS = 1000; /** * Specifies that the parameter is an INOUT parameter for a stored * procedure. You must bitwise-OR this value with an explicit * PDO::PARAM_* data type. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.param-input-output */ public const PARAM_INPUT_OUTPUT = 2147483648; /** * Allocation event * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.param-evt-alloc */ public const PARAM_EVT_ALLOC = 0; /** * Deallocation event * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.param-evt-free */ public const PARAM_EVT_FREE = 1; /** * Event triggered prior to execution of a prepared statement. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.param-evt-exec-pre */ public const PARAM_EVT_EXEC_PRE = 2; /** * Event triggered subsequent to execution of a prepared statement. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.param-evt-exec-post */ public const PARAM_EVT_EXEC_POST = 3; /** * Event triggered prior to fetching a result from a resultset. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.param-evt-fetch-pre */ public const PARAM_EVT_FETCH_PRE = 4; /** * Event triggered subsequent to fetching a result from a resultset. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.param-evt-fetch-post */ public const PARAM_EVT_FETCH_POST = 5; /** * Event triggered during bound parameter registration * allowing the driver to normalize the parameter name. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.param-evt-normalize */ public const PARAM_EVT_NORMALIZE = 6; /** * Specifies that the fetch method shall return each row as an object with * variable names that correspond to the column names returned in the result * set. PDO::FETCH_LAZY creates the object variable names as they are accessed. * Not valid inside PDOStatement::fetchAll. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-lazy */ public const FETCH_LAZY = 1; /** * Specifies that the fetch method shall return each row as an array indexed * by column name as returned in the corresponding result set. If the result * set contains multiple columns with the same name, * PDO::FETCH_ASSOC returns * only a single value per column name. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-assoc */ public const FETCH_ASSOC = 2; /** * Specifies that the fetch method shall return each row as an array indexed * by column number as returned in the corresponding result set, starting at * column 0. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-num */ public const FETCH_NUM = 3; /** * Specifies that the fetch method shall return each row as an array indexed * by both column name and number as returned in the corresponding result set, * starting at column 0. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-both */ public const FETCH_BOTH = 4; /** * Specifies that the fetch method shall return each row as an object with * property names that correspond to the column names returned in the result * set. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-obj */ public const FETCH_OBJ = 5; /** * Specifies that the fetch method shall return TRUE and assign the values of * the columns in the result set to the PHP variables to which they were * bound with the PDOStatement::bindParam or * PDOStatement::bindColumn methods. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-bound */ public const FETCH_BOUND = 6; /** * Specifies that the fetch method shall return only a single requested * column from the next row in the result set. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-column */ public const FETCH_COLUMN = 7; /** * Specifies that the fetch method shall return a new instance of the * requested class, mapping the columns to named properties in the class. * The magic * __set * method is called if the property doesn't exist in the requested class * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-class */ public const FETCH_CLASS = 8; /** * Specifies that the fetch method shall update an existing instance of the * requested class, mapping the columns to named properties in the class. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-into */ public const FETCH_INTO = 9; /** * Allows completely customize the way data is treated on the fly (only * valid inside PDOStatement::fetchAll). * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-func */ public const FETCH_FUNC = 10; /** * Group return by values. Usually combined with * PDO::FETCH_COLUMN or * PDO::FETCH_KEY_PAIR. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-group */ public const FETCH_GROUP = 65536; /** * Fetch only the unique values. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-unique */ public const FETCH_UNIQUE = 196608; /** * Fetch a two-column result into an array where the first column is a key and the second column * is the value. * @since 5.2.3 * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-key-pair */ public const FETCH_KEY_PAIR = 12; /** * Determine the class name from the value of first column. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-classtype */ public const FETCH_CLASSTYPE = 262144; /** * As PDO::FETCH_INTO but object is provided as a serialized string. * Available since PHP 5.1.0. Since PHP 5.3.0 the class constructor is never called if this * flag is set. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-serialize */ public const FETCH_SERIALIZE = 524288; /** * Call the constructor before setting properties. * @since 5.2 * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-props-late */ public const FETCH_PROPS_LATE = 1048576; /** * Specifies that the fetch method shall return each row as an array indexed * by column name as returned in the corresponding result set. If the result * set contains multiple columns with the same name, * PDO::FETCH_NAMED returns * an array of values per column name. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-named */ public const FETCH_NAMED = 11; /** * If this value is FALSE, PDO attempts to disable autocommit so that the * connection begins a transaction. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-autocommit */ public const ATTR_AUTOCOMMIT = 0; /** * Setting the prefetch size allows you to balance speed against memory * usage for your application. Not all database/driver combinations support * setting of the prefetch size. A larger prefetch size results in * increased performance at the cost of higher memory usage. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-prefetch */ public const ATTR_PREFETCH = 1; /** * Sets the timeout value in seconds for communications with the database. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-timeout */ public const ATTR_TIMEOUT = 2; /** * @see https://php.net/manual/en/pdo.error-handling.php Errors and error handling * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-errmode */ public const ATTR_ERRMODE = 3; /** * This is a read only attribute; it will return information about the * version of the database server to which PDO is connected. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr- */ public const ATTR_SERVER_VERSION = 4; /** * This is a read only attribute; it will return information about the * version of the client libraries that the PDO driver is using. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-client-version */ public const ATTR_CLIENT_VERSION = 5; /** * This is a read only attribute; it will return some meta information about the * database server to which PDO is connected. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-server-info */ public const ATTR_SERVER_INFO = 6; public const ATTR_CONNECTION_STATUS = 7; /** * Force column names to a specific case specified by the PDO::CASE_* * constants. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-case */ public const ATTR_CASE = 8; /** * Get or set the name to use for a cursor. Most useful when using * scrollable cursors and positioned updates. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-cursor-name */ public const ATTR_CURSOR_NAME = 9; /** * Selects the cursor type. PDO currently supports either * PDO::CURSOR_FWDONLY and * PDO::CURSOR_SCROLL. Stick with * PDO::CURSOR_FWDONLY unless you know that you need a * scrollable cursor. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-cursor */ public const ATTR_CURSOR = 10; /** * Convert empty strings to SQL NULL values on data fetches. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-oracle-nulls */ public const ATTR_ORACLE_NULLS = 11; /** * Request a persistent connection, rather than creating a new connection. * @see https://php.net/manual/en/pdo.connections.php Connections and Connection Management * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-persistent */ public const ATTR_PERSISTENT = 12; /** * Sets the class name of which statements are returned as. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-statement-class */ public const ATTR_STATEMENT_CLASS = 13; /** * Prepend the containing table name to each column name returned in the * result set. The table name and column name are separated by a decimal (.) * character. Support of this attribute is at the driver level; it may not * be supported by your driver. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-fetch-table-names */ public const ATTR_FETCH_TABLE_NAMES = 14; /** * Prepend the containing catalog name to each column name returned in the * result set. The catalog name and column name are separated by a decimal * (.) character. Support of this attribute is at the driver level; it may * not be supported by your driver. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-fetch-catalog-names */ public const ATTR_FETCH_CATALOG_NAMES = 15; /** * Returns the name of the driver. *

    * using PDO::ATTR_DRIVER_NAME * * if ($db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql') { * echo "Running on mysql; doing something mysql specific here\n"; * } * *

    * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-driver-name */ public const ATTR_DRIVER_NAME = 16; /** * Forces all values fetched to be treated as strings. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-stringify-fetches */ public const ATTR_STRINGIFY_FETCHES = 17; /** * Sets the maximum column name length. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-max-column-len */ public const ATTR_MAX_COLUMN_LEN = 18; /** * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-emulate-prepares * @since 5.1.3 */ public const ATTR_EMULATE_PREPARES = 20; /** * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-default-fetch-mode * @since 5.2 */ public const ATTR_DEFAULT_FETCH_MODE = 19; /** * Do not raise an error or exception if an error occurs. The developer is * expected to explicitly check for errors. This is the default mode. * @see https://php.net/manual/en/pdo.error-handling.php Errors and Error Handling * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.errmode-silent */ public const ERRMODE_SILENT = 0; /** * Issue a PHP E_WARNING message if an error occurs. * @see https://php.net/manual/en/pdo.error-handling.php Errors and Error Handling * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.errmode-warning */ #[Deprecated('use PDO::ERRMODE_SILENT or PDO::ERRMODE_EXCEPTION instead', since: '8.5')] public const ERRMODE_WARNING = 1; /** * Throw a PDOException if an error occurs. * @see https://php.net/manual/en/pdo.error-handling.php Errors and Error Handling * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.errmode-exception */ public const ERRMODE_EXCEPTION = 2; /** * Leave column names as returned by the database driver. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.case-natural */ public const CASE_NATURAL = 0; /** * Force column names to lower case. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.case-lower */ public const CASE_LOWER = 2; /** * Force column names to upper case. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.case-upper */ public const CASE_UPPER = 1; /** * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.null-natural */ public const NULL_NATURAL = 0; /** * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.null-empty-string */ public const NULL_EMPTY_STRING = 1; /** * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.null-to-string */ public const NULL_TO_STRING = 2; /** * Corresponds to SQLSTATE '00000', meaning that the SQL statement was * successfully issued with no errors or warnings. This constant is for * your convenience when checking PDO::errorCode or * PDOStatement::errorCode to determine if an error * occurred. You will usually know if this is the case by examining the * return code from the method that raised the error condition anyway. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.err-none */ public const ERR_NONE = '00000'; /** * Fetch the next row in the result set. Valid only for scrollable cursors. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-ori-next */ public const FETCH_ORI_NEXT = 0; /** * Fetch the previous row in the result set. Valid only for scrollable * cursors. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-ori-prior */ public const FETCH_ORI_PRIOR = 1; /** * Fetch the first row in the result set. Valid only for scrollable cursors. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-ori-first */ public const FETCH_ORI_FIRST = 2; /** * Fetch the last row in the result set. Valid only for scrollable cursors. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-ori-last */ public const FETCH_ORI_LAST = 3; /** * Fetch the requested row by row number from the result set. Valid only * for scrollable cursors. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-ori-abs */ public const FETCH_ORI_ABS = 4; /** * Fetch the requested row by relative position from the current position * of the cursor in the result set. Valid only for scrollable cursors. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-ori-rel */ public const FETCH_ORI_REL = 5; /** * Specifies that the default fetch mode shall be used. * @since 8.0.7 * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.fetch-default */ public const FETCH_DEFAULT = 0; /** * Create a PDOStatement object with a forward-only cursor. This is the * default cursor choice, as it is the fastest and most common data access * pattern in PHP. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.cursor-fwdonly */ public const CURSOR_FWDONLY = 0; /** * Create a PDOStatement object with a scrollable cursor. Pass the * PDO::FETCH_ORI_* constants to control the rows fetched from the result set. * @link https://php.net/manual/en/pdo.constants.php#pdo.constants.cursor-scroll */ public const CURSOR_SCROLL = 1; /** * If this attribute is set to TRUE on a * PDOStatement, the MySQL driver will use the * buffered versions of the MySQL API. If you're writing portable code, you * should use PDOStatement::fetchAll instead. *

    * Forcing queries to be buffered in mysql * * if ($db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql') { * $stmt = $db->prepare('select * from foo', * array(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true)); * } else { * die("my application only works with mysql; I should use \$stmt->fetchAll() instead"); * } * *

    * @link https://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-use-buffered-query */ #[Deprecated('use Pdo\Mysql::ATTR_USE_BUFFERED_QUERY instead', since: '8.5')] public const MYSQL_ATTR_USE_BUFFERED_QUERY = 1000; /** *

    * Enable LOAD LOCAL INFILE. *

    *

    * Note, this constant can only be used in the driver_options * array when constructing a new database handle. *

    * @link https://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-local-infile */ #[Deprecated('use Pdo\Mysql::ATTR_LOCAL_INFILE instead', since: '8.5')] public const MYSQL_ATTR_LOCAL_INFILE = 1001; /** *

    * Command to execute when connecting to the MySQL server. Will * automatically be re-executed when reconnecting. *

    *

    * Note, this constant can only be used in the driver_options * array when constructing a new database handle. *

    * @link https://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-init-command */ #[Deprecated('use Pdo\Mysql::ATTR_INIT_COMMAND instead', since: '8.5')] public const MYSQL_ATTR_INIT_COMMAND = 1002; /** *

    * Maximum buffer size. Defaults to 1 MiB. This constant is not supported when * compiled against mysqlnd. *

    * @link https://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-max-buffer-size */ #[Deprecated('use Pdo\Mysql::ATTR_MAX_BUFFER_SIZE instead', since: '8.5')] public const MYSQL_ATTR_MAX_BUFFER_SIZE = 1005; /** *

    * Read options from the named option file instead of from * my.cnf. This option is not available if * mysqlnd is used, because mysqlnd does not read the mysql * configuration files. *

    * @link https://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-read-default-file */ #[Deprecated('use Pdo\Mysql::ATTR_READ_DEFAULT_FILE instead', since: '8.5')] public const MYSQL_ATTR_READ_DEFAULT_FILE = 1003; /** *

    * Read options from the named group from my.cnf or the * file specified with MYSQL_READ_DEFAULT_FILE. This option * is not available if mysqlnd is used, because mysqlnd does not read the mysql * configuration files. *

    * @link https://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-read-default-group */ #[Deprecated('use Pdo\Mysql::ATTR_READ_DEFAULT_GROUP instead', since: '8.5')] public const MYSQL_ATTR_READ_DEFAULT_GROUP = 1004; /** *

    * Enable network communication compression. This is not supported when * compiled against mysqlnd. *

    * @link https://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-compress */ #[Deprecated('use Pdo\Mysql::ATTR_COMPRESS instead', since: '8.5')] public const MYSQL_ATTR_COMPRESS = 1003; /** *

    * Perform direct queries, don't use prepared statements. *

    * @link https://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-direct-query */ #[Deprecated('use Pdo\Mysql::ATTR_DIRECT_QUERY instead', since: '8.5')] public const MYSQL_ATTR_DIRECT_QUERY = 1004; /** *

    * Return the number of found (matched) rows, not the * number of changed rows. *

    * @link https://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-found-rows */ #[Deprecated('use Pdo\Mysql::ATTR_FOUND_ROWS instead', since: '8.5')] public const MYSQL_ATTR_FOUND_ROWS = 1005; /** *

    * Permit spaces after function names. Makes all functions * names reserved words. *

    * @link https://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-ignore-space */ #[Deprecated('use Pdo\Mysql::ATTR_IGNORE_SPACE instead', since: '8.5')] public const MYSQL_ATTR_IGNORE_SPACE = 1006; #[Deprecated('use Pdo\Mysql::ATTR_SERVER_PUBLIC_KEY instead', since: '8.5')] public const MYSQL_ATTR_SERVER_PUBLIC_KEY = 1012; /** *

    * The file path to the SSL key. *

    * @since 5.3.7 * @link https://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-ssl-key */ #[Deprecated('use Pdo\Mysql::ATTR_SSL_KEY instead', since: '8.5')] public const MYSQL_ATTR_SSL_KEY = 1007; /** *

    * The file path to the SSL certificate. *

    * @since 5.3.7 * @link https://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-ssl-cert */ #[Deprecated('use Pdo\Mysql::ATTR_SSL_CERT instead', since: '8.5')] public const MYSQL_ATTR_SSL_CERT = 1008; /** *

    * The file path to the SSL certificate authority. *

    * @since 5.3.7 * @link https://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-ssl-ca */ #[Deprecated('use Pdo\Mysql::ATTR_SSL_CA instead', since: '8.5')] public const MYSQL_ATTR_SSL_CA = 1009; /** *

    * The file path to the directory that contains the trusted SSL * CA certificates, which are stored in PEM format. *

    * @since 5.3.7 * @link https://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-ssl-capath */ #[Deprecated('use Pdo\Mysql::ATTR_SSL_CAPATH instead', since: '8.5')] public const MYSQL_ATTR_SSL_CAPATH = 1010; /** *

    * A list of one or more permissible ciphers to use for SSL encryption, * in a format understood by OpenSSL. * For example: DHE-RSA-AES256-SHA:AES128-SHA *

    * @since 5.3.7 * @link https://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-cipher */ #[Deprecated('use Pdo\Mysql::ATTR_SSL_CIPHER instead', since: '8.5')] public const MYSQL_ATTR_SSL_CIPHER = 1011; /** *

    * Disables multi query execution in both {@see PDO::prepare()} and {@see PDO::query()} when set to FALSE. *

    *

    * Note, this constant can only be used in the driver_options array when constructing a new database handle. *

    * @since 5.5.21 * @link https://php.net/manual/en/ref.pdo-mysql.php#pdo.constants.mysql-attr-multi-statements */ #[Deprecated('use Pdo\Mysql::ATTR_MULTI_STATEMENTS instead', since: '8.5')] public const MYSQL_ATTR_MULTI_STATEMENTS = 1013; /** *

    * Disables SSL peer verification when set to FALSE. *

    * @since 7.0.18 * @since 7.1.4 * @link https://bugs.php.net/bug.php?id=71003 */ #[Deprecated('use Pdo\Mysql::ATTR_SSL_VERIFY_SERVER_CERT instead', since: '8.5')] public const MYSQL_ATTR_SSL_VERIFY_SERVER_CERT = 1014; /** * @since 8.1 */ #[Deprecated('use Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY instead', since: '8.5')] public const MYSQL_ATTR_LOCAL_INFILE_DIRECTORY = 1015; #[Deprecated("Use PDO::ATTR_EMULATE_PREPARES instead")] public const PGSQL_ASSOC = 1; /** * @removed 7.1 */ public const PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT = 1000; /** * @since 5.6 */ #[Deprecated('Deprecated: it has no effect', since: '8.5')] public const PGSQL_ATTR_DISABLE_PREPARES = 1000; public const PGSQL_BAD_RESPONSE = 5; public const PGSQL_BOTH = 3; #[Deprecated('Deprecated: it has no effect', since: '8.5')] public const PGSQL_TRANSACTION_IDLE = 0; #[Deprecated('Deprecated: it has no effect', since: '8.5')] public const PGSQL_TRANSACTION_ACTIVE = 1; #[Deprecated('Deprecated: it has no effect', since: '8.5')] public const PGSQL_TRANSACTION_INTRANS = 2; #[Deprecated('Deprecated: it has no effect', since: '8.5')] public const PGSQL_TRANSACTION_INERROR = 3; #[Deprecated('Deprecated: it has no effect', since: '8.5')] public const PGSQL_TRANSACTION_UNKNOWN = 4; public const PGSQL_CONNECT_ASYNC = 4; public const PGSQL_CONNECT_FORCE_NEW = 2; public const PGSQL_CONNECTION_AUTH_OK = 5; public const PGSQL_CONNECTION_AWAITING_RESPONSE = 4; public const PGSQL_CONNECTION_BAD = 1; public const PGSQL_CONNECTION_OK = 0; public const PGSQL_CONNECTION_MADE = 3; public const PGSQL_CONNECTION_SETENV = 6; public const PGSQL_CONNECTION_SSL_STARTUP = 7; public const PGSQL_CONNECTION_STARTED = 2; public const PGSQL_COMMAND_OK = 1; public const PGSQL_CONV_FORCE_NULL = 4; public const PGSQL_CONV_IGNORE_DEFAULT = 2; public const PGSQL_CONV_IGNORE_NOT_NULL = 8; public const PGSQL_COPY_IN = 4; public const PGSQL_COPY_OUT = 3; public const PGSQL_DIAG_CONTEXT = 87; public const PGSQL_DIAG_INTERNAL_POSITION = 112; public const PGSQL_DIAG_INTERNAL_QUERY = 113; public const PGSQL_DIAG_MESSAGE_DETAIL = 68; public const PGSQL_DIAG_MESSAGE_HINT = 72; public const PGSQL_DIAG_MESSAGE_PRIMARY = 77; public const PGSQL_DIAG_SEVERITY = 83; public const PGSQL_DIAG_SOURCE_FILE = 70; public const PGSQL_DIAG_SOURCE_FUNCTION = 82; public const PGSQL_DIAG_SOURCE_LINE = 76; public const PGSQL_DIAG_SQLSTATE = 67; public const PGSQL_DIAG_STATEMENT_POSITION = 80; public const PGSQL_DML_ASYNC = 1024; public const PGSQL_DML_EXEC = 512; public const PGSQL_DML_NO_CONV = 256; public const PGSQL_DML_STRING = 2048; public const PGSQL_DML_ESCAPE = 4096; public const PGSQL_EMPTY_QUERY = 0; public const PGSQL_ERRORS_DEFAULT = 1; public const PGSQL_ERRORS_TERSE = 0; public const PGSQL_ERRORS_VERBOSE = 2; public const PGSQL_FATAL_ERROR = 7; public const PGSQL_NONFATAL_ERROR = 6; public const PGSQL_NOTICE_ALL = 2; public const PGSQL_NOTICE_CLEAR = 3; public const PGSQL_NOTICE_LAST = 1; public const PGSQL_NUM = 2; public const PGSQL_POLLING_ACTIVE = 4; public const PGSQL_POLLING_FAILED = 0; public const PGSQL_POLLING_OK = 3; public const PGSQL_POLLING_READING = 1; public const PGSQL_POLLING_WRITING = 2; public const PGSQL_SEEK_CUR = 1; public const PGSQL_SEEK_END = 2; public const PGSQL_SEEK_SET = 0; public const PGSQL_STATUS_LONG = 1; public const PGSQL_STATUS_STRING = 2; public const PGSQL_TUPLES_OK = 2; public const SQLSRV_TXN_READ_UNCOMMITTED = "READ_UNCOMMITTED"; public const SQLSRV_TXN_READ_COMMITTED = "READ_COMMITTED"; public const SQLSRV_TXN_REPEATABLE_READ = "REPEATABLE_READ"; public const SQLSRV_TXN_SNAPSHOT = "SNAPSHOT"; public const SQLSRV_TXN_SERIALIZABLE = "SERIALIZABLE"; public const SQLSRV_ENCODING_BINARY = 2; public const SQLSRV_ENCODING_SYSTEM = 3; public const SQLSRV_ENCODING_UTF8 = 65001; public const SQLSRV_ENCODING_DEFAULT = 1; public const SQLSRV_ATTR_ENCODING = 1000; public const SQLSRV_ATTR_QUERY_TIMEOUT = 1001; public const SQLSRV_ATTR_DIRECT_QUERY = 1002; public const SQLSRV_ATTR_CURSOR_SCROLL_TYPE = 1003; public const SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE = 1004; public const SQLSRV_ATTR_FETCHES_NUMERIC_TYPE = 1005; public const SQLSRV_ATTR_FETCHES_DATETIME_TYPE = 1006; public const SQLSRV_ATTR_FORMAT_DECIMALS = 1007; public const SQLSRV_ATTR_DECIMAL_PLACES = 1008; public const SQLSRV_ATTR_DATA_CLASSIFICATION = 1009; public const SQLSRV_PARAM_OUT_DEFAULT_SIZE = -1; public const SQLSRV_CURSOR_KEYSET = 1; public const SQLSRV_CURSOR_DYNAMIC = 2; public const SQLSRV_CURSOR_STATIC = 3; public const SQLSRV_CURSOR_BUFFERED = 42; /** * @since 7.4 */ #[Deprecated('use Pdo\Sqlite::ATTR_READONLY_STATEMENT instead', since: '8.5')] public const SQLITE_ATTR_READONLY_STATEMENT = 1001; /** * @since 7.4 */ #[Deprecated('use Pdo\Sqlite::ATTR_EXTENDED_RESULT_CODES instead', since: '8.5')] public const SQLITE_ATTR_EXTENDED_RESULT_CODES = 1002; /** * Provides a way to specify the action on the database session. * @since 7.2.16 * @since 7.3.3 */ public const OCI_ATTR_ACTION = 1000; /** * Provides a way to specify the client info on the database session. * @since 7.2.16 * @since 7.3.3 */ public const OCI_ATTR_CLIENT_INFO = 1001; /** * Provides a way to specify the client identifier on the database session. * @since 7.2.16 * @since 7.3.3 */ public const OCI_ATTR_CLIENT_IDENTIFIER = 1002; /** * Provides a way to specify the module on the database session. * @since 7.2.16 * @since 7.3.3 */ public const OCI_ATTR_MODULE = 1003; /** * The number of milliseconds to wait for individual round trips to the database to complete before timing out. * @since 8.0 */ public const OCI_ATTR_CALL_TIMEOUT = 1004; /** * Sets the date format. */ #[Deprecated('use Pdo\Firebird::ATTR_DATE_FORMAT instead', since: '8.5')] public const FB_ATTR_DATE_FORMAT = 1000; /** * Sets the time format. */ #[Deprecated('use Pdo\Firebird::ATTR_TIME_FORMAT instead', since: '8.5')] public const FB_ATTR_TIME_FORMAT = 1001; /** * Sets the timestamp format. */ #[Deprecated('use Pdo\Firebird::ATTR_TIMESTAMP_FORMAT instead', since: '8.5')] public const FB_ATTR_TIMESTAMP_FORMAT = 1002; /** * Sets the connection timeout in seconds. */ #[Deprecated('use Pdo\Dblib::ATTR_CONNECTION_TIMEOUT instead', since: '8.5')] public const DBLIB_ATTR_CONNECTION_TIMEOUT = 1000; /** * Sets the query timeout in seconds. */ #[Deprecated('use Pdo\Dblib::ATTR_QUERY_TIMEOUT instead', since: '8.5')] public const DBLIB_ATTR_QUERY_TIMEOUT = 1001; /** * Returns uniqueidentifier values as strings. */ #[Deprecated('use Pdo\Dblib::ATTR_STRINGIFY_UNIQUEIDENTIFIER instead', since: '8.5')] public const DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER = 1002; /** * Returns the version of the underlying DB-Library. */ #[Deprecated('use Pdo\Dblib::ATTR_VERSION instead', since: '8.5')] public const DBLIB_ATTR_VERSION = 1003; /** * Returns the TDS version used by the connection. */ #[Deprecated('use Pdo\Dblib::ATTR_TDS_VERSION instead', since: '8.5')] public const DBLIB_ATTR_TDS_VERSION = 1004; /** * Skips empty result sets returned by stored procedures. */ #[Deprecated('use Pdo\Dblib::ATTR_SKIP_EMPTY_ROWSETS instead', since: '8.5')] public const DBLIB_ATTR_SKIP_EMPTY_ROWSETS = 1005; /** * Controls datetime conversion to strings. */ #[Deprecated('use Pdo\Dblib::ATTR_DATETIME_CONVERT instead', since: '8.5')] public const DBLIB_ATTR_DATETIME_CONVERT = 1006; /** * Selects the ODBC cursor library to use. */ #[Deprecated('use Pdo\Odbc::ATTR_USE_CURSOR_LIBRARY instead', since: '8.5')] public const ODBC_ATTR_USE_CURSOR_LIBRARY = 1000; /** * Assume that data in the database is stored in UTF-8. */ #[Deprecated('use Pdo\Odbc::ATTR_ASSUME_UTF8 instead', since: '8.5')] public const ODBC_ATTR_ASSUME_UTF8 = 1001; /** * Use the driver's cursor library if needed. */ #[Deprecated('use Pdo\Odbc::SQL_USE_IF_NEEDED instead', since: '8.5')] public const ODBC_SQL_USE_IF_NEEDED = 0; /** * Use the ODBC cursor library. */ #[Deprecated('use Pdo\Odbc::SQL_USE_ODBC instead', since: '8.5')] public const ODBC_SQL_USE_ODBC = 1; /** * Use the driver's native cursor library. */ #[Deprecated('use Pdo\Odbc::SQL_USE_DRIVER instead', since: '8.5')] public const ODBC_SQL_USE_DRIVER = 2; /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Creates a PDO instance representing a connection to a database * @link https://php.net/manual/en/pdo.construct.php * @param string $dsn * @param string $username [optional] * @param string $password [optional] * @param array $options [optional] * @throws PDOException if the attempt to connect to the requested database fails. */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $dsn, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $username = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $password = null, #[LanguageLevelTypeAware(['8.0' => 'array|null'], default: '')] $options = null ) {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Prepares a statement for execution and returns a statement object * @link https://php.net/manual/en/pdo.prepare.php * @param string $query

    * This must be a valid SQL statement for the target database server. *

    * @param array $options [optional]

    * This array holds one or more key=>value pairs to set * attribute values for the PDOStatement object that this method * returns. You would most commonly use this to set the * PDO::ATTR_CURSOR value to * PDO::CURSOR_SCROLL to request a scrollable cursor. * Some drivers have driver specific options that may be set at * prepare-time. *

    * @return PDOStatement|false If the database server successfully prepares the statement, * PDO::prepare returns a * PDOStatement object. * If the database server cannot successfully prepare the statement, * PDO::prepare returns FALSE or emits * PDOException (depending on error handling). *

    * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. *

    * Emulated prepared statements does not communicate with the database server * so PDO::prepare does not check the statement. */ #[TentativeType] public function prepare( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $query, #[LanguageLevelTypeAware(['8.0' => 'array'], default: '')] $options = [] ): PDOStatement|false {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Initiates a transaction *

    * Turns off autocommit mode. While autocommit mode is turned off, * changes made to the database via the PDO object instance are not committed * until you end the transaction by calling {@link PDO::commit()}. * Calling {@link PDO::rollBack()} will roll back all changes to the database and * return the connection to autocommit mode. *

    *

    * Some databases, including MySQL, automatically issue an implicit COMMIT * when a database definition language (DDL) statement * such as DROP TABLE or CREATE TABLE is issued within a transaction. * The implicit COMMIT will prevent you from rolling back any other changes * within the transaction boundary. *

    * @link https://php.net/manual/en/pdo.begintransaction.php * @return bool TRUE on success or FALSE on failure. * @throws PDOException If there is already a transaction started or * the driver does not support transactions
    * Note: An exception is raised even when the PDO::ATTR_ERRMODE * attribute is not PDO::ERRMODE_EXCEPTION. */ #[TentativeType] public function beginTransaction(): bool {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Commits a transaction * @link https://php.net/manual/en/pdo.commit.php * @return bool TRUE on success or FALSE on failure. * @throws PDOException if there is no active transaction. */ #[TentativeType] public function commit(): bool {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Rolls back a transaction * @link https://php.net/manual/en/pdo.rollback.php * @return bool TRUE on success or FALSE on failure. * @throws PDOException if there is no active transaction. */ #[TentativeType] public function rollBack(): bool {} /** * (PHP 5 >= 5.3.3, Bundled pdo_pgsql, PHP 7)
    * Checks if inside a transaction * @link https://php.net/manual/en/pdo.intransaction.php * @return bool TRUE if a transaction is currently active, and FALSE if not. */ #[TentativeType] public function inTransaction(): bool {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Set an attribute * @link https://php.net/manual/en/pdo.setattribute.php * @param int $attribute * @param mixed $value * @return bool TRUE on success or FALSE on failure. * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. */ #[TentativeType] public function setAttribute( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $attribute, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value ): bool {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Execute an SQL statement and return the number of affected rows * @link https://php.net/manual/en/pdo.exec.php * @param string $statement

    * The SQL statement to prepare and execute. *

    *

    * Data inside the query should be properly escaped. *

    * @return int|false PDO::exec returns the number of rows that were modified * or deleted by the SQL statement you issued. If no rows were affected, * PDO::exec returns 0. *

    * This function may * return Boolean FALSE, but may also return a non-Boolean value which * evaluates to FALSE. Please read the section on Booleans for more * information. Use the === * operator for testing the return value of this * function. *

    * The following example incorrectly relies on the return value of * PDO::exec, wherein a statement that affected 0 rows * results in a call to die: * * $db->exec() or die(print_r($db->errorInfo(), true)); * * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. */ #[TentativeType] public function exec(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $statement): int|false {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.2.0)
    * Executes an SQL statement, returning a result set as a PDOStatement object * @link https://php.net/manual/en/pdo.query.php * @param string $query

    * The SQL statement to prepare and execute. *

    *

    * Data inside the query should be properly escaped. *

    * @param int $fetchMode

    * The fetch mode must be one of the PDO::FETCH_* constants. *

    * @param mixed $arg3

    * The second and following parameters are the same as the parameters for PDOStatement::setFetchMode. *

    * @param array $ctorargs [optional]

    * Arguments of custom class constructor when the mode * parameter is set to PDO::FETCH_CLASS. *

    * @return PDOStatement|false PDO::query returns a PDOStatement object, or FALSE * on failure or emits PDOException (depending on error handling) * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. * @see PDOStatement::setFetchMode For a full description of the second and following parameters. */ #[PhpStormStubsElementAvailable(to: '7.4')] public function query($query, $fetchMode = PDO::ATTR_DEFAULT_FETCH_MODE, $arg3 = null, $ctorargs = []) {} /** * (PHP 5 >= 5.1.0, PHP 7, PHP 8, PECL pdo >= 0.2.0)
    * Executes an SQL statement, returning a result set as a PDOStatement object * @link https://php.net/manual/en/pdo.query.php * @param string $query

    * The SQL statement to prepare and execute. *

    *

    * Data inside the query should be properly escaped. *

    * @param int|null $fetchMode

    * The fetch mode must be one of the PDO::FETCH_* constants. *

    * @param mixed ...$fetch_mode_args

    * Arguments of custom class constructor when the mode * parameter is set to PDO::FETCH_CLASS. *

    * @return PDOStatement|false PDO::query returns a PDOStatement object, or FALSE * on failure or emits PDOException (depending on error handling). * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. * @see PDOStatement::setFetchMode For a full description of the second and following parameters. */ #[PhpStormStubsElementAvailable('8.0')] public function query( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $query, #[LanguageLevelTypeAware(['8.0' => 'int|null'], default: '')] $fetchMode = null, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] ...$fetchModeArgs ) {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Returns the ID of the last inserted row or sequence value * @link https://php.net/manual/en/pdo.lastinsertid.php * @param string $name [optional]

    * Name of the sequence object from which the ID should be returned. *

    * @return string|false If a sequence name was not specified for the name * parameter, PDO::lastInsertId returns a * string representing the row ID of the last row that was inserted into * the database. *

    *

    * If a sequence name was specified for the name * parameter, PDO::lastInsertId returns a * string representing the last value retrieved from the specified sequence * object. *

    *

    * If the PDO driver does not support this capability, * PDO::lastInsertId triggers an * IM001 SQLSTATE. * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. */ #[TentativeType] public function lastInsertId(#[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $name = null): string|false {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Fetch the SQLSTATE associated with the last operation on the database handle * @link https://php.net/manual/en/pdo.errorcode.php * @return mixed an SQLSTATE, a five characters alphanumeric identifier defined in * the ANSI SQL-92 standard. Briefly, an SQLSTATE consists of a * two characters class value followed by a three characters subclass value. A * class value of 01 indicates a warning and is accompanied by a return code * of SQL_SUCCESS_WITH_INFO. Class values other than '01', except for the * class 'IM', indicate an error. The class 'IM' is specific to warnings * and errors that derive from the implementation of PDO (or perhaps ODBC, * if you're using the ODBC driver) itself. The subclass value '000' in any * class indicates that there is no subclass for that SQLSTATE. *

    *

    * PDO::errorCode only retrieves error codes for operations * performed directly on the database handle. If you create a PDOStatement * object through PDO::prepare or * PDO::query and invoke an error on the statement * handle, PDO::errorCode will not reflect that error. * You must call PDOStatement::errorCode to return the error * code for an operation performed on a particular statement handle. *

    *

    * Returns NULL if no operation has been run on the database handle. */ #[TentativeType] public function errorCode(): ?string {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Fetch extended error information associated with the last operation on the database handle * @link https://php.net/manual/en/pdo.errorinfo.php * @return array PDO::errorInfo returns an array of error information * about the last operation performed by this database handle. The array * consists of the following fields: * * Element * Information * * * 0 * SQLSTATE error code (a five characters alphanumeric identifier defined * in the ANSI SQL standard). * * * 1 * Driver-specific error code. * * * 2 * Driver-specific error message. * *

    *

    * If the SQLSTATE error code is not set or there is no driver-specific * error, the elements following element 0 will be set to NULL. *

    *

    * PDO::errorInfo only retrieves error information for * operations performed directly on the database handle. If you create a * PDOStatement object through PDO::prepare or * PDO::query and invoke an error on the statement * handle, PDO::errorInfo will not reflect the error * from the statement handle. You must call * PDOStatement::errorInfo to return the error * information for an operation performed on a particular statement handle. */ #[ArrayShape([0 => "string", 1 => "int", 2 => "string"])] #[TentativeType] public function errorInfo(): array {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.2.0)
    * Retrieve a database connection attribute * @link https://php.net/manual/en/pdo.getattribute.php * @param int $attribute

    * One of the PDO::ATTR_* constants. The constants that * apply to database connections are as follows: * PDO::ATTR_AUTOCOMMIT * PDO::ATTR_CASE * PDO::ATTR_CLIENT_VERSION * PDO::ATTR_CONNECTION_STATUS * PDO::ATTR_DRIVER_NAME * PDO::ATTR_ERRMODE * PDO::ATTR_ORACLE_NULLS * PDO::ATTR_PERSISTENT * PDO::ATTR_PREFETCH * PDO::ATTR_SERVER_INFO * PDO::ATTR_SERVER_VERSION * PDO::ATTR_TIMEOUT *

    * @return mixed A successful call returns the value of the requested PDO attribute. * An unsuccessful call returns null. * @throws PDOException when the underlying driver does not support the requested attribute. */ #[TentativeType] public function getAttribute(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $attribute): mixed {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.2.1)
    * Quotes a string for use in a query. * @link https://php.net/manual/en/pdo.quote.php * @param string $string

    * The string to be quoted. *

    * @param int $type [optional]

    * Provides a data type hint for drivers that have alternate quoting styles. *

    * @return string|false a quoted string that is theoretically safe to pass into an * SQL statement. Returns FALSE if the driver does not support quoting in * this way. */ #[TentativeType] public function quote( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $string, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $type = PDO::PARAM_STR ): string|false {} final public function __wakeup() {} final public function __sleep() {} /** * (PHP 5 >= 5.1.3, PHP 7, PECL pdo >= 1.0.3)
    * Return an array of available PDO drivers * @link https://php.net/manual/en/pdo.getavailabledrivers.php * @return array PDO::getAvailableDrivers returns an array of PDO driver names. If * no drivers are available, it returns an empty array. */ #[TentativeType] public static function getAvailableDrivers(): array {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo_sqlite >= 1.0.0)
    * Registers an aggregating User Defined Function for use in SQL statements * @link https://php.net/manual/en/pdo.sqlitecreateaggregate.php * @param string $function_name

    * The name of the function used in SQL statements. *

    * @param callable $step_func

    * Callback function called for each row of the result set. Your PHP function should accumulate the result and store it in the aggregation context. *

    * @param callable $finalize_func

    * Callback function to aggregate the "stepped" data from each row. Once all the rows have been processed, this function will be called and it should then take the data from the aggregation context and return the result. This callback function should return a type understood by SQLite (i.e. scalar type). *

    * @param int $num_args [optional]

    * Hint to the SQLite parser if the callback function accepts a predetermined number of arguments. *

    * @return bool TRUE on success or FALSE on failure. */ #[Deprecated('use Pdo\Sqlite::createAggregate instead', '\Pdo\Sqlite::createAggregate(%parametersList%)', since: '8.5')] public function sqliteCreateAggregate($function_name, $step_func, $finalize_func, $num_args = -1) {} /** * (PHP 5 >= 5.3.11, PHP 7)
    * Registers a User Defined Function for use as a collating function in SQL statements * @link https://php.net/manual/en/pdo.sqlitecreatecollation.php * @param string $name

    * Name of the SQL collating function to be created or redefined. *

    * @param callable $callback

    * The name of a PHP function or user-defined function to apply as a callback, defining the behavior of the collation. It should accept two strings and return as strcmp() does, i.e. it should return -1, 1, or 0 if the first string sorts before, sorts after, or is equal to the second. *

    * @return bool TRUE on success or FALSE on failure. */ #[Deprecated('use Pdo\Sqlite::createCollation instead', '\Pdo\Sqlite::createCollation(%parametersList%)', since: '8.5')] public function sqliteCreateCollation($name, $callback) {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo_sqlite >= 1.0.0)
    * Registers a User Defined Function for use in SQL statements * @link https://php.net/manual/en/pdo.sqlitecreatefunction.php * @param string $function_name

    * The name of the function used in SQL statements. *

    * @param callable $callback

    * Callback function to handle the defined SQL function. *

    * @param int $num_args [optional]

    * The number of arguments that the SQL function takes. If this parameter is -1, * then the SQL function may take any number of arguments. *

    * @param int $flags [optional]

    * A bitwise conjunction of flags. Currently, only PDO::SQLITE_DETERMINISTIC is supported, * which specifies that the function always returns the same result given the same inputs within * a single SQL statement. *

    * @return bool TRUE on success or FALSE on failure. */ #[Deprecated('use Pdo\Sqlite::createFunction instead', '\Pdo\Sqlite::createFunction(%parametersList%)', since: '8.5')] public function sqliteCreateFunction($function_name, $callback, $num_args = -1, $flags = 0) {} /** * (PHP 5 >= 5.3.3, PHP 7, PHP 8)
    * Copy data from PHP array into table * @link https://www.php.net/manual/en/pdo.pgsqlcopyfromarray.php * @param string $tableName

    * String containing table name *

    * @param array $rows

    * Array of strings with fields separated by separator *

    * @param string $separator

    * Separator used in rows array *

    * @param string $nullAs

    * How to interpret null values *

    * @param string|null $fields

    * List of fields to insert *

    * @return bool TRUE on success or FALSE on failure. */ #[Deprecated('use Pdo\Pgsql::copyFromArray instead', '\Pdo\Pgsql::copyFromArray(%parametersList%)', since: '8.5')] public function pgsqlCopyFromArray($tableName, array $rows, $separator = "\t", $nullAs = "\\\\N", $fields = null) {} /** * (PHP 5 >= 5.3.3, PHP 7, PHP 8)
    * Copy data from file into table * @link https://www.php.net/manual/en/pdo.pgsqlcopyfromfile.php * @param string $tableName

    * String containing table name *

    * @param string $filename

    * Filename containing data to import *

    * @param string $separator

    * Separator used in file specified by filename *

    * @param string $nullAs

    * How to interpret null values *

    * @param string|null $fields

    * List of fields to insert *

    * @return bool TRUE on success or FALSE on failure. */ #[Deprecated('use Pdo\Pgsql::copyFromFile instead', '\Pdo\Pgsql::copyFromFile(%parametersList%)', since: '8.5')] public function pgsqlCopyFromFile($tableName, $filename, $separator = "\t", $nullAs = "\\\\N", $fields = null) {} /** * (PHP 5 >= 5.3.3, PHP 7, PHP 8)
    * Copy data from database table into PHP array * @link https://www.php.net/manual/en/pdo.pgsqlcopytoarray.php * @param string $tableName

    * String containing table name *

    * @param string $separator

    * Separator used in rows *

    * @param string $nullAs

    * How to interpret null values *

    * @param string|null $fields

    * List of fields to insert *

    * @return array|false returns an array of rows, or FALSE on failure. */ #[Deprecated('use Pdo\Pgsql::copyToArray instead', '\Pdo\Pgsql::copyToArray(%parametersList%)', since: '8.5')] public function pgsqlCopyToArray($tableName, $separator = "\t", $nullAs = "\\\\N", $fields = null) {} /** * (PHP 5 >= 5.3.3, PHP 7, PHP 8)
    * Copy data from table into file * @link https://www.php.net/manual/en/pdo.pgsqlcopytofile.php * @param string $tableName

    * String containing table name *

    * @param string $filename

    * Filename to export data *

    * @param string $separator

    * Separator used in file specified by filename *

    * @param string $nullAs

    * How to interpret null values *

    * @param string|null $fields

    * List of fields to insert *

    * @return bool TRUE on success or FALSE on failure. */ #[Deprecated('use Pdo\Pgsql::copyToFile instead', '\Pdo\Pgsql::copyToFile(%parametersList%)', since: '8.5')] public function pgsqlCopyToFile($tableName, $filename, $separator = "\t", $nullAs = "\\\\N", $fields = null) {} /** * (PHP 5 >= 5.1.2, PHP 7, PHP 8, PECL pdo_pgsql >= 1.0.2)
    * Creates a new large object * @link https://www.php.net/manual/en/pdo.pgsqllobcreate.php * @return string|false returns the OID of the newly created large object on success, * or FALSE on failure. */ #[Deprecated('use Pdo\Pgsql::lobCreate instead', '\Pdo\Pgsql::lobCreate(%parametersList%)', since: '8.5')] public function pgsqlLOBCreate() {} /** * (PHP 5 >= 5.1.2, PHP 7, PHP 8, PECL pdo_pgsql >= 1.0.2)
    * Opens an existing large object stream * @link https://www.php.net/manual/en/pdo.pgsqllobopen.php * @param string $oid

    * A large object identifier. *

    * @param string $mode

    * If mode is r, open the stream for reading. If mode is w, open the stream for writing. *

    * @return resource|false returns a stream resource on success or FALSE on failure. */ #[Deprecated('use Pdo\Pgsql::lobOpen instead', '\Pdo\Pgsql::lobOpen(%parametersList%)', since: '8.5')] public function pgsqlLOBOpen($oid, $mode = "rb") {} /** * (PHP 5 >= 5.1.2, PHP 7, PHP 8, PECL pdo_pgsql >= 1.0.2)
    * Deletes the large object * @link https://www.php.net/manual/en/pdo.pgsqllobunlink.php * @param string $oid

    * A large object identifier. *

    * @return bool TRUE on success or FALSE on failure. */ #[Deprecated('use Pdo\Pgsql::lobUnlink instead', '\Pdo\Pgsql::lobUnlink(%parametersList%)', since: '8.5')] public function pgsqlLOBUnlink($oid) {} /** * (PHP 5 >= 5.6.0, PHP 7, PHP 8)
    * Get asynchronous notification * @link https://www.php.net/manual/en/pdo.pgsqlgetnotify.php * @param int $fetchMode

    * The format the result set should be returned as, represented as a PDO::FETCH_* constant. *

    * @param int $timeoutMilliseconds

    * The length of time to wait for a response, in milliseconds. *

    * @return array|false if one or more notifications is pending, returns a single row, * with fields message and pid, otherwise FALSE. */ #[Deprecated('use Pdo\Pgsql::getNotify instead', '\Pdo\Pgsql::getNotify(%parametersList%)', since: '8.5')] public function pgsqlGetNotify($fetchMode = 1, $timeoutMilliseconds = 0) {} /** * (PHP 5 >= 5.6.0, PHP 7, PHP 8)
    * Get the server PID * @link https://www.php.net/manual/en/pdo.pgsqlgetpid.php * @return int The server's PID. */ #[Deprecated('use Pdo\Pgsql::getPid instead', '\Pdo\Pgsql::getPid(%parametersList%)', since: '8.5')] public function pgsqlGetPid() {} /** * @throws PDOException if the attempt to connect to the requested database fails, regardless of which PDO::ATTR_ERRMODE is currently set. * @since 8.4 */ public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): static {} } /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 1.0.0)
    * Represents a prepared statement and, after the statement is executed, an * associated result set. * @link https://php.net/manual/en/class.pdostatement.php */ class PDOStatement implements IteratorAggregate { /** * @var string */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $queryString; /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Executes a prepared statement * @link https://php.net/manual/en/pdostatement.execute.php * @param array $params [optional]

    * An array of values with as many elements as there are bound * parameters in the SQL statement being executed. * All values are treated as PDO::PARAM_STR. *

    *

    * You cannot bind multiple values to a single parameter; for example, * you cannot bind two values to a single named parameter in an IN() * clause. *

    *

    * You cannot bind more values than specified; if more keys exist in * input_parameters than in the SQL specified * in the PDO::prepare, then the statement will * fail and an error is emitted. *

    * @return bool TRUE on success or FALSE on failure. * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. */ #[TentativeType] public function execute(#[LanguageLevelTypeAware(['8.0' => 'array|null'], default: '')] $params = null): bool {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Fetches the next row from a result set * @link https://php.net/manual/en/pdostatement.fetch.php * @param int $mode [optional]

    * Controls how the next row will be returned to the caller. This value * must be one of the PDO::FETCH_* constants, * defaulting to value of PDO::ATTR_DEFAULT_FETCH_MODE * (which defaults to PDO::FETCH_BOTH). *

    *

    * PDO::FETCH_ASSOC: returns an array indexed by column * name as returned in your result set *

    * @param int $cursorOrientation [optional]

    * For a PDOStatement object representing a scrollable cursor, this * value determines which row will be returned to the caller. This value * must be one of the PDO::FETCH_ORI_* constants, * defaulting to PDO::FETCH_ORI_NEXT. To request a * scrollable cursor for your PDOStatement object, you must set the * PDO::ATTR_CURSOR attribute to * PDO::CURSOR_SCROLL when you prepare the SQL * statement with PDO::prepare. *

    * @param int $cursorOffset [optional] * @return mixed The return value of this function on success depends on the fetch type. In * all cases, FALSE is returned on failure. * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. */ #[TentativeType] public function fetch( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $mode = PDO::FETCH_DEFAULT, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $cursorOrientation = PDO::FETCH_ORI_NEXT, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $cursorOffset = 0 ): mixed {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Binds a parameter to the specified variable name * @link https://php.net/manual/en/pdostatement.bindparam.php * @param mixed $param

    * Parameter identifier. For a prepared statement using named * placeholders, this will be a parameter name of the form * :name. For a prepared statement using * question mark placeholders, this will be the 1-indexed position of * the parameter. *

    * @param mixed &$var

    * Name of the PHP variable to bind to the SQL statement parameter. *

    * @param int $type [optional]

    * Explicit data type for the parameter using the PDO::PARAM_* * constants. * To return an INOUT parameter from a stored procedure, * use the bitwise OR operator to set the PDO::PARAM_INPUT_OUTPUT bits * for the data_type parameter. *

    * @param int $maxLength [optional]

    * Length of the data type. To indicate that a parameter is an OUT * parameter from a stored procedure, you must explicitly set the * length. *

    * @param mixed $driverOptions [optional]

    *

    * @return bool TRUE on success or FALSE on failure. * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. */ #[TentativeType] public function bindParam( #[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $param, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] &$var, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $type = PDO::PARAM_STR, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $maxLength = 0, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $driverOptions = null ): bool {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Bind a column to a PHP variable * @link https://php.net/manual/en/pdostatement.bindcolumn.php * @param mixed $column

    * Number of the column (1-indexed) or name of the column in the result set. * If using the column name, be aware that the name should match the * case of the column, as returned by the driver. *

    * @param mixed &$var

    * Name of the PHP variable to which the column will be bound. *

    * @param int $type [optional]

    * Data type of the parameter, specified by the PDO::PARAM_* constants. *

    * @param int $maxLength [optional]

    * A hint for pre-allocation. *

    * @param mixed $driverOptions [optional]

    * Optional parameter(s) for the driver. *

    * @return bool TRUE on success or FALSE on failure. * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. */ #[TentativeType] public function bindColumn( #[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $column, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] &$var, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $type = PDO::PARAM_STR, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $maxLength = 0, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $driverOptions = null ): bool {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 1.0.0)
    * Binds a value to a parameter * @link https://php.net/manual/en/pdostatement.bindvalue.php * @param mixed $param

    * Parameter identifier. For a prepared statement using named * placeholders, this will be a parameter name of the form * :name. For a prepared statement using * question mark placeholders, this will be the 1-indexed position of * the parameter. *

    * @param mixed $value

    * The value to bind to the parameter. *

    * @param int $type [optional]

    * Explicit data type for the parameter using the PDO::PARAM_* * constants. *

    * @return bool TRUE on success or FALSE on failure. * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. */ #[TentativeType] public function bindValue( #[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $param, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $type = PDO::PARAM_STR ): bool {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Returns the number of rows affected by the last SQL statement * @link https://php.net/manual/en/pdostatement.rowcount.php * @return int the number of rows. * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. */ #[TentativeType] public function rowCount(): int {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.9.0)
    * Returns a single column from the next row of a result set * @link https://php.net/manual/en/pdostatement.fetchcolumn.php * @param int $column [optional]

    * 0-indexed number of the column you wish to retrieve from the row. If * no value is supplied, PDOStatement::fetchColumn * fetches the first column. *

    * @return mixed Returns a single column from the next row of a result * set or FALSE if there are no more rows. *

    *

    * There is no way to return another column from the same row if you * use PDOStatement::fetchColumn to retrieve data. * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. */ #[TentativeType] public function fetchColumn(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $column = 0): mixed {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Returns an array containing all of the result set rows * @link https://php.net/manual/en/pdostatement.fetchall.php * @param int $mode [optional]

    * Controls the contents of the returned array as documented in * PDOStatement::fetch. * Defaults to value of PDO::ATTR_DEFAULT_FETCH_MODE * (which defaults to PDO::FETCH_BOTH) *

    *

    * To return an array consisting of all values of a single column from * the result set, specify PDO::FETCH_COLUMN. You * can specify which column you want with the * column-index parameter. *

    *

    * To fetch only the unique values of a single column from the result set, * bitwise-OR PDO::FETCH_COLUMN with * PDO::FETCH_UNIQUE. *

    *

    * To return an associative array grouped by the values of a specified * column, bitwise-OR PDO::FETCH_COLUMN with * PDO::FETCH_GROUP. *

    * @param mixed ...$args

    * Arguments of custom class constructor when the fetch_style * parameter is PDO::FETCH_CLASS. *

    * @return array PDOStatement::fetchAll returns an array containing * all of the remaining rows in the result set. The array represents each * row as either an array of column values or an object with properties * corresponding to each column name. * An empty array is returned if there are zero results to fetch. *

    * @throws PDOException PDOStatement::fetchAll throws on failure if the * attribute PDO::ATTR_ERRMODE is set to PDO::ERRMODE_EXCEPTION. *

    *

    * Using this method to fetch large result sets will result in a heavy * demand on system and possibly network resources. Rather than retrieving * all of the data and manipulating it in PHP, consider using the database * server to manipulate the result sets. For example, use the WHERE and * ORDER BY clauses in SQL to restrict results before retrieving and * processing them with PHP. */ #[TentativeType] public function fetchAll( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $mode = PDO::FETCH_DEFAULT, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $fetch_argument = null, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] ...$args ): array {} /** * @template T * * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.2.4)
    * Fetches the next row and returns it as an object. * @link https://php.net/manual/en/pdostatement.fetchobject.php * @param class-string $class [optional]

    * Name of the created class. *

    * @param array $constructorArgs [optional]

    * Elements of this array are passed to the constructor. *

    * @return T|stdClass|null an instance of the required class with property names that * correspond to the column names or FALSE on failure. * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. */ #[TentativeType] public function fetchObject( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $class = "stdClass", #[LanguageLevelTypeAware(['8.0' => 'array'], default: '')] $constructorArgs = [] ): object|false {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Fetch the SQLSTATE associated with the last operation on the statement handle * @link https://php.net/manual/en/pdostatement.errorcode.php * @return string Identical to PDO::errorCode, except that * PDOStatement::errorCode only retrieves error codes * for operations performed with PDOStatement objects. */ #[TentativeType] public function errorCode(): ?string {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
    * Fetch extended error information associated with the last operation on the statement handle * @link https://php.net/manual/en/pdostatement.errorinfo.php * @return array PDOStatement::errorInfo returns an array of * error information about the last operation performed by this * statement handle. The array consists of the following fields: * * Element * Information * * * 0 * SQLSTATE error code (a five characters alphanumeric identifier defined * in the ANSI SQL standard). * * * 1 * Driver specific error code. * * * 2 * Driver specific error message. * */ #[ArrayShape([0 => "string", 1 => "int", 2 => "string"])] #[TentativeType] public function errorInfo(): array {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.2.0)
    * Set a statement attribute * @link https://php.net/manual/en/pdostatement.setattribute.php * @param int $attribute * @param mixed $value * @return bool TRUE on success or FALSE on failure. * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. */ #[TentativeType] public function setAttribute( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $attribute, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value ): bool {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.2.0)
    * Retrieve a statement attribute * @link https://php.net/manual/en/pdostatement.getattribute.php * @param int $name * @return mixed the attribute value. */ #[TentativeType] public function getAttribute(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $name): mixed {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.2.0)
    * Returns the number of columns in the result set * @link https://php.net/manual/en/pdostatement.columncount.php * @return int the number of columns in the result set represented by the * PDOStatement object. If there is no result set, * PDOStatement::columnCount returns 0. * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. */ #[TentativeType] public function columnCount(): int {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.2.0)
    * Returns metadata for a column in a result set * @link https://php.net/manual/en/pdostatement.getcolumnmeta.php * @param int $column

    * The 0-indexed column in the result set. *

    * @return array|false an associative array containing the following values representing * the metadata for a single column: *

    * * Column metadata * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    NameValue
    native_typeThe PHP native type used to represent the column value.
    driver:decl_typeThe SQL type used to represent the column value in the database. * If the column in the result set is the result of a function, this value * is not returned by PDOStatement::getColumnMeta. *
    flagsAny flags set for this column.
    nameThe name of this column as returned by the database.
    tableThe name of this column's table as returned by the database.
    lenThe length of this column. Normally -1 for * types other than floating point decimals.
    precisionThe numeric precision of this column. Normally * 0 for types other than floating point * decimals.
    pdo_typeThe type of this column as represented by the * PDO::PARAM_* constants.
    *

    * Returns FALSE if the requested column does not exist in the result set, * or if no result set exists. */ #[TentativeType] #[ArrayShape([ "name" => "string", "len" => "int", "precision" => "int", "oci:decl_type" => "int|string", "native_type" => "string", "scale" => "int", "flags" => "array", "pdo_type" => "int" ])] public function getColumnMeta(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $column): array|false {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.2.0)
    * Set the default fetch mode for this statement * @link https://php.net/manual/en/pdostatement.setfetchmode.php * @param int $mode

    * The fetch mode must be one of the PDO::FETCH_* constants. *

    * @param mixed ...$args

    Constructor arguments.

    * @return bool TRUE on success or FALSE on failure. * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. */ public function setFetchMode($mode, ...$args) {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.2.0)
    * Advances to the next rowset in a multi-rowset statement handle * @link https://php.net/manual/en/pdostatement.nextrowset.php * @return bool TRUE on success or FALSE on failure. * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. */ #[TentativeType] public function nextRowset(): bool {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.9.0)
    * Closes the cursor, enabling the statement to be executed again. * @link https://php.net/manual/en/pdostatement.closecursor.php * @return bool TRUE on success or FALSE on failure. * @throws PDOException On error if PDO::ERRMODE_EXCEPTION option is true. */ #[TentativeType] public function closeCursor(): bool {} /** * (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.9.0)
    * Dump an SQL prepared command * @link https://php.net/manual/en/pdostatement.debugdumpparams.php * @return bool|null No value is returned. */ #[TentativeType] public function debugDumpParams(): ?bool {} final public function __wakeup() {} final public function __sleep() {} /** * @return Iterator * @since 8.0 */ public function getIterator(): Iterator {} public function connect() {} } final class PDORow { #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $queryString; } /** * (PHP 5 >= 5.1.3, PHP 7, PECL pdo >= 1.0.3)
    * Return an array of available PDO drivers * @link https://php.net/manual/en/pdo.getavailabledrivers.php * @return array PDO::getAvailableDrivers returns an array of PDO driver names. If * no drivers are available, it returns an empty array. */ #[Pure] function pdo_drivers(): array {} function confirm_pdo_ibm_compiled() {} } namespace Pdo { use JetBrains\PhpStorm\Deprecated; use PDO; /** * @since 8.4 */ class Sqlite extends PDO { public const int DETERMINISTIC = 0; public const int OPEN_READONLY = 1; public const int OPEN_READWRITE = 0; public const int OPEN_CREATE = 0; public const int ATTR_OPEN_FLAGS = 0; public const int ATTR_READONLY_STATEMENT = 0; public const int ATTR_EXTENDED_RESULT_CODES = 0; public const IGNORE = 0; public const DENY = 0; public const OK = 0; public const EXPLAIN_MODE_EXPLAIN_QUERY_PLAN = 0; public const EXPLAIN_MODE_EXPLAIN = 0; public const EXPLAIN_MODE_PREPARED = 0; public const ATTR_EXPLAIN_STATEMENT = 0; public const ATTR_BUSY_STATEMENT = 0; /** * @since 8.5 */ public const ATTR_TRANSACTION_MODE = 1005; /** * @since 8.5 */ public const TRANSACTION_MODE_DEFERRED = 0; /** * @since 8.5 */ public const TRANSACTION_MODE_IMMEDIATE = 1; /** * @since 8.5 */ public const TRANSACTION_MODE_EXCLUSIVE = 2; public function createAggregate( string $name, callable $step, callable $finalize, int $numArgs = -1 ): bool {} public function createCollation(string $name, callable $callback): bool {} public function createFunction( string $function_name, callable $callback, int $num_args = -1, int $flags = 0 ): bool {} public function loadExtension(string $name): void {} /** @return resource|false */ public function openBlob( string $table, string $column, int $rowid, ?string $dbname = "main", int $flags = \Pdo\Sqlite::OPEN_READONLY ) {} /** * @since 8.5 */ public function setAuthorizer(?callable $callback): void {} } /** * @since 8.4 */ class Mysql extends PDO { public const int ATTR_USE_BUFFERED_QUERY = 1000; public const int ATTR_LOCAL_INFILE = 1001; public const int ATTR_INIT_COMMAND = 1002; public const int ATTR_READ_DEFAULT_FILE = 1003; public const int ATTR_READ_DEFAULT_GROUP = 1004; public const int ATTR_MAX_BUFFER_SIZE = 1005; public const int ATTR_COMPRESS = 1003; public const int ATTR_DIRECT_QUERY = 1004; public const int ATTR_FOUND_ROWS = 1005; public const int ATTR_IGNORE_SPACE = 1006; public const int ATTR_SSL_KEY = 1007; public const int ATTR_SSL_CERT = 1008; public const int ATTR_SSL_CA = 1009; public const int ATTR_SSL_CAPATH = 1010; public const int ATTR_SSL_CIPHER = 1011; public const int ATTR_SERVER_PUBLIC_KEY = 1012; public const int ATTR_MULTI_STATEMENTS = 1013; public const int ATTR_SSL_VERIFY_SERVER_CERT = 1014; public const int ATTR_LOCAL_INFILE_DIRECTORY = 1015; public function getWarningCount(): int {} } /** * @since 8.4 */ class Pgsql extends PDO { public const int ATTR_DISABLE_PREPARES = 1000; public const int ATTR_RESULT_MEMORY_SIZE = 1001; #[Deprecated('Deprecated: it has no effect', since: '8.5')] public const int TRANSACTION_IDLE = 0; #[Deprecated('Deprecated: it has no effect', since: '8.5')] public const int TRANSACTION_ACTIVE = 1; #[Deprecated('Deprecated: it has no effect', since: '8.5')] public const int TRANSACTION_INTRANS = 2; #[Deprecated('Deprecated: it has no effect', since: '8.5')] public const int TRANSACTION_INERROR = 3; #[Deprecated('Deprecated: it has no effect', since: '8.5')] public const int TRANSACTION_UNKNOWN = 4; public function copyFromArray( string $tableName, array $rows, string $separator = "\t", string $nullAs = "\\\\N", ?string $fields = null ): bool {} public function copyFromFile( string $tableName, string $filename, string $separator = "\t", string $nullAs = "\\\\N", ?string $fields = null ): bool {} public function copyToArray( string $tableName, string $separator = "\t", string $nullAs = "\\\\N", ?string $fields = null ): array|false {} public function copyToFile( string $tableName, string $filename, string $separator = "\t", string $nullAs = "\\\\N", ?string $fields = null ): bool {} public function escapeIdentifier(string $input): string {} public function getNotify(int $fetchMode = \PDO::FETCH_DEFAULT, int $timeoutMilliseconds = 0): array|false {} public function getPid(): int {} public function lobCreate(): string|false {} /** * Opens an existing large object stream. Must be called inside a transaction. * @return resource|false */ public function lobOpen(string $oid, string $mode = "rb") {} public function lobUnlink(string $oid): bool {} public function setNoticeCallback(?callable $callback): void {} } /** * @since 8.4 */ class Firebird extends PDO { public const int ATTR_DATE_FORMAT = 1000; public const int ATTR_TIME_FORMAT = 1001; public const int ATTR_TIMESTAMP_FORMAT = 1002; public const int TRANSACTION_ISOLATION_LEVEL = 1003; public const int READ_COMMITTED = 1004; public const int REPEATABLE_READ = 1005; public const int SERIALIZABLE = 1006; public const int WRITABLE_TRANSACTION = 1007; public static function getApiVersion(): int {} } /** * @since 8.4 */ class Dblib extends PDO { public const int ATTR_CONNECTION_TIMEOUT = 1000; public const int ATTR_QUERY_TIMEOUT = 1001; public const int ATTR_STRINGIFY_UNIQUEIDENTIFIER = 1002; public const int ATTR_VERSION = 1003; public const int ATTR_TDS_VERSION = 1004; public const int ATTR_SKIP_EMPTY_ROWSETS = 1005; public const int ATTR_DATETIME_CONVERT = 1006; } /** * @since 8.4 */ class Odbc extends PDO { public const int ATTR_USE_CURSOR_LIBRARY = 1000; public const int ATTR_ASSUME_UTF8 = 1001; public const int SQL_USE_IF_NEEDED = 0; public const int SQL_USE_ODBC = 1; public const int SQL_USE_DRIVER = 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 {} } * 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 = true, #[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 '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', 'BcMath\Number' => 'bcmath/bcmath.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', 'CurlSharePersistentHandle' => 'curl/curl.stub', 'DDTrace\Integration' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\RootSpanData' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\SpanData' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\SpanLink' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\SpanStack' => 'ddtrace/ddtrace.stub.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', 'DelayedTargetValidation' => 'Core/Core_c.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', 'ExcimerLog' => 'excimer/ExcimerLog.stub', 'ExcimerLogEntry' => 'excimer/ExcimerLogEntry.stub', 'ExcimerProfiler' => 'excimer/ExcimerProfiler.stub', 'ExcimerTimer' => 'excimer/ExcimerTimer.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', 'Filter\FilterException' => 'filter/filter_c.stub', 'Filter\FilterFailedException' => 'filter/filter_c.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', 'IntlListFormatter' => 'intl/IntlListFormatter.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', 'JsonPath\JsonPath' => 'jsonpath/jsonpath.stub', 'JsonPath\JsonPathException' => 'jsonpath/jsonpath.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', 'MaxMind\Db\InvalidDatabaseException' => 'maxminddb/maxminddb.stub', 'MaxMind\Db\Metadata' => 'maxminddb/maxminddb.stub', 'MaxMind\Db\Reader' => 'maxminddb/maxminddb.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\BSON\VectorType' => 'mongodb/BSON/VectorType.stub', 'MongoDB\Driver\BulkWrite' => 'mongodb/BulkWrite.stub', 'MongoDB\Driver\BulkWriteCommand' => 'mongodb/BulkWriteCommand.stub.stub', 'MongoDB\Driver\BulkWriteCommandResult' => 'mongodb/BulkWriteCommandResult.stub.stub', 'MongoDB\Driver\ClientEncryption' => 'mongodb/ClientEncryption.stub', 'MongoDB\Driver\Command' => 'mongodb/Command.stub', 'MongoDB\Driver\Cursor' => 'mongodb/Cursor.stub', 'MongoDB\Driver\CursorInterface' => 'mongodb/CursorInterface.stub', 'MongoDB\Driver\Exception\AuthenticationException' => 'mongodb/Exception/AuthenticationException.stub', 'MongoDB\Driver\Exception\BulkWriteCommandException' => 'mongodb/Exception/BulkWriteCommandException.stub.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\ServerException' => 'mongodb/Exception/ServerException.stub', 'MongoDB\Driver\Exception\UnexpectedValueException' => 'mongodb/Exception/UnexpectedValueException.stub', 'MongoDB\Driver\Exception\WriteConcernException' => 'mongodb/Exception/WriteConcernException.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', 'NoDiscard' => 'Core/Core_c.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', 'Odbc\Connection' => 'odbc/Connection.stub', 'Odbc\Result' => 'odbc/Result.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\Dblib' => 'PDO/PDO.stub', 'Pdo\Firebird' => 'PDO/PDO.stub', 'Pdo\Mysql' => 'PDO/PDO.stub', 'Pdo\Odbc' => 'PDO/PDO.stub', 'Pdo\Pgsql' => '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\AdaptiveCache' => 'relay/AdaptiveCache.stub', 'Relay\Cluster' => 'relay/Cluster.stub', 'Relay\Cluster\FullscanGenerator' => '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\Thread' => 'swoole/Swoole/Thread.stub', 'Swoole\Thread\ArrayList' => 'swoole/Swoole/Thread/ArrayList.stub', 'Swoole\Thread\Atomic' => 'swoole/Swoole/Thread/Atomic.stub', 'Swoole\Thread\Atomic\Long' => 'swoole/Swoole/Thread/Atomic/Long.stub', 'Swoole\Thread\Barrier' => 'swoole/Swoole/Thread/Barrier.stub', 'Swoole\Thread\Lock' => 'swoole/Swoole/Thread/Lock.stub', 'Swoole\Thread\Map' => 'swoole/Swoole/Thread/Map.stub', 'Swoole\Thread\Queue' => 'swoole/Swoole/Thread/Queue.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', 'Uri\InvalidUriException' => 'uri/uri.stub', 'Uri\Rfc3986\Uri' => 'uri/uri.stub', 'Uri\UriComparisonMode' => 'uri/uri.stub', 'Uri\UriError' => 'uri/uri.stub', 'Uri\UriException' => 'uri/uri.stub', 'Uri\WhatWg\InvalidUrlException' => 'uri/uri.stub', 'Uri\WhatWg\Url' => 'uri/uri.stub', 'Uri\WhatWg\UrlValidationError' => 'uri/uri.stub', 'Uri\WhatWg\UrlValidationErrorType' => 'uri/uri.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', 'DDTrace\Config\integration_analytics_enabled' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\Config\integration_analytics_sample_rate' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\Internal\add_span_flag' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\Internal\handle_fork' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\System\container_id' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\Testing\trigger_error' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\UserRequest\has_listeners' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\UserRequest\notify_commit' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\UserRequest\notify_start' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\UserRequest\set_blocking_function' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\active_span' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\active_stack' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\add_distributed_tag' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\add_global_tag' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\close_span' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\close_spans_until' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\consume_distributed_tracing_headers' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\create_stack' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\curl_multi_exec_get_request_spans' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\current_context' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\dogstatsd_count' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\dogstatsd_distribution' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\dogstatsd_gauge' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\dogstatsd_histogram' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\dogstatsd_set' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\extract_ip_from_headers' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\find_active_exception' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\flush' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\generate_distributed_tracing_headers' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\get_priority_sampling' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\get_sanitized_exception_trace' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\hook_function' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\hook_method' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\logs_correlation_trace_id' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\root_span' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\set_distributed_tracing_context' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\set_priority_sampling' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\set_user' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\start_span' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\start_trace_span' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\startup_logs' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\switch_stack' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\trace_function' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\trace_id' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\trace_method' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\update_span_duration' => 'ddtrace/ddtrace.stub.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\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', 'Swoole\Coroutine\go' => 'swoole/functions.stub', 'Swoole\Coroutine\run' => 'swoole/functions.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_first' => 'standard/standard_8.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_last' => 'standard/standard_8.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', 'bcdivmod' => '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', 'clone' => 'Core/Core.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_get_handles' => '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_init_persistent' => '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', 'dd_trace_buffer_span' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_check_memory_under_limit' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_close_all_spans_and_flush' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_closed_spans_count' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_compile_time_microseconds' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_coms_trigger_writer_flush' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_dd_get_memory_limit' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_disable_in_request' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_env_config' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_function' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_internal_fn' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_method' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_noop' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_peek_span_id' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_reset' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_send_traces_via_thread' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_serialize_closed_spans' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_serialize_msgpack' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_set_trace_id' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_synchronous_flush' => 'ddtrace/ddtrace.stub.stub', 'dd_trace_tracer_is_limited' => 'ddtrace/ddtrace.stub.stub', 'dd_untrace' => 'ddtrace/ddtrace.stub.stub', 'ddtrace_config_app_name' => 'ddtrace/ddtrace.stub.stub', 'ddtrace_config_distributed_tracing_enabled' => 'ddtrace/ddtrace.stub.stub', 'ddtrace_config_integration_enabled' => 'ddtrace/ddtrace.stub.stub', 'ddtrace_config_trace_enabled' => 'ddtrace/ddtrace.stub.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', 'die' => 'Core/Core.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', 'excimer_set_timeout' => 'excimer/globals.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', 'exit' => 'Core/Core.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_log' => '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_error_handler' => 'Core/Core.stub', 'get_exception_handler' => '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_levenshtein' => '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', 'litespeed_finish_request' => 'litespeed/litespeed.stub', 'litespeed_request_headers' => 'litespeed/litespeed.stub', 'litespeed_response_headers' => 'litespeed/litespeed.stub', 'locale_accept_from_http' => 'intl/intl.stub', 'locale_add_likely_subtags' => '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_is_right_to_left' => 'intl/intl.stub', 'locale_lookup' => 'intl/intl.stub', 'locale_minimize_subtags' => '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', 'mercure_publish' => 'frankenphp/frankenphp.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_is_script_cached_in_file_cache' => 'Zend OPcache/OPcache.stub', 'opcache_jit_blacklist' => '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_close_stmt' => '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_chunked_rows_size' => '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_fpathconf' => '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_pathconf' => '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' => '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_PACKET' => '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', 'CURLFOLLOW_ALL' => 'curl/curl_d.stub', 'CURLFOLLOW_FIRSTONLY' => 'curl/curl_d.stub', 'CURLFOLLOW_OBEYCODE' => '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_CONN_ID' => '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_DATA_IN' => 'curl/curl_d.stub', 'CURLINFO_DATA_OUT' => '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_IN' => '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_HTTPAUTH_USED' => '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_POSTTRANSFER_TIME_T' => '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_PROXYAUTH_USED' => 'curl/curl_d.stub', 'CURLINFO_PROXY_ERROR' => 'curl/curl_d.stub', 'CURLINFO_PROXY_SSL_VERIFYRESULT' => 'curl/curl_d.stub', 'CURLINFO_QUEUE_TIME_T' => '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_DATA_IN' => 'curl/curl_d.stub', 'CURLINFO_SSL_DATA_OUT' => '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_TEXT' => 'curl/curl_d.stub', 'CURLINFO_TOTAL_TIME' => 'curl/curl_d.stub', 'CURLINFO_TOTAL_TIME_T' => 'curl/curl_d.stub', 'CURLINFO_USED_PROXY' => '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_DEBUGFUNCTION' => '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_INFILESIZE_LARGE' => 'openssl/openssl.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_SERVER_RESPONSE_TIMEOUT' => '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_SIGNATURE_ALGORITHMS' => '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', 'DDTrace\DBM_PROPAGATION_DISABLED' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\DBM_PROPAGATION_FULL' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\DBM_PROPAGATION_SERVICE' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\Internal\SPAN_FLAG_OPENTELEMETRY' => 'ddtrace/ddtrace.stub.stub', 'DDTrace\Internal\SPAN_FLAG_OPENTRACING' => 'ddtrace/ddtrace.stub.stub', 'DD_TRACE_PRIORITY_SAMPLING_AUTO_KEEP' => 'ddtrace/ddtrace.stub.stub', 'DD_TRACE_PRIORITY_SAMPLING_AUTO_REJECT' => 'ddtrace/ddtrace.stub.stub', 'DD_TRACE_PRIORITY_SAMPLING_UNKNOWN' => 'ddtrace/ddtrace.stub.stub', 'DD_TRACE_PRIORITY_SAMPLING_UNSET' => 'ddtrace/ddtrace.stub.stub', 'DD_TRACE_PRIORITY_SAMPLING_USER_KEEP' => 'ddtrace/ddtrace.stub.stub', 'DD_TRACE_PRIORITY_SAMPLING_USER_REJECT' => 'ddtrace/ddtrace.stub.stub', 'DD_TRACE_VERSION' => 'ddtrace/ddtrace.stub.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', 'ETH_P_ALL' => 'sockets/sockets.stub', 'ETH_P_IP' => 'sockets/sockets.stub', 'ETH_P_IPV6' => 'sockets/sockets.stub', 'ETH_P_LOOP' => 'sockets/sockets.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', 'EXCIMER_CPU' => 'excimer/globals.stub', 'EXCIMER_REAL' => 'excimer/globals.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_THROW_ON_FAILURE' => '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', 'FRANKENPHP_LOG_LEVEL_DEBUG' => 'frankenphp/frankenphp.stub', 'FRANKENPHP_LOG_LEVEL_ERROR' => 'frankenphp/frankenphp.stub', 'FRANKENPHP_LOG_LEVEL_INFO' => 'frankenphp/frankenphp.stub', 'FRANKENPHP_LOG_LEVEL_WARN' => 'frankenphp/frankenphp.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_HEIF' => '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_SVG' => '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_ICMP' => 'sockets/sockets.stub', 'IPPROTO_ICMPV6' => 'sockets/sockets.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_NO_XXE' => '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_PKCS1_PSS_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_TRACE_SUPPRESS_TIMESTAMPS' => '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_CHUNK' => '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_BUILD_DATE' => 'Core/Core_d.stub', 'PHP_BUILD_PROVIDER' => '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_CRLFEOL' => 'openssl/openssl.stub', 'PKCS7_DETACHED' => 'openssl/openssl.stub', 'PKCS7_NOATTR' => 'openssl/openssl.stub', 'PKCS7_NOCERTS' => 'openssl/openssl.stub', 'PKCS7_NOCHAIN' => 'openssl/openssl.stub', 'PKCS7_NOCRL' => 'openssl/openssl.stub', 'PKCS7_NOINTERN' => 'openssl/openssl.stub', 'PKCS7_NOOLDMIMETYPE' => 'openssl/openssl.stub', 'PKCS7_NOSIGS' => 'openssl/openssl.stub', 'PKCS7_NOSMIMECAP' => 'openssl/openssl.stub', 'PKCS7_NOVERIFY' => 'openssl/openssl.stub', 'PKCS7_NO_DUAL_CONTENT' => '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_OPEN_MAX' => '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', 'SHUT_RD' => 'sockets/sockets.stub', 'SHUT_RDWR' => 'sockets/sockets.stub', 'SHUT_WR' => 'sockets/sockets.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_BUSY_POLL' => '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_PIPE' => '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_VOID_CAST' => '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', 'UDP_SEGMENT' => 'sockets/sockets.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', 'ZEND_VM_KIND' => 'Core/Core_d.stub', 'ZEND_VM_KIND_HYBRID' => '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', '__PROPERTY__' => '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', '__property__' => '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'); } '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) {} } 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; /** * @since 8.4 */ public const int SKIP_INITIALIZATION_ON_SERIALIZE = 0; /** * @since 8.4 */ public const int SKIP_DESTRUCTOR = 0; /** * 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 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 {} /** * @since 8.4 */ public function newLazyGhost(callable $initializer, int $options = 0): object {} /** * @return T * @since 8.4 */ public function newLazyProxy(callable $factory, int $options = 0): object {} /** * @since 8.4 */ public function resetAsLazyGhost(object $object, callable $initializer, int $options = 0): void {} /** * @since 8.4 */ public function resetAsLazyProxy(object $object, callable $factory, int $options = 0): void {} /** * @since 8.4 */ public function initializeLazyObject(object $object): object {} /** * @since 8.4 */ public function isUninitializedLazyObject(object $object): bool {} /** * @since 8.4 */ public function markLazyObjectAsInitialized(object $object): object {} /** * @since 8.4 */ public function getLazyInitializer(object $object): ?callable {} } 'string'], default: '')] public $name; /** * @var class-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 class-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 {} } 'null|ReflectionNamedType'], default: 'null|ReflectionType')] public function getBackingType() {} } 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 {} } 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 {} } 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() {} } 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 {} } 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 class-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. */ #[PhpStormStubsElementAvailable(from: "8.1")] #[TentativeType] #[Deprecated('Deprecated: it has no effect', since: '8.5')] 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 {} } 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; /** * @since 8.4 */ public const IS_VIRTUAL = 512; /** * @var string Name of the property, same as calling the {@see ReflectionProperty::getName()} method */ #[Immutable] #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $name; /** * @var class-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; /** * @since 8.4 */ public const IS_FINAL = 32; /** * Construct a ReflectionProperty object * * @link https://php.net/manual/en/reflectionproperty.construct.php * @param class-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. */ #[PhpStormStubsElementAvailable(from: "8.1")] #[TentativeType] #[Deprecated('Deprecated: it has no effect', since: '8.5')] 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 hasHooks(): bool {} /** * @since 8.4 */ public function getHooks(): array {} /** * @since 8.4 */ public function hasHook(PropertyHookType $type): bool {} /** * @since 8.4 */ public function getHook(PropertyHookType $type): ?ReflectionMethod {} /** * @since 8.4 */ public function isPrivateSet(): bool {} /** * @since 8.4 */ public function isProtectedSet(): bool {} /** * @since 8.4 */ public function setRawValueWithoutLazyInitialization(object $object, mixed $value): void {} /** * @since 8.4 */ public function skipLazyInitialization(object $object): void {} /** * @since 8.4 */ public function isDynamic(): bool {} /** * @since 8.4 */ public function isFinal(): bool {} /** * @since 8.4 */ public function isLazy(object $object): bool {} /** * @since 8.5 */ public function getMangledName(): string {} } '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 {} } 'ReflectionNamedType[]|ReflectionIntersectionType[]' ], default: 'ReflectionNamedType[]' )] public function getTypes(): array {} } '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 {} } 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(); } 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 = null): ?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 * @template TKey * @template-covariant TValue * @template-extends Iterator */ 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( #[LanguageLevelTypeAware(['8.5' => 'RecursiveIterator|IteratorAggregate'], default: '')] $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 * @template TKey of array-key * @template TValue * @template-implements SeekableIterator * @template-implements ArrayAccess */ 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|object $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 TKey $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 TKey $key

    * The offset to get the value from. *

    * @return TValue|null 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 TKey $key

    * The index to set for. *

    * @param TValue $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 TKey $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 TValue $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(TValue, TValue):int $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(TKey, TKey):int $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 TValue The current array entry. */ #[TentativeType] public function current(): mixed {} /** * Return current array key * @link https://php.net/manual/en/arrayiterator.key.php * @return TKey|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 {} } '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', '8.5' => 'int|null'], default: '')] $length = null ): 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 * @template-extends SplDoublyLinkedList */ 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 {} /** * @return array * @since 8.5 */ #[TentativeType] public function __serialize(): array {} /** * @since 8.5 */ #[TentativeType] public function __unserialize(array $data): void {} } /** * @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 {} /** * @return array * @since 8.5 */ #[TentativeType] public function __serialize(): array {} /** * @since 8.5 */ #[TentativeType] public function __unserialize(array $data): void {} } /** * @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] #[Deprecated("The function is deprecated", since: "8.4")] 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] #[Deprecated('use method SplObjectStorage::offset{Exists|Set|Unset}() instead', since: '8.5')] 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] #[Deprecated('use method SplObjectStorage::offset{Exists|Set|Unset}() instead', since: '8.5')] 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] #[Deprecated('use method SplObjectStorage::offset{Exists|Set|Unset}() instead', since: '8.5')] 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 = 1, #[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 {} } *

    * @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 = null): 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 = null): 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 = null, 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 * @template TKey of int|string * @template TValue * @param Traversable|array $iterator

    * The iterator being copied. *

    * @param bool $preserve_keys [optional]

    * Whether to use the iterator element keys as index. *

    * @return ( * $preserve_keys is true ? array : ( * $preserve_keys is false ? TValue[] : * array|TValue[]) * ) 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 = null): 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 {} The filename of the SQLite database. If the file does not exist, SQLite will attempt to create it. PHP must have write permissions to the file if data is inserted, the database schema is modified or to create the database if it does not exist.

    * @param int $mode [optional]

    The mode of the file. Intended to be used to open the database in read-only mode. Presently, this parameter is ignored by the sqlite library. The default value for mode is the octal value 0666 and this is the recommended value.

    * @param string &$error_message [optional]

    Passed by reference and is set to hold a descriptive error message explaining why the database could not be opened if there was an error.

    */ final public function __construct($filename, $mode = 0666, &$error_message) {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * @link https://php.net/manual/en/function.sqlite-query.php * @param string $query

    * The query to be executed. *

    *

    * Data inside the query should be {@link https://php.net/manual/en/function.sqlite-escape-string.php properly escaped}. *

    * @param int $result_type [optional] *

    The optional result_type parameter accepts a constant and determines how the returned array will be indexed. Using SQLITE_ASSOC will return only associative indices (named fields) while SQLITE_NUM will return only numerical indices (ordinal field numbers). SQLITE_BOTH will return both associative and numerical indices. SQLITE_BOTH is the default for this function.

    * @param string &$error_message [optional]

    The specified variable will be filled if an error occurs. This is specially important because SQL syntax errors can't be fetched using the {@see sqlite_last_error()} function.

    * @return resource|false

    * This function will return a result handle or FALSE on failure. * For queries that return rows, the result handle can then be used with * functions such as {@see sqlite_fetch_array()} and * {@see sqlite_seek()}. *

    *

    * Regardless of the query type, this function will return FALSE if the * query failed. *

    *

    * {@see sqlite_query()} returns a buffered, seekable result * handle. This is useful for reasonably small queries where you need to * be able to randomly access the rows. Buffered result handles will * allocate memory to hold the entire result and will not return until it * has been fetched. If you only need sequential access to the data, it is * recommended that you use the much higher performance * {@see sqlite_unbuffered_query()} instead. *

    */ public function query($query, $result_type = SQLITE_BOTH, &$error_message) {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * @link https://php.net/manual/en/function.sqlite-exec.php * @param string $query

    * The query to be executed. *

    *

    * Data inside the query should be {@link https://php.net/manual/en/function.sqlite-escape-string.php properly escaped}. *

    * @param string &$error_message [optional]

    The specified variable will be filled if an error occurs. This is specially important because SQL syntax errors can't be fetched using the * {@see sqlite_last_error()} function.

    * @return bool

    * This function will return a boolean result; TRUE for success or FALSE for failure. * If you need to run a query that returns rows, see {@see sqlite_query()}. *

    *

    The column names returned by * SQLITE_ASSOC and SQLITE_BOTH will be * case-folded according to the value of the * {@link https://php.net/manual/en/sqlite.configuration.php#ini.sqlite.assoc-case sqlite.assoc_case} configuration * option.

    */ public function queryExec($query, &$error_message) {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * Execute a query against a given database and returns an array * @link https://php.net/manual/en/function.sqlite-array-query.php * @param string $query

    * The query to be executed. *

    *

    * Data inside the query should be {@link https://php.net/manual/en/function.sqlite-escape-string.php properly escaped}. *

    * @param int $result_type [optional]

    The optional result_type * parameter accepts a constant and determines how the returned array will be * indexed. Using SQLITE_ASSOC will return only associative * indices (named fields) while SQLITE_NUM will return * only numerical indices (ordinal field numbers). SQLITE_BOTH * will return both associative and numerical indices. * SQLITE_BOTH is the default for this function.

    * @param bool $decode_binary [optional]

    When the decode_binary * parameter is set to TRUE (the default), PHP will decode the binary encoding * it applied to the data if it was encoded using the * {@see sqlite_escape_string()}. You should normally leave this * value at its default, unless you are interoperating with databases created by * other sqlite capable applications.

    *

    * @return array|false * Returns an array of the entire result set; FALSE otherwise. *

    *

    The column names returned by * SQLITE_ASSOC and SQLITE_BOTH will be * case-folded according to the value of the * {@link https://php.net/manual/en/sqlite.configuration.php#ini.sqlite.assoc-case sqlite.assoc_case} configuration * option.

    */ public function arrayQuery($query, $result_type = SQLITE_BOTH, $decode_binary = true) {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.1) * Executes a query and returns either an array for one single column or the value of the first row * @link https://php.net/manual/en/function.sqlite-single-query.php * @param string $query * @param bool $first_row_only [optional] * @param bool $decode_binary [optional] * @return array */ public function singleQuery($query, $first_row_only = true, $decode_binary = true) {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * Execute a query that does not prefetch and buffer all data * @link https://php.net/manual/en/function.sqlite-unbuffered-query.php * @param string $query

    * The query to be executed. *

    *

    * Data inside the query should be {@link https://php.net/manual/en/function.sqlite-escape-string.php properly escaped}. *

    * @param int $result_type [optional]

    The optional result_type parameter accepts a constant and determines how the returned array will be indexed. * Using SQLITE_ASSOC will return only associative indices (named fields) while SQLITE_NUM will return only numerical indices (ordinal field numbers). * SQLITE_BOTH will return both associative and numerical indices. SQLITE_BOTH is the default for this function. *

    * @param string &$error_message [optional] * @return resource Returns a result handle or FALSE on failure. * {@see sqlite_unbuffered_query()} returns a sequential forward-only result set that can only be used to read each row, one after the other. */ public function unbufferedQuery($query, $result_type = SQLITE_BOTH, &$error_message = null) {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * Returns the rowid of the most recently inserted row * @link https://php.net/manual/en/function.sqlite-last-insert-rowid.php * @return int Returns the row id, as an integer. */ public function lastInsertRowid() {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * Returns the number of rows that were changed by the most recent SQL statement * @link https://php.net/manual/en/function.sqlite-changes.php * @return int Returns the number of changed rows. */ public function changes() {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * Register an aggregating UDF for use in SQL statements * @link https://php.net/manual/en/function.sqlite-create-aggregate.php * @param string $function_name

    The name of the function used in SQL statements.

    * @param callable $step_func

    Callback function called for each row of the result set. Function parameters are &$context, $value, ....

    * @param callable $finalize_func

    Callback function to aggregate the "stepped" data from each row. Function parameter is &$context and the function should return the final result of aggregation.

    * @param int $num_args [optional]

    Hint to the SQLite parser if the callback function accepts a predetermined number of arguments.

    */ public function createAggregate($function_name, $step_func, $finalize_func, $num_args = -1) {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * Registers a "regular" User Defined Function for use in SQL statements * @link https://php.net/manual/en/function.sqlite-create-function.php * @param string $function_name

    The name of the function used in SQL statements.

    * @param callable $callback

    * Callback function to handle the defined SQL function. *

    *

    Note: * Callback functions should return a type understood by SQLite (i.e. * {@link https://php.net/manual/en/language.types.intro.php scalar type}). *

    * @param int $num_args [optional]

    Note: Two alternative syntaxes are * supported for compatibility with other database extensions (such as MySQL). * The preferred form is the first, where the dbhandle * parameter is the first parameter to the function.

    */ public function createFunction($function_name, $callback, $num_args = -1) {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * Set busy timeout duration, or disable busy handlers * @link https://php.net/manual/en/function.sqlite-busy-timeout.php * @param int $milliseconds

    The number of milliseconds. When set to 0, busy handlers will be disabled and SQLite will return immediately with a SQLITE_BUSY status code if another process/thread has the database locked for an update. * PHP sets the default busy timeout to be 60 seconds when the database is opened.

    * @return int

    Returns an error code, or 0 if no error occurred.

    */ public function busyTimeout($milliseconds) {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * Returns the error code of the last error for a database * @link https://php.net/manual/en/function.sqlite-last-error.php * @return int Returns an error code, or 0 if no error occurred. */ public function lastError() {} /** * (PHP 5 < 5.4.0) * Return an array of column types from a particular table * @link https://php.net/manual/en/function.sqlite-fetch-column-types.php * @param string $table_name

    The table name to query.

    * @param int $result_type [optional]

    * The optional result_type parameter accepts a * constant and determines how the returned array will be indexed. Using * SQLITE_ASSOC will return only associative indices * (named fields) while SQLITE_NUM will return only * numerical indices (ordinal field numbers). * SQLITE_ASSOC is the default for * this function. *

    * @return array

    * Returns an array of column data types; FALSE on error. *

    *

    The column names returned by * SQLITE_ASSOC and SQLITE_BOTH will be * case-folded according to the value of the * {@link https://php.net/manual/en/sqlite.configuration.php#ini.sqlite.assoc-case sqlite.assoc_case} configuration * option.

    */ public function fetchColumnTypes($table_name, $result_type = SQLITE_ASSOC) {} } /** * @link https://php.net/manual/en/ref.sqlite.php */ final class SQLiteResult implements Iterator, Countable { /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * Fetches the next row from a result set as an array * @link https://php.net/manual/en/function.sqlite-fetch-array.php * @param int $result_type [optional] *

    * The optional result_type * parameter accepts a constant and determines how the returned array will be * indexed. Using SQLITE_ASSOC will return only associative * indices (named fields) while SQLITE_NUM will return * only numerical indices (ordinal field numbers). SQLITE_BOTH * will return both associative and numerical indices. * SQLITE_BOTH is the default for this function. *

    * @param bool $decode_binary [optional]

    When the decode_binary * parameter is set to TRUE (the default), PHP will decode the binary encoding * it applied to the data if it was encoded using the * {@link https://php.net/manual/en/sqlite.configuration.php#ini.sqlite.assoc-case sqlite.assoc_case}. You should normally leave this * value at its default, unless you are interoperating with databases created by * other sqlite capable applications.

    * @return array *

    * Returns an array of the next row from a result set; FALSE if the * next position is beyond the final row. *

    *

    The column names returned by * SQLITE_ASSOC and SQLITE_BOTH will be * case-folded according to the value of the * {@link https://php.net/manual/en/sqlite.configuration.php#ini.sqlite.assoc-case sqlite.assoc_case} configuration * option.

    */ public function fetch($result_type = SQLITE_BOTH, $decode_binary = true) {} /** * (PHP 5 < 5.4.0) * Fetches the next row from a result set as an object * @link https://php.net/manual/en/function.sqlite-fetch-object.php * @param string $class_name [optional] * @param array $ctor_params [optional] * @param bool $decode_binary [optional] * @return object */ public function fetchObject($class_name = 'stdClass', $ctor_params = [], $decode_binary = true) {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.1) * Fetches the first column of a result set as a string * @link https://php.net/manual/en/function.sqlite-fetch-single.php * @param bool $decode_binary [optional] * @return string

    Returns the first column value, as a string.

    */ public function fetchSingle($decode_binary = true) {} /** * (PHP 5 < 5.4.0) * Fetches the next row from a result set as an object * @link https://www.php.net/manual/en/function.sqlite-fetch-all.php * @param int $result_type [optional]

    * The optional result_type parameter accepts a constant and determines how the returned array will be indexed. * Using SQLITE_ASSOC will return only associative indices (named fields) while SQLITE_NUM will return only numerical indices (ordinal field numbers). * {@see SQLITE_BOTH} will return both associative and numerical indices. {@see SQLITE_BOTH} is the default for this function.

    * @param bool $decode_binary [optional]

    When the decode_binary parameter is set to TRUE (the default), * PHP will decode the binary encoding it applied to the data if it was encoded using the {@see sqlite_escape_string()}. * You should normally leave this value at its default, unless you are interoperating with databases created by other sqlite capable applications.

    * @return object */ public function fetchAll($result_type = SQLITE_BOTH, $decode_binary = true) {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * Fetches a column from the current row of a result set * @link https://php.net/manual/en/function.sqlite-column.php * @param $index_or_name * @param $decode_binary [optional]

    When the decode_binary * parameter is set to TRUE (the default), PHP will decode the binary encoding * it applied to the data if it was encoded using the * {@see sqlite_escape_string()}. You should normally leave this * value at its default, unless you are interoperating with databases created by * other sqlite capable applications.

    * @return mixed

    Returns the column value

    */ public function column($index_or_name, $decode_binary = true) {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * Returns the number of fields in a result set * @link https://php.net/manual/en/function.sqlite-num-fields.php * @return int

    Returns the number of fields, as an integer.

    */ public function numFields() {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * Returns the name of a particular field * @link https://php.net/manual/en/function.sqlite-field-name.php * @param int $field_index

    The ordinal column number in the result set.

    * @return string

    * Returns the name of a field in an SQLite result set, given the ordinal * column number; FALSE on error. *

    *

    The column names returned by * SQLITE_ASSOC and SQLITE_BOTH will be * case-folded according to the value of the * {@link https://php.net/manual/en/sqlite.configuration.php#ini.sqlite.assoc-case sqlite.assoc_case}configuration * option.

    */ public function fieldName($field_index) {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * Fetches the current row from a result set as an array * @link https://php.net/manual/en/function.sqlite-current.php * @param int $result_type [optional]

    The optional result_type * parameter accepts a constant and determines how the returned array will be * indexed. Using {@see SQLITE_ASSOC} will return only associative * indices (named fields) while {@see SQLITE_NUM} will return * only numerical indices (ordinal field numbers). SQLITE_BOTH * will return both associative and numerical indices. * {@see SQLITE_BOTH} is the default for this function.

    * @param bool $decode_binary [optional]

    When the decode_binary * parameter is set to TRUE (the default), PHP will decode the binary encoding * it applied to the data if it was encoded using the * {@see sqlite_escape_string()}. You should normally leave this * value at its default, unless you are interoperating with databases created by * other sqlite capable applications.

    * @return array

    * Returns an array of the current row from a result set; FALSE if the * current position is beyond the final row. *

    *

    The column names returned by * SQLITE_ASSOC and SQLITE_BOTH will be * case-folded according to the value of the * {@link https://php.net/manual/en/sqlite.configuration.php#ini.sqlite.assoc-case sqlite.assoc_case} configuration * option.

    */ public function current($result_type = SQLITE_BOTH, $decode_binary = true) {} /** * Return the key of the current element * @link https://php.net/manual/en/iterator.key.php * @return mixed scalar on success, or null on failure. * @since 5.0.0 */ public function key() {} /** * Seek to the next row number * @link https://php.net/manual/en/function.sqlite-next.php * @return bool Returns TRUE on success, or FALSE if there are no more rows. * @since 5.0.0 */ public function next() {} /** * Checks if current position is valid * @link https://php.net/manual/en/iterator.valid.php * @return bool

    * Returns TRUE if there are more rows available from the * result handle, or FALSE otherwise. *

    * @since 5.0.0 */ 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. * @since 5.0.0 */ public function rewind() {} /** * 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.0 */ public function count() {} /** * Seek to the previous row number of a result set * @link https://php.net/manual/en/function.sqlite-prev.php * @return bool

    Returns TRUE on success, or FALSE if there are no more previous rows. *

    * @since 5.4.0 */ public function prev() {} /** *@since 5.4.0 * Returns whether or not a previous row is available * @link https://php.net/manual/en/function.sqlite-has-prev.php * @return bool

    * Returns TRUE if there are more previous rows available from the * result handle, or FALSE otherwise. *

    */ public function hasPrev() {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * Returns the number of rows in a buffered result set * @link https://php.net/manual/en/function.sqlite-num-rows.php * @return int Returns the number of rows, as an integer. */ public function numRows() {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0) * Seek to a particular row number of a buffered result set * @link https://php.net/manual/en/function.sqlite-seek.php * @param $row *

    * The ordinal row number to seek to. The row number is zero-based (0 is * the first row). *

    *

    Note:

    This function cannot be used with * unbuffered result handles.

    */ public function seek($row) {} } /** * Represents an unbuffered SQLite result set. Unbuffered results sets are sequential, forward-seeking only. * @link https://php.net/manual/en/ref.sqlite.php */ final class SQLiteUnbuffered { /** * @param int $result_type [optional] * @param bool $decode_binary [optional] */ public function fetch($result_type = SQLITE_BOTH, $decode_binary = true) {} /** * @link https://www.php.net/manual/en/function.sqlite-fetch-object.php * @param string $class_name [optional] * @param array $ctor_params [optional] * @param bool $decode_binary [optional] */ public function fetchObject($class_name = 'stdClass', $ctor_params = [], $decode_binary = true) {} /** * @param bool $decode_binary [optional] */ public function fetchSingle($decode_binary = true) {} /** * @param int $result_type [optional] * @param bool $decode_binary [optional] */ public function fetchAll($result_type = SQLITE_BOTH, $decode_binary = true) {} /** * @param $index_or_name * @param $decode_binary [optional] */ public function column($index_or_name, $decode_binary = true) {} public function numFields() {} /** * @param int $field_index */ public function fieldName($field_index) {} /** * @param int $result_type [optional] * @param bool $decode_binary [optional] */ public function current($result_type = SQLITE_BOTH, $decode_binary = true) {} public function next() {} public function valid() {} } final class SQLiteException extends RuntimeException { protected $message; protected $code; protected $file; protected $line; /** * Clone the exception * @link https://php.net/manual/en/exception.clone.php * @return void * @since 5.1.0 */ final private function __clone() {} /** * Construct the exception * @link https://php.net/manual/en/exception.construct.php * @param $message [optional] * @param $code [optional] * @param $previous [optional] * @since 5.1.0 */ #[Pure] public function __construct($message, $code, $previous) {} /** * String representation of the exception * @link https://php.net/manual/en/exception.tostring.php * @return string the string representation of the exception. * @since 5.1.0 */ public function __toString() {} } /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Opens a SQLite database and create the database if it does not exist * @link https://php.net/manual/en/function.sqlite-open.php * @param string $filename

    * The filename of the SQLite database. If the file does not exist, SQLite * will attempt to create it. PHP must have write permissions to the file * if data is inserted, the database schema is modified or to create the * database if it does not exist. *

    * @param int $mode [optional]

    * The mode of the file. Intended to be used to open the database in * read-only mode. Presently, this parameter is ignored by the sqlite * library. The default value for mode is the octal value * 0666 and this is the recommended value. *

    * @param string &$error_message [optional]

    * Passed by reference and is set to hold a descriptive error message * explaining why the database could not be opened if there was an error. *

    * @return resource|false a resource (database handle) on success, false on error. */ function sqlite_open($filename, $mode = null, &$error_message = null) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Opens a persistent handle to an SQLite database and create the database if it does not exist * @link https://php.net/manual/en/function.sqlite-popen.php * @param string $filename

    * The filename of the SQLite database. If the file does not exist, SQLite * will attempt to create it. PHP must have write permissions to the file * if data is inserted, the database schema is modified or to create the * database if it does not exist. *

    * @param int $mode [optional]

    * The mode of the file. Intended to be used to open the database in * read-only mode. Presently, this parameter is ignored by the sqlite * library. The default value for mode is the octal value * 0666 and this is the recommended value. *

    * @param string &$error_message [optional]

    * Passed by reference and is set to hold a descriptive error message * explaining why the database could not be opened if there was an error. *

    * @return resource|false

    a resource (database handle) on success, false on error.

    */ function sqlite_popen($filename, $mode = null, &$error_message = null) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Closes an open SQLite database * @link https://php.net/manual/en/function.sqlite-close.php * @param resource $dbhandle

    * The SQLite Database resource; returned from sqlite_open * when used procedurally. *

    * @return void */ function sqlite_close($dbhandle) {} /** * (PHP 5 < 5.4.0, PECL sqlite >= 1.0.0)
    * Executes a query against a given database and returns a result handle * there are two signatures with $query first and with $dbhandle first. * @link https://php.net/manual/en/function.sqlite-query.php * @param string|resource $query

    * The query to be executed. *

    *

    * Data inside the query should be properly escaped. *

    * @param resource|string $dbhandle The SQLite Database resource; returned from sqlite_open() when used procedurally. This parameter is not required when using the object-oriented method. * @param int $result_type [optional]

    The optional result_type * parameter accepts a constant and determines how the returned array will be * indexed. Using SQLITE_ASSOC will return only associative * indices (named fields) while SQLITE_NUM will return * only numerical indices (ordinal field numbers). SQLITE_BOTH * will return both associative and numerical indices. * SQLITE_BOTH is the default for this function.

    * @param string &$error_msg [optional]

    * The specified variable will be filled if an error occurs. This is * specially important because SQL syntax errors can't be fetched using * the * {@see sqlite_last_error} function. *

    * @return resource|false This function will return a result handle or FALSE on failure. * For queries that return rows, the result handle can then be used with * functions such as * {@see sqlite_fetch_array} and * {@see sqlite_seek}. *

    *

    * Regardless of the query type, this function will return false if the * query failed. *

    *

    * {@see sqlite_query} returns a buffered, seekable result * handle. This is useful for reasonably small queries where you need to * be able to randomly access the rows. Buffered result handles will * allocate memory to hold the entire result and will not return until it * has been fetched. If you only need sequential access to the data, it is * recommended that you use the much higher performance * {@see sqlite_unbuffered_query} instead. */ function sqlite_query($query, $dbhandle, $result_type = SQLITE_BOTH, &$error_msg = null) {} /** * (PHP 5, PECL sqlite >= 1.0.3)
    * Executes a result-less query against a given database * @link https://php.net/manual/en/function.sqlite-exec.php * @param string $query

    * The query to be executed. *

    *

    * Data inside the query should be properly escaped. *

    * @param resource $dbhandle

    * The SQLite Database resource; returned from * {@see sqlite_open()} when used procedurally. This parameter * is not required when using the object-oriented method. *

    * @param string &$error_msg [optional]

    * The specified variable will be filled if an error occurs. This is * specially important because SQL syntax errors can't be fetched using * the * {@see sqlite_last_error} function. *

    * @return bool

    This function will return a boolean result; true for success or false for failure. * If you need to run a query that returns rows, see sqlite_query.

    */ function sqlite_exec($dbhandle, $query, &$error_msg = null) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Execute a query against a given database and returns an array * @link https://php.net/manual/en/function.sqlite-array-query.php * @param string $query

    * The query to be executed. *

    *

    * Data inside the query should be properly escaped. *

    * @param resource $dbhandle

    * The SQLite Database resource; returned from * {@see sqlite_open()} * when used procedurally. This parameter is not required * when using the object-oriented method. *

    * @param int $result_type [optional]

    The optional result_type * parameter accepts a constant and determines how the returned array will be * indexed. Using SQLITE_ASSOC will return only associative * indices (named fields) while SQLITE_NUM will return * only numerical indices (ordinal field numbers). SQLITE_BOTH * will return both associative and numerical indices. * SQLITE_BOTH is the default for this function.

    * @param bool $decode_binary [optional]

    When the decode_binary * parameter is set to TRUE (the default), PHP will decode the binary encoding * it applied to the data if it was encoded using the * {@link sqlite_escape_string()}. You should normally leave this * value at its default, unless you are interoperating with databases created by * other sqlite capable applications.

    * @return array|false an array of the entire result set; false otherwise. *

    The column names returned by * SQLITE_ASSOC and SQLITE_BOTH will be * case-folded according to the value of the * {@link php.net/en/sqlite.configuration.php#ini.sqlite.assoc-case sqlite.assoc_case} configuration * option.

    */ function sqlite_array_query($dbhandle, $query, $result_type = null, $decode_binary = null) {} /** * (PHP 5, PECL sqlite >= 1.0.1)
    * Executes a query and returns either an array for one single column or the value of the first row * @link https://php.net/manual/en/function.sqlite-single-query.php * @param resource $db * @param string $query * @param bool $first_row_only [optional] * @param bool $decode_binary [optional] * @return array */ function sqlite_single_query($db, $query, $first_row_only = null, $decode_binary = null) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Fetches the next row from a result set as an array * @link https://php.net/manual/en/function.sqlite-fetch-array.php * @param resource $result

    The SQLite result resource. This parameter is not required when using the object-oriented method.

    * @param int $result_type [optional] * @param bool $decode_binary [optional] * @return array|false

    an array of the next row from a result set; false if the * next position is beyond the final row.

    */ function sqlite_fetch_array($result, $result_type = SQLITE_BOTH, $decode_binary = null) {} /** * Fetches the next row from a result set as an object * @link https://php.net/manual/en/function.sqlite-fetch-object.php * @param resource $result * @param string $class_name [optional] * @param null|array $ctor_params [optional] * @param bool $decode_binary [optional] * @return object */ function sqlite_fetch_object($result, $class_name = null, ?array $ctor_params = null, $decode_binary = null) {} /** * (PHP 5, PECL sqlite >= 1.0.1)
    * Fetches the first column of a result set as a string * @link https://php.net/manual/en/function.sqlite-fetch-single.php * @param resource $result

    The SQLite result resource. This parameter is not required when using the object-oriented method.

    * @param bool $decode_binary [optional]

    When the decode_binary * parameter is set to TRUE (the default), PHP will decode the binary encoding * it applied to the data if it was encoded using the * {@see sqlite_escape_string()}. You should normally leave this * value at its default, unless you are interoperating with databases created by * other sqlite capable applications.

    * @return string

    the first column value, as a string.

    */ function sqlite_fetch_single($result, $decode_binary = null) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Alias: * {@see sqlite_fetch_single} * @link https://php.net/manual/en/function.sqlite-fetch-string.php * @param resource $result

    The SQLite result resource. This parameter is not required when using the object-oriented method.

    * @param bool $decode_binary [optional]

    When the decode_binary * parameter is set to TRUE (the default), PHP will decode the binary encoding * it applied to the data if it was encoded using the * {@see sqlite_escape_string()}. You should normally leave this * value at its default, unless you are interoperating with databases created by * other sqlite capable applications.

    * @return string

    the first column value, as a string.

    */ function sqlite_fetch_string($result, $decode_binary) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Fetches all rows from a result set as an array of arrays * @link https://php.net/manual/en/function.sqlite-fetch-all.php * @param int $result_type [optional] * @param bool $decode_binary [optional] * @return array

    an array of the remaining rows in a result set. If called right * after * {@see sqlite_query}, it returns all rows. If called * after * {@see sqlite_fetch_array}, it returns the rest. If * there are no rows in a result set, it returns an empty array.

    *

    The column names returned by SQLITE_ASSOC and SQLITE_BOTH will be case-folded according to the value of the * {@link https://php.net/manual/en/sqlite.configuration.php#ini.sqlite.assoc-case sqlite.assoc_case} configuration option.

    */ function sqlite_fetch_all($result_type = null, $decode_binary = null) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Fetches the current row from a result set as an array * @link https://php.net/manual/en/function.sqlite-current.php * @param resource $result

    The SQLite result resource. This parameter is not required when using the object-oriented method.

    * @param int $result_type [optional]

    The optional result_type parameter accepts a constant and determines how the returned array will be indexed. Using SQLITE_ASSOC will return only associative indices (named fields) while SQLITE_NUM will return only numerical indices (ordinal field numbers). SQLITE_BOTH will return both associative and numerical indices. SQLITE_BOTH is the default for this function.

    * @param bool $decode_binary [optional]

    When the decode_binary parameter is set to TRUE (the default), PHP will decode the binary encoding it applied to the data if it was encoded using the sqlite_escape_string(). You should normally leave this value at its default, unless you are interoperating with databases created by other sqlite capable applications.

    * @return array|false an array of the current row from a result set; false if the * current position is beyond the final row. */ function sqlite_current($result, $result_type = null, $decode_binary = null) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Fetches a column from the current row of a result set * @link https://php.net/manual/en/function.sqlite-column.php * @param resource $result

    The SQLite result resource. This parameter is not required when using the object-oriented method.

    * @param mixed $index_or_name

    * The column index or name to fetch. *

    * @param bool $decode_binary [optional]

    When the decode_binary * parameter is set to TRUE (the default), PHP will decode the binary encoding * it applied to the data if it was encoded using the * {@see sqlite_escape_string()}. You should normally leave this * value at its default, unless you are interoperating with databases created by * other sqlite capable applications.

    * @return mixed the column value. */ function sqlite_column($result, $index_or_name, $decode_binary = null) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Returns the version of the linked SQLite library * @link https://php.net/manual/en/function.sqlite-libversion.php * @return string the library version, as a string. */ function sqlite_libversion() {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Returns the encoding of the linked SQLite library * @link https://php.net/manual/en/function.sqlite-libencoding.php * @return string the library encoding. */ function sqlite_libencoding() {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Returns the number of rows that were changed by the most * recent SQL statement * @link https://php.net/manual/en/function.sqlite-changes.php * @param $db * @return int the number of changed rows. */ function sqlite_changes($db) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Returns the rowid of the most recently inserted row * @link https://php.net/manual/en/function.sqlite-last-insert-rowid.php * @param resource $dbhandle

    The SQLite Database resource; returned from * {@see sqlite_open()} when used procedurally. This parameter is not required when using the object-oriented method.

    * @return int the row id, as an integer. */ function sqlite_last_insert_rowid($dbhandle) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Returns the number of rows in a buffered result set * @link https://php.net/manual/en/function.sqlite-num-rows.php * @param resource $result

    * The SQLite result resource. This parameter is not required when using * the object-oriented method. *

    *

    Note:

    This function cannot be used with * unbuffered result handles.

    * @return int the number of rows, as an integer. */ function sqlite_num_rows($result) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Returns the number of fields in a result set * @link https://php.net/manual/en/function.sqlite-num-fields.php * @param resource $result

    The SQLite result resource. This parameter is not required when using the object-oriented method.

    * @return int the number of fields, as an integer. */ function sqlite_num_fields($result) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Returns the name of a particular field * @link https://php.net/manual/en/function.sqlite-field-name.php * @param resource $result

    The SQLite result resource. This parameter is not required when using the object-oriented method.

    * @param int $field_index

    * The ordinal column number in the result set. *

    * @return string the name of a field in an SQLite result set, given the ordinal * column number; false on error. */ function sqlite_field_name($result, $field_index) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Seek to a particular row number of a buffered result set * @link https://php.net/manual/en/function.sqlite-seek.php * @param resource $result

    * The SQLite result resource. This parameter is not required when using * the object-oriented method. *

    *

    Note:

    This function cannot be used with * unbuffered result handles.

    * @param int $rownum

    * The ordinal row number to seek to. The row number is zero-based (0 is * the first row). *

    * @return bool false if the row does not exist, true otherwise. */ function sqlite_seek($result, $rownum) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Seek to the first row number * @link https://php.net/manual/en/function.sqlite-rewind.php * @param resource $result

    * The SQLite result resource. This parameter is not required when using * the object-oriented method. *

    *

    Note:

    This function cannot be used with * unbuffered result handles.

    * @return bool false if there are no rows in the result set, true otherwise. */ function sqlite_rewind($result) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Seek to the next row number * @link https://php.net/manual/en/function.sqlite-next.php * @param resource $result

    * The SQLite result resource. This parameter is not required when using * the object-oriented method. *

    *

    Note:

    This function cannot be used with * unbuffered result handles.

    * @return bool TRUE on success, or FALSE if there are no more rows. */ function sqlite_next($result) {} /** * Seek to the previous row number of a result set * @link https://php.net/manual/en/function.sqlite-prev.php * @param resource $result

    * The SQLite result resource. This parameter is not required when using * the object-oriented method. *

    *

    Note:

    This function cannot be used with * unbuffered result handles.

    * @return bool true on success, or false if there are no more previous rows. */ function sqlite_prev($result) {} /** * Returns whether more rows are available * @link https://php.net/manual/en/function.sqlite-valid.php * @param resource $result

    * The SQLite result resource. This parameter is not required when using * the object-oriented method. *

    *

    Note:

    This function cannot be used with * unbuffered result handles.

    * @return bool TRUE if there are more rows available from the * result handle, or FALSE otherwise. */ function sqlite_valid($result) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Finds whether or not more rows are available * @link https://php.net/manual/en/function.sqlite-has-more.php * @param resource $result

    * The SQLite result resource. *

    * @return bool TRUE if there are more rows available from the * result handle, or FALSE otherwise. */ function sqlite_has_more($result) {} /** * Returns whether or not a previous row is available * @link https://php.net/manual/en/function.sqlite-has-prev.php * @param resource $result

    * The SQLite result resource. This parameter is not required when using * the object-oriented method. *

    * @return bool TRUE if there are more previous rows available from the * result handle, or FALSE otherwise. */ function sqlite_has_prev($result) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Escapes a string for use as a query parameter * @link https://php.net/manual/en/function.sqlite-escape-string.php * @param string $item

    * The string being quoted. *

    *

    * If the item contains a NUL * character, or if it begins with a character whose ordinal value is * 0x01, PHP will apply a binary encoding scheme so that * you can safely store and retrieve binary data. *

    * @return string an escaped string for use in an SQLite SQL statement. */ function sqlite_escape_string($item) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Set busy timeout duration, or disable busy handlers * @link https://php.net/manual/en/function.sqlite-busy-timeout.php * @param resource $dbhandle

    The SQLite Database resource; returned from * {@see sqlite_open()} when used procedurally. * This parameter is not required when using the object-oriented method.

    * @param int $milliseconds

    * The number of milliseconds. When set to * 0, busy handlers will be disabled and SQLite will * return immediately with a SQLITE_BUSY status code * if another process/thread has the database locked for an update. *

    *

    * PHP sets the default busy timeout to be 60 seconds when the database is * opened. *

    *

    * There are one thousand (1000) milliseconds in one second. *

    * @return void */ function sqlite_busy_timeout($dbhandle, $milliseconds) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Returns the error code of the last error for a database * @link https://php.net/manual/en/function.sqlite-last-error.php * @param resource $dbhandle

    The SQLite Database resource; returned from * {@see sqlite_open()} when used procedurally. * This parameter is not required when using the object-oriented method.

    * @return int an error code, or 0 if no error occurred. */ function sqlite_last_error($dbhandle) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Returns the textual description of an error code * @link https://php.net/manual/en/function.sqlite-error-string.php * @param int $error_code

    * The error code being used, which might be passed in from * {@see sqlite_last_error}. *

    * @return string a human readable description of the error_code, * as a string. */ function sqlite_error_string($error_code) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Execute a query that does not prefetch and buffer all data * @link https://php.net/manual/en/function.sqlite-unbuffered-query.php * @param resource $dbhandle

    The SQLite Database resource; returned from * {@see sqlite_open()} when used procedurally. * This parameter is not required when using the object-oriented method.

    * @param string $query

    * The query to be executed. *

    *

    * Data inside the query should be properly escaped. *

    * @param int $result_type [optional] * @param string &$error_msg [optional]

    * The specified variable will be filled if an error occurs. This is * specially important because SQL syntax errors can't be fetched using * the sqlite_last_error function. *

    * @return SQLiteUnbuffered|false a result handle or false on failure. *

    * sqlite_unbuffered_query returns a sequential * forward-only result set that can only be used to read each row, one after * the other. *

    */ function sqlite_unbuffered_query($dbhandle, $query, $result_type = SQLITE_BOTH, &$error_msg = null) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Register an aggregating UDF for use in SQL statements * @link https://php.net/manual/en/function.sqlite-create-aggregate.php * @param resource $dbhandle

    The SQLite Database resource; returned from * {@see sqlite_open()} when used procedurally. * This parameter is not required when using the object-oriented method.

    * @param string $function_name

    * The name of the function used in SQL statements. *

    * @param callable $step_func

    * Callback function called for each row of the result set. *

    * @param callable $finalize_func

    * Callback function to aggregate the "stepped" data from each row. *

    * @param int $num_args [optional]

    * Hint to the SQLite parser if the callback function accepts a * predetermined number of arguments. *

    * @return void */ function sqlite_create_aggregate($dbhandle, $function_name, $step_func, $finalize_func, $num_args = null) {} /** * (PHP 5, sqlite >= 1.0.0)
    * Registers a "regular" User Defined Function for use in SQL statements * @link https://php.net/manual/en/function.sqlite-create-function.php * @param resource $dbhandle

    The SQLite Database resource; returned from * {@see sqlite_open()} when used procedurally. * This parameter is not required when using the object-oriented method.

    * @param string $function_name

    * The name of the function used in SQL statements. *

    * @param callable $callback

    * Callback function to handle the defined SQL function. *

    * Callback functions should return a type understood by SQLite (i.e. * scalar type). * @param int $num_args [optional]

    * Hint to the SQLite parser if the callback function accepts a * predetermined number of arguments. *

    * @return void */ function sqlite_create_function($dbhandle, $function_name, $callback, $num_args = null) {} /** * Opens a SQLite database and returns a SQLiteDatabase object * @link https://php.net/manual/en/function.sqlite-factory.php * @param string $filename

    * The filename of the SQLite database. *

    * @param int $mode [optional]

    * The mode of the file. Intended to be used to open the database in * read-only mode. Presently, this parameter is ignored by the sqlite * library. The default value for mode is the octal value * 0666 and this is the recommended value. *

    * @param string &$error_message [optional]

    * Passed by reference and is set to hold a descriptive error message * explaining why the database could not be opened if there was an error. *

    * @return SQLiteDatabase|null a SQLiteDatabase object on success, null on error. */ function sqlite_factory($filename, $mode = null, &$error_message = null) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Encode binary data before returning it from an UDF * @link https://php.net/manual/en/function.sqlite-udf-encode-binary.php * @param string $data

    * The string being encoded. *

    * @return string The encoded string. */ function sqlite_udf_encode_binary($data) {} /** * (PHP 5, PECL sqlite >= 1.0.0)
    * Decode binary data passed as parameters to an UDF * @link https://php.net/manual/en/function.sqlite-udf-decode-binary.php * @param string $data

    * The encoded data that will be decoded, data that was applied by either * sqlite_udf_encode_binary or * sqlite_escape_string. *

    * @return string The decoded string. */ function sqlite_udf_decode_binary($data) {} /** * Return an array of column types from a particular table * @link https://php.net/manual/en/function.sqlite-fetch-column-types.php * @param string $table_name

    * The table name to query. *

    * @param resource $dbhandle

    The SQLite Database resource; returned from * {@see sqlite_open()} when used procedurally. * This parameter is not required when using the object-oriented method.

    * @param int $result_type [optional]

    * The optional result_type parameter accepts a * constant and determines how the returned array will be indexed. Using * SQLITE_ASSOC will return only associative indices * (named fields) while SQLITE_NUM will return only * numerical indices (ordinal field numbers). * SQLITE_BOTH will return both associative and * numerical indices. SQLITE_ASSOC is the default for * this function. *

    * @return array|false an array of column data types; false on error. */ function sqlite_fetch_column_types($dbhandle, $table_name, $result_type = null) {} /** * Columns are returned into the array having both a numerical index * and the field name as the array index. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_BOTH', 3); /** * 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/sqlite.constants.php */ define('SQLITE_NUM', 2); /** * Columns are returned into the array having the field name as the array * index. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_ASSOC', 1); /** * Successful result. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_OK', 0); /** * SQL error or missing database. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_ERROR', 1); /** * An internal logic error in SQLite. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_INTERNAL', 2); /** * Access permission denied. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_PERM', 3); /** * Callback routine requested an abort. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_ABORT', 4); /** * The database file is locked. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_BUSY', 5); /** * A table in the database is locked. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_LOCKED', 6); /** * Memory allocation failed. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_NOMEM', 7); /** * Attempt to write a readonly database. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_READONLY', 8); /** * Operation terminated internally. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_INTERRUPT', 9); /** * Disk I/O error occurred. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_IOERR', 10); /** * The database disk image is malformed. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_CORRUPT', 11); /** * (Internal) Table or record not found. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_NOTFOUND', 12); /** * Insertion failed because database is full. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_FULL', 13); /** * Unable to open the database file. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_CANTOPEN', 14); /** * Database lock protocol error. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_PROTOCOL', 15); /** * (Internal) Database table is empty. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_EMPTY', 16); /** * The database schema changed. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_SCHEMA', 17); /** * Too much data for one row of a table. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_TOOBIG', 18); /** * Abort due to constraint violation. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_CONSTRAINT', 19); /** * Data type mismatch. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_MISMATCH', 20); /** * Library used incorrectly. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_MISUSE', 21); /** * Uses of OS features not supported on host. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_NOLFS', 22); /** * Authorized failed. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_AUTH', 23); /** * File opened that is not a database file. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_NOTADB', 26); /** * Auxiliary database format error. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_FORMAT', 24); /** * Internal process has another row ready. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_ROW', 100); /** * Internal process has finished executing. * @link https://php.net/manual/en/sqlite.constants.php */ define('SQLITE_DONE', 101); 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() {} } '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 {} /** * @since 8.3 */ public function __debugInfo(): ?array {} } /** * 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 * Compiles and caches a PHP script without executing it * @link https://secure.php.net/manual/en/function.opcache-compile-file.php * @param string $filename The path to the PHP script to be compiled. * @return bool * Returns TRUE if the opcode cache for script was * invalidated or if there was nothing to invalidate, or FALSE if the opcode * cache is disabled. * @since 5.5 */ function opcache_compile_file(string $filename): bool {} /** * (PHP 5 >= 5.5.0, PECL ZendOpcache >= 7.0.0 )
    * Invalidates a cached script * @link https://secure.php.net/manual/en/function.opcache-invalidate.php * @param string $filename

    The path to the script being invalidated.

    * @param bool $force [optional]

    If set to TRUE, the script will be invalidated regardless of whether invalidation is necessary.

    * @return bool * Returns TRUE if the opcode cache for script was * invalidated or if there was nothing to invalidate, or FALSE if the opcode * cache is disabled. * @since 5.5 */ function opcache_invalidate(string $filename, bool $force = false): bool {} /** * (PHP 5 >= 5.5.0, PECL ZendOpcache >= 7.0.0 )
    * Resets the contents of the opcode cache * @link https://secure.php.net/manual/en/function.opcache-reset.php * @return bool Returns TRUE if the opcode cache was reset, or FALSE if the opcode cache is disabled. * @since 5.5 */ function opcache_reset(): bool {} /** * (PHP 5 >= 5.5.5, PECL ZendOpcache >= 7.0.2 )
    * Get status information about the cache * @link https://php.net/manual/en/function.opcache-get-status.php * @param bool $include_scripts

    Include script specific state information

    * @return array|false

    Returns an array of information, optionally containing script specific state information

    * @since 5.5 */ #[ArrayShape([ 'opcache_enabled' => 'bool', 'file_cache' => 'string', 'file_cache_only' => 'bool', 'cache_full' => 'bool', 'restart_pending' => 'bool', 'restart_in_progress' => 'bool', 'memory_usage' => 'array', 'interned_strings_usage' => 'array', 'opcache_statistics' => 'array', 'preload_statistics' => 'array', 'scripts' => 'array', 'jit' => 'array', ])] function opcache_get_status(bool $include_scripts = true): array|false {} /** * (PHP 5 >= 5.5.5, PECL ZendOpcache >= 7.0.2 )
    * Get configuration information about the cache * @link https://php.net/manual/en/function.opcache-get-configuration.php * @return array|false

    Returns an array of information, including ini, blacklist and version

    * @since 5.5 */ #[ArrayShape(["directives" => "array", "version" => "string[]", "blacklist" => "array"])] function opcache_get_configuration(): array|false {} /** * (PHP 5 >= 5.6, PECL ZendOpcache >= 7.0.4 )
    * This function checks if a PHP script has been cached in OPCache. * This can be used to more easily detect the "warming" of the cache for a particular script. * @link https://secure.php.net/manual/en/function.opcache-is-script-cached.php * @param string $filename The path to the PHP script to be checked. * @return bool Returns TRUE if file is cached in OPCache, FALSE otherwise. * @since 5.6 */ function opcache_is_script_cached(string $filename): bool {} /** * @since 8.4 */ function opcache_jit_blacklist(Closure $closure): void {} /** * @since 8.5 */ function opcache_is_script_cached_in_file_cache(string $filename): bool {} * @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 ] ) */ } 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|null $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|null $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|null $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 = null, 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|null $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 = null, 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|null $exchangeName Optional name of exchange to delete. * @param int|null $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 = null) {} /** * 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 bool|int|float|string|null $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 void */ 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|null $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|null $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 void */ 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 void */ 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|null $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 = null) {} /** * 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|null $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|null $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 void */ public function nack($deliveryTag, $flags = null) {} /** * 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 void */ 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 void */ public function setFlags($flags = null) {} /** * Set the queue name. * * @param string $name The name of the queue. * * @return void */ 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 void */ 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 {} TRUE if PHP is running as an Apache 1 module, the Apache version is non-multithreaded, and the child_terminate PHP directive is enabled (disabled by default). If these conditions are not met, FALSE is returned and an error of level E_WARNING is generated. */ function apache_child_terminate() {} /** * Get a list of loaded Apache modules * @link https://php.net/manual/en/function.apache-get-modules.php * @return array of loaded Apache modules. */ #[Pure] function apache_get_modules() {} /** * Fetch the Apache version * @link https://php.net/manual/en/function.apache-get-version.php * @return string|false the Apache version on success or FALSE on failure. */ #[Pure] function apache_get_version() {} /** * Get an Apache subprocess_env variable * Retrieve an Apache environment variable specified by $variable. * This function requires Apache 2 otherwise it's undefined. * @link https://php.net/manual/en/function.apache-getenv.php * @param string $variable

    * The Apache environment variable. *

    * @param bool $walk_to_top

    * Whether to get the top-level variable available to all Apache layers. *

    * @return string|false The value of the Apache environment variable on success, or FALSE on failure. */ #[Pure] function apache_getenv($variable, $walk_to_top = false) {} /** * Perform a partial request for the specified URI and return all info about it * This performs a partial request for a URI. It goes just far enough to obtain all the important information about the given resource. * This function is supported when PHP is installed as an Apache module or by the NSAPI server module in Netscape/iPlanet/SunONE webservers. * @link https://php.net/manual/en/function.apache-lookup-uri.php * @param string $filename

    * The filename (URI) that's being requested. *

    * @return object of related URI information. */ function apache_lookup_uri($filename) {} /** * Get and set apache request notes * This function is a wrapper for Apache's table_get and table_set. It edits the table of notes that exists during a request. The table's purpose is to allow Apache modules to communicate. * The main use for apache_note() is to pass information from one module to another within the same request. * @link https://php.net/manual/en/function.apache-note.php * @param string $note_name

    * The name of the note. *

    * @param string $note_value

    * The value of the note. *

    * @return string|false If called with one argument, it returns the current value of note note_name. If called with two arguments, it sets the value of note note_name to note_value and returns the previous value of note note_name. If the note cannot be retrieved, FALSE is returned. */ function apache_note($note_name, $note_value = '') {} /** * Reset the Apache write timer * apache_reset_timeout() resets the Apache write timer, which defaults to 300 seconds. With set_time_limit(0); ignore_user_abort(true) and periodic apache_reset_timeout() calls, Apache can theoretically run forever. * This function requires Apache 1. * @link https://php.net/manual/en/function.apache-reset-timeout.php * @return bool TRUE on success or FALSE on failure. */ function apache_reset_timeout() {} /** * Fetch all HTTP response headers * @link https://php.net/manual/en/function.apache-response-headers.php * @return array|false An array of all Apache response headers on success or FALSE on failure. */ function apache_response_headers() {} /** * Sets the value of the Apache environment variable specified by variable. * Note: When setting an Apache environment variable, the corresponding $_SERVER variable is not changed. * @link https://php.net/manual/en/function.apache-setenv.php * @param string $variable

    * The environment variable that's being set. *

    * @param string $value

    * The new variable value. *

    * @param bool $walk_to_top

    * Whether to set the top-level variable available to all Apache layers. *

    * @return bool TRUE on success or FALSE on failure. */ function apache_setenv($variable, $value, $walk_to_top = false) {} /** * Perform an Apache sub-request * virtual() is an Apache-specific function which is similar to in mod_include. It performs an Apache sub-request. It is useful for including CGI scripts or .shtml files, or anything else that you would parse through Apache. Note that for a CGI script, the script must generate valid CGI headers. At the minimum that means it must generate a Content-Type header. * To run the sub-request, all buffers are terminated and flushed to the browser, pending headers are sent too. * This function is supported when PHP is installed as an Apache module or by the NSAPI server module in Netscape/iPlanet/SunONE webservers. * @link https://secure.php.net/manual/en/function.virtual.php * @param string $filename

    * The file that the virtual command will be performed on. *

    * @return bool Performs the virtual command on success, or returns FALSE on failure. */ function virtual($filename) {} 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() {} } ] value) {stmts} (children: expr, value, key, stmts) */ const AST_FOREACH = 1025; /** A global function declaration. (children: name, docComment, params, stmts, returnType, __declId) */ const AST_FUNC_DECL = 67; /** A usage of a global variable of the form `global var`. (children: var) */ const AST_GLOBAL = 277; /** A goto statement of the form `goto label;` (children: label) */ const AST_GOTO = 285; /** A use statement (for classes, namespaces, functions, and/or constants) containing a list of one or more elements. (children: prefix, uses) */ const AST_GROUP_USE = 545; /** A `__halt_compiler;` statement. (children: offset) */ const AST_HALT_COMPILER = 282; /** A list of `ast\AST_IF_ELEM` nodes for a chain of 1 or more `if`/`elseif`/`else` statements (numerically indexed children) */ const AST_IF = 133; /** An `if`/`elseif`/`elseif` statement of the form `if (cond) stmts` (children: cond, stmts) */ const AST_IF_ELEM = 535; /** An `include*(expr)`, `require*(expr)`, or `eval(expr)` statement. The type can be determined from the flags (`ast\flags\EXEC_*`). (children: expr) */ const AST_INCLUDE_OR_EVAL = 269; /** An `expr instanceof class` expression. (children: expr, class) */ const AST_INSTANCEOF = 528; /** An `isset(var)` expression. (children: var) */ const AST_ISSET = 263; /** A `name:` expression (a target for `goto name`). (children: name) */ const AST_LABEL = 280; /** Used for `list() = ` unpacking, etc. Predates AST version 50. (numerically indexed children) */ const AST_LIST = 255; /** A magic constant (depends on flags that are one of `ast\flags\MAGIC_*`) */ const AST_MAGIC_CONST = 0; /** A match expression of the form `match(cond) { stmts }` (children: cond, stmts) */ const AST_MATCH = 548; /** An arm of a match expression of the form `cond => expr` (children: cond, expr) */ const AST_MATCH_ARM = 549; /** Numerically indexed children of the kind `ast\AST_MATCH_ARM` for the statements of a match expression */ const AST_MATCH_ARM_LIST = 147; /** A method declaration. (children: name, docComment, params, stmts, returnType, __declId) */ const AST_METHOD = 69; /** An invocation of an instance method, of the form `expr->method(args)` (children: expr, method, args) */ const AST_METHOD_CALL = 768; /** A reference to a method when using a trait inside a class declaration. (children: class, method) */ const AST_METHOD_REFERENCE = 541; /** A name token (e.g. of a constant/class/class type) (children: name) */ const AST_NAME = 2048; /** A named argument in an argument list of a function/method call. (children: name, expr) */ const AST_NAMED_ARG = 550; /** A namespace declaration of the form `namespace name;` or `namespace name { stmts }`. (children: name, stmts) */ const AST_NAMESPACE = 542; /** A list of names (e.g. for catching multiple classes in a `catch` statement) (numerically indexed children) */ const AST_NAME_LIST = 141; /** An object creation expression of the form `new class(args)` (children: class, args) */ const AST_NEW = 527; /** A nullable node with a child node of kind `ast\AST_TYPE` or `ast\AST_NAME` (children: type) */ const AST_NULLABLE_TYPE = 2050; /** A nullsafe method call of the form `expr?->method(args)`. (children: expr, method, args) */ const AST_NULLSAFE_METHOD_CALL = 769; /** A nullsafe property read of the form `expr?->prop`. (children: expr, prop) */ const AST_NULLSAFE_PROP = 514; /** A parameter of a function, closure, or method declaration. (children: type, name, default) */ const AST_PARAM = 1280; /** The list of parameters of a function, closure, or method declaration. (numerically indexed children) */ const AST_PARAM_LIST = 136; /** A `var--` expression. (children: var) */ const AST_POST_DEC = 274; /** A `var++` expression. (children: var) */ const AST_POST_INC = 273; /** A `--var` expression. (children: var) */ const AST_PRE_DEC = 272; /** A `++var` expression. (children: var) */ const AST_PRE_INC = 271; /** A `print expr` expression. (children: expr) */ const AST_PRINT = 268; /** An instance property usage of the form `expr->prop` (children: expr, prop) */ const AST_PROP = 513; /** A single group of property declarations inside a class. (numerically indexed children) */ const AST_PROP_DECL = 138; /** A class property declaration. (children: name, default, docComment) */ const AST_PROP_ELEM = 775; /** A class property group declaration with optional type information for the group (in PHP 7.4+). Used in AST version 70+ (children: type, props, __declId) */ const AST_PROP_GROUP = 774; /** Used for `&$v` in `foreach ($a as &$v)` (children: var) */ const AST_REF = 281; /** A `return;` or `return expr` statement. (children: expr) */ const AST_RETURN = 279; /** A `\`some_shell_command\`` expression. (children: expr) */ const AST_SHELL_EXEC = 265; /** A declaration of a static local variable of the form `static var = default`. (children: var, default) */ const AST_STATIC = 532; /** A call of a static method, of the form `class::method(args)`. (children: class, method, args) */ const AST_STATIC_CALL = 770; /** A usage of a static property, of the form `class::prop`. (children: class, prop) */ const AST_STATIC_PROP = 515; /** A list of statements. The statements are usually nodes but can be non-nodes, e.g. `;2;`. (numerically indexed children) */ const AST_STMT_LIST = 132; /** A switch statement of the form `switch(cond) { stmts }`. `stmts` is a node of the kind `ast\AST_SWITCH_LIST`. (children: cond, stmts) */ const AST_SWITCH = 536; /** A case statement of a switch, of the form `case cond: stmts` (children: cond, stmts) */ const AST_SWITCH_CASE = 537; /** The full list of nodes inside a switch statement body, each of kind `ast\AST_SWITCH_CASE`. (numerically indexed children) */ const AST_SWITCH_LIST = 134; /** A throw statement of the form `throw expr;` (children: expr) */ const AST_THROW = 284; /** The optional adaptations to a statement using a trait inside a class (numerically indexed children) */ const AST_TRAIT_ADAPTATIONS = 142; /** Adds an alias inside of a use of a trait (`method as alias`) (children: method, alias) */ const AST_TRAIT_ALIAS = 544; /** Indicates the precedent of a trait over another trait (`method INSTEADOF insteadof`) (children: method, insteadof) */ const AST_TRAIT_PRECEDENCE = 540; /** A try/catch(es)/finally block. (children: try, catches, finally) */ const AST_TRY = 772; /** A type such as `bool`. Other types such as specific classes are represented as `ast\AST_NAME`s (depends on flags of `ast\flags\TYPE_*`) */ const AST_TYPE = 1; /** A union type made up of individual types, such as `bool|int` (numerically indexed children) */ const AST_TYPE_UNION = 144; /** A unary operation of the form `op expr` (e.g. `-expr`, the flags can be one of `ast\flags\UNARY_*`) (children: expr) */ const AST_UNARY_OP = 270; /** An expression unpacking an array/iterable (i.e. `...expr`) (children: expr) */ const AST_UNPACK = 258; /** `unset(var)` - A statement unsetting the expression `var` (children: var) */ const AST_UNSET = 278; /** A list of uses of classes/namespaces, functions, and constants. The child nodes are of the kind `ast\AST_USE_ELEM` (numerically indexed children) */ const AST_USE = 143; /** A single use statement for a group of (children: name, alias) */ const AST_USE_ELEM = 543; /** Represents `use traits {[adaptations]}` within a class declaration (children: traits, adaptations) */ const AST_USE_TRAIT = 539; /** An occurrence of a variable `$name` or `${name}`. (children: name) */ const AST_VAR = 256; /** A while loop of the form `while (cond) { stmts }` (children: cond, stmts) */ const AST_WHILE = 533; /** An expression of the form `yield [key =>] value` (children: value, key) */ const AST_YIELD = 529; /** An expression of the form `yield from expr` (children: expr) */ const AST_YIELD_FROM = 275; } namespace ast\flags { /** Marks an `ast\AST_ARRAY_ELEM` as a reference */ const ARRAY_ELEM_REF = 1; /** Marks an `ast\AST_ARRAY` as using the `list(...)` syntax */ const ARRAY_SYNTAX_LIST = 1; /** Marks an `ast\AST_ARRAY` as using the `array(...)` syntax */ const ARRAY_SYNTAX_LONG = 2; /** Marks an `ast\AST_ARRAY` as using the `[...]` syntax */ const ARRAY_SYNTAX_SHORT = 3; /** Marks an ast\AST_BINARY_OP as being a `+` */ const BINARY_ADD = 1; /** Marks an ast\AST_BINARY_OP as being a `&` */ const BINARY_BITWISE_AND = 10; /** Marks an ast\AST_BINARY_OP as being a `|` */ const BINARY_BITWISE_OR = 9; /** Marks an ast\AST_BINARY_OP as being a `^` */ const BINARY_BITWISE_XOR = 11; /** Marks an ast\AST_BINARY_OP as being a `&&` or `and` */ const BINARY_BOOL_AND = 259; /** Marks an ast\AST_BINARY_OP as being a `||` or `or` */ const BINARY_BOOL_OR = 258; /** Marks an ast\AST_BINARY_OP as being an `xor` */ const BINARY_BOOL_XOR = 15; /** Marks an ast\AST_BINARY_OP as being a `??` */ const BINARY_COALESCE = 260; /** Marks an ast\AST_BINARY_OP as being a `.` */ const BINARY_CONCAT = 8; /** Marks an ast\AST_BINARY_OP as being a `/` */ const BINARY_DIV = 4; /** Marks an ast\AST_BINARY_OP as being a `==` */ const BINARY_IS_EQUAL = 18; /** Marks an ast\AST_BINARY_OP as being a `>` */ const BINARY_IS_GREATER = 256; /** Marks an ast\AST_BINARY_OP as being a `>=` */ const BINARY_IS_GREATER_OR_EQUAL = 257; /** Marks an ast\AST_BINARY_OP as being a `===` */ const BINARY_IS_IDENTICAL = 16; /** Marks an ast\AST_BINARY_OP as being a `!=` */ const BINARY_IS_NOT_EQUAL = 19; /** Marks an ast\AST_BINARY_OP as being a `!==` */ const BINARY_IS_NOT_IDENTICAL = 17; /** Marks an ast\AST_BINARY_OP as being a `<` */ const BINARY_IS_SMALLER = 20; /** Marks an ast\AST_BINARY_OP as being a `<=` */ const BINARY_IS_SMALLER_OR_EQUAL = 21; /** Marks an ast\AST_BINARY_OP as being a `%` */ const BINARY_MOD = 5; /** Marks an ast\AST_BINARY_OP as being a `*` */ const BINARY_MUL = 3; /** Marks an ast\AST_BINARY_OP as being a `**` */ const BINARY_POW = 12; /** Marks an ast\AST_BINARY_OP as being a `<<` */ const BINARY_SHIFT_LEFT = 6; /** Marks an ast\AST_BINARY_OP as being a `>>` */ const BINARY_SHIFT_RIGHT = 7; /** Marks an ast\AST_BINARY_OP as being a `<=>` */ const BINARY_SPACESHIP = 170; /** Marks an ast\AST_BINARY_OP as being a `-` */ const BINARY_SUB = 2; /** Marks a `ast\AST_CLASS` (class-like declaration) as being abstract */ const CLASS_ABSTRACT = 64; /** Marks a `ast\AST_CLASS` (class-like declaration) as being anonymous */ const CLASS_ANONYMOUS = 4; /** Marks a `ast\AST_CLASS` (class-like declaration) as being final */ const CLASS_FINAL = 32; /** Marks a `ast\AST_CLASS` (class-like declaration) as being an interface */ const CLASS_INTERFACE = 1; /** Marks a `ast\AST_CLASS` (class-like declaration) as being a trait */ const CLASS_TRAIT = 2; /** Marks an `ast\AST_CLOSURE_USE` as using a variable by reference */ const CLOSURE_USE_REF = 1; /** Marks an `ast\AST_DIM` as using the alternative `expr{dim}` syntax */ const DIM_ALTERNATIVE_SYNTAX = 2; /** Marks an `ast\AST_EXEC` as being an `eval(...)` */ const EXEC_EVAL = 1; /** Marks an `ast\AST_EXEC` as being an `include` */ const EXEC_INCLUDE = 2; /** Marks an `ast\AST_EXEC` as being an `include_once` */ const EXEC_INCLUDE_ONCE = 4; /** Marks an `ast\AST_EXEC` as being a `require` */ const EXEC_REQUIRE = 8; /** Marks an `ast\AST_EXEC` as being a `require_once` */ const EXEC_REQUIRE_ONCE = 16; /** Marks an `ast\AST_FUNC_DECL` as being a generator */ const FUNC_GENERATOR = 16777216; /** Marks an `ast\AST_FUNC_DECL` as returning a value by reference */ const FUNC_RETURNS_REF = 4096; /** Marks an `ast\AST_MAGIC_CONST` as being `__CLASS__` */ const MAGIC_CLASS = 378; /** Marks an `ast\AST_MAGIC_CONST` as being `__DIR__` */ const MAGIC_DIR = 377; /** Marks an `ast\AST_MAGIC_CONST` as being `__FILE__` */ const MAGIC_FILE = 376; /** Marks an `ast\AST_MAGIC_CONST` as being `__FUNCTION__` */ const MAGIC_FUNCTION = 381; /** Marks an `ast\AST_MAGIC_CONST` as being `__LINE__` */ const MAGIC_LINE = 375; /** Marks an `ast\AST_MAGIC_CONST` as being `__METHOD__` */ const MAGIC_METHOD = 380; /** Marks an `ast\AST_MAGIC_CONST` as being `__NAMESPACE__` */ const MAGIC_NAMESPACE = 382; /** Marks an `ast\AST_MAGIC_CONST` as being `__TRAIT__` */ const MAGIC_TRAIT = 379; /** Marks an element declaration as being `abstract` */ const MODIFIER_ABSTRACT = 64; /** Marks an element declaration as being `final` */ const MODIFIER_FINAL = 32; /** Marks an element declaration as being `private` */ const MODIFIER_PRIVATE = 4; /** Marks an element declaration as being `protected` */ const MODIFIER_PROTECTED = 2; /** Marks an element declaration as being `public` */ const MODIFIER_PUBLIC = 1; /** Marks an element declaration as being `static` */ const MODIFIER_STATIC = 16; /** Marks an `ast\AST_NAME` as being fully qualified (`\Name`) */ const NAME_FQ = 0; /** Marks an `ast\AST_NAME` as being not fully qualified (`Name`) */ const NAME_NOT_FQ = 1; /** Marks an `ast\AST_NAME` as being relative to the current namespace (`namespace\Name`) */ const NAME_RELATIVE = 2; /** Marks a promoted constructor property as being `private` */ const PARAM_MODIFIER_PRIVATE = 4; /** Marks a promoted constructor property as being `protected` */ const PARAM_MODIFIER_PROTECTED = 2; /** Marks a promoted constructor property as being `public` */ const PARAM_MODIFIER_PUBLIC = 1; /** Marks an `ast\AST_PARAM` as being a reference (`&$x`) */ const PARAM_REF = 8; /** Marks an `ast\AST_PARAM` as being variadic (`...$x`) */ const PARAM_VARIADIC = 16; /** Marks a `ast\AST_CONDITIONAL` as being parenthesized (`(cond ? true : false)`) */ const PARENTHESIZED_CONDITIONAL = 1; /** Marks a function-like as returning an argument by reference */ const RETURNS_REF = 4096; /** Marks an `ast\AST_TYPE` as being `array` */ const TYPE_ARRAY = 7; /** Marks an `ast\AST_TYPE` as being `bool` */ const TYPE_BOOL = 17; /** Marks an `ast\AST_TYPE` as being `callable` */ const TYPE_CALLABLE = 12; /** Marks an `ast\AST_TYPE` as being `float` */ const TYPE_DOUBLE = 5; /** Marks an `ast\AST_TYPE` as being `false` (for union types) */ const TYPE_FALSE = 2; /** Marks an `ast\AST_TYPE` as being `iterable` */ const TYPE_ITERABLE = 13; /** Marks an `ast\AST_TYPE` as being `int` */ const TYPE_LONG = 4; /** Marks an `ast\AST_TYPE` as being `mixed` */ const TYPE_MIXED = 16; /** Marks an `ast\AST_TYPE` as being `null` (for union types) */ const TYPE_NULL = 1; /** Marks an `ast\AST_TYPE` as being `object` */ const TYPE_OBJECT = 8; /** Marks an `ast\AST_TYPE` as being `static` (for return types) */ const TYPE_STATIC = 15; /** Marks an `ast\AST_TYPE` as being `string` */ const TYPE_STRING = 6; /** Marks an `ast\AST_TYPE` as being `void` (for return types) */ const TYPE_VOID = 14; /** Marks an `ast\AST_UNARY_OP` as being `~expr` */ const UNARY_BITWISE_NOT = 13; /** Marks an `ast\AST_UNARY_OP` as being `!expr` */ const UNARY_BOOL_NOT = 14; /** Marks an `ast\AST_UNARY_OP` as being `-expr` */ const UNARY_MINUS = 262; /** Marks an `ast\AST_UNARY_OP` as being `+expr` */ const UNARY_PLUS = 261; /** Marks an `ast\AST_UNARY_OP` as being `@expr` */ const UNARY_SILENCE = 260; /** Marks an `ast\AST_USE` or `ast\AST_GROUP_USE` (namespace use statement) as being `use const name;` */ const USE_CONST = 4; /** Marks an `ast\AST_USE` or `ast\AST_GROUP_USE` (namespace use statement) as being `use function name;` */ const USE_FUNCTION = 2; /** Marks an `ast\AST_USE` or `ast\AST_GROUP_USE` (namespace use statement) as being `use name;` */ const USE_NORMAL = 1; } * The left operand, as a string. *

    * @param string $num2

    * The right operand, as a string. *

    * @param int|null $scale

    * This optional parameter is used to set the number of digits after the * decimal place in the result. If omitted, it will default to the scale * set globally with the {@link bcscale()} function, or fallback to 0 if * this has not been set. *

    * @return string The sum of the two operands, as a string. */ #[Pure] function bcadd(string $num1, string $num2, ?int $scale = null): string {} /** * Subtract one arbitrary precision number from another * @link https://php.net/manual/en/function.bcsub.php * @param string $num1

    * The left operand, as a string. *

    * @param string $num2

    * The right operand, as a string. *

    * @param int|null $scale

    * This optional parameter is used to set the number of digits after the * decimal place in the result. If omitted, it will default to the scale * set globally with the {@link bcscale()} function, or fallback to 0 if * this has not been set. *

    * @return string The result of the subtraction, as a string. */ #[Pure] function bcsub(string $num1, string $num2, ?int $scale = null): string {} /** * Multiply two arbitrary precision numbers * @link https://php.net/manual/en/function.bcmul.php * @param string $num1

    * The left operand, as a string. *

    * @param string $num2

    * The right operand, as a string. *

    * @param int|null $scale

    * This optional parameter is used to set the number of digits after the * decimal place in the result. If omitted, it will default to the scale * set globally with the {@link bcscale()} function, or fallback to 0 if * this has not been set. *

    * @return string the result as a string. */ #[Pure] function bcmul(string $num1, string $num2, ?int $scale = null): string {} /** * Divide two arbitrary precision numbers * @link https://php.net/manual/en/function.bcdiv.php * @param string $num1

    * The dividend, as a string. *

    * @param string $num2

    * The divisor, as a string. *

    * @param int|null $scale [optional]

    * This optional parameter is used to set the number of digits after the * decimal place in the result. If omitted, it will default to the scale * set globally with the {@link bcscale()} function, or fallback to 0 if * this has not been set. *

    * @return string|null the result of the division as a string, or NULL if * divisor is 0. */ #[Pure] #[PhpStormStubsElementAvailable(to: '7.4')] function bcdiv(string $num1, string $num2, ?int $scale = 0): ?string {} /** * Divide two arbitrary precision numbers * @link https://php.net/manual/en/function.bcdiv.php * @param string $num1

    * The dividend, as a string. *

    * @param string $num2

    * The divisor, as a string. *

    * @param int|null $scale [optional]

    * This optional parameter is used to set the number of digits after the * decimal place in the result. If omitted, it will default to the scale * set globally with the {@link bcscale()} function, or fallback to 0 if * this has not been set. *

    * @return string the result of the division as a string. * @throws \DivisionByZeroError if divisor is 0. Available since PHP 8.0. */ #[Pure] #[PhpStormStubsElementAvailable('8.0')] function bcdiv(string $num1, string $num2, ?int $scale = null): string {} /** * Get modulus of an arbitrary precision number * @link https://php.net/manual/en/function.bcmod.php * @param string $num1

    * The dividend, as a string. Since PHP 7.2, the divided is no longer truncated to an integer. *

    * @param string $num2

    * The divisor, as a string. Since PHP 7.2, the divisor is no longer truncated to an integer. *

    * @param int|null $scale [optional]

    * This optional parameter is used to set the number of digits after the * decimal place in the result. If omitted, it will default to the scale * set globally with the {@link bcscale()} function, or fallback to 0 if * this has not been set. Available since PHP 7.2. *

    * @return string|null the modulus as a string, or NULL if * divisor is 0. */ #[Pure] #[PhpStormStubsElementAvailable(to: '7.4')] function bcmod(string $num1, string $num2, ?int $scale = 0): ?string {} /** * Get modulus of an arbitrary precision number * @link https://php.net/manual/en/function.bcmod.php * @param string $num1

    * The dividend, as a string. Since PHP 7.2, the divided is no longer truncated to an integer. *

    * @param string $num2

    * The divisor, as a string. Since PHP 7.2, the divisor is no longer truncated to an integer. *

    * @param int|null $scale [optional]

    * This optional parameter is used to set the number of digits after the * decimal place in the result. If omitted, it will default to the scale * set globally with the {@link bcscale()} function, or fallback to 0 if * this has not been set. Available since PHP 7.2. *

    * @return string the modulus as a string. * @throws \DivisionByZeroError if divisor is 0. Available since PHP 8.0. */ #[Pure] #[PhpStormStubsElementAvailable('8.0')] function bcmod(string $num1, string $num2, ?int $scale = null): string {} /** * Raise an arbitrary precision number to another * @link https://php.net/manual/en/function.bcpow.php * @param string $num

    * The base, as a string. *

    * @param string $exponent

    * The exponent, as a string. If the exponent is non-integral, it is truncated. * The valid range of the exponent is platform specific, but is at least * -2147483648 to 2147483647. *

    * @param int|null $scale

    * This optional parameter is used to set the number of digits after the * decimal place in the result. If omitted, it will default to the scale * set globally with the {@link bcscale()} function, or fallback to 0 if * this has not been set. *

    * @return string the result as a string. */ #[Pure] function bcpow(string $num, string $exponent, ?int $scale = null): string {} /** * Get the square root of an arbitrary precision number * @link https://php.net/manual/en/function.bcsqrt.php * @param string $num

    * The operand, as a string. *

    * @param int|null $scale [optional] * @return string|null the square root as a string, or NULL if * operand is negative. */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "string"], default: "string|null")] function bcsqrt(string $num, ?int $scale = null) {} /** * Set default scale parameter for all bc math functions * @link https://php.net/manual/en/function.bcscale.php * @param int $scale * @return int|bool */ #[LanguageLevelTypeAware(['7.3' => 'int'], default: 'bool')] function bcscale( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.2')] int $scale, #[PhpStormStubsElementAvailable(from: '7.3')] #[LanguageLevelTypeAware(['8.0' => 'int|null'], default: 'int')] $scale = null ) {} /** * Compare two arbitrary precision numbers * @link https://php.net/manual/en/function.bccomp.php * @param string $num1

    * The left operand, as a string. *

    * @param string $num2

    * The right operand, as a string. *

    * @param int|null $scale

    * The optional scale parameter is used to set the * number of digits after the decimal place which will be used in the * comparison. *

    * @return int 0 if the two operands are equal, 1 if the * left_operand is larger than the * right_operand, -1 otherwise. */ #[Pure] function bccomp(string $num1, string $num2, ?int $scale = null): int {} /** * Raise an arbitrary precision number to another, reduced by a specified modulus * @link https://php.net/manual/en/function.bcpowmod.php * @param string $num

    * The base, as an integral string (i.e. the scale has to be zero). *

    * @param string $exponent

    * The exponent, as an non-negative, integral string (i.e. the scale has to be * zero). *

    * @param string $modulus

    * The modulus, as an integral string (i.e. the scale has to be zero). *

    * @param int|null $scale

    * This optional parameter is used to set the number of digits after the * decimal place in the result. If omitted, it will default to the scale * set globally with the {@link bcscale()} function, or fallback to 0 if * this has not been set. *

    * @return string|null the result as a string, or NULL if modulus * is 0 or exponent is negative. */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "string"], default: "string|null")] function bcpowmod(string $num, string $exponent, string $modulus, ?int $scale = null) {} /** * @since 8.4 */ function bcfloor(string $num): string {} /** * @since 8.4 */ function bcceil(string $num): string {} /** * @since 8.4 */ function bcround(string $num, int $precision = 0, RoundingMode $mode = RoundingMode::HalfAwayFromZero): string {} /** * @return string[] */ function bcdivmod(string $num1, string $num2, ?int $scale = null): array {} } namespace BcMath { /** * @since 8.4 */ final readonly class Number implements \Stringable { /** @var numeric-string */ public readonly string $value; public readonly int $scale; /** * @param int|numeric-string $num * @throws \ValueError */ public function __construct(string|int $num) {} /** * @param Number|int|numeric-string $num * @throws \ValueError */ public function add(Number|string|int $num, ?int $scale = null): Number {} /** * @param Number|int|numeric-string $num * @throws \ValueError */ public function sub(Number|string|int $num, ?int $scale = null): Number {} /** * @param Number|int|numeric-string $num * @throws \ValueError */ public function mul(Number|string|int $num, ?int $scale = null): Number {} /** * @param Number|int|numeric-string $num * @throws \DivisionByZeroError * @throws \ValueError */ public function div(Number|string|int $num, ?int $scale = null): Number {} /** * @param Number|int|numeric-string $num * @throws \DivisionByZeroError * @throws \ValueError */ public function mod(Number|string|int $num, ?int $scale = null): Number {} /** * @param Number|int|numeric-string $num * @return array{Number, Number} * @throws \DivisionByZeroError * @throws \ValueError */ public function divmod(Number|string|int $num, ?int $scale = null): array {} /** * @param Number|int|numeric-string $exponent * @param Number|int|numeric-string $modulus * @throws \DivisionByZeroError * @throws \ValueError */ public function powmod(Number|string|int $exponent, Number|string|int $modulus, ?int $scale = null): Number {} /** * @param Number|int|numeric-string $exponent * @throws \DivisionByZeroError * @throws \ValueError */ public function pow(Number|string|int $exponent, ?int $scale = null): Number {} /** @throws \ValueError */ public function sqrt(?int $scale = null): Number {} public function floor(): Number {} public function ceil(): Number {} /** @throws \ValueError */ public function round(int $precision = 0, \RoundingMode $mode = \RoundingMode::HalfAwayFromZero): Number {} /** * @param Number|int|numeric-string $num * @return int Returns -1, 0, or 1 * @throws \ValueError */ public function compare(Number|string|int $num, ?int $scale = null): int {} public function __toString(): string {} /** @return array{value:numeric-string} */ public function __serialize(): array {} /** @param array{value:numeric-string} $data */ public function __unserialize(array $data): void {} } } * 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 = null): 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.0' => 'int|false', '8.1' => 'int'], default: 'int')] function bzerrno($bz): int {} /** * 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.0' => 'string|false', '8.1' => 'string'], default: 'string')] function bzerrstr($bz): string {} /** * 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] #[ArrayShape(["errno" => "int", "errstr" => "string"])] #[LanguageLevelTypeAware(['8.0' => 'array|false', '8.1' => 'array'], default: 'array')] function bzerror($bz): array {} /** * 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 {} * A julian day number as integer *

    * @return string The gregorian date as a string in the form "month/day/year" */ function jdtogregorian(int $julian_day): string {} /** * Converts a Gregorian date to Julian Day Count * @link https://php.net/manual/en/function.gregoriantojd.php * @param int $month

    * The month as a number from 1 (for January) to 12 (for December) *

    * @param int $day

    * The day as a number from 1 to 31 *

    * @param int $year

    * The year as a number between -4714 and 9999 *

    * @return int The julian day for the given gregorian date as an integer. */ function gregoriantojd(int $month, int $day, int $year): int {} /** * Converts a Julian Day Count to a Julian Calendar Date * @link https://php.net/manual/en/function.jdtojulian.php * @param int $julian_day

    * A julian day number as integer *

    * @return string The julian date as a string in the form "month/day/year" */ function jdtojulian(int $julian_day): string {} /** * Converts a Julian Calendar date to Julian Day Count * @link https://php.net/manual/en/function.juliantojd.php * @param int $month

    * The month as a number from 1 (for January) to 12 (for December) *

    * @param int $day

    * The day as a number from 1 to 31 *

    * @param int $year

    * The year as a number between -4713 and 9999 *

    * @return int The julian day for the given julian date as an integer. */ function juliantojd(int $month, int $day, int $year): int {} /** * Converts a Julian day count to a Jewish calendar date * @link https://php.net/manual/en/function.jdtojewish.php * @param int $julian_day * @param bool $hebrew [optional]

    * If the hebrew parameter is set to TRUE, the * fl parameter is used for Hebrew, string based, * output format. *

    * @param int $flags [optional]

    * The available formats are: * CAL_JEWISH_ADD_ALAFIM_GERESH, * CAL_JEWISH_ADD_ALAFIM, * CAL_JEWISH_ADD_GERESHAYIM. *

    * @return string The jewish date as a string in the form "month/day/year" */ function jdtojewish(int $julian_day, bool $hebrew = false, int $flags = 0): string {} /** * Converts a date in the Jewish Calendar to Julian Day Count * @link https://php.net/manual/en/function.jewishtojd.php * @param int $month

    * The month as a number from 1 to 13 *

    * @param int $day

    * The day as a number from 1 to 30 *

    * @param int $year

    * The year as a number between 1 and 9999 *

    * @return int The julian day for the given jewish date as an integer. */ function jewishtojd(int $month, int $day, int $year): int {} /** * Converts a Julian Day Count to the French Republican Calendar * @link https://php.net/manual/en/function.jdtofrench.php * @param int $julian_day * @return string The french revolution date as a string in the form "month/day/year" */ function jdtofrench(int $julian_day): string {} /** * Converts a date from the French Republican Calendar to a Julian Day Count * @link https://php.net/manual/en/function.frenchtojd.php * @param int $month

    * The month as a number from 1 (for Vendémiaire) to 13 (for the period of 5-6 days at the end of each year) *

    * @param int $day

    * The day as a number from 1 to 30 *

    * @param int $year

    * The year as a number between 1 and 14 *

    * @return int The julian day for the given french revolution date as an integer. */ function frenchtojd(int $month, int $day, int $year): int {} /** * Returns the day of the week * @link https://php.net/manual/en/function.jddayofweek.php * @param int $julian_day

    * A julian day number as integer *

    * @param int $mode [optional] * Calendar week modes * * * * * * * * * * * * * * * * *
    ModeMeaning
    0 (Default) * Return the day number as an int (0=Sunday, 1=Monday, etc) *
    1 * Returns string containing the day of week * (English-Gregorian) *
    2 * Return a string containing the abbreviated day of week * (English-Gregorian) *
    * @return string|int The gregorian weekday as either an integer or string. */ function jddayofweek(int $julian_day, int $mode = CAL_DOW_DAYNO): string|int {} /** * Returns a month name * @link https://php.net/manual/en/function.jdmonthname.php * @param int $julian_day * @param int $mode * @return string The month name for the given Julian Day and calendar. */ function jdmonthname(int $julian_day, int $mode): string {} /** * Get Unix timestamp for midnight on Easter of a given year * @link https://php.net/manual/en/function.easter-date.php * @param int|null $year [optional]

    * The year as a number between 1970 an 2037 *

    * @param int $mode [optional] Allows Easter dates to be calculated based on the Julian calendar when set to CAL_EASTER_ALWAYS_JULIAN * @return int The easter date as a unix timestamp. */ function easter_date(?int $year = null, #[PhpStormStubsElementAvailable(from: '8.0')] int $mode = CAL_EASTER_DEFAULT): int {} /** * Get number of days after March 21 on which Easter falls for a given year * @link https://php.net/manual/en/function.easter-days.php * @param positive-int|null $year [optional]

    * The year as a positive number *

    * @param int $mode [optional]

    * Allows to calculate easter dates based * on the Gregorian calendar during the years 1582 - 1752 when set to * CAL_EASTER_ROMAN. See the calendar constants for more valid * constants. *

    * @return int The number of days after March 21st that the Easter Sunday * is in the given year. */ function easter_days(?int $year = null, int $mode = CAL_EASTER_DEFAULT): int {} /** * Convert Unix timestamp to Julian Day * @link https://php.net/manual/en/function.unixtojd.php * @param int|null $timestamp defaults to time()

    * A unix timestamp to convert. *

    * @return int|false A julian day number as integer. */ function unixtojd(?int $timestamp = null): int|false {} /** * Convert Julian Day to Unix timestamp * @link https://php.net/manual/en/function.jdtounix.php * @param int $julian_day

    * A julian day number between 2440588 and 2465342. *

    * @return int The unix timestamp for the start of the given julian day. */ function jdtounix(int $julian_day): int {} /** * Converts from a supported calendar to Julian Day Count * @link https://php.net/manual/en/function.cal-to-jd.php * @param int $calendar

    * Calendar to convert from, one of * CAL_GREGORIAN, * CAL_JULIAN, * CAL_JEWISH or * CAL_FRENCH. *

    * @param int $month

    * The month as a number, the valid range depends * on the calendar *

    * @param int $day

    * The day as a number, the valid range depends * on the calendar *

    * @param int $year

    * The year as a number, the valid range depends * on the calendar *

    * @return int A Julian Day number. */ function cal_to_jd(int $calendar, int $month, int $day, int $year): int {} /** * Converts from Julian Day Count to a supported calendar * @link https://php.net/manual/en/function.cal-from-jd.php * @param int $julian_day

    * Julian day as integer *

    * @param int $calendar

    * Calendar to convert to *

    * @return array an array containing calendar information like month, day, year, * day of week, abbreviated and full names of weekday and month and the * date in string form "month/day/year". */ #[ArrayShape([ "date" => "string", "month" => "int", "day" => "int", "year" => "int", "dow" => "int", "abbrevdayname" => "string", "dayname" => "string", "abbrevmonth" => "string", "monthname" => "string" ])] function cal_from_jd(int $julian_day, int $calendar): array {} /** * Return the number of days in a month for a given year and calendar * @link https://php.net/manual/en/function.cal-days-in-month.php * @param int $calendar

    * Calendar to use for calculation *

    * @param int $month

    * Month in the selected calendar *

    * @param int $year

    * Year in the selected calendar *

    * @return int The length in days of the selected month in the given calendar */ function cal_days_in_month(int $calendar, int $month, int $year): int {} /** * Returns information about a particular calendar * @link https://php.net/manual/en/function.cal-info.php * @param int $calendar [optional]

    * Calendar to return information for. If no calendar is specified * information about all calendars is returned. *

    * @return array */ #[ArrayShape(["months" => "array", "abbrevmonths" => "array", "maxdaysinmonth" => "int", "calname" => "string", "calsymbol" => "string"])] function cal_info(int $calendar = -1): array {} define('CAL_GREGORIAN', 0); define('CAL_JULIAN', 1); define('CAL_JEWISH', 2); define('CAL_FRENCH', 3); define('CAL_NUM_CALS', 4); define('CAL_DOW_DAYNO', 0); define('CAL_DOW_SHORT', 2); define('CAL_DOW_LONG', 1); define('CAL_MONTH_GREGORIAN_SHORT', 0); define('CAL_MONTH_GREGORIAN_LONG', 1); define('CAL_MONTH_JULIAN_SHORT', 2); define('CAL_MONTH_JULIAN_LONG', 3); define('CAL_MONTH_JEWISH', 4); define('CAL_MONTH_FRENCH', 5); define('CAL_EASTER_DEFAULT', 0); define('CAL_EASTER_ROMAN', 1); define('CAL_EASTER_ALWAYS_GREGORIAN', 2); define('CAL_EASTER_ALWAYS_JULIAN', 3); define('CAL_JEWISH_ADD_ALAFIM_GERESH', 2); define('CAL_JEWISH_ADD_ALAFIM', 4); define('CAL_JEWISH_ADD_GERESHAYIM', 8); // End of calendar v. * @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 = 0, $previous = null) {} /** * @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 = 0, $previous = null) {} /** * @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 = 0, $previous = null) {} /** * @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 = 0, $previous = null) {} /** * @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 = 0, $previous = null) {} /** * @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() {} } } * 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. = 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) {} } * 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 {} * Open a connection to a CUBRID Server * @link https://php.net/manual/en/function.cubrid-connect.php * @param string $host

    * Host name or IP address of CUBRID CAS server. *

    * @param int $port

    * Port number of CUBRID CAS server (BROKER_PORT configured in * $CUBRID/conf/cubrid_broker.conf). *

    * @param string $dbname

    * Name of database. *

    * @param string $userid [optional]

    * User name for the database. Default value is 'PUBLIC'. *

    * @param string $passwd [optional]

    * User password. Default value is empty string, i.e. no * password is defined. *

    * @param bool $new_link [optional]

    * If a second call is made to cubrid_connect() * with the same arguments, no new link will be established, * but instead, the connection identifier of the already * opened connection will be * returned. The new_link parameter modifies this * behavior and makes cubrid_connect() always open * a new connection, even if cubrid_connect() was called * before with the same parameters. *

    * @return resource|false

    * a CUBRID connection identifier on success or false on failure. *

    */ function cubrid_connect($host, $port, $dbname, $userid = 'PUBLIC', $passwd = '', $new_link = false) {} /** * (PHP 5, CUBRID >= 8.3.1)
    * Establish the environment for connecting to CUBRID server. * @link https://php.net/manual/en/function.cubrid-connect.php * @param string $conn_url

    * A character string that contains server connection information.
    * Syntax: 'CUBRID:>host<:>port<:>dbname<:>username<:>password<:?>params<'.
    * E.g. CUBRID:127.0.0.1:33088:demodb:dba:123456:?autocommit=off&althost=10.34.63.132:33088&rctime=100 *

    * @param string $userid [optional]

    * User name for the database. Default value is 'PUBLIC'. *

    * @param string $passwd [optional]

    * User password. Default value is empty string, i.e. no * password is defined. *

    * @param bool $new_link [optional]

    * If a second call is made to cubrid_connect() * with the same arguments, no new link will be established, * but instead, the connection identifier of the already * opened connection will be * returned. The new_link parameter modifies this * behavior and makes cubrid_connect() always open * a new connection, even if cubrid_connect() was called * before with the same parameters. *

    * @return resource|false

    * a CUBRID connection identifier on success or false on failure. *

    */ function cubrid_connect_with_url($conn_url, $userid = 'PUBLIC', $passwd = '', $new_link = false) {} /** * (PHP 5, CUBRID >= 8.3.1)
    * Open a persistent connection to a CUBRID server * @link https://php.net/manual/en/function.cubrid-pconnect.php * @param string $host

    * Host name or IP address of CUBRID CAS server. *

    * @param int $port

    * Port number of CUBRID CAS server (BROKER_PORT configured in * $CUBRID/conf/cubrid_broker.conf). *

    * @param string $dbname

    * Name of database. *

    * @param string $userid [optional]

    * User name for the database. Default value is 'PUBLIC'. *

    * @param string $passwd [optional]

    * User password. Default value is empty string, i.e. no * password is defined. *

    * @return resource|false

    * Connection identifier, when process is successful. * FALSE, when process is unsuccessful. *

    */ function cubrid_pconnect($host, $port, $dbname, $userid = 'PUBLIC', $passwd = '') {} /** * (PHP 5, CUBRID >= 8.3.1)
    * Open a persistent connection to CUBRID server * @link https://secure.php.net/manual/en/function.cubrid-pconnect-with-url.php * @param string $conn_url

    * A character string that contains server connection information.
    * Syntax: 'CUBRID:>host<:>port<:>dbname<:>username<:>password<:?>params<'.
    * E.g. CUBRID:127.0.0.1:33088:demodb:dba:123456:?autocommit=off&althost=10.34.63.132:33088&rctime=100 *

    * @param string $userid [optional]

    * User name for the database. Default value is 'PUBLIC'. *

    * @param string $passwd [optional]

    * User password. Default value is empty string, i.e. no * password is defined. *

    * @return resource|false

    * Connection identifier, when process is successful. * FALSE, when process is unsuccessful. *

    */ function cubrid_pconnect_with_url($conn_url, $userid = 'PUBLIC', $passwd = '') {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Close CUBRID connection. Same as cubrid_disconnect(). * @link https://php.net/manual/en/function.cubrid-close.php * @param resource $conn_identifier [optional]

    * The CUBRID connection identifier. If the connection * identifier is not specified, the last connection * opened by cubrid_connect() is assumed. *

    * @return bool

    * TRUE, when process is successful. * FALSE, when process is unsuccessful. *

    */ function cubrid_close($conn_identifier = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Close CUBRID connection. Same as cubrid_close(). * @link https://php.net/manual/en/function.cubrid-disconnect.php * @param resource $conn_identifier [optional]

    * Connection identifier. *

    * @return bool Returns true on success or false on failure. */ function cubrid_disconnect($conn_identifier = null) {} /** * (PHP 5, CUBRID >= 8.3.1)
    * Send a CUBRID query * @link https://php.net/manual/en/function.cubrid-query.php * @param string $query

    * A SQL query. Data inside the query should be properly escaped. *

    * @param resource $conn_identifier [optional]

    * The CUBRID connection. If the connection identifier * is not specified, the last connection opened by * cubrid_connect() is assumed. *

    * @return resource|bool
    • * For SELECT, SHOW, DESCRIBE, EXPLAIN and other statements * returning resultset, cubrid_query() returns a resource * on success, or false on error. *
    • *
    • * For other type of SQL statements, INSERT, UPDATE, DELETE, DROP, etc, * cubrid_query() returns true on success or false on error. *
    • *

      * The returned result resource should be passed to * cubrid_fetch_array(), and other functions for dealing * with result tables, to access the returned data. *

      *

      * Use cubrid_num_rows() to find out how many rows * were returned for a SELECT statement. *

      *

      * Use cubrid_affected_rows() to find out how many * rows were affected by a DELETE, INSERT, REPLACE, or UPDATE * statement. *

      *
    • * cubrid_query() will also fail and return false * if the user does not have permission to access the table(s) * referenced by the query. *
    • *
    */ function cubrid_query($query, $conn_identifier = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Execute a prepared SQL statement * @link https://php.net/manual/en/function.cubrid-execute.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $sql

    * SQL to be executed. *

    * @param int $option [optional]

    * Query execution option CUBRID_INCLUDE_OID, CUBRID_ASYNC, * CUBRID_EXEC_QUERY_ALL. *

    * @return resource|bool

    * Request identifier, when process is successful, * or FALSE, when process is unsuccessful. *

    */ function cubrid_execute($conn_identifier, $sql, $option = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Execute a prepared SQL statement * @link https://php.net/manual/en/function.cubrid-execute.php * @param resource $request_identifier

    * cubrid_prepare() identifier. *

    * @param int $option [optional]

    * Query execution option CUBRID_INCLUDE_OID, CUBRID_ASYNC, * CUBRID_EXEC_QUERY_ALL. *

    * @return bool

    * TRUE, when process is successful. FALSE, when * process is unsuccessful. *

    */ function cubrid_execute($request_identifier, $option = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Bind variables to a prepared statement as parameters * @link https://php.net/manual/en/function.cubrid-bind.php * @param resource $req_identifier

    * Request identifier as a result of cubrid_prepare(). *

    * @param int $bind_index

    * Location of binding parameters. It starts with 1. *

    * @param mixed $bind_value

    * Actual value for binding. *

    * @param string $bind_value_type [optional]

    * A type of the value to bind. (It is omitted by default. Thus, system * internally use string by default. However, you need to specify the * exact type of the value as an argument when * they are NCHAR, BIT, or BLOB/CLOB). *

    *

    * The following bind types are supported: * "STRING", "NCHAR", "BIT", "NUMERIC", "NUMBER", "FLOAT", "DOUBLE", * "TIME", "DATE", "TIMESTAMP", "OBJECT", "BLOB", "CLOB", "NULL". *

    * @return bool TRUE, when process is successful, otherwise FALSE. */ function cubrid_bind($req_identifier, $bind_index, $bind_value, $bind_value_type = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Close the request handle. Same as cubrid_close_request(). * @link https://php.net/manual/en/function.cubrid-close-prepare.php * @param resource $req_identifier

    * Request identifier. *

    * @return bool TRUE, when process is successful, otherwise FALSE. */ function cubrid_close_prepare($req_identifier) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Close the request handle. Same as cubrid_close_prepare(). * @link https://php.net/manual/en/function.cubrid-close-request.php * @param resource $req_identifier

    * Request identifier. *

    * @return bool TRUE, when process is successful, or FALSE. */ function cubrid_close_request($req_identifier) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Get contents of collection type column using OID * @link https://php.net/manual/en/function.cubrid-col-get.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $oid

    * OID of the instance that you want to read. *

    * @param string $attr_name

    * Attribute name that you want to read from the instance. *

    * @return array
    • * Array (0-based numerical array) containing the * elements requested, when process is successful; *
    • *
    • * FALSE (to distinguish the error from the situation of * attribute having empty collection; * or NULL, in case of error, a warning message is shown; * in such case you can check the error by using * cubrid_error_code()), when process is unsuccessful. *
    • *
    */ function cubrid_col_get($conn_identifier, $oid, $attr_name) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Get the number of elements in collection type column using OID * @link https://php.net/manual/en/function.cubrid-col-size.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $oid

    * OID of the instance that you want to read. *

    * @param string $attr_name

    * Attribute name that you want to read from the instance. *

    * @return int

    * Number of elements, when process is successful. * FALSE, when process is unsuccessful. *

    */ function cubrid_col_size($conn_identifier, $oid, $attr_name) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Perform a query without fetching the results into memory * @link https://php.net/manual/en/function.cubrid-unbuffered-query.php * @param string $query

    * The SQL query to execute. *

    * @param resource $conn_identifier [optional]

    * The CUBRID connection. If the connection identifier is not * specified, the last connection opened by cubrid_connect() is assumed. *

    * @return resource|bool

    * For SELECT, SHOW, DESCRIBE or EXPLAIN statements, * cubrid_unbuffered_query() returns a resource on success, or false on * error. *

    *

    * For other type of SQL statements, UPDATE, DELETE, DROP, etc, * cubrid_unbuffered_query returns true on success * or false on error. *

    */ function cubrid_unbuffered_query($query, $conn_identifier = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return an array with the list of all existing CUBRID databases * @link https://php.net/manual/en/function.cubrid-list-dbs.php * @param resource $conn_identifier [optional]

    * The CUBRID connection. *

    * @return array

    * a numeric array with all existing CUBRID databases on success, * or false on failure. *

    */ function cubrid_list_dbs($conn_identifier) {} /** * (PHP 5, CUBRID >= 8.3.1)
    * Get the error message. Same as cubrid_error_msg(); * @link https://php.net/manual/en/function.cubrid-error.php * @param resource $connection [optional]

    * The CUBRID connection. *

    * @return string

    * Error message that occurred. *

    */ function cubrid_error($connection = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Get last error message for the most recent function call. * Same as cubrid_error(); * @link https://php.net/manual/en/function.cubrid-error-msg.php * @return string

    * Error message that occurred. *

    */ function cubrid_error_msg() {} /** * (PHP 5, CUBRID >= 8.3.1)
    * Returns the numerical value of the error message from previous * CUBRID operation. Same as cubrid_error_code(); * @link https://php.net/manual/en/function.cubrid-errno.php * @param resource $conn_identifier [optional]

    * The CUBRID connection identifier. If the connection * identifier is not specified, the last connection * opened by cubrid_connect() is assumed. *

    * @return int

    * the error number from the last CUBRID function, or * 0 (zero) if no error occurred. *

    */ function cubrid_errno($conn_identifier = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Get error code for the most recent function call. * Same as cubrid_errno(); * @link https://php.net/manual/en/function.cubrid-error-code.php * @return int

    * Error code of the error that occurred, or * 0 (zero) if no error occurred. *

    */ function cubrid_error_code() {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return the number of rows affected by the last SQL statement * @link https://php.net/manual/en/function.cubrid-affected-rows.php * @param resource $conn_identifier [optional]

    * The CUBRID connection. If the connection identifier is not * specified, the last link opened by cubrid_connect() is assumed. *

    * @return int

    * the number of affected rows on success, * or -1, when SQL statement is not INSERT, DELETE or UPDATE, * or FALSE, when the request identifier is not specified, * and there is no last request. *

    */ function cubrid_affected_rows($conn_identifier = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return the ID generated for the last updated AUTO_INCREMENT column * @link https://php.net/manual/en/function.cubrid-insert-id.php * @param resource $conn_identifier [optional]

    * The connection identifier previously obtained by a call * to cubrid_connect(). *

    * @return string

    * A string representing the ID generated for an AUTO_INCREMENT column * by the previous query, on success. 0, if the previous query does * not generate new rows. FALSE on failure. *

    */ function cubrid_insert_id($conn_identifier = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return the value of a specific field in a specific row * @link https://php.net/manual/en/function.cubrid-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

    * Value of a specific field, on success (NULL if value if null). * FALSE on failure. *

    */ function cubrid_result($result, $row, $field = 0) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Get the number of rows in the result set * @link https://php.net/manual/en/function.cubrid-num-rows.php * @param resource $result

    * result comes from a call to cubrid_execute(), * cubrid_query() and cubrid_prepare() *

    * @return int

    * Number of rows, when process is successful. * 0 when the query was done in async mode. * -1, if SQL statement is not SELECT. * FALSE when process is unsuccessful. *

    */ function cubrid_num_rows($result) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return the number of columns in the result set * @link https://php.net/manual/en/function.cubrid-num-cols.php * @param resource $result

    * Result. *

    * @return int

    * Number of columns, when process is successful. * FALSE, if SQL statement is not SELECT. *

    */ function cubrid_num_cols($result) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return the number of columns in the result set * @link https://php.net/manual/en/function.cubrid-num-fields.php * @param resource $result

    * result comes from a call to cubrid_execute(), * cubrid_query() and cubrid_prepare() *

    * @return int

    * Number of columns, on success. * -1 if SQL sentence is not SELECT. * FALSE when process is unsuccessful. *

    */ function cubrid_num_fields($result) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Fetch the next row from a result set * @link https://php.net/manual/en/function.cubrid-fetch.php * @param resource $result

    * result comes from a call to cubrid_execute() *

    * @param int $type [optional]

    * Array type of the fetched result CUBRID_NUM, * CUBRID_ASSOC, CUBRID_BOTH, CUBRID_OBJECT. If you want to * operate the lob object, you can use CUBRID_LOB. *

    * @return mixed *
      *
    • array or object, when process is successful.
    • *
    • FALSE, when there are no more rows;
    • *
    • NULL, when process is unsuccessful.
    • *
    *

    * The result can be received either as an array or as an object, * and you can decide which data type to use by setting the type * argument. The type variable can be set to one of the following * values: *

    *
      *
    • CUBRID_NUM : Numerical array (0-based)
    • *
    • CUBRID_ASSOC : Associative array
    • *
    • CUBRID_BOTH : Numerical & Associative array (default)
    • *
    • CUBRID_OBJECT : object that has the attribute name as the * column name of query result
    • *
    *

    * When type argument is omitted, the result will be received using * CUBRID_BOTH option as default. When you want to receive query * result in object data type, the column name of the result must * obey the naming rules for identifiers in PHP. For example, * column name such as "count(*)" cannot be received in object type. *

    */ function cubrid_fetch($result, $type = CUBRID_BOTH) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return a numerical array with the values of the current row * @link https://php.net/manual/en/function.cubrid-fetch-row.php * @param resource $result

    * result comes from a call to cubrid_execute() *

    * @param int $type

    * Type can only be CUBRID_LOB, this parameter will be * used only when you need to operate the lob object. *

    * @return array

    * A numerical array, when process is successful. * FALSE, when there are no more rows; * NULL, when process is unsuccessful. *

    */ function cubrid_fetch_row($result, $type = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Fetch a result row as an associative array, a numeric array, or both * @link https://php.net/manual/en/function.cubrid-fetch-array.php * @param resource $result * @param int $type [optional]

    * The type of array that is to be fetched. It's a constant and can * take the following values: CUBRID_ASSOC, CUBRID_NUM, and CUBRID_BOTH. *

    * @return array

    * Returns an array of strings that corresponds to the fetched row, * when process is successful. * FALSE, when there are no more rows; * NULL, when process is unsuccessful. *

    *

    * The type of returned array depends on how result_type is defined. * By using CUBRID_BOTH (default), you'll get an array with both * associative and number indices, and you can decide which data * type to use by setting the type argument. The type variable can * be set to one of the following values: *

    *
      *
    • CUBRID_NUM : Numerical array (0-based)
    • *
    • CUBRID_ASSOC : Associative array
    • *
    • CUBRID_BOTH : Numerical & Associative array (default)
    • *
    */ function cubrid_fetch_array($result, $type = CUBRID_BOTH) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return the associative array that corresponds to the fetched row * @link https://php.net/manual/en/function.cubrid-fetch-assoc.php * @param resource $result

    * result comes from a call to cubrid_execute() *

    * @param int $type [optional]

    * Type can only be CUBRID_LOB, this parameter will be used * only when you need to operate the lob object. *

    * @return array

    * Associative array, when process is successful. * FALSE, when there are no more rows; * NULL, when process is unsuccessful. *

    */ function cubrid_fetch_assoc($result, $type = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Fetch the next row and return it as an object * @link https://php.net/manual/en/function.cubrid-fetch-object.php * @param resource $result

    * result comes from a call to cubrid_execute() *

    * @param string $class_name [optional]

    * The name of the class to instantiate. If not specified, * a stdClass (stdClass is PHP's generic empty class that's * used when casting other types to objects) object is returned. *

    * @param array $params [optional]

    * An optional array of parameters to pass to the constructor * for class_name objects. *

    * @param int $type [optional]

    * Type can only be CUBRID_LOB, this parameter will be used * only when you need to operate the lob object. *

    * @return object

    * an object with string properties * that correspond to the fetched row, or false if there * are no more rows, or NULL, when process is unsuccessful. *

    */ function cubrid_fetch_object($result, $class_name = null, $params = null, $type = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Move the internal row pointer of the CUBRID result * @link https://php.net/manual/en/function.cubrid-data-seek.php * @param resource $result

    * The result. *

    * @param int $row_number

    * The desired row number of the new result pointer. *

    * @return bool

    * Returns TRUE on success or FALSE on failure. *

    */ function cubrid_data_seek($result, $row_number) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return an array with the lengths of the values of * each field from the current row * @link https://php.net/manual/en/function.cubrid-fetch-lengths.php * @param resource $result

    * result comes from a call to cubrid_execute() *

    * @return array

    * A numerical array of lengths on success, * or false on failure. *

    */ function cubrid_fetch_lengths($result) {} /** * (PHP 5, CUBRID >= 8.3.1)
    * Get column information from a result and return as an object * @link https://php.net/manual/en/function.cubrid-fetch-field.php * @param resource $result

    * result comes from a call to cubrid_execute() *

    * @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
    • *
    */ function cubrid_fetch_field($result, $field_offset = 0) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Get the column names in result * @link https://php.net/manual/en/function.cubrid-column-names.php * @param resource $req_identifier

    * Request identifier. *

    * @return array

    * Array of string which containing column names, * when process is successful. FALSE, when process is unsuccessful. *

    */ function cubrid_column_names($req_identifier) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Get column types in result * @link https://php.net/manual/en/function.cubrid-column-names.php * @param resource $req_identifier

    * Request identifier. *

    * @return array

    * Array of string which containing column types, * when process is successful. FALSE, when process is unsuccessful. *

    */ function cubrid_column_types($req_identifier) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Move the result set cursor to the specified field offset * @link https://php.net/manual/en/function.cubrid-field-seek.php * @param resource $result

    * result comes from a call to cubrid_execute() *

    * @param int $field_offset

    * The numerical field offset. The field_offset starts at 0. * If field_offset does not exist, an error of level * E_WARNING is also issued. *

    * @return bool

    * Returns true on success or false on failure. *

    */ function cubrid_field_seek($result, $field_offset = 0) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Free the memory occupied by the result data * @link https://php.net/manual/en/function.cubrid-free-result.php * @param resource $req_identifier

    * Request identifier. *

    * @return bool

    * Returns true on success or false on failure. *

    *

    * Note that it can only free the client fetch buffer now, * and if you want to free all the memory, use function * cubrid_close_request(). *

    */ function cubrid_free_result($req_identifier) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return the name of the specified field index * @link https://php.net/manual/en/function.cubrid-field-name.php * @param resource $result

    * result comes from a call to cubrid_execute() *

    * @param int $field_offset

    * The field_offset starts at 0. If field_offset does not exist, * an error of level E_WARNING is also issued. *

    * @return string

    * The name of the specified field index on * success or false on failure. *

    */ function cubrid_field_name($result, $field_offset) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return the name of the table of the specified field * @link https://php.net/manual/en/function.cubrid-field-table.php * @param resource $result

    * result comes from a call to cubrid_execute() *

    * @param int $field_offset

    * The field_offset starts at 0. If field_offset does not exist, * an error of level E_WARNING is also issued. *

    * @return string

    * The name of the table on success, * FALSE when field_offset value is invalid, or * -1 if SQL sentence is not SELECT. *

    */ function cubrid_field_table($result, $field_offset) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Get the maximum length of the specified field * @link https://php.net/manual/en/function.cubrid-field-len.php * @param resource $result

    * result comes from a call to cubrid_execute() *

    * @param int $field_offset

    * The field_offset starts at 0. If field_offset does not exist, * an error of level E_WARNING is also issued. *

    * @return int

    * Maximum length, when process is successful. FALSE on failure. *

    */ function cubrid_field_len($result, $field_offset) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return the type of the column corresponding to the given field offset * @link https://php.net/manual/en/function.cubrid-field-type.php * @param resource $result

    * result comes from a call to cubrid_execute() *

    * @param int $field_offset

    * The field_offset starts at 0. If field_offset does not exist, * an error of level E_WARNING is also issued. *

    * @return string

    * On success the returned field type will be one of * "int", "real", "string", "blob", and others as * detailed in the CUBRID documentation. Otherwise, FALSE * when invalid field_offset value, or -1 if SQL sentence * is not SELECT. *

    */ function cubrid_field_type($result, $field_offset) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return a string with the flags of the given field offset * @link https://php.net/manual/en/function.cubrid-field-flags.php * @param resource $result

    * result comes from a call to cubrid_execute() *

    * @param int $field_offset

    * The numerical field offset. The field_offset starts at 0. * If field_offset does not exist, an error of level * E_WARNING is also issued. *

    * @return string

    * a string of flags associated with the result, * or FALSE when invalid field_offset value, or -1 if SQL sentence * is not SELECT. *

    *

    * The following flags are reported, if your version of CUBRID * is current enough to support them: "not_null", "primary_key", * "unique_key", "foreign_key", "auto_increment", "shared", * "reverse_index", "reverse_unique", and "timestamp". *

    */ function cubrid_field_flags($result, $field_offset) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Escapes special characters in a string for use in an SQL statement * @link https://php.net/manual/en/function.cubrid-real-escape-string.php * @param string $unescaped_string

    * The string that is to be escaped. *

    * @param resource $conn_identifier [optional]

    * The CUBRID connection. If the connection identifier is not * specified, the last connection opened by cubrid_connect() is assumed. *

    * @return string

    * Escaped string version of the given string, on success. * FALSE on failure. *

    */ function cubrid_real_escape_string($unescaped_string, $conn_identifier = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return the current CUBRID connection charset * @link https://php.net/manual/en/function.cubrid-client-encoding.php * @param resource $conn_identifier [optional]

    * The CUBRID connection. If the connection identifier is not * specified, the last link opened by cubrid_connect() is assumed. *

    * @return string

    * A string that represents the CUBRID connection charset; on success. * FALSE on failure. *

    */ function cubrid_client_encoding($conn_identifier = null) {} /** * (PHP 5, CUBRID >= 8.3.1)
    * Ping a server connection or reconnect if there is no connection * @link https://php.net/manual/en/function.cubrid-ping.php * @param resource $conn_identifier [optional]

    * The CUBRID connection identifier. If the connection identifier * is not specified, the last connection opened by * cubrid_connect() is assumed. *

    * @return bool

    * true if the connection to the server is working, * otherwise false. *

    */ function cubrid_ping($conn_identifier = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return the client library version * @link https://php.net/manual/en/function.cubrid-get-client-info.php * @return string

    * A string that represents the client library version; on success. * FALSE on failure. *

    */ function cubrid_get_client_info() {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return the CUBRID server version * @link https://php.net/manual/en/function.cubrid-get-server-info.php * @param resource $conn_identifier * @return string

    * A string that represents the CUBRID server version; on success. * FALSE on failure. *

    */ function cubrid_get_server_info($conn_identifier) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Returns the CUBRID database parameters * @link https://secure.php.net/manual/en/function.cubrid-get-db-parameter.php * @param resource $conn_identifier

    * Connection identifier. *

    * @return array

    * An associative array with CUBRID database parameters; on success. * FALSE on failure. *

    */ function cubrid_get_db_parameter($conn_identifier) {} /** * (PHP 5, CUBRID >= 8.4.0)
    * Get auto-commit mode of the connection * @link https://php.net/manual/en/function.cubrid-get-autocommit.php * @param resource $conn_identifier

    * Connection identifier. *

    * @return bool

    * TRUE, if autocommit is set to true. FALSE otherwise. * NULL on error. *

    */ function cubrid_get_autocommit($conn_identifier) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Return the current CUBRID connection charset * @link https://secure.php.net/manual/en/function.cubrid-get-charset.php * @param resource $conn_identifier

    * Connection identifier. *

    * @return string

    * A string that represents the CUBRID connection charset; on success. * FALSE on failure. *

    */ function cubrid_get_charset($conn_identifier) {} /** * (PHP 5, CUBRID >= 8.4.0)
    * Set auto-commit mode of the connection * @link https://php.net/manual/en/function.cubrid-set-autocommit.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param bool $mode

    * Auto-commit mode. The following constants can be used: * CUBRID_AUTOCOMMIT_FALSE, CUBRID_AUTOCOMMIT_TRUE *

    * @return bool

    * TRUE, when process is successful. FALSE, when * process is unsuccessful. *

    */ function cubrid_set_autocommit($conn_identifier, $mode) {} /** * (PHP 5, CUBRID >= 8.3.1)
    * Get db name from results of cubrid_list_dbs * @link https://php.net/manual/en/function.cubrid-db-name.php * @param array $result

    * The result pointer from a call to cubrid_list_dbs. *

    * @param int $index

    * The index into the result set. *

    * @return string

    * the database name on success, and false on failure. If false * is returned, use cubrid_error() to determine the nature * of the error. *

    */ function cubrid_db_name($result, $index) {} /** * (PHP 5, CUBRID >= 8.3.1)
    * Get result data * @link https://php.net/manual/en/function.cubrid-db-parameter.php * @param resource $conn_identifier

    * The CUBRID connection. If the connection identifier is not specified, * the last link opened by cubrid_connect() is assumed. *

    * @return array

    * An associative array with CUBRID database * parameters; on success. FALSE on failure. *

    */ function cubrid_db_parameter($conn_identifier) {} /** * (PHP 5, CUBRID >= 8.4.0)
    * Sets the CUBRID database parameters * @link https://php.net/manual/en/function.cubrid-set-db-parameter.php * @param resource $conn_identifier

    * The CUBRID connection. If the connection identifier is not specified, * the last link opened by cubrid_connect() is assumed. *

    * @param int $param_type

    * Database parameter type. Can be PARAM_ISOLATION_LEVEL, * or PARAM_LOCK_TIMEOUT. *

    * @param int $param_value

    * Isolation level value (1-6) or lock timeout (in seconds) value. *

    * @return bool

    * TRUE on success. FALSE on failure. *

    */ function cubrid_set_db_parameter($conn_identifier, $param_type, $param_value) {} /** * (PHP 5, CUBRID >= 8.4.1)
    * Get the query timeout value of the request * @link https://php.net/manual/en/function.cubrid-get-query-timeout.php * @param resource $req_identifier

    * Request identifier. *

    * @return int

    * Success: the query timeout value of the current request. * Units of msec. Failure: FALSE *

    */ function cubrid_get_query_timeout($req_identifier) {} /** * (PHP 5, CUBRID >= 8.4.1)
    * Set the query timeout value of the request * @link https://php.net/manual/en/function.cubrid-set-query-timeout.php * @param resource $req_identifier

    * Request identifier. *

    * @param int $timeout

    * Timeout time, unit of msec. *

    * @return bool

    * TRUE, when process is successful. FALSE, when * process is unsuccessful. *

    */ function cubrid_set_query_timeout($req_identifier, $timeout) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Get the class name using OID * @link https://php.net/manual/en/function.cubrid-tablename.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $oid

    * OID of the instance that you want to check the existence. * To get the current OID of the request, use * cubrid_current_oid() function. *

    * @return string

    * Class name when process is successful. * FALSE, when process is unsuccessful. *

    */ function cubrid_get_class_name($conn_identifier, $oid) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Get a column using OID * @link https://php.net/manual/en/function.cubrid-get.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $oid

    * OID of the instance that you want to read. * To get the current OID of the request, use * cubrid_current_oid() function. *

    * @param mixed $attr [optional]

    * Name of the attribute that you want to read. *

    * @return mixed

    * Content of the requested attribute, * when process is successful; When attr is set with string * data type, the result is returned as a string; when attr is * set with array data type (0-based numerical array), then the * result is returned in associative array. When attr is omitted, * then all attributes are received in array form. *

    *

    * FALSE when process is unsuccessful or result is NULL * (If error occurs to distinguish empty string from NULL, * then it prints the warning message. You can check the * error by using cubrid_error_code()). *

    */ function cubrid_get($conn_identifier, $oid, $attr = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Check whether the instance pointed by OID exists * @link https://php.net/manual/en/function.cubrid-is-instance.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $oid

    * OID of the instance that you want to check the existence. * To get the current OID of the request, use * cubrid_current_oid() function. *

    * @return int

    * 1, if such instance exists; 0, if such instance * does not exist; -1, in case of error *

    */ function cubrid_is_instance($conn_identifier, $oid) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Commit a transaction * @link https://php.net/manual/en/function.cubrid-commit.php * @param resource $conn_identifier

    * Connection identifier. *

    * @return bool

    * TRUE, when process is successful. FALSE, when * process is unsuccessful. *

    */ function cubrid_commit($conn_identifier) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Roll back a transaction * @link https://php.net/manual/en/function.cubrid-rollback.php * @param resource $conn_identifier

    * Connection identifier. *

    * @return bool

    * TRUE, when process is successful. FALSE, when * process is unsuccessful. *

    */ function cubrid_rollback($conn_identifier) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Get OID of the current cursor location * @link https://php.net/manual/en/function.cubrid-commit.php * @param resource $req_identifier

    * Request identifier. *

    * @return string

    * OID of current cursor location, when process * is successful. FALSE, when process is unsuccessful. *

    */ function cubrid_current_oid($req_identifier) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Delete an instance using OID * @link https://php.net/manual/en/function.cubrid-commit.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $oid

    * OID of the instance that you want to delete. *

    * @return bool

    * TRUE, when process is successful. FALSE, * when process is unsuccessful. *

    */ function cubrid_drop($conn_identifier, $oid) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Get the facility code of error * @link https://php.net/manual/en/function.cubrid-error-code-facility.php * @return int

    * Facility code of the error code that occurred: * CUBRID_FACILITY_DBMS, CUBRID_FACILITY_CAS, * CUBRID_FACILITY_CCI, CUBRID_FACILITY_CLIENT *

    */ function cubrid_error_code_facility() {} /** * (PHP 5, CUBRID >= 8.3.1)
    * Close BLOB/CLOB data * @link https://php.net/manual/en/function.cubrid-lob-close.php * @param array $lob_identifier_array

    * LOB identifier array return from cubrid_lob_get(). *

    * @return bool

    * TRUE, when process is successful. * FALSE, when process is unsuccessful. *

    */ function cubrid_lob_close($lob_identifier_array) {} /** * (PHP 5, CUBRID >= 8.3.1)
    * Export BLOB/CLOB data to file * @link https://php.net/manual/en/function.cubrid-lob-export.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param resource $lob_identifier

    * LOB identifier. *

    * @param string $path_name

    * Path name of the file. *

    * @return bool

    * TRUE, when process is successful. * FALSE, when process is unsuccessful. *

    */ function cubrid_lob_export($conn_identifier, $lob_identifier, $path_name) {} /** * (PHP 5, CUBRID >= 8.3.1)
    * cubrid_lob_get() is used to get BLOB/CLOB meta info from * CUBRID database. CUBRID gets BLOB/CLOB by executing the SQL statement, * and returns all LOBs as a resource array. Be sure that the SQL * retrieves only one column and its data type is BLOB or CLOB. * Remember to use cubrid_lob_close() to release the LOBs if you * don't need it any more. * @link https://php.net/manual/en/function.cubrid-lob-get.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $sql

    * SQL statement to be executed. *

    * @return array

    * Return an array of LOB resources, when process * is successful. FALSE, when process is unsuccessful. *

    */ function cubrid_lob_get($conn_identifier, $sql) {} /** * (PHP 5, CUBRID >= 8.3.1)
    * Read BLOB/CLOB data and send straight to browser * @link https://php.net/manual/en/function.cubrid-lob-send.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param resource $lob_identifier

    * LOB identifier. *

    * @return bool

    * TRUE, when process is successful. FALSE, when * process is unsuccessful. *

    */ function cubrid_lob_send($conn_identifier, $lob_identifier) {} /** * (PHP 5, CUBRID >= 8.3.1)
    * Get BLOB/CLOB data size * @link https://php.net/manual/en/function.cubrid-lob-size.php * @param resource $lob_identifier

    * LOB identifier. *

    * @return string

    * A string representing LOB data size, when * process is successful. FALSE, when process is unsuccessful. *

    */ function cubrid_lob_size($lob_identifier) {} /** * (PHP 5, CUBRID >= 8.4.1)
    * Bind a lob object or a string as a lob object to a * prepared statement as parameters. * @link https://secure.php.net/manual/en/function.cubrid-lob2-bind.php * @param resource $req_identifier

    * Reqeust identifier. *

    * @param int $bind_index

    * Location of binding parameters. It starts with 1. *

    * @param mixed $bind_value

    * Actual value for binding. *

    * @param string $bind_value_type [optional]

    * It must be "BLOB" or "CLOB" and it won't be case-sensitive. * If it not be given, the default value is "BLOB". *

    * @return bool

    * TRUE, when process is successful. * FALSE, when process is unsuccessful. *

    */ function cubrid_lob2_bind($req_identifier, $bind_index, $bind_value, $bind_value_type = null) {} /** * (PHP 5, CUBRID >= 8.4.1)
    * Close BLOB/CLOB data * @link https://php.net/manual/en/function.cubrid-lob2-close.php * @param resource $lob_identifier

    * Lob identifier as a result of cubrid_lob2_new() * or get from the result set. *

    * @return bool

    * TRUE, on success. * FALSE, on failure. *

    */ function cubrid_lob2_close($lob_identifier) {} /** * (PHP 5, CUBRID >= 8.4.1)
    * Export the lob object to a file. * @link https://php.net/manual/en/function.cubrid-lob2-export.php * @param resource $lob_identifier

    * Lob identifier as a result of cubrid_lob2_new() or get * from the result set. *

    * @param string $file_name

    * File name you want to store BLOB/CLOB data. * It also supports the path of the file. *

    * @return bool

    * TRUE if the process is successful and FALSE for failure. *

    */ function cubrid_lob2_export($lob_identifier, $file_name) {} /** * (PHP 5, CUBRID >= 8.4.1)
    * Import the lob object from a file. * @link https://php.net/manual/en/function.cubrid-lob2-import.php * @param resource $lob_identifier

    * Lob identifier as a result of cubrid_lob2_new() or get * from the result set. *

    * @param string $file_name

    * File name you want to import BLOB/CLOB data. * It also supports the path of the file. *

    * @return bool

    * TRUE if the process is successful and FALSE for failure. *

    */ function cubrid_lob2_import($lob_identifier, $file_name) {} /** * (PHP 5, CUBRID >= 8.4.1)
    * Create a lob object. * @link https://php.net/manual/en/function.cubrid-lob2-new.php * @param resource $conn_identifier [optional]

    * Connection identifier. If the connection identifier is * not specified, the last connection opened by * cubrid_connect() or cubrid_connect_with_url() is assumed. *

    * @param string $type [optional]

    * It may be "BLOB" or "CLOB", it won't be case-sensitive. * The default value is "BLOB". *

    * @return resource|false

    * Lob identifier when it is successful. FALSE on failure. *

    */ function cubrid_lob2_new($conn_identifier = null, $type = "BLOB") {} /** * (PHP 5, CUBRID >= 8.4.1)
    * Read from BLOB/CLOB data. * @link https://php.net/manual/en/function.cubrid-lob2-read.php * @param resource $lob_identifier

    * Lob identifier as a result of cubrid_lob2_new() or get * from the result set. *

    * @param int $len

    * Length from buffer you want to read from the lob data. *

    * @return string

    * Returns the contents as a string. * FALSE when there is no more data. * NULL on failure. *

    */ function cubrid_lob2_read($lob_identifier, $len) {} /** * (PHP 5, CUBRID >= 8.4.1)
    * Move the cursor of a lob object. * @link https://php.net/manual/en/function.cubrid-lob2-seek64.php * @param resource $lob_identifier

    * Lob identifier as a result of cubrid_lob2_new() or get * from the result set. *

    * @param string $offset

    * Number of units you want to move the cursor. *

    * @param int $origin [optional]

    * This parameter can be the following values: *

    *
      *
    • CUBRID_CURSOR_FIRST: move forward from the first * beginning.
    • *
    • CUBRID_CURSOR_CURRENT: move forward or backward * from the current position.
    • *
    • CUBRID_CURSOR_LAST: move backward at the end of LOB object.
    • *
    * @return bool

    * TRUE if the process is successful and FALSE for failure. *

    */ function cubrid_lob2_seek64($lob_identifier, $offset, $origin = CUBRID_CURSOR_CURRENT) {} /** * (PHP 5, CUBRID >= 8.4.1)
    * Move the cursor of a lob object. * @link https://php.net/manual/en/function.cubrid-lob2-seek.php * @param resource $lob_identifier

    * Lob identifier as a result of cubrid_lob2_new() or get * from the result set. *

    * @param int $offset

    * Number of units you want to move the cursor. *

    * @param int $origin [optional]

    * This parameter can be the following values: *

    *
      *
    • CUBRID_CURSOR_FIRST: move forward from the first * beginning.
    • *
    • CUBRID_CURSOR_CURRENT: move forward or backward * from the current position.
    • *
    • CUBRID_CURSOR_LAST: move backward at the end of LOB object.
    • *
    * @return bool

    * TRUE if the process is successful and FALSE for failure. *

    */ function cubrid_lob2_seek($lob_identifier, $offset, $origin = CUBRID_CURSOR_CURRENT) {} /** * (PHP 5, CUBRID >= 8.4.1)
    * Get a lob object's size. * @link https://php.net/manual/en/function.cubrid-lob2-size64.php * @param resource $lob_identifier

    * Lob identifier as a result of cubrid_lob2_new() or get * from the result set. *

    * @return string

    * It will return the size of the LOB object as a string * when it processes successfully. FALSE on failure. *

    */ function cubrid_lob2_size64($lob_identifier) {} /** * (PHP 5, CUBRID >= 8.4.1)
    * Get a lob object's size. * @link https://php.net/manual/en/function.cubrid-lob2-size.php * @param resource $lob_identifier

    * Lob identifier as a result of cubrid_lob2_new() or get * from the result set. *

    * @return int

    * It will return the size of the LOB object as a string * when it processes successfully. FALSE on failure. *

    */ function cubrid_lob2_size($lob_identifier) {} /** * (PHP 5, CUBRID >= 8.4.1)
    * Tell the cursor position of the LOB object. * @link https://php.net/manual/en/function.cubrid-lob2-tell64.php * @param resource $lob_identifier

    * Lob identifier as a result of cubrid_lob2_new() or get * from the result set. *

    * @return string

    * It will return the cursor position on the LOB object as a * string when it processes successfully. FALSE on failure. *

    */ function cubrid_lob2_tell64($lob_identifier) {} /** * (PHP 5, CUBRID >= 8.4.1)
    * Tell the cursor position of the LOB object. * @link https://php.net/manual/en/function.cubrid-lob2-tell.php * @param resource $lob_identifier

    * Lob identifier as a result of cubrid_lob2_new() or get * from the result set. *

    * @return int

    * It will return the cursor position on the LOB object as a * string when it processes successfully. FALSE on failure. *

    */ function cubrid_lob2_tell($lob_identifier) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Set a read lock on the given OID * @link https://php.net/manual/en/function.cubrid-lock-read.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $oid

    * OID of the instance that you want to put read lock on. *

    * @return bool

    * TRUE, when process is successful. FALSE, when * process is unsuccessful. *

    */ function cubrid_lock_read($conn_identifier, $oid) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Set a write lock on the given OID * @link https://php.net/manual/en/function.cubrid-lock-write.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $oid

    * OID of the instance that you want to put write lock on. *

    * @return bool

    * TRUE, when process is successful. FALSE, when * process is unsuccessful. *

    */ function cubrid_lock_write($conn_identifier, $oid) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Move the cursor in the result * @link https://php.net/manual/en/function.cubrid-move-cursor.php * @param resource $req_identifier

    * Request identifier. *

    * @param int $offset

    * Number of units you want to move the cursor. *

    * @param int $origin [optional]

    * Location where you want to move the cursor from * CUBRID_CURSOR_FIRST, CUBRID_CURSOR_CURRENT, CUBRID_CURSOR_LAST. *

    * @return int

    * CUBRID_CURSOR_SUCCESS, when process is successful. * CUBRID_NO_MORE_DATA, when it is not a valid cursor location. * CUBRID_CURSOR_ERROR, in case of error. *

    */ function cubrid_move_cursor($req_identifier, $offset, $origin = CUBRID_CURSOR_CURRENT) {} /** * (PHP 5, CUBRID >= 8.4.0)
    * Get result of next query when executing multiple SQL statements * @link https://php.net/manual/en/function.cubrid-next-result.php * @param resource $result

    * result comes from a call to cubrid_execute(). *

    * @return bool

    * TRUE, when process is successful. FALSE, when * process is unsuccessful. *

    */ function cubrid_next_result($result) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Prepare an SQL statement for execution * @link https://php.net/manual/en/function.cubrid-prepare.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $prepare_stmt

    * Prepare query. *

    * @param int $option [optional]

    * OID return option CUBRID_INCLUDE_OID. *

    * @return resource|false

    * Request identifier, if process is successful; * FALSE, if process is unsuccessful. *

    */ function cubrid_prepare($conn_identifier, $prepare_stmt, $option = 0) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Update a column using OID * @link https://php.net/manual/en/function.cubrid-put.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $oid

    * OID of the instance that you want to update. *

    * @param string $attr [optional]

    * Name of the attribute that you want to update. *

    * @param mixed $value

    * New value that you want to assign to the attribute. *

    * @return bool

    * TRUE, when process is successful. * FALSE, when process is unsuccessful. *

    */ function cubrid_put($conn_identifier, $oid, $attr = null, $value) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Get the requested schema information * @link https://php.net/manual/en/function.cubrid-schema.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param int $schema_type

    * Schema data that you want to know. *

    * @param string $class_name [optional]

    * Table you want to know the schema of. *

    * @param string $attr_name [optional]

    * Attribute you want to know the schema of. *

    * @return array

    * Array containing the schema information, * when process is successful; FALSE, when process is * unsuccessful. *

    */ function cubrid_schema($conn_identifier, $schema_type, $class_name = null, $attr_name = null) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Delete an element from sequence type column using OID * @link https://php.net/manual/en/function.cubrid-seq-drop.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $oid

    * OID of the instance you want to work with. *

    * @param string $attr_name

    * Name of the attribute that you want to delete an element from. *

    * @param int $index

    * Index of the element that you want to delete (1-based). *

    * @return bool

    * TRUE, when process is successful. FALSE, * when process is unsuccessful. *

    */ function cubrid_seq_drop($conn_identifier, $oid, $attr_name, $index) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Insert an element to a sequence type column using OID * @link https://php.net/manual/en/function.cubrid-seq-insert.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $oid

    * OID of the instance you want to work with. *

    * @param string $attr_name

    * Name of the attribute you want to insert an instance to. *

    * @param int $index

    * Location of the element, you want to insert the element to (1-based). *

    * @param string $seq_element

    * Content of the element that you want to insert. *

    * @return bool

    * TRUE, when process is successful. FALSE, * when process is unsuccessful. *

    */ function cubrid_seq_insert($conn_identifier, $oid, $attr_name, $index, $seq_element) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Update the element value of sequence type column using OID * @link https://php.net/manual/en/function.cubrid-seq-put.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $oid

    * OID of the instance you want to work with. *

    * @param string $attr_name

    * Name of the attribute that you want to update an element. *

    * @param int $index

    * Index of the element that you want to delete (1-based). *

    * @param string $seq_element

    * New content that you want to use for the update. *

    * @return bool

    * TRUE, when process is successful. FALSE, * when process is unsuccessful. *

    */ function cubrid_seq_put($conn_identifier, $oid, $attr_name, $index, $seq_element) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Insert a single element to set type column using OID * @link https://php.net/manual/en/function.cubrid-seq-add.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $oid

    * OID of the instance you want to work with. *

    * @param string $attr_name

    * Name of the attribute you want to insert an element. *

    * @param string $seq_element

    * Content of the element that you want to insert. *

    * @return bool

    * TRUE, when process is successful. FALSE, * when process is unsuccessful. *

    */ function cubrid_seq_add($conn_identifier, $oid, $attr_name, $seq_element) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Insert a single element to set type column using OID * @link https://php.net/manual/en/function.cubrid-set-add.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $oid

    * OID of the instance you want to work with. *

    * @param string $attr_name

    * Name of the attribute you want to insert an element. *

    * @param string $set_element

    * Content of the element you want to insert. *

    * @return bool

    * TRUE, when process is successful. FALSE, * when process is unsuccessful. *

    */ function cubrid_set_add($conn_identifier, $oid, $attr_name, $set_element) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Delete an element from set type column using OID * @link https://php.net/manual/en/function.cubrid-set-drop.php * @param resource $conn_identifier

    * Connection identifier. *

    * @param string $oid

    * OID of the instance you want to work with. *

    * @param string $attr_name

    * Name of the attribute you want to delete an element from. *

    * @param string $set_element

    * Content of the element you want to delete. *

    * @return bool

    * TRUE, when process is successful. FALSE, * when process is unsuccessful. *

    */ function cubrid_set_drop($conn_identifier, $oid, $attr_name, $set_element) {} /** * (PHP 5, CUBRID >= 8.3.0)
    * Get the CUBRID PHP module's version * @link https://php.net/manual/en/function.cubrid-version.php * @return string

    * Version information (eg. "8.4.1.0001"). *

    */ function cubrid_version() {} /** * (PHP 5, CUBRID >= 8.4.0)
    * Write a string into the LOB large object * * @link https://php.net/manual/en/function.cubrid-lob2-write.php * @param resource $lob_identifier

    * LOB identifier obtained by cubrid_lob2_new() or cubrid_lob2_import(). *

    * @param string $buf

    * The string to be written into the LOB. *

    * @return bool

    * Returns true on success, false on failure. *

    */ function cubrid_lob2_write($lob_identifier, string $buf): bool {} /** * 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/cubrid.constants.php */ define('CUBRID_NUM', 1); /** * Columns are returned into the array having the fieldname as the array * index. * @link https://php.net/manual/en/cubrid.constants.php */ define('CUBRID_ASSOC', 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/cubrid.constants.php */ define('CUBRID_BOTH', 3); /** * Get query result as an object. * @link https://php.net/manual/en/cubrid.constants.php */ define('CUBRID_OBJECT', 4); /** * Determine whether to get OID during query execution. * @link https://php.net/manual/en/cubrid.constants.php */ define('CUBRID_INCLUDE_OID', 1); /** * Execute the query in asynchronous mode. * @link https://php.net/manual/en/cubrid.constants.php */ define('CUBRID_ASYNC', 2); /** * Execute the query in synchronous mode. * This flag must be set when executing multiple SQL statements. * @link https://php.net/manual/en/cubrid.constants.php */ define('CUBRID_EXEC_QUERY_ALL', 4); /** * Returned value of cubrid_move_cursor() function * in case of success. * @link https://php.net/manual/en/cubrid.constants.php */ define('CUBRID_CURSOR_SUCCESS', 1); /** * Returned value of cubrid_move_cursor() function in case * of failure. * @link https://php.net/manual/en/cubrid.constants.php */ define('CUBRID_NO_MORE_DATA', 0); /** * Returned value of cubrid_move_cursor() function in case * of failure. * @link https://php.net/manual/en/cubrid.constants.php */ define('CUBRID_CURSOR_ERROR', -1); /** * Enable the auto-commit mode. * @link https://php.net/manual/en/cubrid.constants.php */ define('CUBRID_AUTOCOMMIT_TRUE', 1); /** * Disable the auto-commit mode. * @link https://php.net/manual/en/cubrid.constants.php */ define('CUBRID_AUTOCOMMIT_FALSE', 0); /** * Move current cursor to the first position in the result. * @link https://php.net/manual/en/cubrid.constants.php */ define('CUBRID_CURSOR_FIRST', 0); /** * Move current cursor as a default value if the origin is * not specified. * @link https://php.net/manual/en/cubrid.constants.php */ define('CUBRID_CURSOR_CURRENT', 1); /** * Move current cursor to the last position in the result. * @link https://php.net/manual/en/cubrid.constants.php */ define('CUBRID_CURSOR_LAST', 2); // End of cubrid v.1.0 '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() {} } /** * @since 8.5 */ final class CurlSharePersistentHandle { public readonly array $options; } /** * 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 = null) {} /** * 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 */ #[\JetBrains\PhpStorm\Deprecated('Deprecated: it has no effect', since: '8.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 = null): 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 */ #[\JetBrains\PhpStorm\Deprecated('Deprecated: it has no effect', since: '8.5')] 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 = null): 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.5 */ function curl_multi_get_handles(CurlMultiHandle $multi_handle): array {} /** * @since 8.5 */ function curl_share_init_persistent(array $share_options): CurlSharePersistentHandle {} /** * @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() {} } 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); /** * @since 8.4 */ define('CURLOPT_SERVER_RESPONSE_TIMEOUT', 112); /** * @since 8.4 */ define('CURLOPT_DEBUGFUNCTION', 1); /** * @since 8.4 */ define('CURLINFO_TEXT', 0); /** * @since 8.4 */ define('CURLINFO_HEADER_IN', 1); /* * CURLINFO_HEADER_OUT is defined above and has existed since PHP 5.1.3, * but is reused in a different context relating to CURLINFO_DEBUGFUNCTION * * define('CURLINFO_HEADER_OUT', 2); */ /** * @since 8.4 */ define('CURLINFO_DATA_IN', 3); /** * @since 8.4 */ define('CURLINFO_DATA_OUT', 4); /** * @since 8.4 */ define('CURLINFO_SSL_DATA_OUT', 5); /** * @since 8.4 */ define('CURLINFO_SSL_DATA_IN', 6); /** * @since 8.4 */ define('CURLINFO_POSTTRANSFER_TIME_T', 6291523); define('CURLFOLLOW_ALL', 1); define('CURLFOLLOW_OBEYCODE', 2); define('CURLFOLLOW_FIRSTONLY', 3); define('CURLINFO_HTTPAUTH_USED', 2097221); define('CURLINFO_PROXYAUTH_USED', 2097222); define('CURLINFO_QUEUE_TIME_T', 6291521); define('CURLINFO_USED_PROXY', 2097218); define('CURLINFO_CONN_ID', 6291520); define('CURLOPT_SSL_SIGNATURE_ALGORITHMS', 10328); * 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 = null): 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 = null) {} /** * 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 = null): 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 = null) {} /** * 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] 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 = null): 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 = null): 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 = null, 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 = null): 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 = null): 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 = null): 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)] #[PhpStormStubsElementAvailable(from: '5.5', to: '7.4')] function date_create_immutable_from_format(string $format, string $datetime, ?DateTimeZone $timezone = null): 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 * @throws ValueError when the datetime contains NULL-bytes. */ #[Pure(true)] #[PhpStormStubsElementAvailable(from: '8.0')] function date_create_immutable_from_format(string $format, string $datetime, ?DateTimeZone $timezone = null): 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)] #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] function date_create_from_format(string $format, string $datetime, ?DateTimeZone $timezone = null): DateTime|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.

    * @throws ValueError when the datetime contains NULL-bytes. */ #[Pure(true)] #[PhpStormStubsElementAvailable(from: '8.0')] function date_create_from_format(string $format, string $datetime, ?DateTimeZone $timezone = null): 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 (for PHP < 8.0) 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 = null) {} /** * 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 = null, ?float $longitude = null, ?float $zenith = null, ?float $utcOffset = null): 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 = null, ?float $longitude = null, ?float $zenith = null, ?float $utcOffset = null): 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 * 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. */ #[Pure(true)] #[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 getMicrosecond(): int; } /** * @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 Exception Emits Exception in case of an error. */ #[PhpStormStubsElementAvailable(from: '5.5', to: '8.2')] public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $datetime = "now", #[LanguageLevelTypeAware(['8.0' => 'DateTimeZone|null'], default: 'DateTimeZone')] $timezone = null ) {} /** * (PHP 8 >=8.3.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. */ #[PhpStormStubsElementAvailable(from: '8.3')] 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] #[\NoDiscard(message: "as DateTimeImmutable::add() does not modify the object itself")] 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] #[PhpStormStubsElementAvailable(from: '5.5', to: '7.4')] 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.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 * @throws ValueError when the datetime contains NULL-bytes. */ #[TentativeType] #[PhpStormStubsElementAvailable(from: '8.0')] 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. * Returns the {@link https://secure.php.net/manual/en/class.datetimeimmutable.php DateTimeImmutable} object for method chaining or FALSE on failure. */ #[PhpStormStubsElementAvailable(from: '5.5', to: '8.2')] #[Pure] #[TentativeType] #[LanguageLevelTypeAware(['8.4' => 'DateTimeImmutable'], default: 'static|false')] public function modify(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $modifier) {} /** * (PHP 8 >=8.3.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. */ #[PhpStormStubsElementAvailable(from: '8.3')] #[Pure] #[TentativeType] #[LanguageLevelTypeAware(['8.4' => 'DateTimeImmutable'], default: 'DateTimeImmutable|false')] #[\NoDiscard(message: "as DateTimeImmutable::modify() does not modify the object itself")] 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] #[\NoDiscard(message: "as DateTimeImmutable::setDate() does not modify the object itself")] 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] #[\NoDiscard(message: "as DateTimeImmutable::setISODate() does not modify the object itself")] 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] #[\NoDiscard(message: "as DateTimeImmutable::setTime() does not modify the object itself")] #[Pure] 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] #[\NoDiscard(message: "as DateTimeImmutable::setTimestamp() does not modify the object itself")] 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] #[\NoDiscard(message: "as DateTimeImmutable::setTimezone() does not modify the object itself")] 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] #[\NoDiscard(message: "as DateTimeImmutable::sub() does not modify the object itself")] 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 * The {@link https://secure.php.net/manual/en/class.dateinterval.php DateInterval} object representing the * difference between the two dates. */ #[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. */ #[Pure(true)] #[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 static * @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 */ #[\NoDiscard(message: "as DateTimeImmutable::setMicrosecond() does not modify the object itself")] 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 Exception Emits Exception in case of an error. */ #[PhpStormStubsElementAvailable(from: '5.3', to: '8.2')] public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $datetime = 'now', #[LanguageLevelTypeAware(['8.0' => 'DateTimeZone|null'], default: 'DateTimeZone')] $timezone = null ) {} /** * (PHP 8 >=8.3.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. */ #[PhpStormStubsElementAvailable(from: '8.3')] 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 */ #[Pure(true)] #[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. * @link https://php.net/manual/en/datetime.modify.php */ #[PhpStormStubsElementAvailable(from: '5.3', to: '8.2')] #[TentativeType] #[LanguageLevelTypeAware(['8.4' => 'DateTime'], default: 'static|false')] public function modify(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $modifier) {} /** * 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 */ #[PhpStormStubsElementAvailable(from: '8.3')] #[TentativeType] #[LanguageLevelTypeAware(['8.4' => 'DateTime'], default: 'static|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 * @throws DateInvalidOperationException */ #[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 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] #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] 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 {} /** * 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 * @throws ValueError when the datetime contains NULL-bytes. */ #[TentativeType] #[PhpStormStubsElementAvailable(from: '8.0')] 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 static * @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 = PHP_INT_MIN, #[PhpStormStubsElementAvailable(from: '5.3', to: '5.6')] $timestampEnd = 2147483647, #[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 Exception when the $duration cannot be parsed as an interval. * @link https://php.net/manual/en/dateinterval.construct.php */ #[PhpStormStubsElementAvailable(from: '5.3', to: '8.2')] public function __construct(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $duration) {} /** * @param string $duration * @throws DateMalformedIntervalStringException when the $duration cannot be parsed as an interval. * @link https://php.net/manual/en/dateinterval.construct.php */ #[PhpStormStubsElementAvailable(from: '8.3')] 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] #[PhpStormStubsElementAvailable(from: '5.3', to: '8.2')] #[LanguageLevelTypeAware(['8.4' => 'DateInterval'], default: 'DateInterval|false')] public static function createFromDateString(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $datetime) {} /** * 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. * @throws DateMalformedIntervalStringException * @link https://php.net/manual/en/dateinterval.createfromdatestring.php */ #[TentativeType] #[PhpStormStubsElementAvailable(from: '8.3')] #[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 {} * Commonly a regular path in your filesystem. *

    * @param string $mode

    * It is r for read access, w for * read/write access to an already existing database, c * for read/write access and database creation if it doesn't currently exist, * and n for create, truncate and read/write access. * The database is created in BTree mode, other modes (like Hash or Queue) * are not supported. *

    *

    * Additionally you can set the database lock method with the next char. * Use l to lock the database with a .lck * file or d to lock the databasefile itself. It is * important that all of your applications do this consistently. *

    *

    * If you want to test the access and do not want to wait for the lock * you can add t as third character. When you are * absolutely sure that you do not require database locking you can do * so by using - instead of l or * d. When none of d, * l or - is used, dba will lock * on the database file as it would with d. *

    *

    * There can only be one writer for one database file. When you use dba on * a web server and more than one request requires write operations they can * only be done one after another. Also read during write is not allowed. * The dba extension uses locks to prevent this. See the following table: * * DBA locking * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    already openmode = "rl"mode = "rlt"mode = "wl"mode = "wlt"mode = "rd"mode = "rdt"mode = "wd"mode = "wdt"
    not openokokokokokokokok
    mode = "rl"okokwaitfalseillegalillegalillegalillegal
    mode = "wl"waitfalsewaitfalseillegalillegalillegalillegal
    mode = "rd"illegalillegalillegalillegalokokwaitfalse
    mode = "wd"illegalillegalillegalillegalwaitfalsewaitfalse
    * ok: the second call will be successful. * wait: the second call waits until dba_close is called for the first. * false: the second call returns false. * illegal: you must not mix "l" and "d" modifiers for mode parameter. *

    * @param string $handler [optional]

    * The name of the handler which * shall be used for accessing path. It is passed * all optional parameters given to dba_open and * can act on behalf of them. *

    * @param mixed ...$handler_params [optional] * @return resource|false a positive handle on success or FALSE on failure. */ #[PhpStormStubsElementAvailable(from: '5.3', to: '8.1')] function dba_open($path, $mode, $handler = null, ...$handler_params) {} #[PhpStormStubsElementAvailable(from: '8.2')] #[LanguageLevelTypeAware(["8.4" => "Dba\Connection|false"], default: "resource|false")] function dba_open(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0, ?int $flags = null) {} /** * Open database persistently * @link https://php.net/manual/en/function.dba-popen.php * @param string $path

    * Commonly a regular path in your filesystem. *

    * @param string $mode

    * It is r for read access, w for * read/write access to an already existing database, c * for read/write access and database creation if it doesn't currently exist, * and n for create, truncate and read/write access. *

    * @param string $handler [optional]

    * The name of the handler which * shall be used for accessing path. It is passed * all optional parameters given to dba_popen and * can act on behalf of them. *

    * @param mixed ...$handler_params [optional] * @return resource|false a positive handle on success or FALSE on failure. */ #[PhpStormStubsElementAvailable(from: '5.3', to: '8.1')] function dba_popen($path, $mode, $handler = null, ...$handler_params) {} #[PhpStormStubsElementAvailable(from: '8.2')] #[LanguageLevelTypeAware(["8.4" => "Dba\Connection|false"], default: "resource|false")] function dba_popen(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0, ?int $flags = null) {} /** * Close a DBA database * @link https://php.net/manual/en/function.dba-close.php * @param resource $dba

    * The database handler, returned by dba_open or * dba_popen. *

    * @return void No value is returned. */ function dba_close(#[LanguageLevelTypeAware(['8.4' => 'Dba\Connection'], default: 'resource')] $dba): void {} /** * Delete DBA entry specified by key * @link https://php.net/manual/en/function.dba-delete.php * @param string $key

    * The key of the entry which is deleted. *

    * @param resource $dba

    * The database handler, returned by dba_open or * dba_popen. *

    * @return bool TRUE on success or FALSE on failure. */ function dba_delete( #[LanguageLevelTypeAware(['8.2' => 'array|string'], default: '')] $key, #[LanguageLevelTypeAware(['8.4' => 'Dba\Connection'], default: 'resource')] $dba ): bool {} /** * Check whether key exists * @link https://php.net/manual/en/function.dba-exists.php * @param string $key

    * The key the check is performed for. *

    * @param resource $dba

    * The database handler, returned by dba_open or * dba_popen. *

    * @return bool TRUE if the key exists, FALSE otherwise. */ function dba_exists( #[LanguageLevelTypeAware(['8.2' => 'array|string'], default: '')] $key, #[LanguageLevelTypeAware(['8.4' => 'Dba\Connection'], default: 'resource')] $dba ): bool {} /** * Fetch data specified by key * @link https://php.net/manual/en/function.dba-fetch.php * @param string $key

    * The key the data is specified by. *

    *

    * When working with inifiles this function accepts arrays as keys * where index 0 is the group and index 1 is the value name. See: * dba_key_split. *

    * @param resource $handle

    * The database handler, returned by dba_open or * dba_popen. *

    * @return string|false the associated string if the key/data pair is found, FALSE * otherwise. */ function dba_fetch($key, $handle): string|false {} /** * Fetch data specified by key * @link https://php.net/manual/en/function.dba-fetch.php * @param string $key

    * The key the data is specified by. *

    *

    * When working with inifiles this function accepts arrays as keys * where index 0 is the group and index 1 is the value name. See: * dba_key_split. *

    * @param int $skip The number of key-value pairs to ignore when using cdb databases. This value is ignored for all other databases which do not support multiple keys with the same name. * @param resource $dba

    * The database handler, returned by dba_open or * dba_popen. *

    * @return string|false the associated string if the key/data pair is found, FALSE * otherwise. */ #[Deprecated(since: 8.3)] function dba_fetch($key, $skip, $dba): string|false {} /** * Insert entry * @link https://php.net/manual/en/function.dba-insert.php * @param string $key

    * The key of the entry to be inserted. If this key already exist in the * database, this function will fail. Use dba_replace * if you need to replace an existent key. *

    * @param string $value

    * The value to be inserted. *

    * @param resource $dba

    * The database handler, returned by dba_open or * dba_popen. *

    * @return bool TRUE on success or FALSE on failure. */ function dba_insert( #[LanguageLevelTypeAware(['8.2' => 'array|string'], default: '')] $key, string $value, #[LanguageLevelTypeAware(['8.4' => 'Dba\Connection'], default: 'resource')] $dba ): bool {} /** * Replace or insert entry * @link https://php.net/manual/en/function.dba-replace.php * @param string $key

    * The key of the entry to be replaced. *

    * @param string $value

    * The value to be replaced. *

    * @param resource $dba

    * The database handler, returned by dba_open or * dba_popen. *

    * @return bool TRUE on success or FALSE on failure. */ function dba_replace( #[LanguageLevelTypeAware(['8.2' => 'array|string'], default: '')] $key, string $value, #[LanguageLevelTypeAware(['8.4' => 'Dba\Connection'], default: 'resource')] $dba ): bool {} /** * Fetch first key * @link https://php.net/manual/en/function.dba-firstkey.php * @param resource $dba

    * The database handler, returned by dba_open or * dba_popen. *

    * @return string|false the key on success or FALSE on failure. */ function dba_firstkey(#[LanguageLevelTypeAware(['8.4' => 'Dba\Connection'], default: 'resource')] $dba): string|false {} /** * Fetch next key * @link https://php.net/manual/en/function.dba-nextkey.php * @param resource $dba

    * The database handler, returned by dba_open or * dba_popen. *

    * @return string|false the key on success or FALSE on failure. */ function dba_nextkey(#[LanguageLevelTypeAware(['8.4' => 'Dba\Connection'], default: 'resource')] $dba): string|false {} /** * Optimize database * @link https://php.net/manual/en/function.dba-optimize.php * @param resource $dba

    * The database handler, returned by dba_open or * dba_popen. *

    * @return bool TRUE on success or FALSE on failure. */ function dba_optimize(#[LanguageLevelTypeAware(['8.4' => 'Dba\Connection'], default: 'resource')] $dba): bool {} /** * Synchronize database * @link https://php.net/manual/en/function.dba-sync.php * @param resource $dba

    * The database handler, returned by dba_open or * dba_popen. *

    * @return bool TRUE on success or FALSE on failure. */ function dba_sync(#[LanguageLevelTypeAware(['8.4' => 'Dba\Connection'], default: 'resource')] $dba): bool {} /** * List all the handlers available * @link https://php.net/manual/en/function.dba-handlers.php * @param bool $full_info [optional]

    * Turns on/off full information display in the result. *

    * @return array an array of database handlers. If full_info * is set to TRUE, the array will be associative with the handlers names as * keys, and their version information as value. Otherwise, the result will be * an indexed array of handlers names. *

    *

    * When the internal cdb library is used you will see * cdb and cdb_make. */ function dba_handlers(bool $full_info = false): array {} /** * List all open database files * @link https://php.net/manual/en/function.dba-list.php * @return array An associative array, in the form resourceid => filename. */ function dba_list(): array {} /** * Splits a key in string representation into array representation * @link https://php.net/manual/en/function.dba-key-split.php * @param string|false|null $key

    * The key in string representation. *

    * @return array|false an array of the form array(0 => group, 1 => * value_name). This function will return FALSE if * key is NULL or FALSE. */ function dba_key_split(string|false|null $key): array|false {} // End of dba v. ) applied to the 'meta' section of the root span * @param bool|null $propagate If set to 'true', user's information will be propagated in distributed traces */ function set_user(string $userId, array $metadata = [], bool|null $propagate = null): void {} /** * Close child spans of a parent span if a non-internal span is given, * else if 'null' is given, close active, non-internal spans * * @param SpanData|null $span The parent span * @return false|int 'false' if spans couldn't be closed, else the number of span closed */ function close_spans_until(?SpanData $span): false|int {} /** * Get the active span * * @return SpanData|null 'null' if tracing isn't enabled or there isn't any active span, else the active span */ function active_span(): null|SpanData {} /** * Get the root span * * @return RootSpanData|null 'null' if tracing isn't enabled or if the active stack doesn't have a root span, * else the root span of the active stack */ function root_span(): null|RootSpanData {} /** * Start a new custom user-span on the top of the stack. If no active span exists, the new created span will be a * root span, on its own new span stack (i.e., it is equivalent to 'start_trace_span'). In that case, distributed * tracing information will be applied if available. * * @param float $startTime Start time of the span in seconds. * @return SpanData|false The newly started span, or 'false' if a wrong parameter was given. */ function start_span(float $startTime = 0): SpanData|false {} /** * Close the currently active user-span on the top of the stack * * @param float $finishTime Finish time in seconds. Defaults to now if zero. * @return false|null 'false' if unexpected parameters were given, else 'null' */ function close_span(float $finishTime = 0): false|null {} /** * Update the duration of an already closed span * * Note that this API won't cause an update of a closed span if it's already sent. Its usage, particularly on * root spans with datadog.trace.auto_flush_enabled may not yield the expected results. * * @param SpanData $span The span to update. * @param float $finishTime Finish time in seconds. Defaults to now if zero. * @return false|null 'false' if unexpected parameters were given, else 'null' */ function update_span_duration(SpanData $span, float $finishTime = 0): false|null {} /** * Start a new trace * * More precisely, a new root span stack will be created and switched on to, and a new span started. * * @param float $startTime Start time of the span in seconds. * @return SpanData The newly created root span */ function start_trace_span(float $startTime = 0): SpanData {} /** * Get the active stack * * @return SpanStack|null A copy of the active stack, or 'null' if the tracer is disabled. Won't happen * under normal operation. */ function active_stack(): SpanStack|null {} /** * Initialize a new span stack and switch to it. If tracing isn't enabled, a root span stack will be created. * * @return SpanStack The newly created span stack */ function create_stack(): SpanStack {} /** * Switch back to a specific stack (even if there is no active span on that stack), or to the parent of the active * stack if no stack is given. * * @param SpanData|SpanStack|null $newStack Stack to switch to. If 'null' is given, switches to the parent of the * active stack. If a SpanData object is given, it will switch to the stack of the latter. * @return null|false|SpanStack The newly active stack, or 'null' if the tracer is disabled (Won't happen under * normal operation), or 'false' if unexpected parameters were given. */ function switch_stack(SpanData|SpanStack|null $newStack = null): null|false|SpanStack {} /** * Set the priority sampling level * * @param int $priority The priority level to be set to. * @param bool $global If set to 'true' and if there is no active stack (or the active stack doesn't have a * root span), then the default priority sampling will be set to the provided priority level. Otherwise, the root's * priority sampling level will be updated with the new value. */ function set_priority_sampling(int $priority, bool $global = false): void {} /** * Get the priority sampling level * * @param bool $global If set to 'true' and if there is no active stack (or the active stack doesn't have a * root span), then the default priority sampling will be returned, else it will be fetched from the root. * @return int|null The priority sampling level, or 'null' if an unexpected parameter was given. */ function get_priority_sampling(bool $global = false): int|null {} /** * Sanitize an exception * * @param \Exception|\Throwable $exception * @param int $skipFrames The number of frames to be dropped from the start. E.g. to hide the fact that we're * in a hook function. */ function get_sanitized_exception_trace(\Exception|\Throwable $exception, int $skipFrames = 0): string {} /** * Update datadog headers for distributed tracing for new spans. Also applies this information to the current trace, * if there is one, as well as the future ones if it isn't overwritten * * @param null|array|callable(string):mixed $headersOrCallback Either an array with a lowercase header to value mapping, * or a callback, which given a header name for distributed tracing, returns the value it should be updated to. If null, * this reads the headers directly from the $_SERVER superglobal. */ function consume_distributed_tracing_headers(null|array|callable $headersOrCallback): void {} /** * Get information on the key-value pairs of the datadog headers for distributed tracing * * @param null|string[] $inject The types of sampling headers which shall be generated, equivalent to what * DD_TRACE_PROPAGATION_STYLE_INJECT supports. Defaults to DD_TRACE_PROPAGATION_STYLE_INJECT if null. * * @return array{x-datadog-sampling-priority: string, * x-datadog-origin: string, * x-datadog-trace-id: string, * x-datadog-parent-id: string, * traceparent: string, * tracestate: string * } */ function generate_distributed_tracing_headers(array|null $inject = null): array {} /** * Searches parent frames to see whether it's currently within a catch block and returns that exception. * * @return \Throwable|null The active exception if there is one, else 'null'. */ function find_active_exception(): \Throwable|null {} /** * Retrieve IPs from the given array if valid headers are found, and return them in * a metadata formatting * * @param string[] $headers */ function extract_ip_from_headers(array $headers): array {} /** * Get startup information in JSON format * * @return string Startup information */ function startup_logs(): string {} /** * Return the id of the current trace * * @return string The id of the current trace */ function trace_id(): string {} /** * Formatted trace id to be used for logs correlation. * * This function handles 128-bit trace ids and 64-bit trace ids. More specifically, if * DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED is set to true and the current trace id is 128-bit, then the trace id * will be returned as a 32-character hexadecimal string. Otherwise, the trace id will be returned as the * decimal representation of the 64-bit trace id. * * @return string The formatted id of the current trace */ function logs_correlation_trace_id(): string {} /** * Get information on the current context * * @return array{trace_id: string, span_id: string, version: string, env: string} */ function current_context(): array {} /** * Apply the distributed tracing information on the current and future spans. That API can be called if there is no * other currently active span. * * The distributed tracing context can be reset by calling 'set_distributed_tracing_context("0", "0")' * * @param string $traceId The unique integer (128-bit unsigned) ID of the trace containing this span * @param string $parentId The span integer ID of the parent span * @param string|null $origin The distributed tracing origin * @param array|string|null $propagated_tags If provided, propagated tags from the root span will be cleared and * replaced by the given tags and applied to existing spans * @return bool 'true' if the distributed tracing context was properly set, else 'false' if an error occurred */ function set_distributed_tracing_context( string $traceId, string $parentId, ?string $origin = null, array|string|null $propagated_tags = null ): bool {} /** * Closes all spans and force-send finished traces to the agent */ function flush(): void {} /** * Registers an array to be populated with spans for each request during the next curl_multi_exec() call. * * @internal * @param list{\CurlHandle, SpanData}[] $array An array which will be populated with curl handles and spans. */ function curl_multi_exec_get_request_spans(&$array): void {} /** * Update a DogStatsD counter * * @param string $metric The metric name * @param int $value The metric value * @param array $tags A list of tags associated to the metric */ function dogstatsd_count(string $metric, int $value, array $tags = []): void {} /** * Update a DogStatsD distribution * * @param string $metric The metric name * @param float $value The metric value * @param array $tags A list of tags associated to the metric */ function dogstatsd_distribution(string $metric, float $value, array $tags = []): void {} /** * Update a DogStatsD gauge * * @param string $metric The metric name * @param float $value The metric value * @param array $tags A list of tags associated to the metric */ function dogstatsd_gauge(string $metric, float $value, array $tags = []): void {} /** * Update a DogStatsD histogram * * @param string $metric The metric name * @param float $value The metric value * @param array $tags A list of tags associated to the metric */ function dogstatsd_histogram(string $metric, float $value, array $tags = []): void {} /** * Update a DogStatsD set * * @param string $metric The metric name * @param int $value The metric value * @param array $tags A list of tags associated to the metric */ function dogstatsd_set(string $metric, int $value, array $tags = []): void {} } namespace DDTrace\System { /** * Get the unique identifier of the container * * @return string|null The container id, or 'null' if no id was found */ function container_id(): string|null {} } namespace DDTrace\Config { /** * Check if the app analytics of an app is enabled for a given integration * * @param string $integrationName The name of the integration (e.g., mysqli) * @return bool The status of the app analytics of the integration */ function integration_analytics_enabled(string $integrationName): bool {} /** * Check the app analytics sample rate of a given integration * * @param string $integrationName The name of the integration (e.g., mysqli) * @return float The sample rate of the app analytics of the integration */ function integration_analytics_sample_rate(string $integrationName): float {} } namespace DDTrace\UserRequest { /** * If there are any listeners of user request events. * @return bool true iif there are any listeners */ function has_listeners(): bool {} /** * Notifies the user request listeners of the start of a user request. * * @param \DDTrace\RootSpanData $span the span associated with this user request. * @param array $data an array with keys named '_GET', '_POST', '_SERVER', '_FILES', '_COOKIE' * @param string|resource|null $body the body of the request (a string or a seekable resource) * @return array|null an array with the keys 'status', 'headers' and 'body', or null */ function notify_start(\DDTrace\RootSpanData $span, array $data, mixed $body = null): ?array {} /** * Notifies the user request listeners of the imminence of a commit, and allows for the replacement of the response. * @param \DDTrace\RootSpanData $span the span associated with this user request. * @param int $status the HTTP status code of the response * @param array $headers the HTTP headers of the response in the form name => array(values) * @param string|resource|null $body the body of the response (a string or a seekable resource) * @return array|null an array with the keys 'status', 'headers' and 'body', or null */ function notify_commit(\DDTrace\RootSpanData $span, int $status, array $headers, mixed $body = null): ?array {} /** * Sets a function to be called when blocking a request midway. * * @param \DDTrace\RootSpanData $span * @param callable $blockingFunction a blocking function taking an array with the keys 'status', 'headers', 'body' */ function set_blocking_function(\DDTrace\RootSpanData $span, callable $blockingFunction): void {} } namespace DDTrace\Testing { /** * Overrides PHP's default error handling. * * @param string $message Error message * @param int $errorType Error Type. Supported error types are: E_ERROR, E_WARNING, E_PARSE, E_NOTICE, E_CORE_ERROR, * E_CORE_WARNING, E_COMPILE_ERROR, E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE, E_STRICT, E_RECOVERABLE_ERROR, * E_DEPRECATED, E_USER_DEPRECATED */ function trigger_error(string $message, int $errorType): void {} } namespace DDTrace\Internal { /** * @var int */ const SPAN_FLAG_OPENTELEMETRY = 0; /** * @var int */ const SPAN_FLAG_OPENTRACING = 0; /** * Adds a flag to a span. * * @internal * * @param \DDTrace\SpanData $span the span to flag * @param int $flag the flag to add to the span */ function add_span_flag(\DDTrace\SpanData $span, int $flag): void {} /** * To be called when a fork is performed. * * @internal */ function handle_fork(): void {} } namespace { /** * @var string */ const DD_TRACE_VERSION = '0'; /** * @var int */ const DD_TRACE_PRIORITY_SAMPLING_AUTO_KEEP = 0; /** * @var int */ const DD_TRACE_PRIORITY_SAMPLING_AUTO_REJECT = 0; /** * @var int */ const DD_TRACE_PRIORITY_SAMPLING_USER_KEEP = 0; /** * @var int */ const DD_TRACE_PRIORITY_SAMPLING_USER_REJECT = 0; /** * @var int */ const DD_TRACE_PRIORITY_SAMPLING_UNKNOWN = 0; /** * @var int */ const DD_TRACE_PRIORITY_SAMPLING_UNSET = 0; /** * Get the value of a DD environment variable * * @param string $envName Environment variable name * @return mixed Value of the environment variable */ function dd_trace_env_config(string $envName): mixed {} /** * Disable tracing in the current request */ function dd_trace_disable_in_request(): bool {} /** * (Noop/To do) Untrace traced functions and methods * * @internal * @return bool 'true' if reset was successful, else 'false' */ function dd_trace_reset(): bool {} /** * If tracing is enabled, serialize the trace into a string to send to the agent * * @internal * @param array $traceArray Serialize values must be of type array, string, int, float, bool or null * @return bool|string The serialized array, else 'false' if an error was encountered */ function dd_trace_serialize_msgpack(array $traceArray): bool|string {} /** * Null function to easily breakpoint the execution at specific PHP line in GDB * * @internal * @return bool Return 'true' if tracing is enabled, else 'false' */ function dd_trace_noop(mixed ...$args): bool {} /** * Get the parsed value of the memory limit DD_TRACE_MEMORY_LIMIT in binary bytes * * @return int The memory limit */ function dd_trace_dd_get_memory_limit(): int {} /** * Check if the current memory usage is under the memory limit DD_TRACE_MEMORY_LIMIT * * @return bool 'true' if the current memory usage is under the memory limit, else 'false' */ function dd_trace_check_memory_under_limit(): bool {} /** * Get the name of the app (DD_SERVICE) * * @param string|null $fallbackName Fallback name if the app's name wasn't set * @return string|null The app name, else the fallback name. Return 'null' if the app name isn't set and no * fallback name is provided. */ function ddtrace_config_app_name(?string $fallbackName = null): ?string {} /** * Check if distributed tracing is enabled (DD_DISTRIBUTED_TRACING) * * @return bool 'true' if distributed tracing is enabled, else 'false' */ function ddtrace_config_distributed_tracing_enabled(): bool {} /** * Check if tracing is enabled (DD_TRACE_ENABLED) * * @return bool 'true' is tracing is enabled, else 'false' */ function ddtrace_config_trace_enabled(): bool {} /** * Check if a specific integration is enabled * * @param string $integrationName The name of the integration (e.g., mysqli) * @return bool The status of the integration, or 'false' if tracing isn't enabled. */ function ddtrace_config_integration_enabled(string $integrationName): bool {} /** * Send payload to background sender's buffer * * @internal * @param int $numTraces Trace count. Note that at the moment, the background sender is only capable of sending * exactly one trace * @param array $curlHeaders HTTP Headers * @param string $payload HTTP Body * @return bool 'true' if tracers were successfully sent or if the tracer is disabled, and 'false' if not exactly * one trace was sent or if the procedure was unsuccessful */ function dd_trace_send_traces_via_thread(int $numTraces, array $curlHeaders, string $payload): bool {} /** * Serializes and sends traces to the agent (in the format dd_trace_serialize_closed_spans() returns spans). * * @internal * @param array $traceArray Array in the format returned by dd_trace_serialize_closed_spans() */ function dd_trace_buffer_span(array $traceArray): bool {} /** * Used to send any already buffered spans to the agent * * @internal */ function dd_trace_coms_trigger_writer_flush(): int {} /** * Execute a given internal function * * Internal functions are: init_and_start_writer, ddtrace_coms_next_group_id, ddtrace_coms_buffer_span, * ddtrace_coms_buffer_data, shutdown_writer, set_writer_send_on_flush, test_consumer, test_writers, * test_msgpack_consumer, synchronous_flush, and root_span_add_tag * * @internal * @param string $functionName Internal function name * @param mixed $args,... Arguments of the function * @return mixed false if void function was properly executed, else the return value of it */ function dd_trace_internal_fn(string $functionName, mixed ...$args): mixed {} /** * Set the distributed trace id * * @param string|null $traceId New trace id * @return bool 'true' if the change was properly applied, else 'false' */ function dd_trace_set_trace_id(?string $traceId = null): bool {} /** * Tracks closed spans * * @return int Number of closed spans */ function dd_trace_closed_spans_count(): int {} /** * Check if the tracer's current memory usage is higher than the set limits * * @return bool 'true' if memory is overused, else 'false' */ function dd_trace_tracer_is_limited(): bool {} /** * Get the compiling time of all files compiled up to now (in µs) * * @return int Compile time */ function dd_trace_compile_time_microseconds(): int {} /** * Get serialized information about closed spans as arrays. Note that calling this function will result in * automatically closing unfinished spans (destroys the open span stack). * * @return array Closed spans data */ function dd_trace_serialize_closed_spans(): array {} /** * Get the currently active span id, or the distributed parent trace id if there is no currently active span * * @return string Currently active span/trace unique identifier */ function dd_trace_peek_span_id(): string {} /** * Force-finish all spans and force-send finished traces to the agent. Note that this function drops (resp. closes) * all currently open spans if DD_AUTOFINISH_SPANS is set to 'false' (resp. 'true'). Dropped spans are not sent to * the agent. */ function dd_trace_close_all_spans_and_flush(): void {} /** * @see DDTrace_trace_function */ function dd_trace_function(string $functionName, \Closure|array|null $tracingClosureOrConfigArray): bool {} /** * @see DDTrace_trace_method */ function dd_trace_method( string $className, string $methodName, \Closure|array|null $tracingClosureOrConfigArray ): bool {} /** * Untrace a function or a method. * * @param string $functionName The name of the function or method to untrace * @param string|null $className In the case of a method, its respective class should be provided as well * @return bool 'true' if the un-tracing process was successful, else 'false' */ function dd_untrace(string $functionName, string|null $className = null): bool {} /** * Blocking-call synchronously flushing all spans to the agent * * @param int $timeout Timeout in milliseconds to wait for the flush to complete */ function dd_trace_synchronous_flush(int $timeout = 100): void {} } ` operator. * * @param mixed $other * * @return int 0 if this decimal is considered is equal to $other, * -1 if this decimal should be placed before $other, * 1 if this decimal should be placed after $other. */ public function compareTo($other): int {} /** * String representation. * * This method is equivalent to a cast to string, as well as `toString`. * * @return string the value of this decimal represented exactly, in either * fixed or scientific form, depending on the value. */ public function __toString(): string {} /** * JSON * * This method is only here to honour the interface, and is equivalent to * `toString`. JSON does not have a decimal type so all decimals are encoded * as strings in the same format as `toString`. * * @return string */ public function jsonSerialize() {} } *
  • "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) {} 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', '8.2' => 'DOMAttr|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 * @deprecated 8.4 */ 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 * @template TNode of DOMNode * @param TNode $node

    * The new node. *

    * @param null|DOMNode $child [optional]

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

    * @return TNode|false 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 * @template TNode of DOMNode * @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 TNode $child

    * The old node. *

    * @return TNode|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 * @template TNode of DOMNode * @param TNode $child

    * The removed child. *

    * @return TNode|false 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 * @template TNode of DOMNode * @param TNode $node

    * The appended child. *

    * @return TNode|false 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|false 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) {} /** * @removed 8.0 */ public function getFeature($feature, $version) {} /** * @removed 8.0 */ public function setUserData($key, $data, $handler) {} /** * @removed 8.0 */ 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 * @removed 8.4 */ #[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("The property is deprecated", since: "8.4")] #[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("The property is deprecated", since: "8.4")] #[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; /** * @var 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' => 'null'], default: '')] public $ownerDocument; /** * 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|null'], 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 * * @template-covariant TNode of DOMNode|DOMNameSpaceNode * @implements IteratorAggregate */ 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 TNode|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. * * @template-covariant TNode of DOMNode * @implements IteratorAggregate */ 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 TNode|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 {} /** * @removed 8.0 * @param DOMNode $arg * @return void */ public function setNamedItem(DOMNode $arg) {} /** * @removed 8.0 * @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 TNode|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 {} /** * @removed 8.0 * @param DOMNode $arg [optional] */ public function setNamedItemNS(DOMNode $arg) {} /** * @removed 8.0 * @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|false The attribute node or false if there is none. */ 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|null 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 */ #[Deprecated("The property is deprecated", since: "8.4")] #[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 */ #[Deprecated("The property is deprecated", since: "8.4")] #[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 */ #[Deprecated("The property is deprecated", since: "8.4")] #[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|false * 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; } */ class NodeList implements \IteratorAggregate, \Countable { public int $length; public function count(): int {} /** * @return \Iterator */ public function getIterator(): \Iterator {} /** @return TNode|null */ public function item(int $index): ?Node {} } /** * @since 8.4 * @implements \IteratorAggregate */ class NamedNodeMap implements \IteratorAggregate, \Countable { public int $length; public function item(int $index): ?Attr {} public function getNamedItem(string $qualifiedName): ?Attr {} public function getNamedItemNS(?string $namespace, string $localName): ?Attr {} public function count(): int {} /** * @return \Iterator */ public function getIterator(): \Iterator {} } /** * @since 8.4 * * @template TDtdNode of Entity|Notation Should be template-covariant but DocBlock::getTagsByName() does not support it * @implements \IteratorAggregate */ class DtdNamedNodeMap implements \IteratorAggregate, \Countable { public int $length; /** @return TDtdNode|null */ public function item(int $index): Entity|Notation|null {} /** @return TDtdNode|null */ public function getNamedItem(string $qualifiedName): Entity|Notation|null {} /** @return TDtdNode|null */ public function getNamedItemNS(?string $namespace, string $localName): Entity|Notation|null {} public function count(): int {} /** @return \Iterator */ public function getIterator(): \Iterator {} } /** * @since 8.4 * @implements \IteratorAggregate */ class HTMLCollection implements \IteratorAggregate, \Countable { public int $length; public function item(int $index): ?Element {} public function namedItem(string $key): ?Element {} public function count(): int {} /** * @return \Iterator */ public function getIterator(): \Iterator {} } /** * @since 8.4 */ final class XPath { public Document $document; public bool $registerNodeNamespaces; public function __construct(Document $document, bool $registerNodeNS = true) {} /** @return null|bool|float|string|NodeList */ public function evaluate(string $expression, ?Node $contextNode = null, bool $registerNodeNS = true): null|bool|float|string|NodeList {} /** @return NodeList */ public function query(string $expression, ?Node $contextNode = null, bool $registerNodeNS = true): NodeList {} public function registerNamespace(string $prefix, string $namespace): bool {} public function registerPhpFunctions(string|array|null $restrict = null): void {} public function registerPhpFunctionNS(string $namespaceURI, string $name, callable $callable): void {} public static function quote(string $str): string {} } /** * @since 8.4 */ final class TokenList implements \IteratorAggregate, \Countable { private function __construct() {} public int $length; public function item(int $index): ?string {} public function contains(string $token): bool {} public function add(string ...$tokens): void {} public function remove(string ...$tokens): void {} public function toggle(string $token, ?bool $force = null): bool {} public function replace(string $token, string $newToken): bool {} public function supports(string $token): bool {} public string $value; public function count(): int {} public function getIterator(): \Iterator {} } /** * @since 8.4 */ interface ParentNode { public function append(Node|string ...$nodes): void; public function prepend(Node|string ...$nodes): void; public function replaceChildren(Node|string ...$nodes): void; public function querySelector(string $selectors): ?Element; /** @return NodeList */ public function querySelectorAll(string $selectors): NodeList; } /** * @since 8.4 */ interface ChildNode { public function remove(): void; public function before(Node|string ...$nodes): void; public function after(Node|string ...$nodes): void; public function replaceWith(Node|string ...$nodes): void; } /** * @since 8.4 */ enum AdjacentPosition implements \BackedEnum, \UnitEnum { case BeforeBegin = "beforebegin"; case AfterBegin = "afterbegin"; case BeforeEnd = "beforeend"; case AfterEnd = "afterend"; public static function cases(): array {} public static function from(string|int $value): static {} public static function tryFrom(string|int $value): ?static {} } /** * @since 8.4 */ class Node { final private function __construct() {} public int $nodeType; public string $nodeName; public string $baseURI; public bool $isConnected; public ?Document $ownerDocument; public function getRootNode(array $options = []): Node {} public ?Node $parentNode; public ?Element $parentElement; public function hasChildNodes(): bool {} /** @var NodeList */ public NodeList $childNodes; public ?Node $firstChild; public ?Node $lastChild; public ?Node $previousSibling; public ?Node $nextSibling; public ?string $nodeValue; public ?string $textContent; public function normalize(): void {} public function cloneNode(bool $deep = false): Node {} public function isEqualNode(?Node $otherNode): bool {} public function isSameNode(?Node $otherNode): bool {} public const int DOCUMENT_POSITION_DISCONNECTED = 0x01; public const int DOCUMENT_POSITION_PRECEDING = 0x02; public const int DOCUMENT_POSITION_FOLLOWING = 0x04; public const int DOCUMENT_POSITION_CONTAINS = 0x08; public const int DOCUMENT_POSITION_CONTAINED_BY = 0x10; public const int DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20; public function compareDocumentPosition(Node $other): int {} public function contains(?Node $other): bool {} public function lookupPrefix(?string $namespace): ?string {} public function lookupNamespaceURI(?string $prefix): ?string {} public function isDefaultNamespace(?string $namespace): bool {} public function insertBefore(Node $node, ?Node $child): Node {} public function appendChild(Node $node): Node {} public function replaceChild(Node $node, Node $child): Node {} public function removeChild(Node $child): Node {} public function getLineNo(): int {} public function getNodePath(): string {} public function C14N(bool $exclusive = false, bool $withComments = false, ?array $xpath = null, ?array $nsPrefixes = null): string|false {} public function C14NFile(string $uri, bool $exclusive = false, bool $withComments = false, ?array $xpath = null, ?array $nsPrefixes = null): int|false {} public function __sleep(): array {} public function __wakeup(): void {} } /** * @since 8.4 */ class DocumentFragment extends Node implements ParentNode { public ?Element $firstElementChild; public ?Element $lastElementChild; public int $childElementCount; /** * @since 8.5 */ public \Dom\HTMLCollection $children; public function appendXml(string $data): bool {} public function append(Node|string ...$nodes): void {} public function prepend(Node|string ...$nodes): void {} public function replaceChildren(Node|string ...$nodes): void {} public function querySelector(string $selectors): ?Element {} /** @return NodeList */ public function querySelectorAll(string $selectors): NodeList {} } /** * @since 8.4 */ class Document extends Node implements ParentNode { /** @readonly */ public Implementation $implementation; public string $URL; public string $documentURI; public string $characterSet; public string $charset; public string $inputEncoding; public ?DocumentType $doctype; public ?Element $documentElement; /** * @since 8.5 */ public \Dom\HTMLCollection $children; public function getElementsByTagName(string $qualifiedName): HTMLCollection {} public function getElementsByTagNameNS(?string $namespace, string $localName): HTMLCollection {} public function createElement(string $localName): Element {} public function createElementNS(?string $namespace, string $qualifiedName): Element {} public function createDocumentFragment(): DocumentFragment {} public function createTextNode(string $data): Text {} public function createCDATASection(string $data): CDATASection {} public function createComment(string $data): Comment {} public function createProcessingInstruction(string $target, string $data): ProcessingInstruction {} public function importNode(?Node $node, bool $deep = false): Node {} public function adoptNode(Node $node): Node {} public function createAttribute(string $localName): Attr {} public function createAttributeNS(?string $namespace, string $qualifiedName): Attr {} public ?Element $firstElementChild; public ?Element $lastElementChild; public int $childElementCount; public function getElementById(string $elementId): ?Element {} public function registerNodeClass(string $baseClass, ?string $extendedClass): void {} public function schemaValidate(string $filename, int $flags = 0): bool {} public function schemaValidateSource(string $source, int $flags = 0): bool {} public function relaxNgValidate(string $filename): bool {} public function relaxNgValidateSource(string $source): bool {} public function append(Node|string ...$nodes): void {} public function prepend(Node|string ...$nodes): void {} public function replaceChildren(Node|string ...$nodes): void {} public function importLegacyNode(\DOMNode $node, bool $deep = false): Node {} public function querySelector(string $selectors): ?Element {} /** @return NodeList */ public function querySelectorAll(string $selectors): NodeList {} /** * @since 8.5 */ public function getElementsByClassName(string $classNames): HTMLCollection {} public ?HTMLElement $body; public ?HTMLElement $head; public string $title; } /** * @since 8.4 */ final class HTMLDocument extends Document { public static function createEmpty(string $encoding = "UTF-8"): HTMLDocument {} public static function createFromFile(string $path, int $options = 0, ?string $overrideEncoding = null): HTMLDocument {} public static function createFromString(string $source, int $options = 0, ?string $overrideEncoding = null): HTMLDocument {} public function saveXml(?Node $node = null, int $options = 0): string|false {} public function saveXmlFile(string $filename, int $options = 0): int|false {} public function saveHtml(?Node $node = null): string {} public function saveHtmlFile(string $filename): int|false {} public function debugGetTemplateCount(): int {} } /** * @since 8.4 */ final class XMLDocument extends Document { public static function createEmpty(string $version = "1.0", string $encoding = "UTF-8"): XMLDocument {} public static function createFromFile(string $path, int $options = 0, ?string $overrideEncoding = null): XMLDocument {} public static function createFromString(string $source, int $options = 0, ?string $overrideEncoding = null): XMLDocument {} public string $xmlEncoding; public bool $xmlStandalone; public string $xmlVersion; public bool $formatOutput; public function createEntityReference(string $name): EntityReference {} public function validate(): bool {} public function xinclude(int $options = 0): int {} public function saveXml(?Node $node = null, int $options = 0): string|false {} public function saveXmlFile(string $filename, int $options = 0): int|false {} } /** * @since 8.4 */ class CharacterData extends Node implements ChildNode { public ?Element $previousElementSibling; public ?Element $nextElementSibling; public string $data; public int $length; public function substringData(int $offset, int $count): string {} public function appendData(string $data): void {} public function insertData(int $offset, string $data): void {} public function deleteData(int $offset, int $count): void {} public function replaceData(int $offset, int $count, string $data): void {} public function remove(): void {} public function before(Node|string ...$nodes): void {} public function after(Node|string ...$nodes): void {} public function replaceWith(Node|string ...$nodes): void {} } /** * @since 8.4 */ class Attr extends Node { public ?string $namespaceURI; public ?string $prefix; public string $localName; public string $name; public string $value; public ?Element $ownerElement; public bool $specified; public function isId(): bool {} public function rename(?string $namespaceURI, string $qualifiedName): void {} } /** * @since 8.4 */ class Element extends Node implements ParentNode, ChildNode { public ?string $namespaceURI; public ?string $prefix; public string $localName; public string $tagName; public string $id; public string $className; /** * @since 8.5 */ public \Dom\HTMLCollection $children; /** @readonly */ public TokenList $classList; public function hasAttributes(): bool {} public NamedNodeMap $attributes; public function getAttributeNames(): array {} public function getAttribute(string $qualifiedName): ?string {} public function getAttributeNS(?string $namespace, string $localName): ?string {} public function setAttribute(string $qualifiedName, string $value): void {} public function setAttributeNS(?string $namespace, string $qualifiedName, string $value): void {} public function removeAttribute(string $qualifiedName): void {} public function removeAttributeNS(?string $namespace, string $localName): void {} public function toggleAttribute(string $qualifiedName, ?bool $force = null): bool {} public function hasAttribute(string $qualifiedName): bool {} public function hasAttributeNS(?string $namespace, string $localName): bool {} public function getAttributeNode(string $qualifiedName): ?Attr {} public function getAttributeNodeNS(?string $namespace, string $localName): ?Attr {} public function setAttributeNode(Attr $attr): ?Attr {} public function setAttributeNodeNS(Attr $attr): ?Attr {} public function removeAttributeNode(Attr $attr): Attr {} public function getElementsByTagName(string $qualifiedName): HTMLCollection {} public function getElementsByTagNameNS(?string $namespace, string $localName): HTMLCollection {} public function insertAdjacentElement(AdjacentPosition $where, Element $element): ?Element {} public function insertAdjacentText(AdjacentPosition $where, string $data): void {} public ?Element $firstElementChild; public ?Element $lastElementChild; public int $childElementCount; public ?Element $previousElementSibling; public ?Element $nextElementSibling; public function setIdAttribute(string $qualifiedName, bool $isId): void {} public function setIdAttributeNS(?string $namespace, string $qualifiedName, bool $isId): void {} public function setIdAttributeNode(Attr $attr, bool $isId): void {} public function remove(): void {} public function before(Node|string ...$nodes): void {} public function after(Node|string ...$nodes): void {} public function replaceWith(Node|string ...$nodes): void {} public function append(Node|string ...$nodes): void {} public function prepend(Node|string ...$nodes): void {} public function replaceChildren(Node|string ...$nodes): void {} public function querySelector(string $selectors): ?Element {} /** @return NodeList */ public function querySelectorAll(string $selectors): NodeList {} public function closest(string $selectors): ?Element {} public function matches(string $selectors): bool {} public string $innerHTML; public string $outerHTML; public string $substitutedNodeValue; /** @return list */ public function getInScopeNamespaces(): array {} /** @return list */ public function getDescendantNamespaces(): array {} public function rename(?string $namespaceURI, string $qualifiedName): void {} /** * @since 8.5 */ public function getElementsByClassName(string $classNames): HTMLCollection {} /** * @since 8.5 */ public function insertAdjacentHTML(\Dom\AdjacentPosition $where, string $string): void {} } /** * @since 8.4 */ class HTMLElement extends Element {} /** * @since 8.4 */ class Text extends CharacterData { public function splitText(int $offset): Text {} public string $wholeText; } /** * @since 8.4 */ class Comment extends CharacterData {} /** * @since 8.4 */ class CDATASection extends Text {} /** * @since 8.4 */ class DocumentType extends Node implements ChildNode { public string $name; public DtdNamedNodeMap $entities; public DtdNamedNodeMap $notations; public string $publicId; public string $systemId; public ?string $internalSubset; public function remove(): void {} public function before(Node|string ...$nodes): void {} public function after(Node|string ...$nodes): void {} public function replaceWith(Node|string ...$nodes): void {} } /** * @since 8.4 */ class Notation extends Node { public string $publicId; public string $systemId; } /** * @since 8.4 */ class Entity extends Node { public ?string $publicId; public ?string $systemId; public ?string $notationName; } /** * @since 8.4 */ class EntityReference extends Node {} /** * @since 8.4 */ class ProcessingInstruction extends CharacterData { public string $target; } /** * @since 8.4 */ class Sqlite {} /** * @since 8.4 */ class RandomError {} /** * @since 8.4 */ class BrokenRandomEngineError {} /** * @since 8.4 */ class RandomException {} /** * @since 8.4 */ class Mysql {} /** * @since 8.4 */ function import_simplexml(object $node): Attr|Element {} /** * @since 8.4 */ const INDEX_SIZE_ERR = 1, STRING_SIZE_ERR = 2, HIERARCHY_REQUEST_ERR = 3, WRONG_DOCUMENT_ERR = 4, INVALID_CHARACTER_ERR = 5; /** * @since 8.4 */ const NO_DATA_ALLOWED_ERR = 6, NO_MODIFICATION_ALLOWED_ERR = 7, NOT_FOUND_ERR = 8, NOT_SUPPORTED_ERR = 9, INUSE_ATTRIBUTE_ERR = 10; /** * @since 8.4 */ const INVALID_STATE_ERR = 11, SYNTAX_ERR = 12, INVALID_MODIFICATION_ERR = 13, NAMESPACE_ERR = 14, VALIDATION_ERR = 16, HTML_NO_DEFAULT_NS = 2147483648; * @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 static */ 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 */ final class Vector implements Sequence { public const MIN_CAPACITY = 8; /** * 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 $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 = ''): 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|int */ 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. * @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 list 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 * * @return void */ public function offsetSet(mixed $offset, mixed $value) {} /** * @param int $offset */ public function offsetUnset(mixed $offset): void {} } /** * @template TValue * @implements Sequence */ final class Deque implements Sequence { /** * 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-deque.construct.php */ public function __construct(iterable $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 list 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 * * @return void */ public function offsetSet(mixed $offset, mixed $value) {} /** * @param int $offset */ public function offsetUnset(mixed $offset): void {} } /** * @template TKey * @template TValue * @implements Collection */ final 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(iterable $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. * * @return void * * @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. * * @return void * * @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.

    * @return void * @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. * * @return void * * @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. * * @return void * * @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. * * @return void * * @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. * * @return void * * @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 * * @return void */ 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 */ final 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. * * @return void * * @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 */ final 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. * * @return void * * @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. * * @return void * * @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 = ''): 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. * * @return void */ public function remove(...$values) {} /** * Reverses the set in-place. * * @return void * * @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. * * @return void * * @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 list 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 * * @return void */ 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 */ final 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. * * @return void * *

    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 list 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. * * @return void */ 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 * * @return void */ 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 */ final 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. * * @return void * *

    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 list 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. * * @return void */ 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 * * @return void */ 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 */ final 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 * * @return void */ 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 list 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() {} } * @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 Traversable; /** * Creates a sequence containing the given values. * @template TValue * @param iterable $values * @return Seq * @since PECL ds 2.0.0 */ function seq(iterable $values = []): Seq {} /** * Creates a map containing the given values. * @template TKey * @template TValue * @param iterable $values * @return Map * @since PECL ds 2.0.0 */ function map(iterable $values = []): Map {} /** * Creates a set containing the given values. * @template TValue * @param iterable $values * @return Set * @since PECL ds 2.0.0 */ function set(iterable $values = []): Set {} /** * Creates a heap containing the given values. * @template TValue * @param iterable $values * @param null|callable(TValue, TValue): int $comparator * @return Heap * @since PECL ds 2.0.0 */ function heap(iterable $values = [], ?callable $comparator = null): Heap {} /** * Key allows objects to define custom equality when used as map keys or set values. * @since PECL ds 2.0.0 */ interface Key { /** * Determines whether another value is equal to this instance. * @param mixed $other */ public function equals($other): bool; /** * Returns a value used as this object's hash. * @return mixed */ public function hash(); } /** * @template TValue * @implements IteratorAggregate * @implements ArrayAccess * @since PECL ds 2.0.0 */ final class Seq implements Countable, IteratorAggregate, JsonSerializable, ArrayAccess { public const MIN_CAPACITY = 8; /** * @param iterable $values */ public function __construct(iterable $values = []) {} public function allocate(int $capacity): void {} /** * @param callable(TValue): TValue $callback */ public function apply(callable $callback): void {} public function capacity(): int {} public function clear(): void {} /** * @param TValue ...$values */ public function contains(...$values): bool {} /** * @return Seq */ public function copy(): Seq {} public function count(): int {} /** * @param null|callable(TValue): bool $callback * @return Seq */ public function filter(?callable $callback = null): Seq {} /** * @param TValue $value * @return int|false */ public function find($value) {} /** * @return TValue */ public function first() {} /** * @return Traversable */ public function getIterator(): Traversable {} /** * @return TValue */ public function get(int $index) {} /** * @param TValue ...$values */ public function insert(int $index, ...$values): void {} public function isEmpty(): bool {} public function join(string $glue = ''): string {} /** * @return array */ public function jsonSerialize(): array {} /** * @return TValue */ public function last() {} /** * @template TReturn * @param callable(TValue): TReturn $callback * @return Seq */ public function map(callable $callback): Seq {} /** * @param iterable $values * @return Seq */ public function merge($values): Seq {} /** * @return TValue */ public function pop() {} /** * @param TValue ...$values */ public function push(...$values): void {} /** * @template TInitial * @template TReturn * @param callable(TInitial|TReturn|null, TValue): TReturn $callback * @param TInitial|null $initial * @return TReturn|null */ public function reduce(callable $callback, $initial = null) {} /** * @return TValue */ public function remove(int $index) {} public function reverse(): void {} /** * @return Seq */ public function reversed(): Seq {} public function rotate(int $rotations): void {} /** * @param TValue $value */ public function set(int $index, $value): void {} /** * @return TValue */ public function shift() {} /** * @return Seq */ public function slice(int $index, ?int $length = null): Seq {} /** * @param null|callable(TValue, TValue): int $comparator */ public function sort(?callable $comparator = null): void {} /** * @param null|callable(TValue, TValue): int $comparator * @return Seq */ public function sorted(?callable $comparator = null): Seq {} /** * @return int|float */ public function sum() {} /** * @return array */ public function toArray(): array {} /** * @param TValue ...$values */ public function unshift(...$values): void {} /** * @return array */ public function __serialize(): array {} public function __unserialize(array $data): void {} public function offsetExists(mixed $offset): bool {} public function offsetGet(mixed $offset): mixed {} public function offsetSet(mixed $offset, mixed $value): void {} public function offsetUnset(mixed $offset): void {} } /** * @template TKey * @template TValue * @implements IteratorAggregate * @implements ArrayAccess * @since PECL ds 2.0.0 */ final class Map implements Countable, IteratorAggregate, JsonSerializable, ArrayAccess { public const MIN_CAPACITY = 8; /** * @param iterable $values */ public function __construct(iterable $values = []) {} public function allocate(int $capacity): void {} /** * @param callable(TKey, TValue): TValue $callback */ public function apply(callable $callback): void {} public function capacity(): int {} public function clear(): void {} /** @return Map */ public function copy(): Map {} public function count(): int {} /** @return Map */ public function diff(Map $map): Map {} /** * @param null|callable(TKey, TValue): bool $callback * @return Map */ public function filter(?callable $callback = null): Map {} /** @return Pair */ public function first(): Pair {} /** * @param TKey $key * @param TValue|null $default * @return TValue|null */ public function get($key, $default = null) {} /** @return Traversable */ public function getIterator(): Traversable {} /** @param TKey $key */ public function hasKey($key): bool {} /** @param TValue $value */ public function hasValue($value): bool {} /** @return Map */ public function intersect(Map $map): Map {} public function isEmpty(): bool {} /** @return mixed */ public function jsonSerialize(): mixed {} /** @return Set */ public function keys(): Set {} /** @param null|callable(TKey, TKey): int $comparator */ public function ksort(?callable $comparator = null): void {} /** * @param null|callable(TKey, TKey): int $comparator * @return Map */ public function ksorted(?callable $comparator = null): Map {} /** @return Pair */ public function last(): Pair {} /** * @template TReturn * @param callable(TKey, TValue): TReturn $callback * @return Map */ public function map(callable $callback): Map {} /** * @param iterable $values * @return Map */ public function merge($values): Map {} /** @return Seq> */ public function pairs(): Seq {} /** * @param TKey $key * @param TValue $value */ public function put($key, $value): void {} /** @param iterable $values */ public function putAll($values): void {} /** * @template TInitial * @template TReturn * @param callable(TInitial|TReturn|null, TKey, TValue): TReturn $callback * @param TInitial|null $initial * @return TReturn|null */ public function reduce(callable $callback, $initial = null) {} /** * @param TKey $key * @param TValue|null $default * @return TValue|null */ public function remove($key, $default = null) {} public function reverse(): void {} /** @return Map */ public function reversed(): Map {} /** @return Pair */ public function skip(int $position): Pair {} /** @return Map */ public function slice(int $index, ?int $length = null): Map {} /** @param null|callable(TValue, TValue): int $comparator */ public function sort(?callable $comparator = null): void {} /** * @param null|callable(TValue, TValue): int $comparator * @return Map */ public function sorted(?callable $comparator = null): Map {} /** @return int|float */ public function sum() {} /** @return array */ public function toArray(): array {} /** @return Map */ public function union(Map $map): Map {} /** @return Seq */ public function values(): Seq {} /** @return Map */ public function xor(Map $map): Map {} public function __serialize(): array {} public function __unserialize(array $data): void {} public function offsetExists(mixed $offset): bool {} public function &offsetGet(mixed $offset): mixed {} public function offsetSet(mixed $offset, mixed $value): void {} public function offsetUnset(mixed $offset): void {} } /** * @template TKey * @template TValue * @since PECL ds 2.0.0 */ final readonly class Pair implements JsonSerializable { /** @var TKey */ public mixed $key; /** @var TValue */ public mixed $value; /** * @param TKey $key * @param TValue $value */ public function __construct($key, $value) {} /** @return array{key: TKey, value: TValue} */ public function jsonSerialize(): array {} /** @return array{key: TKey, value: TValue} */ public function toArray(): array {} /** @return array{key: TKey, value: TValue} */ public function __serialize(): array {} public function __unserialize(array $data): void {} } /** * @template TValue * @implements IteratorAggregate * @implements ArrayAccess * @since PECL ds 2.0.0 */ final class Set implements Countable, IteratorAggregate, JsonSerializable, ArrayAccess { public const MIN_CAPACITY = 8; /** @param iterable $values */ public function __construct(iterable $values = []) {} /** @param TValue ...$values */ public function add(...$values): void {} public function allocate(int $capacity): void {} public function capacity(): int {} public function clear(): void {} /** @param TValue ...$values */ public function contains(...$values): bool {} /** @return Set */ public function copy(): Set {} public function count(): int {} /** @return Set */ public function diff(Set $set): Set {} /** * @param null|callable(TValue): bool $callback * @return Set */ public function filter(?callable $callback = null): Set {} /** @return TValue */ public function first() {} /** @return TValue */ public function get(int $index) {} /** @return Traversable */ public function getIterator(): Traversable {} /** @return Set */ public function intersect(Set $set): Set {} public function isEmpty(): bool {} public function join(string $glue = ''): string {} /** @return array */ public function jsonSerialize(): array {} /** @return TValue */ public function last() {} /** * @template TReturn * @param callable(TValue): TReturn $callback * @return Set */ public function map(callable $callback): Set {} /** * @param iterable $values * @return Set */ public function merge($values): Set {} /** * @template TInitial * @template TReturn * @param callable(TInitial|TReturn|null, TValue): TReturn $callback * @param TInitial|null $initial * @return TReturn|null */ public function reduce(callable $callback, $initial = null) {} /** @param TValue ...$values */ public function remove(...$values): void {} public function reverse(): void {} /** @return Set */ public function reversed(): Set {} /** @return Set */ public function slice(int $index, ?int $length = null): Set {} /** @param null|callable(TValue, TValue): int $comparator */ public function sort(?callable $comparator = null): void {} /** * @param null|callable(TValue, TValue): int $comparator * @return Set */ public function sorted(?callable $comparator = null): Set {} /** @return int|float */ public function sum() {} /** @return array */ public function toArray(): array {} /** @return Set */ public function union(Set $set): Set {} /** @return Set */ public function xor(Set $set): Set {} public function __serialize(): array {} public function __unserialize(array $data): void {} public function offsetExists(mixed $offset): bool {} public function offsetGet(mixed $offset): mixed {} public function offsetSet(mixed $offset, mixed $value): void {} public function offsetUnset(mixed $offset): void {} } /** * @template TValue * @implements IteratorAggregate * @since PECL ds 2.0.0 */ final class Heap implements Countable, IteratorAggregate, JsonSerializable { public const MIN_CAPACITY = 8; /** * @param iterable $values * @param null|callable(TValue, TValue): int $comparator */ public function __construct(iterable $values = [], ?callable $comparator = null) {} public function clear(): void {} /** @return Heap */ public function copy(): Heap {} public function count(): int {} /** @return Traversable */ public function getIterator(): Traversable {} public function isEmpty(): bool {} /** @return array */ public function jsonSerialize(): array {} /** @return TValue */ public function peek() {} /** @return TValue */ public function pop() {} /** @param TValue ...$values */ public function push(...$values): void {} /** @return array */ public function toArray(): array {} /** @return array */ public function __serialize(): array {} public function __unserialize(array $data): void {} } 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; } * 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 getLog() as $entry) { * var_dump($entry->getTrace()); * } */ class ExcimerLog implements ArrayAccess, Iterator { /** * ExcimerLog is not constructible by user code. Objects of this type * are available via: * - ExcimerProfiler::getLog() * - ExcimerProfiler::flush() * - The callback to ExcimerProfiler::setFlushCallback() */ final private function __construct() {} /** * Aggregate the stack traces and convert them to a line-based format * understood by Brendan Gregg's FlameGraph utility. Each stack trace is * represented as a series of function names, separated by semicolons. * After this identifier, there is a single space character, then a number * giving the number of times the stack appeared. Then there is a line * break. This is repeated for each unique stack trace. * * @return string */ public function formatCollapsed() {} /** * Produce an array with an element for every function which appears in * the log. The key is a human-readable unique identifier for the function, * method or closure. The value is an associative array with the following * elements: * * - self: The number of events in which the function itself was running, * no other userspace function was being called. This includes time * spent in internal functions that this function called. * - inclusive: The number of events in which this function appeared * somewhere in the stack. * * And optionally the following elements, if they are relevant: * * - file: The filename in which the function appears * - line: The exact line number at which the first relevant event * occurred. * - class: The class name in which the method is defined * - function: The name of the function or method * - closure_line: The line number at which the closure was defined * * The event counts in the "self" and "inclusive" fields are adjusted for * overruns. They represent an estimate of the number of profiling periods * in which those functions were present. * * @return array */ public function aggregateByFunction() {} /** * Get an array which can be JSON encoded for import into speedscope * * @return array */ public function getSpeedscopeData() {} /** * Get the total number of profiling periods represented by this log. * * @return int */ public function getEventCount() {} /** * Get the current ExcimerLogEntry object. Part of the Iterator interface. * * @return ExcimerLogEntry|null */ public function current() {} /** * Get the current integer key or null. Part of the Iterator interface. * * @return int|null */ public function key() {} /** * Advance to the next log entry. Part of the Iterator interface. */ public function next() {} /** * Rewind back to the first log entry. Part of the Iterator interface. */ public function rewind() {} /** * Check if the current position is valid. Part of the Iterator interface. * * @return bool */ public function valid() {} /** * Get the number of log entries contained in this log. This is always less * than or equal to the number returned by getEventCount(), which includes * overruns. * * @return int */ public function count() {} /** * Determine whether a log entry exists at the specified array offset. * Part of the ArrayAccess interface. * * @param int $offset * @return bool */ public function offsetExists($offset) {} /** * Get the ExcimerLogEntry object at the specified array offset. * * @param int $offset * @return ExcimerLogEntry|null */ public function offsetGet($offset) {} /** * This function is included for compliance with the ArrayAccess interface. * It raises a warning and does nothing. * * @param int $offset * @param mixed $value */ public function offsetSet($offset, $value) {} /** * This function is included for compliance with the ArrayAccess interface. * It raises a warning and does nothing. * * @param int $offset */ public function offsetUnset($offset) {} } setCallback($callback); * $timer->setInterval($interval); * $timer->start(); * return $timer; * * Note that you must keep a copy of the return value. If it goes out of scope, * the object will be destroyed and the timer will stop. * * If the callback is not callable, a warning is raised and null is returned. * * @param callable $callback * @param float $interval * @return ExcimerTimer|null */ function excimer_set_timeout($callback, $interval) {} * 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 = null, 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 = null, &$height = null, &$image_type = null): 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$ expect_expectl(), when EOF is reached. * @link https://www.php.net/manual/en/expect.constants.php */ const EXP_EOF = -11; /** * Value, returned by expect_expectl() upon timeout of seconds, specified in value of expect.timeout * @link https://www.php.net/manual/en/expect.constants.php */ const EXP_TIMEOUT = -2; /** * Value, returned by expect_expectl() if no pattern have been matched. * @link https://www.php.net/manual/en/expect.constants.php */ const EXP_FULLBUFFER = -5; /** * Execute command via Bourne shell, and open the PTY stream to the process * * @param string $command Command to execute. * @return resource|false Returns an open PTY stream to the processes stdio, stdout, and stderr. * On failure this function returns FALSE. * @since PECL expect >= 0.1.0 * @link https://www.php.net/manual/en/function.expect-popen.php */ function expect_popen(string $command) { unset($command); return false; } /** * Waits until the output from a process matches one of the patterns, a specified time period has passed, * or an EOF is seen. * * If match is provided, then it is filled with the result of search. The matched string can be found in match[0]. * The match substrings (according to the parentheses) in the original pattern can be found in match[1], match[2], * and so on, up to match[9] (the limitation of libexpect). * * @param resource $expect An Expect stream, previously opened with expect_popen() * @param array $cases

    An array of expect cases. Each expect case is an indexed array, as described in the following table:

    *

    * * Index Key * Value Type * Description * Is Mandatory * Default Value * * * 0 * string * pattern, that will be matched against the output from the stream * Yes * * * * 1 * mixed * value, that will be returned by this function, if the pattern matches * Yes * * * * 2 * integer * pattern type, one of: EXP_GLOB, EXP_EXACT or EXP_REGEXP * No * EXP_GLOB * *

    * @param array &$match * * @return int Returns value associated with the pattern that was matched. * On failure this function returns: EXP_EOF, EXP_TIMEOUT or EXP_FULLBUFFER * @since PECL expect >= 0.1.0 * @link https://www.php.net/manual/en/function.expect-expectl.php */ function expect_expectl($expect, array $cases, array &$match = []): int { unset($expect, $cases, $match); return 0; } 'int'], default: '')] $flags = 0, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $magic_database = null ) {} /** * @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(true)] #[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(true)] #[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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] #[\JetBrains\PhpStorm\Deprecated('Deprecated: it has no effect', since: '8.5')] function finfo_close(#[LanguageLevelTypeAware(['8.1' => 'finfo'], default: 'resource')] $finfo) {} /** * (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 = 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 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, #[\JetBrains\PhpStorm\Deprecated('Deprecated: it has no effect', since: '8.5')] $context = null): string|false {} /** * Detect MIME Content-type for a file * @link https://php.net/manual/en/function.mime-content-type.php * @param resource|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 * One of INPUT_GET, INPUT_POST, * INPUT_COOKIE, INPUT_SERVER, or * INPUT_ENV. *

    * @param string $var_name

    * Name of a variable to get. *

    * @param int $filter [optional]

    * The ID of the filter to apply. The * manual page lists the available filters. *

    * @param array|int $options

    * Associative array of options or bitwise disjunction of flags. If filter * accepts options, flags can be provided in "flags" field of array. *

    * @return mixed Value of the requested variable on success, FALSE if the filter fails, * or NULL if the variable_name variable is not set. * If the flag FILTER_NULL_ON_FAILURE is used, it * returns FALSE if the variable is not set and NULL if the filter fails. */ #[Pure] function filter_input(int $type, string $var_name, int $filter = FILTER_DEFAULT, array|int $options = 0): mixed {} /** * Filters a variable with a specified filter * @link https://php.net/manual/en/function.filter-var.php * @param mixed $value

    * Value to filter. *

    * @param int $filter [optional]

    * The ID of the filter to apply. The * manual page lists the available filters. *

    * @param array|int $options

    * Associative array of options or bitwise disjunction of flags. If filter * accepts options, flags can be provided in "flags" field of array. For * the "callback" filter, callable type should be passed. The * callback must accept one argument, the value to be filtered, and return * the value after filtering/sanitizing it. *

    *

    * * // for filters that accept options, use this format * $options = array( * 'options' => array( * 'default' => 3, // value to return if the filter fails * // other options here * 'min_range' => 0 * ), * 'flags' => FILTER_FLAG_ALLOW_OCTAL, * ); * $var = filter_var('0755', FILTER_VALIDATE_INT, $options); * // for filter that only accept flags, you can pass them directly * $var = filter_var('oops', FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); * // for filter that only accept flags, you can also pass as an array * $var = filter_var('oops', FILTER_VALIDATE_BOOLEAN, * array('flags' => FILTER_NULL_ON_FAILURE)); * // callback validate filter * function foo($value) * { * // Expected format: Surname, GivenNames * if (strpos($value, ", ") === false) return false; * list($surname, $givennames) = explode(", ", $value, 2); * $empty = (empty($surname) || empty($givennames)); * $notstrings = (!is_string($surname) || !is_string($givennames)); * if ($empty || $notstrings) { * return false; * } else { * return $value; * } * } * $var = filter_var('Doe, Jane Sue', FILTER_CALLBACK, array('options' => 'foo')); * *

    * @return mixed the filtered data, or FALSE if the filter fails. */ #[Pure] function filter_var(mixed $value, int $filter = FILTER_DEFAULT, array|int $options = 0): mixed {} /** * Gets external variables and optionally filters them * @link https://php.net/manual/en/function.filter-input-array.php * @param int $type

    * One of INPUT_GET, INPUT_POST, * INPUT_COOKIE, INPUT_SERVER, or * INPUT_ENV. *

    * @param array|int $options [optional]

    * An array defining the arguments. A valid key is a string * containing a variable name and a valid value is either a filter type, or an array * optionally specifying the filter, flags and options. If the value is an * array, valid keys are filter which specifies the * filter type, * flags which specifies any flags that apply to the * filter, and options which specifies any options that * apply to the filter. See the example below for a better understanding. *

    *

    * This parameter can be also an integer holding a filter constant. Then all values in the * input array are filtered by this filter. *

    * @param bool $add_empty [optional]

    * Add missing keys as NULL to the return value. *

    * @return array|false|null An array containing the values of the requested variables on success, or FALSE * on failure. An array value will be FALSE if the filter fails, or NULL if * the variable is not set. Or if the flag FILTER_NULL_ON_FAILURE * is used, it returns FALSE if the variable is not set and NULL if the filter * fails. */ #[Pure] function filter_input_array(int $type, array|int $options = FILTER_DEFAULT, bool $add_empty = true): array|false|null {} /** * Gets multiple variables and optionally filters them * @link https://php.net/manual/en/function.filter-var-array.php * @param array $array

    * An array with string keys containing the data to filter. *

    * @param array|int $options [optional]

    * An array defining the arguments. A valid key is a string * containing a variable name and a valid value is either a * filter type, or an * array optionally specifying the filter, flags and options. * If the value is an array, valid keys are filter * which specifies the filter type, * flags which specifies any flags that apply to the * filter, and options which specifies any options that * apply to the filter. See the example below for a better understanding. *

    *

    * This parameter can be also an integer holding a filter constant. Then all values in the * input array are filtered by this filter. *

    * @param bool $add_empty [optional]

    * Add missing keys as NULL to the return value. *

    * @return array|false|null An array containing the values of the requested variables on success, or FALSE * on failure. An array value will be FALSE if the filter fails, or NULL if * the variable is not set. */ #[Pure] function filter_var_array(array $array, array|int $options = FILTER_DEFAULT, bool $add_empty = true): array|false|null {} /** * Returns a list of all supported filters * @link https://php.net/manual/en/function.filter-list.php * @return array an array of names of all supported filters, empty array if there * are no such filters. Indexes of this array are not filter IDs, they can be * obtained with filter_id from a name instead. */ #[Pure] function filter_list(): array {} /** * Checks if variable of specified type exists * @link https://php.net/manual/en/function.filter-has-var.php * @param int $input_type

    * One of INPUT_GET, INPUT_POST, * INPUT_COOKIE, INPUT_SERVER, or * INPUT_ENV. *

    * @param string $var_name

    * Name of a variable to check. *

    * @return bool TRUE on success or FALSE on failure. */ #[Pure] function filter_has_var(int $input_type, string $var_name): bool {} /** * Returns the filter ID belonging to a named filter * @link https://php.net/manual/en/function.filter-id.php * @param string $name

    * Name of a filter to get. *

    * @return int|false ID of a filter on success or FALSE if filter doesn't exist. */ #[Pure] function filter_id(string $name): int|false {} /** * POST variables. * @link https://php.net/manual/en/filter.constants.php */ define('INPUT_POST', 0); /** * GET variables. * @link https://php.net/manual/en/filter.constants.php */ define('INPUT_GET', 1); /** * COOKIE variables. * @link https://php.net/manual/en/filter.constants.php */ define('INPUT_COOKIE', 2); /** * ENV variables. * @link https://php.net/manual/en/filter.constants.php */ define('INPUT_ENV', 4); /** * SERVER variables. * @link https://php.net/manual/en/filter.constants.php */ define('INPUT_SERVER', 5); /** * SESSION variables. * (not implemented yet) * @link https://php.net/manual/en/filter.constants.php * @removed 8.0 */ define('INPUT_SESSION', 6); /** * REQUEST variables. * (not implemented yet) * @link https://php.net/manual/en/filter.constants.php * @removed 8.0 */ define('INPUT_REQUEST', 99); /** * No flags. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_NONE', 0); /** * Flag used to require scalar as input * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_REQUIRE_SCALAR', 33554432); /** * Require an array as input. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_REQUIRE_ARRAY', 16777216); /** * Always returns an array. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FORCE_ARRAY', 67108864); /** * Use NULL instead of FALSE on failure. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_NULL_ON_FAILURE', 134217728); /** * ID of "int" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_VALIDATE_INT', 257); /** * ID of "boolean" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_VALIDATE_BOOLEAN', 258); /** * ID of "boolean" filter. * @link https://php.net/manual/en/filter.constants.php * @link https://php.net/manual/en/filter.filters.validate.php * @since 8.0 Using `FILTER_VALIDATE_BOOL` is preferred. */ define('FILTER_VALIDATE_BOOL', 258); /** * ID of "float" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_VALIDATE_FLOAT', 259); /** * ID of "validate_regexp" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_VALIDATE_REGEXP', 272); define('FILTER_VALIDATE_DOMAIN', 277); /** * ID of "validate_url" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_VALIDATE_URL', 273); /** * ID of "validate_email" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_VALIDATE_EMAIL', 274); /** * ID of "validate_ip" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_VALIDATE_IP', 275); define('FILTER_VALIDATE_MAC', 276); /** * ID of default ("string") filter. * @link https://php.net/manual/en/filter.constants.php * @deprecated 8.5 use FILTER_UNSAFE_RAW instead */ define('FILTER_DEFAULT', 516); /** * @since 7.3 */ define('FILTER_SANITIZE_ADD_SLASHES', 523); /** * ID of "unsafe_raw" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_UNSAFE_RAW', 516); /** * ID of "string" filter. * @link https://php.net/manual/en/filter.constants.php * @deprecated 8.1 */ define('FILTER_SANITIZE_STRING', 513); /** * ID of "stripped" filter. * @link https://php.net/manual/en/filter.constants.php * @deprecated 8.1 */ define('FILTER_SANITIZE_STRIPPED', 513); /** * ID of "encoded" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_SANITIZE_ENCODED', 514); /** * ID of "special_chars" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_SANITIZE_SPECIAL_CHARS', 515); define('FILTER_SANITIZE_FULL_SPECIAL_CHARS', 522); /** * ID of "email" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_SANITIZE_EMAIL', 517); /** * ID of "url" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_SANITIZE_URL', 518); /** * ID of "number_int" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_SANITIZE_NUMBER_INT', 519); /** * ID of "number_float" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_SANITIZE_NUMBER_FLOAT', 520); /** * ID of "magic_quotes" filter. * @link https://php.net/manual/en/filter.constants.php * @deprecated 7.4 * @removed 8.0 */ define('FILTER_SANITIZE_MAGIC_QUOTES', 521); /** * ID of "callback" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_CALLBACK', 1024); /** * Allow octal notation (0[0-7]+) in "int" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_ALLOW_OCTAL', 1); /** * Allow hex notation (0x[0-9a-fA-F]+) in "int" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_ALLOW_HEX', 2); /** * Strip characters with ASCII value less than 32. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_STRIP_LOW', 4); /** * Strip characters with ASCII value greater than 127. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_STRIP_HIGH', 8); define('FILTER_FLAG_STRIP_BACKTICK', 512); /** * Encode characters with ASCII value less than 32. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_ENCODE_LOW', 16); /** * Encode characters with ASCII value greater than 127. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_ENCODE_HIGH', 32); /** * Encode &. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_ENCODE_AMP', 64); /** * Don't encode ' and ". * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_NO_ENCODE_QUOTES', 128); /** * (No use for now.) * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_EMPTY_STRING_NULL', 256); /** * Allow fractional part in "number_float" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_ALLOW_FRACTION', 4096); /** * Allow thousand separator (,) in "number_float" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_ALLOW_THOUSAND', 8192); /** * Allow scientific notation (e, E) in * "number_float" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_ALLOW_SCIENTIFIC', 16384); /** * Require scheme in "validate_url" filter. * @link https://php.net/manual/en/filter.constants.php * @deprecated 7.3 * @removed 8.0 */ define('FILTER_FLAG_SCHEME_REQUIRED', 65536); /** * Require host in "validate_url" filter. * @link https://php.net/manual/en/filter.constants.php * @deprecated 7.3 * @removed 8.0 */ define('FILTER_FLAG_HOST_REQUIRED', 131072); /** * Require path in "validate_url" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_PATH_REQUIRED', 262144); /** * Require query in "validate_url" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_QUERY_REQUIRED', 524288); /** * Allow only IPv4 address in "validate_ip" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_IPV4', 1048576); /** * Allow only IPv6 address in "validate_ip" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_IPV6', 2097152); /** * Deny reserved addresses in "validate_ip" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_NO_RES_RANGE', 4194304); /** * Deny private addresses in "validate_ip" filter. * @link https://php.net/manual/en/filter.constants.php */ define('FILTER_FLAG_NO_PRIV_RANGE', 8388608); define('FILTER_FLAG_HOSTNAME', 1048576); define('FILTER_FLAG_EMAIL_UNICODE', 1048576); /** * filters Global IPs per RFC 6890 * @since 8.2 */ define('FILTER_FLAG_GLOBAL_RANGE', 268435456); define('FILTER_THROW_ON_FAILURE', 268435456); // End of filter v.0.11.0 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 {} /** * Publishes a Mercure update to all currently connected subscribers. * * @link https://frankenphp.dev/docs/mercure/ * @link https://mercure.rocks * * @param string|string[] $topics */ function mercure_publish(string|array $topics, string $data = '', bool $private = false, ?string $id = null, ?string $type = null, ?int $retry = null): string {} const FRANKENPHP_LOG_LEVEL_DEBUG = -4; const FRANKENPHP_LOG_LEVEL_INFO = 0; const FRANKENPHP_LOG_LEVEL_WARN = 4; const FRANKENPHP_LOG_LEVEL_ERROR = 8; /** * Emits a structured log record with the current time and the given message, level and context. * * @param int $level The importance or severity of a log event. The higher the level, the more important or severe the event. For more details, see: https://pkg.go.dev/log/slog#Level * array $context Values of the array will be converted to the corresponding Go type (if supported by FrankenPHP) and added to the context of the structured logs using https://pkg.go.dev/log/slog#Attr */ function frankenphp_log(string $message, int $level = FRANKENPHP_LOG_LEVEL_INFO, array $context = []): void {} '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 = null): 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. * * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagearc(GdImage $image, int $center_x, int $center_y, int $width, int $height, int $start_angle, int $end_angle, int $color) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imageellipse(GdImage $image, int $center_x, int $center_y, int $width, int $height, int $color) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagechar( GdImage $image, #[LanguageLevelTypeAware(['8.1' => 'GdFont|int'], default: 'int')] $font, int $x, int $y, string $char, int $color ) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagecharup( GdImage $image, #[LanguageLevelTypeAware(['8.1' => 'GdFont|int'], default: 'int')] $font, int $x, int $y, string $char, int $color ) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagecolordeallocate(GdImage $image, int $color) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] 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) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] 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) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] 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) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] 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) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagesetthickness(GdImage $image, int $thickness) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagefilledarc(GdImage $image, int $center_x, int $center_y, int $width, int $height, int $start_angle, int $end_angle, int $color, int $style) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagefilledellipse(GdImage $image, int $center_x, int $center_y, int $width, int $height, int $color) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagealphablending(GdImage $image, bool $enable) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagesavealpha(GdImage $image, bool $enable) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] 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) {} /** * 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 is compiled 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imageantialias(GdImage $image, bool $enable) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagesettile(GdImage $image, GdImage $tile) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagesetbrush(GdImage $image, GdImage $brush) {} /** * 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. */ #[Deprecated('Deprecated: it has no effect', since: '8.5')] #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagedestroy(GdImage $image) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagegammacorrect(GdImage $image, float $input_gamma, float $output_gamma) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagefill(GdImage $image, int $x, int $y, int $color) {} /** * 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 = null ): 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 = null ): 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagefilledrectangle(GdImage $image, int $x1, int $y1, int $x2, int $y2, int $color) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagefilltoborder(GdImage $image, int $x, int $y, int $border_color, int $color) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imageline(GdImage $image, int $x1, int $y1, int $x2, int $y2, int $color) {} /** * 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 = null, #[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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagerectangle(GdImage $image, int $x1, int $y1, int $x2, int $y2, int $color) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagesetpixel(GdImage $image, int $x, int $y, int $color) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagestring( GdImage $image, #[LanguageLevelTypeAware(['8.1' => 'GdFont|int'], default: 'int')] $font, int $x, int $y, string $string, int $color ) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagestringup( GdImage $image, #[LanguageLevelTypeAware(['8.1' => 'GdFont|int'], default: 'int')] $font, int $x, int $y, string $string, int $color ) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagedashedline(GdImage $image, int $x1, int $y1, int $x2, int $y2, int $color) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagelayereffect(GdImage $image, int $effect) {} /** * 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. */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagecolormatch(GdImage $image1, GdImage $image2) {} /** * 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 */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imagesetclip(GdImage $image, int $x1, int $y1, int $x2, int $y2) {} /** * 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 = null, #[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 */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function imageflip(GdImage $image, int $mode) {} /** * 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() {} } * 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 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 {} } * The new message domain, or NULL to get the current setting without * changing it *

    * @return string If successful, this function returns the current message * domain, after possibly changing it. */ function textdomain(?string $domain = null): string {} /** * Lookup a message in the current domain * @link https://php.net/manual/en/function.gettext.php * @param string $message

    * The message being translated. *

    * @return string a translated string if one is found in the * translation table, or the submitted message if not found. */ #[Pure] function _(string $message): string {} /** * Lookup a message in the current domain * @link https://php.net/manual/en/function.gettext.php * @param string $message

    * The message being translated. *

    * @return string a translated string if one is found in the * translation table, or the submitted message if not found. */ #[Pure] function gettext(string $message): string {} /** * Override the current domain * @link https://php.net/manual/en/function.dgettext.php * @param string $domain

    * The domain *

    * @param string $message

    * The message *

    * @return string A string on success. */ function dgettext(string $domain, string $message): string {} /** * Overrides the domain for a single lookup * @link https://php.net/manual/en/function.dcgettext.php * @param string $domain

    * The domain *

    * @param string $message

    * The message *

    * @param int $category

    * The category *

    * @return string A string on success. */ function dcgettext(string $domain, string $message, int $category): string {} /** * Sets the path for a domain * @link https://php.net/manual/en/function.bindtextdomain.php * @param string $domain

    * The domain *

    * @param string|null $directory

    * The directory path. Since PHP 8.0.3 directory is nullable. If null is passed, the currently set directory is returned. *

    * @return string|false The full pathname for the domain currently being set. */ function bindtextdomain(string $domain, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: 'string')] $directory = null): string|false {} /** * Plural version of gettext * @link https://php.net/manual/en/function.ngettext.php * @param string $singular * @param string $plural * @param int $count * @return string correct plural form of message identified by * msgid1 and msgid2 * for count n. */ #[Pure] function ngettext(string $singular, string $plural, int $count): string {} /** * Plural version of dgettext * @link https://php.net/manual/en/function.dngettext.php * @param string $domain

    * The domain *

    * @param string $singular * @param string $plural * @param int $count * @return string A string on success. */ #[Pure] function dngettext(string $domain, string $singular, string $plural, int $count): string {} /** * Plural version of dcgettext * @link https://php.net/manual/en/function.dcngettext.php * @param string $domain

    * The domain *

    * @param string $singular * @param string $plural * @param int $count * @param int $category * @return string A string on success. */ #[Pure] function dcngettext(string $domain, string $singular, string $plural, int $count, int $category): string {} /** * Specify the character encoding in which the messages from the DOMAIN message catalog will be returned * @link https://php.net/manual/en/function.bind-textdomain-codeset.php * @param string $domain

    * The domain *

    * @param string|null $codeset

    * The code set. Since 8.0.3 is nullable. If null is passed, the currently set encoding is returned. *

    * @return string|false A string on success. */ function bind_textdomain_codeset(string $domain, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: 'string')] $codeset = null): string|false {} // End of gettext v. * An integer or a string. The string representation can be decimal, * hexadecimal or octal. *

    * @param int $base [optional]

    * The base. *

    *

    * The base may vary from 2 to 36. If base is 0 (default value), the * actual base is determined from the leading characters: if the first * two characters are 0x or 0X, * hexadecimal is assumed, otherwise if the first character is "0", * octal is assumed, otherwise decimal is assumed. *

    * @return resource|GMP A GMP number resource. */ #[Pure] function gmp_init(string|int $num, int $base = 0): GMP {} /** * Convert GMP number to integer * @link https://php.net/manual/en/function.gmp-intval.php * @param resource|int|string|GMP $num

    * A GMP number. *

    * @return int An integer value of gmpnumber. */ #[Pure] function gmp_intval(GMP|string|int $num): int {} /** * Sets the RNG seed * @param resource|string|int|GMP $seed

    * The seed to be set for the {@see gmp_random()}, {@see gmp_random_bits()}, and {@see gmp_random_range()} functions. *

    * Either a GMP number resource in PHP 5.5 and earlier, a GMP object in PHP 5.6 and later, or a numeric string provided that it is possible to convert the latter to a number. * @return void|false * @since 7.0 */ #[LanguageLevelTypeAware(['8.0' => 'void'], default: 'void|false')] function gmp_random_seed(GMP|string|int $seed): void {} /** * Convert GMP number to string * @link https://php.net/manual/en/function.gmp-strval.php * @param resource|int|string|GMP $num

    * The GMP number that will be converted to a string. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param int $base [optional]

    * The base of the returned number. The default base is 10. * Allowed values for the base are from 2 to 62 and -2 to -36. *

    * @return string The number, as a string. */ #[Pure] function gmp_strval(GMP|string|int $num, int $base = 10): string {} /** * Add numbers * @link https://php.net/manual/en/function.gmp-add.php * @param resource|int|string|GMP $num1

    * A number that will be added. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    * A number that will be added. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP A GMP number representing the sum of the arguments. */ #[Pure] function gmp_add(GMP|string|int $num1, GMP|string|int $num2): GMP {} /** * Subtract numbers * @link https://php.net/manual/en/function.gmp-sub.php * @param resource|string|GMP $num1

    * The number being subtracted from. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    * The number subtracted from a. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP A GMP number resource. */ #[Pure] function gmp_sub(GMP|string|int $num1, GMP|string|int $num2): GMP {} /** * Multiply numbers * @link https://php.net/manual/en/function.gmp-mul.php * @param resource|string|GMP $num1

    * A number that will be multiplied by b. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    * A number that will be multiplied by a. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP A GMP number resource. */ #[Pure] function gmp_mul(GMP|string|int $num1, GMP|string|int $num2): GMP {} /** * Divide numbers and get quotient and remainder * @link https://php.net/manual/en/function.gmp-div-qr.php * @param resource|string|GMP $num1

    * The number being divided. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    * The number that n is being divided by. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param int $rounding_mode [optional]

    * See the gmp_div_q function for description * of the round argument. *

    * @return array{resource|GMP, resource|GMP} an array, with the first * element being [n/d] (the integer result of the * division) and the second being (n - [n/d] * d) * (the remainder of the division). */ #[Pure] function gmp_div_qr(GMP|string|int $num1, GMP|string|int $num2, int $rounding_mode = GMP_ROUND_ZERO): array {} /** * Divide numbers * @link https://php.net/manual/en/function.gmp-div-q.php * @param resource|string|GMP $num1

    * The number being divided. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    * The number that a is being divided by. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param int $rounding_mode [optional]

    * The result rounding is defined by the * round, which can have the following * values: * GMP_ROUND_ZERO: The result is truncated * towards 0.

    * @return resource|GMP A GMP number resource. */ #[Pure] function gmp_div_q(GMP|string|int $num1, GMP|string|int $num2, int $rounding_mode = GMP_ROUND_ZERO): GMP {} /** * Remainder of the division of numbers * @link https://php.net/manual/en/function.gmp-div-r.php * @param resource|string|GMP $num1

    * The number being divided. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    * The number that n is being divided by. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param int $rounding_mode [optional]

    * See the gmp_div_q function for description * of the round argument. *

    * @return resource|GMP The remainder, as a GMP number. */ #[Pure] function gmp_div_r(GMP|string|int $num1, GMP|string|int $num2, int $rounding_mode = GMP_ROUND_ZERO): GMP {} /** * Divide numbers * @link https://php.net/manual/en/function.gmp-div-q.php * @param resource|string|GMP $num1

    * The number being divided. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    * The number that a is being divided by. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param int $rounding_mode [optional]

    * The result rounding is defined by the * round, which can have the following * values: * GMP_ROUND_ZERO: The result is truncated * towards 0.

    * @return resource|GMP A GMP number resource. */ #[Pure] function gmp_div(GMP|string|int $num1, GMP|string|int $num2, int $rounding_mode = GMP_ROUND_ZERO): GMP {} /** * Modulo operation * @link https://php.net/manual/en/function.gmp-mod.php * @param resource|string|GMP $num1

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    * The modulo that is being evaluated. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP A GMP number resource. */ #[Pure] function gmp_mod(GMP|string|int $num1, GMP|string|int $num2): GMP {} /** * Exact division of numbers * @link https://php.net/manual/en/function.gmp-divexact.php * @param resource|string|GMP $num1

    * The number being divided. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    * The number that a is being divided by. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP A GMP number resource. */ #[Pure] function gmp_divexact(GMP|string|int $num1, GMP|string|int $num2): GMP {} /** * Negate number * @link https://php.net/manual/en/function.gmp-neg.php * @param resource|string|GMP $num

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP -a, as a GMP number. */ #[Pure] function gmp_neg(GMP|string|int $num): GMP {} /** * Absolute value * @link https://php.net/manual/en/function.gmp-abs.php * @param resource|string|GMP $num

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP the absolute value of a, as a GMP number. */ #[Pure] function gmp_abs(GMP|string|int $num): GMP {} /** * Factorial * @link https://php.net/manual/en/function.gmp-fact.php * @param resource|string|GMP $num

    * The factorial number. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP A GMP number resource. */ #[Pure] function gmp_fact(GMP|string|int $num): GMP {} /** * Calculate square root * @link https://php.net/manual/en/function.gmp-sqrt.php * @param resource|string|GMP $num

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP The integer portion of the square root, as a GMP number. */ #[Pure] function gmp_sqrt(GMP|string|int $num): GMP {} /** * Square root with remainder * @link https://php.net/manual/en/function.gmp-sqrtrem.php * @param resource|string|GMP $num

    * The number being square rooted. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return array array where first element is the integer square root of * a and the second is the remainder * (i.e., the difference between a and the * first element squared). */ #[Pure] function gmp_sqrtrem(GMP|string|int $num): array {} /** * Raise number into power * @link https://php.net/manual/en/function.gmp-pow.php * @param resource|string|GMP $num

    * The base number. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param positive-int $exponent

    * The positive power to raise the base. *

    * @return resource|GMP The new (raised) number, as a GMP number. The case of * 0^0 yields 1. */ #[Pure] function gmp_pow(GMP|string|int $num, int $exponent): GMP {} /** * Raise number into power with modulo * @link https://php.net/manual/en/function.gmp-powm.php * @param resource|string|GMP $num

    * The base number. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $exponent

    * The positive power to raise the base. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $modulus

    * The modulo. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP The new (raised) number, as a GMP number. */ #[Pure] function gmp_powm(GMP|string|int $num, GMP|string|int $exponent, GMP|string|int $modulus): GMP {} /** * Perfect square check * @link https://php.net/manual/en/function.gmp-perfect-square.php * @param resource|string|GMP $num

    * The number being checked as a perfect square. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return bool TRUE if a is a perfect square, * FALSE otherwise. */ #[Pure] function gmp_perfect_square(GMP|string|int $num): bool {} /** * Check if number is "probably prime" * @link https://php.net/manual/en/function.gmp-prob-prime.php * @param resource|string|GMP $num

    * The number being checked as a prime. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param int $repetitions [optional]

    * Reasonable values * of reps vary from 5 to 10 (default being * 10); a higher value lowers the probability for a non-prime to * pass as a "probable" prime. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return int If this function returns 0, a is * definitely not prime. If it returns 1, then * a is "probably" prime. If it returns 2, * then a is surely prime. */ #[Pure] function gmp_prob_prime(GMP|string|int $num, int $repetitions = 10): int {} /** * Random number * @link https://php.net/manual/en/function.gmp-random-bits.php * @param int $bits

    The number of bits. Either a GMP number resource in PHP 5.5 and earlier, * a GMP object in PHP 5.6 and later, * or a numeric string provided that it is possible to convert the latter to a number.

    * @return GMP A random GMP number. */ function gmp_random_bits(int $bits): GMP {} /** * Random number * @link https://php.net/manual/en/function.gmp-random-range.php * @param GMP|string|int $min

    A GMP number representing the lower bound for the random number

    * @param GMP|string|int $max

    A GMP number representing the upper bound for the random number

    * @return GMP A random GMP number. */ function gmp_random_range(GMP|string|int $min, GMP|string|int $max): GMP {} /** * Calculate GCD * @link https://php.net/manual/en/function.gmp-gcd.php * @param resource|string|GMP $num1

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP A positive GMP number that divides into both * a and b. */ #[Pure] function gmp_gcd(GMP|string|int $num1, GMP|string|int $num2): GMP {} /** * Calculate GCD and multipliers * @link https://php.net/manual/en/function.gmp-gcdext.php * @param resource|string|GMP $num1

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return array An array of GMP numbers. */ #[Pure] #[ArrayShape(["g" => "mixed", "s" => "mixed", "t" => "mixed"])] function gmp_gcdext(GMP|string|int $num1, GMP|string|int $num2): array {} /** * Inverse by modulo * @link https://php.net/manual/en/function.gmp-invert.php * @param resource|string|GMP $num1

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP|false A GMP number on success or FALSE if an inverse does not exist. */ #[Pure] function gmp_invert(GMP|string|int $num1, GMP|string|int $num2): GMP|false {} /** * Jacobi symbol * @link https://php.net/manual/en/function.gmp-jacobi.php * @param resource|string|GMP $num1

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    *

    * Should be odd and must be positive. *

    * @return int A GMP number resource. */ #[Pure] function gmp_jacobi(GMP|string|int $num1, GMP|string|int $num2): int {} /** * Legendre symbol * @link https://php.net/manual/en/function.gmp-legendre.php * @param resource|string|GMP $num1

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    *

    * Should be odd and must be positive. *

    * @return int A GMP number resource. */ #[Pure] function gmp_legendre(GMP|string|int $num1, GMP|string|int $num2): int {} /** * Compare numbers * @link https://php.net/manual/en/function.gmp-cmp.php * @param resource|string|GMP $num1

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return int a positive value if a > b, zero if * a = b and a negative value if a < * b. */ #[Pure] function gmp_cmp(GMP|string|int $num1, GMP|string|int $num2): int {} /** * Sign of number * @link https://php.net/manual/en/function.gmp-sign.php * @param resource|string|GMP $num

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return int 1 if a is positive, * -1 if a is negative, * and 0 if a is zero. */ #[Pure] function gmp_sign(GMP|string|int $num): int {} /** * Random number * @link https://php.net/manual/en/function.gmp-random.php * @param int $limiter [optional]

    * The limiter. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP A random GMP number. * @see gmp_random_bits() * @see gmp_random_range() * @removed 8.0 */ #[Deprecated(reason: "Use see gmp_random_bits() or see gmp_random_range() instead", since: "7.2")] function gmp_random($limiter = 20) {} /** * Bitwise AND * @link https://php.net/manual/en/function.gmp-and.php * @param resource|string|GMP $num1

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP A GMP number representing the bitwise AND comparison. */ #[Pure] function gmp_and(GMP|string|int $num1, GMP|string|int $num2): GMP {} /** * Bitwise OR * @link https://php.net/manual/en/function.gmp-or.php * @param resource|string|GMP $num1

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP A GMP number resource. */ #[Pure] function gmp_or(GMP|string|int $num1, GMP|string|int $num2): GMP {} /** * Calculates one's complement * @link https://php.net/manual/en/function.gmp-com.php * @param resource|string|GMP $num

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP the one's complement of a, as a GMP number. */ #[Pure] function gmp_com(GMP|string|int $num): GMP {} /** * Bitwise XOR * @link https://php.net/manual/en/function.gmp-xor.php * @param resource|string|GMP $num1

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param resource|string|GMP $num2

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP A GMP number resource. */ #[Pure] function gmp_xor(GMP|string|int $num1, GMP|string|int $num2): GMP {} /** * Set bit * @link https://php.net/manual/en/function.gmp-setbit.php * @param resource|string|GMP $num

    * The number being set to. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param int $index

    * The set bit. *

    * @param bool $value [optional]

    * Defines if the bit is set to 0 or 1. By default the bit is set to * 1. Index starts at 0. *

    * @return void */ function gmp_setbit(GMP $num, int $index, bool $value = true): void {} /** * Clear bit * @link https://php.net/manual/en/function.gmp-clrbit.php * @param resource|string|GMP $num

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param int $index

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return void */ function gmp_clrbit(GMP $num, int $index): void {} /** * Scan for 0 * @link https://php.net/manual/en/function.gmp-scan0.php * @param resource|string|GMP $num1

    * The number to scan. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param int $start

    * The starting bit. *

    * @return int the index of the found bit, as an integer. The * index starts from 0. */ #[Pure] function gmp_scan0(GMP|string|int $num1, int $start): int {} /** * Scan for 1 * @link https://php.net/manual/en/function.gmp-scan1.php * @param resource|string|GMP $num1

    * The number to scan. *

    *

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param int $start

    * The starting bit. *

    * @return int the index of the found bit, as an integer. * If no set bit is found, -1 is returned. */ #[Pure] function gmp_scan1(GMP|string|int $num1, int $start): int {} /** * Tests if a bit is set * @link https://php.net/manual/en/function.gmp-testbit.php * @param resource|string|GMP $num

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @param int $index

    * The bit to test *

    * @return bool TRUE on success or FALSE on failure. */ #[Pure] function gmp_testbit(GMP|string|int $num, int $index): bool {} /** * Population count * @link https://php.net/manual/en/function.gmp-popcount.php * @param resource|string|GMP $num

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return int The population count of a, as an integer. */ #[Pure] function gmp_popcount(GMP|string|int $num): int {} /** * Hamming distance * @link https://php.net/manual/en/function.gmp-hamdist.php * @param resource|string|GMP $num1

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    *

    * It should be positive. *

    * @param resource|string|GMP $num2

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    *

    * It should be positive. *

    * @return int A GMP number resource. */ #[Pure] function gmp_hamdist(GMP|string|int $num1, GMP|string|int $num2): int {} /** * Import from a binary string * @link https://php.net/manual/en/function.gmp-import.php * @param string $data The binary string being imported * @param int $word_size

    Default value is 1. The number of bytes in each chunk of binary * data. This is mainly used in conjunction with the options parameter.

    * @param int $flags Default value is GMP_MSW_FIRST | GMP_NATIVE_ENDIAN. * @return GMP|false Returns a GMP number or FALSE on failure. * @since 5.6.1 */ #[Pure] #[LanguageLevelTypeAware(['8.0' => 'GMP'], default: 'GMP|false')] function gmp_import(string $data, int $word_size = 1, int $flags = GMP_MSW_FIRST|GMP_NATIVE_ENDIAN): GMP {} /** * Export to a binary string * @link https://php.net/manual/en/function.gmp-export.php * @param GMP|string|int $num The GMP number being exported * @param int $word_size

    Default value is 1. The number of bytes in each chunk of binary * data. This is mainly used in conjunction with the options parameter.

    * @param int $flags Default value is GMP_MSW_FIRST | GMP_NATIVE_ENDIAN. * @return string|false Returns a string or FALSE on failure. * @since 5.6.1 */ #[Pure] #[LanguageLevelTypeAware(['8.0' => 'string'], default: 'string|false')] function gmp_export(GMP|string|int $num, int $word_size = 1, int $flags = GMP_MSW_FIRST|GMP_NATIVE_ENDIAN): string {} /** * Takes the nth root of a and returns the integer component of the result. * @link https://php.net/manual/en/function.gmp-root.php * @param GMP|string|int $num

    Either a GMP number resource in PHP 5.5 and earlier, a GMP object in PHP 5.6 * and later, or a numeric string provided that it is possible to convert the latter to a number.

    * @param positive-int $nth The positive root to take of a num. * @return GMP The integer component of the resultant root, as a GMP number. * @since 5.6 */ #[Pure] function gmp_root(GMP|string|int $num, int $nth): GMP {} /** * Takes the nth root of a and returns the integer component and remainder of the result. * @link https://php.net/manual/en/function.gmp-rootrem.php * @param GMP|string|int $num

    Either a GMP number resource in PHP 5.5 and earlier, a GMP object in PHP 5.6 * and later, or a numeric string provided that it is possible to convert the latter to a number.

    * @param positive-int $nth The positive root to take of a num. * @return array|GMP[]

    A two element array, where the first element is the integer component of * the root, and the second element is the remainder, both represented as GMP numbers.

    * @since 5.6 */ #[Pure] function gmp_rootrem(GMP|string|int $num, int $nth): array {} /** * Find next prime number * @link https://php.net/manual/en/function.gmp-nextprime.php * @param int|resource|string|GMP $num

    It can be either a GMP number resource, or a * numeric string given that it is possible to convert the latter to a number.

    * @return resource|GMP Return the next prime number greater than a, * as a GMP number. */ #[Pure] function gmp_nextprime(GMP|string|int $num): GMP {} /** * Calculates binomial coefficient * * @link https://www.php.net/manual/en/function.gmp-binomial.php * * @param GMP|string|int $n * @param int $k * @return GMP|false * @since 7.3 */ #[Pure] #[LanguageLevelTypeAware(['8.0' => 'GMP'], default: 'GMP|false')] function gmp_binomial(GMP|string|int $n, int $k): GMP {} /** * Computes the Kronecker symbol * * @link https://www.php.net/manual/en/function.gmp-kronecker.php * * @param GMP|string|float|int $num1 * @param GMP|string|float|int $num2 * @return int * * @since 7.3 */ #[Pure] function gmp_kronecker(GMP|string|int $num1, GMP|string|int $num2): int {} /** * Computes the least common multiple of A and B * * @link https://www.php.net/manual/en/function.gmp-lcm.php * * @param GMP|string|float|int $num1 * @param GMP|string|float|int $num2 * @return GMP * * @since 7.3 */ #[Pure] function gmp_lcm(GMP|string|int $num1, GMP|string|int $num2): GMP {} /** * Perfect power check * * @link https://www.php.net/manual/en/function.gmp-perfect-power.php * * @param GMP|string|float|int $num * @return bool * * @since 7.3 */ #[Pure] function gmp_perfect_power(GMP|string|int $num): bool {} define('GMP_ROUND_ZERO', 0); define('GMP_ROUND_PLUSINF', 1); define('GMP_ROUND_MINUSINF', 2); define('GMP_MSW_FIRST', 1); define('GMP_LSW_FIRST', 2); define('GMP_LITTLE_ENDIAN', 4); define('GMP_BIG_ENDIAN', 8); define('GMP_NATIVE_ENDIAN', 16); /** * The GMP library version * @link https://php.net/manual/en/gmp.constants.php */ define('GMP_VERSION', "6.3.0"); define('GMP_MPIR_VERSION', '3.0.0'); final class GMP { /** * @since 8.2 */ public function __construct(int|string $num = 0, int $base = 0) {} /** * Get array representation of object * @link https://www.php.net/manual/en/language.oop5.magic.php#object.serialize * @return array

    * The array representation of the GMP object. *

    */ public function __serialize(): array {} /** * Reconstructs the GMP object from array representation * @link https://www.php.net/manual/en/language.oop5.magic.php#object.serialize * @param array $data

    * The array representation of the GMP object. *

    * @return void */ public function __unserialize(array $data): void {} } // End of gmp v. * @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() {} } * Generate a hash value (message digest) * @link https://php.net/manual/en/function.hash.php * @param string $algo

    * Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..) *

    * @param string $data

    * Message to be hashed. *

    * @param bool $binary [optional]

    * When set to TRUE, outputs raw binary data. * FALSE outputs lowercase hexits. *

    * @return string a string containing the calculated message digest as lowercase hexits * unless binary is set to true in which case the raw * binary representation of the message digest is returned. */ #[Pure] function hash(string $algo, string $data, bool $binary = false, #[PhpStormStubsElementAvailable('8.1')] array $options = []): string {} /** * Timing attack safe string comparison * @link https://php.net/manual/en/function.hash-equals.php * @param string $known_string

    The known string that must be kept secret.

    * @param string $user_string

    The user-supplied string to compare against.

    * @return bool

    Returns TRUE when the two strings are equal, FALSE otherwise.

    * @since 5.6 */ #[Pure] function hash_equals(string $known_string, string $user_string): bool {} /** * (PHP 5 >= 5.1.2, PECL hash >= 1.1)
    * Generate a hash value using the contents of a given file * @link https://php.net/manual/en/function.hash-file.php * @param string $algo

    * Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..) *

    * @param string $filename

    * URL describing location of file to be hashed; Supports fopen wrappers. *

    * @param bool $binary [optional]

    * When set to TRUE, outputs raw binary data. * FALSE outputs lowercase hexits. *

    * @return string|false a string containing the calculated message digest as lowercase hexits * unless binary is set to true in which case the raw * binary representation of the message digest is returned. */ #[Pure] function hash_file(string $algo, string $filename, bool $binary = false, #[PhpStormStubsElementAvailable('8.1')] array $options = []): string|false {} /** * (PHP 5 >= 5.1.2, PECL hash >= 1.1)
    * Generate a keyed hash value using the HMAC method * @link https://php.net/manual/en/function.hash-hmac.php * @param string $algo

    * Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..) See hash_algos for a list of supported algorithms.
    * Since 7.2.0 usage of non-cryptographic hash functions (adler32, crc32, crc32b, fnv132, fnv1a32, fnv164, fnv1a64, joaat) was disabled. *

    * @param string $data

    * Message to be hashed. *

    * @param string $key

    * Shared secret key used for generating the HMAC variant of the message digest. *

    * @param bool $binary [optional]

    * When set to TRUE, outputs raw binary data. * FALSE outputs lowercase hexits. *

    * @return string a string containing the calculated message digest as lowercase hexits * unless binary is set to true in which case the raw * binary representation of the message digest is returned. */ #[Pure] function hash_hmac(string $algo, string $data, string $key, bool $binary = false): string {} /** * (PHP 5 >= 5.1.2, PECL hash >= 1.1)
    * Generate a keyed hash value using the HMAC method and the contents of a given file * @link https://php.net/manual/en/function.hash-hmac-file.php * @param string $algo

    * Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..) See hash_algos for a list of supported algorithms.
    * Since 7.2.0 usage of non-cryptographic hash functions (adler32, crc32, crc32b, fnv132, fnv1a32, fnv164, fnv1a64, joaat) was disabled. *

    * @param string $filename

    * URL describing location of file to be hashed; Supports fopen wrappers. *

    * @param string $key

    * Shared secret key used for generating the HMAC variant of the message digest. *

    * @param bool $binary [optional]

    * When set to TRUE, outputs raw binary data. * FALSE outputs lowercase hexits. *

    * @return string|false a string containing the calculated message digest as lowercase hexits * unless binary is set to true in which case the raw * binary representation of the message digest is returned. */ #[Pure] function hash_hmac_file(string $algo, string $filename, string $key, bool $binary = false): string|false {} /** * (PHP 5 >= 5.1.2, PECL hash >= 1.1)
    * Initialize an incremental hashing context * @link https://php.net/manual/en/function.hash-init.php * @param string $algo

    * Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..). For a list of supported algorithms see hash_algos.
    * Since 7.2.0 usage of non-cryptographic hash functions (adler32, crc32, crc32b, fnv132, fnv1a32, fnv164, fnv1a64, joaat) was disabled. *

    * @param int $flags [optional]

    * Optional settings for hash generation, currently supports only one option: * HASH_HMAC. When specified, the key * must be specified. *

    * @param string $key

    * When HASH_HMAC is specified for options, * a shared secret key to be used with the HMAC hashing method must be supplied in this * parameter. *

    * @return HashContext|resource a Hashing Context resource for use with hash_update, * hash_update_stream, hash_update_file, * and hash_final. */ #[Pure] #[LanguageLevelTypeAware(["7.2" => "HashContext"], default: "resource")] function hash_init(string $algo, int $flags = 0, string $key = "", #[PhpStormStubsElementAvailable('8.1')] array $options = []) {} /** * (PHP 5 >= 5.1.2, PECL hash >= 1.1)
    * Pump data into an active hashing context * @link https://php.net/manual/en/function.hash-update.php * @param HashContext|resource $context

    * Hashing context returned by {@see hash_init}. *

    * @param string $data

    * Message to be included in the hash digest. *

    * @return bool TRUE. */ #[LanguageLevelTypeAware(["8.4" => "true"], default: "bool")] function hash_update(#[LanguageLevelTypeAware(["7.2" => "HashContext"], default: "resource")] $context, string $data) {} /** * (PHP 5 >= 5.1.2, PECL hash >= 1.1)
    * Pump data into an active hashing context from an open stream * @link https://php.net/manual/en/function.hash-update-stream.php * @param HashContext|resource $context

    * Hashing context returned by {@see hash_init}. *

    * @param resource $stream

    * Open file handle as returned by any stream creation function. *

    * @param int $length [optional]

    * Maximum number of characters to copy from handle * into the hashing context. *

    * @return int Actual number of bytes added to the hashing context from handle. */ function hash_update_stream(#[LanguageLevelTypeAware(["7.2" => "HashContext"], default: "resource")] $context, $stream, int $length = -1): int {} /** * (PHP 5 >= 5.1.2, PECL hash >= 1.1)
    * Pump data into an active hashing context from a file * @link https://php.net/manual/en/function.hash-update-file.php * @param HashContext|resource $context

    * Hashing context returned by hash_init. *

    * @param string $filename

    * URL describing location of file to be hashed; Supports fopen wrappers. *

    * @param resource $stream_context [optional]

    * Stream context as returned by stream_context_create. *

    * @return bool TRUE on success or FALSE on failure. */ function hash_update_file(#[LanguageLevelTypeAware(["7.2" => "HashContext"], default: "resource")] $context, string $filename, $stream_context = null): bool {} /** * (PHP 5 >= 5.1.2, PECL hash >= 1.1)
    * Finalize an incremental hash and return resulting digest * @link https://php.net/manual/en/function.hash-final.php * @param HashContext|resource $context

    * Hashing context returned by {@see hash_init}. *

    * @param bool $binary [optional]

    * When set to TRUE, outputs raw binary data. * FALSE outputs lowercase hexits. *

    * @return string a string containing the calculated message digest as lowercase hexits * unless binary is set to true in which case the raw * binary representation of the message digest is returned. */ function hash_final(#[LanguageLevelTypeAware(["7.2" => "HashContext"], default: "resource")] $context, bool $binary = false): string {} /** * Copy hashing context * @link https://php.net/manual/en/function.hash-copy.php * @param HashContext|resource $context

    * Hashing context returned by {@see hash_init}. *

    * @return HashContext|resource a copy of Hashing Context resource. */ #[Pure] #[LanguageLevelTypeAware(["7.2" => "HashContext"], default: "resource")] function hash_copy(#[LanguageLevelTypeAware(["7.2" => "HashContext"], default: "resource")] $context) {} /** * (PHP 5 >= 5.1.2, PECL hash >= 1.1)
    * Return a list of registered hashing algorithms * @link https://php.net/manual/en/function.hash-algos.php * @return array a numerically indexed array containing the list of supported * hashing algorithms. */ #[Pure] function hash_algos(): array {} /** * Generate a hkdf key derivation of a supplied key input * @param string $algo Name of selected hashing algorithm (i.e. "sha256", "sha512", "haval160,4", etc..) * See {@see hash_algos()} for a list of supported algorithms. *
    *

    Note

    *

    * Non-cryptographic hash functions are not allowed. *

    *
    * @param string $key

    Input keying material (raw binary). Cannot be empty.

    * @param int $length [optional]

    Desired output length in bytes. Cannot be greater than 255 times the chosen hash function size. * If length is 0, the output length will default to the chosen hash function size.

    * @param string $info [optional]

    Application/context-specific info string.

    * @param string $salt [optional]

    Salt to use during derivation. While optional, adding random salt significantly improves the strength of HKDF.

    * @return string|false

    Returns a string containing a raw binary representation of the derived key (also known as output keying material - OKM); or FALSE on failure.

    * @since 7.1.2 * Generate a HKDF key derivation of a supplied key input * @link https://php.net/manual/en/function.hash-hkdf.php */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "string"], default: "string|false")] function hash_hkdf(string $algo, string $key, int $length = 0, string $info = '', string $salt = '') {} /** * Return a list of registered hashing algorithms suitable for hash_hmac * @since 7.2 * Return a list of registered hashing algorithms suitable for hash_hmac * @return string[] Returns a numerically indexed array containing the list of supported hashing algorithms suitable for {@see hash_hmac()}. */ #[Pure] function hash_hmac_algos(): array {} /** * Generate a PBKDF2 key derivation of a supplied password * @link https://php.net/manual/en/function.hash-pbkdf2.php * @param string $algo

    * Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..) See hash_algos for a list of supported algorithms.
    * Since 7.2.0 usage of non-cryptographic hash functions (adler32, crc32, crc32b, fnv132, fnv1a32, fnv164, fnv1a64, joaat) was disabled. *

    * @param string $password

    * The password to use for the derivation. *

    * @param string $salt

    * The salt to use for the derivation. This value should be generated randomly. *

    * @param int $iterations

    * The number of internal iterations to perform for the derivation. *

    * @param int $length [optional]

    * The length of the output string. If binary is TRUE this corresponds to the byte-length of the derived key, * if binary is FALSE this corresponds to twice the byte-length of the derived key (as every byte of the key is returned as two hexits).
    * If 0 is passed, the entire output of the supplied algorithm is used. *

    * @param bool $binary [optional]

    * When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits. *

    * @param array $options [optional]

    * Additional options. This parameter was added for PHP 8.1 only. *

    * @return string a string containing the derived key as lowercase hexits unless * binary is set to TRUE in which case the raw * binary representation of the derived key is returned. * @since 5.5 */ #[Pure] function hash_pbkdf2( string $algo, string $password, string $salt, int $iterations, int $length = 0, bool $binary = false, #[PhpStormStubsElementAvailable(from: '8.1')] array $options = [] ): string {} /** * Generates a key * @link https://php.net/manual/en/function.mhash-keygen-s2k.php * @param int $algo

    * The hash ID used to create the key. * One of the MHASH_hashname constants. *

    * @param string $password

    * An user supplied password. *

    * @param string $salt

    * Must be different and random enough for every key you generate in * order to create different keys. Because salt * must be known when you check the keys, it is a good idea to append * the key to it. Salt has a fixed length of 8 bytes and will be padded * with zeros if you supply less bytes. *

    * @param int $length

    * The key length, in bytes. *

    * @return string|false the generated key as a string, or FALSE on error. * @deprecated 8.1 */ #[Pure] #[Deprecated(since: '8.1')] function mhash_keygen_s2k(int $algo, string $password, string $salt, int $length): string|false {} /** * Gets the block size of the specified hash * @link https://php.net/manual/en/function.mhash-get-block-size.php * @param int $algo

    * The hash ID. One of the MHASH_hashname constants. *

    * @return int|false the size in bytes or FALSE, if the hash * does not exist. * @deprecated 8.1 */ #[Pure] #[Deprecated(since: '8.1')] function mhash_get_block_size(int $algo): int|false {} /** * Gets the name of the specified hash * @link https://php.net/manual/en/function.mhash-get-hash-name.php * @param int $algo

    * The hash ID. One of the MHASH_hashname constants. *

    * @return string|false the name of the hash or FALSE, if the hash does not exist. * @deprecated 8.1 */ #[Pure] #[Deprecated(since: '8.1')] function mhash_get_hash_name(int $algo): string|false {} /** * Gets the highest available hash ID * @link https://php.net/manual/en/function.mhash-count.php * @return int<0, max> the highest available hash ID. Hashes are numbered from 0 to this * hash ID. * @deprecated 8.1 */ #[Pure] #[Deprecated(since: '8.1')] function mhash_count(): int {} /** * Computes hash * @link https://php.net/manual/en/function.mhash.php * @param int $algo

    * The hash ID. One of the MHASH_hashname constants. *

    * @param string $data

    * The user input, as a string. *

    * @param string|null $key [optional]

    * If specified, the function will return the resulting HMAC instead. * HMAC is keyed hashing for message authentication, or simply a message * digest that depends on the specified key. Not all algorithms * supported in mhash can be used in HMAC mode. *

    * @return string|false the resulting hash (also called digest) or HMAC as a string, or * FALSE on error. * @deprecated 8.1 */ #[Pure] #[Deprecated(since: '8.1')] function mhash(int $algo, string $data, ?string $key = null): string|false {} /** * Optional flag for hash_init. * Indicates that the HMAC digest-keying algorithm should be * applied to the current hashing context. * @link https://php.net/manual/en/hash.constants.php */ define('HASH_HMAC', 1); define('MHASH_CRC32', 0); /** * @since 7.4 */ define('MHASH_CRC32C', 34); define('MHASH_MD5', 1); define('MHASH_SHA1', 2); define('MHASH_HAVAL256', 3); define('MHASH_RIPEMD160', 5); define('MHASH_TIGER', 7); define('MHASH_GOST', 8); define('MHASH_CRC32B', 9); define('MHASH_HAVAL224', 10); define('MHASH_HAVAL192', 11); define('MHASH_HAVAL160', 12); define('MHASH_HAVAL128', 13); define('MHASH_TIGER128', 14); define('MHASH_TIGER160', 15); define('MHASH_MD4', 16); define('MHASH_SHA256', 17); define('MHASH_ADLER32', 18); define('MHASH_SHA224', 19); define('MHASH_SHA512', 20); define('MHASH_SHA384', 21); define('MHASH_WHIRLPOOL', 22); define('MHASH_RIPEMD128', 23); define('MHASH_RIPEMD256', 24); define('MHASH_RIPEMD320', 25); define('MHASH_SNEFRU256', 27); define('MHASH_MD2', 28); define('MHASH_FNV132', 29); define('MHASH_FNV1A32', 30); define('MHASH_FNV164', 31); define('MHASH_FNV1A64', 32); define('MHASH_JOAAT', 33); /** * @since 8.1 */ define('MHASH_MURMUR3A', 35); /** * @since 8.1 */ define('MHASH_MURMUR3C', 36); /** * @since 8.1 */ define('MHASH_MURMUR3F', 37); /** * @since 8.1 */ define('MHASH_XXH32', 38); /** * @since 8.1 */ define('MHASH_XXH64', 39); /** * @since 8.1 */ define('MHASH_XXH3', 40); /** * @since 8.1 */ define('MHASH_XXH128', 41); /** * @since 7.2 */ final class HashContext { private function __construct() {} public function __serialize(): array {} /** * @param array $data */ public function __unserialize(#[LanguageLevelTypeAware(['8.0' => 'array'], default: '')] $data): void {} /** * @since 8.4 */ public function __debugInfo(): array {} } // End of hash v.1.0 * HttpDeflateStream class constructor * @link https://php.net/manual/en/function.httpdeflatestream-construct.php * @param int $flags [optional]

    * initialization flags *

    */ public function __construct($flags = null) {} /** * (PECL pecl_http >= 0.21.0)
    * Update deflate stream * @link https://php.net/manual/en/function.httpdeflatestream-update.php * @param string $data

    * data to deflate *

    * @return string|false deflated data on success or false on failure. */ public function update($data) {} /** * (PECL pecl_http >= 0.21.0)
    * Flush deflate stream * @link https://php.net/manual/en/function.httpdeflatestream-flush.php * @param string $data [optional]

    * more data to deflate *

    * @return string|false some deflated data as string on success or false on failure. */ public function flush($data = null) {} /** * (PECL pecl_http >= 0.21.0)
    * Finalize deflate stream * @link https://php.net/manual/en/function.httpdeflatestream-finish.php * @param string $data [optional]

    * data to deflate *

    * @return string the final part of deflated data. */ public function finish($data = null) {} /** * (PECL pecl_http >= 1.4.0)
    * HttpDeflateStream class factory * @link https://php.net/manual/en/function.httpdeflatestream-factory.php * @param int $flags [optional]

    * initialization flags *

    * @param string $class_name [optional]

    * name of a subclass of HttpDeflateStream *

    * @return HttpDeflateStream */ public static function factory($flags = null, $class_name = null) {} } /** * @link https://php.net/manual/en/class.httpinflatestream.php */ class HttpInflateStream { public const FLUSH_NONE = 0; public const FLUSH_SYNC = 1048576; public const FLUSH_FULL = 2097152; /** * (PECL pecl_http >= 1.0.0)
    * HttpInflateStream class constructor * @link https://php.net/manual/en/function.httpinflatestream-construct.php * @param int $flags [optional]

    * initialization flags *

    */ public function __construct($flags = null) {} /** * (PECL pecl_http >= 0.21.0)
    * Update inflate stream * @link https://php.net/manual/en/function.httpinflatestream-update.php * @param string $data

    * data to inflate *

    * @return string|false inflated data on success or false on failure. */ public function update($data) {} /** * (PECL pecl_http >= 0.21.0)
    * Flush inflate stream * @link https://php.net/manual/en/function.httpinflatestream-flush.php * @param string $data [optional]

    * more data to inflate *

    * @return string|false some inflated data as string on success or false on failure. */ public function flush($data = null) {} /** * (PECL pecl_http >= 0.21.0)
    * Finalize inflate stream * @link https://php.net/manual/en/function.httpinflatestream-finish.php * @param string $data [optional]

    * data to inflate *

    * @return string the final part of inflated data. */ public function finish($data = null) {} /** * (PECL pecl_http >= 1.4.0)
    * HttpInflateStream class factory * @link https://php.net/manual/en/function.httpinflatestream-factory.php * @param int $flags [optional]

    * initialization flags *

    * @param string $class_name [optional]

    * name of a subclass of HttpInflateStream *

    * @return HttpInflateStream */ public static function factory($flags = null, $class_name = null) {} } /** * @link https://php.net/manual/en/class.httpmessage.php */ class HttpMessage implements Countable, Serializable, Iterator { public const TYPE_NONE = 0; public const TYPE_REQUEST = 1; public const TYPE_RESPONSE = 2; protected $type; protected $body; protected $requestMethod; protected $requestUrl; protected $responseStatus; protected $responseCode; protected $httpVersion; protected $headers; protected $parentMessage; /** * (PECL pecl_http >= 0.10.0)
    * HttpMessage constructor * @link https://php.net/manual/en/function.httpmessage-construct.php * @param string $message [optional]

    * a single or several consecutive HTTP messages *

    */ public function __construct($message = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Get message body * @link https://php.net/manual/en/function.httpmessage-getbody.php * @return string the message body as string. */ #[Pure] public function getBody() {} /** * (PECL pecl_http >= 0.14.0)
    * Set message body * @link https://php.net/manual/en/function.httpmessage-setbody.php * @param string $body

    * the new body of the message *

    * @return void */ public function setBody($body) {} /** * (PECL pecl_http >= 1.1.0)
    * Get header * @link https://php.net/manual/en/function.httpmessage-getheader.php * @param string $header

    * header name *

    * @return string|null the header value on success or NULL if the header does not exist. */ #[Pure] public function getHeader($header) {} /** * (PECL pecl_http >= 0.10.0)
    * Get message headers * @link https://php.net/manual/en/function.httpmessage-getheaders.php * @return array an associative array containing the messages HTTP headers. */ #[Pure] public function getHeaders() {} /** * (PECL pecl_http >= 0.10.0)
    * Set headers * @link https://php.net/manual/en/function.httpmessage-setheaders.php * @param array $header

    * associative array containing the new HTTP headers, which will replace all previous HTTP headers of the message *

    * @return void */ public function setHeaders(array $header) {} /** * (PECL pecl_http >= 0.10.0)
    * Add headers * @link https://php.net/manual/en/function.httpmessage-addheaders.php * @param array $headers

    * associative array containing the additional HTTP headers to add to the messages existing headers *

    * @param bool $append [optional]

    * if true, and a header with the same name of one to add exists already, this respective * header will be converted to an array containing both header values, otherwise * it will be overwritten with the new header value *

    * @return void */ public function addHeaders(array $headers, $append = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Get message type * @link https://php.net/manual/en/function.httpmessage-gettype.php * @return int the HttpMessage::TYPE. */ #[Pure] public function getType() {} /** * (PECL pecl_http >= 0.10.0)
    * Set message type * @link https://php.net/manual/en/function.httpmessage-settype.php * @param int $type

    * the HttpMessage::TYPE *

    * @return void */ public function setType($type) {} #[Pure] public function getInfo() {} /** * @param $http_info */ public function setInfo($http_info) {} /** * (PECL pecl_http >= 0.10.0)
    * Get response code * @link https://php.net/manual/en/function.httpmessage-getresponsecode.php * @return int|false the HTTP response code if the message is of type HttpMessage::TYPE_RESPONSE, else FALSE. */ #[Pure] public function getResponseCode() {} /** * (PECL pecl_http >= 0.10.0)
    * Set response code * @link https://php.net/manual/en/function.httpmessage-setresponsecode.php * @param int $code

    * HTTP response code *

    * @return bool TRUE on success, or FALSE if the message is not of type * HttpMessage::TYPE_RESPONSE or the response code is out of range (100-510). */ public function setResponseCode($code) {} /** * (PECL pecl_http >= 0.23.0)
    * Get response status * @link https://php.net/manual/en/function.httpmessage-getresponsestatus.php * @return string the HTTP response status string if the message is of type * HttpMessage::TYPE_RESPONSE, else FALSE. */ #[Pure] public function getResponseStatus() {} /** * (PECL pecl_http >= 0.23.0)
    * Set response status * @link https://php.net/manual/en/function.httpmessage-setresponsestatus.php * @param string $status

    * the response status text *

    * @return bool TRUE on success or FALSE if the message is not of type * HttpMessage::TYPE_RESPONSE. */ public function setResponseStatus($status) {} /** * (PECL pecl_http >= 0.10.0)
    * Get request method * @link https://php.net/manual/en/function.httpmessage-getrequestmethod.php * @return string|false the request method name on success, or FALSE if the message is * not of type HttpMessage::TYPE_REQUEST. */ #[Pure] public function getRequestMethod() {} /** * (PECL pecl_http >= 0.10.0)
    * Set request method * @link https://php.net/manual/en/function.httpmessage-setrequestmethod.php * @param string $method

    * the request method name *

    * @return bool TRUE on success, or FALSE if the message is not of type * HttpMessage::TYPE_REQUEST or an invalid request method was supplied. */ public function setRequestMethod($method) {} /** * (PECL pecl_http >= 0.21.0)
    * Get request URL * @link https://php.net/manual/en/function.httpmessage-getrequesturl.php * @return string|false the request URL as string on success, or FALSE if the message * is not of type HttpMessage::TYPE_REQUEST. */ #[Pure] public function getRequestUrl() {} /** * (PECL pecl_http >= 0.21.0)
    * Set request URL * @link https://php.net/manual/en/function.httpmessage-setrequesturl.php * @param string $url

    * the request URL *

    * @return bool TRUE on success, or FALSE if the message is not of type * HttpMessage::TYPE_REQUEST or supplied URL was empty. */ public function setRequestUrl($url) {} /** * (PECL pecl_http >= 0.10.0)
    * Get HTTP version * @link https://php.net/manual/en/function.httpmessage-gethttpversion.php * @return string the HTTP protocol version as string. */ #[Pure] public function getHttpVersion() {} /** * (PECL pecl_http >= 0.10.0)
    * Set HTTP version * @link https://php.net/manual/en/function.httpmessage-sethttpversion.php * @param string $version

    * the HTTP protocol version *

    * @return bool TRUE on success, or FALSE if supplied version is out of range (1.0/1.1). */ public function setHttpVersion($version) {} /** * (PECL pecl_http >= 1.0.0)
    * Guess content type * @link https://php.net/manual/en/function.httpmessage-guesscontenttype.php * @param string $magic_file

    * the magic.mime database to use *

    * @param int $magic_mode [optional]

    * flags for libmagic *

    * @return string|false the guessed content type on success or false on failure. */ public function guessContentType($magic_file, $magic_mode = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Get parent message * @link https://php.net/manual/en/function.httpmessage-getparentmessage.php * @return HttpMessage the parent HttpMessage object. */ #[Pure] public function getParentMessage() {} /** * (PECL pecl_http >= 0.10.0)
    * Send message * @link https://php.net/manual/en/function.httpmessage-send.php * @return bool true on success or false on failure. */ public function send() {} /** * (PECL pecl_http >= 0.10.0)
    * Get string representation * @link https://php.net/manual/en/function.httpmessage-tostring.php * @param bool $include_parent [optional]

    * specifies whether the returned string should also contain any parent messages *

    * @return string the message as string. */ public function toString($include_parent = null) {} /** * (PECL pecl_http >= 0.22.0)
    * Create HTTP object regarding message type * @link https://php.net/manual/en/function.httpmessage-tomessagetypeobject.php * @return HttpRequest|HttpResponse|null either an HttpRequest or HttpResponse object on success, or NULL on failure. */ public function toMessageTypeObject() {} public function count() {} public function serialize() {} /** * @param $serialized */ public function unserialize($serialized) {} public function rewind() {} public function valid() {} public function current() {} public function key() {} public function next() {} /** * @return string */ public function __toString() {} /** * (PECL pecl_http >= 1.4.0)
    * Create HttpMessage from string * @link https://php.net/manual/en/function.httpmessage-factory.php * @param string $raw_message [optional]

    * a single or several consecutive HTTP messages *

    * @param string $class_name [optional]

    * a class extending HttpMessage *

    * @return HttpMessage|null an HttpMessage object on success or NULL on failure. */ public static function factory($raw_message = null, $class_name = null) {} /** * (PECL pecl_http 0.10.0-1.3.3)
    * Create HttpMessage from string * @link https://php.net/manual/en/function.httpmessage-fromstring.php * @param string $raw_message [optional]

    * a single or several consecutive HTTP messages *

    * @param string $class_name [optional]

    * a class extending HttpMessage *

    * @return HttpMessage|null an HttpMessage object on success or NULL on failure. */ public static function fromString($raw_message = null, $class_name = null) {} /** * (PECL pecl_http >= 1.5.0)
    * Create HttpMessage from environment * @link https://php.net/manual/en/function.httpmessage-fromenv.php * @param int $message_type

    * The message type. See HttpMessage type constants. *

    * @param string $class_name [optional]

    * a class extending HttpMessage *

    * @return HttpMessage|null an HttpMessage object on success or NULL on failure. */ public static function fromEnv($message_type, $class_name = null) {} /** * (PECL pecl_http >= 0.22.0)
    * Detach HttpMessage * @link https://php.net/manual/en/function.httpmessage-detach.php * @return HttpMessage detached HttpMessage object copy. */ public function detach() {} /** * (PECL pecl_http >= 0.22.0)
    * Prepend message(s) * @link https://php.net/manual/en/function.httpmessage-prepend.php * @param HttpMessage $message

    * HttpMessage object to prepend *

    * @param bool $top [optional]

    * whether to prepend to the top most or right this message *

    * @return void */ public function prepend(HttpMessage $message, $top = null) {} /** * (PECL pecl_http >= 0.23.0)
    * Reverse message chain * @link https://php.net/manual/en/function.httpmessage-reverse.php * @return HttpMessage the most parent HttpMessage object. */ public function reverse() {} } /** * @link https://php.net/manual/en/class.httpquerystring.php */ class HttpQueryString implements Serializable, ArrayAccess { public const TYPE_BOOL = 3; public const TYPE_INT = 1; public const TYPE_FLOAT = 2; public const TYPE_STRING = 6; public const TYPE_ARRAY = 4; public const TYPE_OBJECT = 5; private static $instance; private $queryArray; private $queryString; /** * (PECL pecl_http >= 0.22.0)
    * HttpQueryString constructor * @link https://php.net/manual/en/function.httpquerystring-construct.php * @param bool $global [optional]

    * whether to operate on $_GET and * $_SERVER['QUERY_STRING'] *

    * @param mixed $add [optional]

    * additional/initial query string parameters *

    */ final public function __construct($global = null, $add = null) {} /** * (PECL pecl_http >= 0.22.0)
    * Get query string as array * @link https://php.net/manual/en/function.httpquerystring-toarray.php * @return array the array representation of the query string. */ public function toArray() {} /** * (PECL pecl_http >= 0.22.0)
    * Get query string * @link https://php.net/manual/en/function.httpquerystring-tostring.php * @return string the string representation of the query string. */ public function toString() {} /** * @return string */ public function __toString() {} /** * (PECL pecl_http >= 0.22.0)
    * Get (part of) query string * @link https://php.net/manual/en/function.httpquerystring-get.php * @param string $key [optional]

    * key of the query string param to retrieve *

    * @param mixed $type [optional]

    * which variable type to enforce *

    * @param mixed $defval [optional]

    * default value if key does not exist *

    * @param bool $delete [optional]

    * whether to remove the key/value pair from the query string *

    * @return mixed the value of the query string param or the whole query string if no key was specified on success or defval if key does not exist. */ #[Pure] public function get($key = null, $type = null, $defval = null, $delete = null) {} /** * (PECL pecl_http >= 0.22.0)
    * Set query string params * @link https://php.net/manual/en/function.httpquerystring-set.php * @param mixed $params

    * query string params to add *

    * @return string the current query string. */ public function set($params) {} /** * (PECL pecl_http >= 1.1.0)
    * Modifiy query string copy * @link https://php.net/manual/en/function.httpquerystring-mod.php * @param mixed $params

    * query string params to add *

    * @return HttpQueryString a new HttpQueryString object */ public function mod($params) {} /** * @param $name * @param $defval [optional] * @param $delete [optional] */ #[Pure] public function getBool($name, $defval, $delete) {} /** * @param $name * @param $defval [optional] * @param $delete [optional] */ #[Pure] public function getInt($name, $defval, $delete) {} /** * @param $name * @param $defval [optional] * @param $delete [optional] */ #[Pure] public function getFloat($name, $defval, $delete) {} /** * @param $name * @param $defval [optional] * @param $delete [optional] */ #[Pure] public function getString($name, $defval, $delete) {} /** * @param $name * @param $defval [optional] * @param $delete [optional] */ #[Pure] public function getArray($name, $defval, $delete) {} /** * @param $name * @param $defval [optional] * @param $delete [optional] */ #[Pure] public function getObject($name, $defval, $delete) {} /** * @param $global [optional] * @param $params [optional] * @param $class_name [optional] */ public static function factory($global, $params, $class_name) {} /** * (PECL pecl_http >= 0.25.0)
    * HttpQueryString singleton * @link https://php.net/manual/en/function.httpquerystring-singleton.php * @param bool $global [optional]

    * whether to operate on $_GET and * $_SERVER['QUERY_STRING'] *

    * @return HttpQueryString always the same HttpQueryString instance regarding the global setting. */ public static function singleton($global = null) {} /** * (PECL pecl_http >= 0.25.0)
    * Change query strings charset * @link https://php.net/manual/en/function.httpquerystring-xlate.php * @param string $ie

    * input encoding *

    * @param string $oe

    * output encoding *

    * @return bool true on success or false on failure. */ public function xlate($ie, $oe) {} /** * String representation of object * @link https://php.net/manual/en/serializable.serialize.php * @return string the string representation of the object or null * @since 5.1.0 */ public function serialize() {} /** * Offset to retrieve * @link https://php.net/manual/en/arrayaccess.offsetget.php * @param mixed $offset

    * The offset to retrieve. *

    * @return mixed Can return all value types. * @since 5.0.0 */ public function offsetGet($offset) {} /** * Constructs the object * @link https://php.net/manual/en/serializable.unserialize.php * @param string $serialized

    * The string representation of the object. *

    * @return void * @since 5.1.0 */ public function unserialize($serialized) {} /** * Whether a offset exists * @link https://php.net/manual/en/arrayaccess.offsetexists.php * @param mixed $offset

    * An offset to check for. *

    * @return bool true on success or false on failure. *

    *

    * The return value will be casted to boolean if non-boolean was returned. * @since 5.0.0 */ public function offsetExists($offset) {} /** * Offset to set * @link https://php.net/manual/en/arrayaccess.offsetset.php * @param mixed $offset

    * The offset to assign the value to. *

    * @param mixed $value

    * The value to set. *

    * @return void * @since 5.0.0 */ public function offsetSet($offset, $value) {} /** * Offset to unset * @link https://php.net/manual/en/arrayaccess.offsetunset.php * @param mixed $offset

    * The offset to unset. *

    * @return void * @since 5.0.0 */ public function offsetUnset($offset) {} } /** * @link https://php.net/manual/en/class.httprequest.php */ class HttpRequest { public const METH_GET = 1; public const METH_HEAD = 2; public const METH_POST = 3; public const METH_PUT = 4; public const METH_DELETE = 5; public const METH_OPTIONS = 6; public const METH_TRACE = 7; public const METH_CONNECT = 8; public const METH_PROPFIND = 9; public const METH_PROPPATCH = 10; public const METH_MKCOL = 11; public const METH_COPY = 12; public const METH_MOVE = 13; public const METH_LOCK = 14; public const METH_UNLOCK = 15; public const METH_VERSION_CONTROL = 16; public const METH_REPORT = 17; public const METH_CHECKOUT = 18; public const METH_CHECKIN = 19; public const METH_UNCHECKOUT = 20; public const METH_MKWORKSPACE = 21; public const METH_UPDATE = 22; public const METH_LABEL = 23; public const METH_MERGE = 24; public const METH_BASELINE_CONTROL = 25; public const METH_MKACTIVITY = 26; public const METH_ACL = 27; public const VERSION_1_0 = 1; public const VERSION_1_1 = 2; public const VERSION_NONE = 0; public const VERSION_ANY = 0; public const SSL_VERSION_TLSv1 = 1; public const SSL_VERSION_SSLv2 = 2; public const SSL_VERSION_SSLv3 = 3; public const SSL_VERSION_ANY = 0; public const IPRESOLVE_V4 = 1; public const IPRESOLVE_V6 = 2; public const IPRESOLVE_ANY = 0; public const AUTH_BASIC = 1; public const AUTH_DIGEST = 2; public const AUTH_NTLM = 8; public const AUTH_GSSNEG = 4; public const AUTH_ANY = -1; public const PROXY_SOCKS4 = 4; public const PROXY_SOCKS5 = 5; public const PROXY_HTTP = 0; private $options; private $postFields; private $postFiles; private $responseInfo; private $responseMessage; private $responseCode; private $responseStatus; private $method; private $url; private $contentType; private $requestBody; private $queryData; private $putFile; private $putData; private $history; public $recordHistory; /** * (PECL pecl_http >= 0.10.0)
    * HttpRequest constructor * @link https://php.net/manual/en/function.httprequest-construct.php * @param string $url [optional]

    * the target request url *

    * @param int $request_method [optional]

    * the request method to use *

    * @param null|array $options [optional]

    * an associative array with request options *

    */ public function __construct($url = null, $request_method = null, ?array $options = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Set options * @link https://php.net/manual/en/function.httprequest-setoptions.php * @param null|array $options [optional]

    * an associative array, which values will overwrite the * currently set request options; * if empty or omitted, the options of the HttpRequest object will be reset *

    * @return bool true on success or false on failure. */ public function setOptions(?array $options = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Get options * @link https://php.net/manual/en/function.httprequest-getoptions.php * @return array an associative array containing currently set options. */ #[Pure] public function getOptions() {} /** * (PECL pecl_http >= 0.10.0)
    * Set ssl options * @link https://php.net/manual/en/function.httprequest-setssloptions.php * @param null|array $options [optional]

    * an associative array containing any SSL specific options; * if empty or omitted, the SSL options will be reset *

    * @return bool true on success or false on failure. */ public function setSslOptions(?array $options = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Get ssl options * @link https://php.net/manual/en/function.httprequest-getssloptions.php * @return array an associative array containing any previously set SSL options. */ #[Pure] public function getSslOptions() {} /** * (PECL pecl_http >= 0.12.0)
    * Add ssl options * @link https://php.net/manual/en/function.httprequest-addssloptions.php * @param array $option

    * an associative array as parameter containing additional SSL specific options *

    * @return bool true on success or false on failure. */ public function addSslOptions(array $option) {} /** * (PECL pecl_http >= 0.10.0)
    * Add headers * @link https://php.net/manual/en/function.httprequest-addheaders.php * @param array $headers

    * an associative array as parameter containing additional header name/value pairs *

    * @return bool true on success or false on failure. */ public function addHeaders(array $headers) {} /** * (PECL pecl_http >= 0.10.0)
    * Get headers * @link https://php.net/manual/en/function.httprequest-getheaders.php * @return array an associative array containing all currently set headers. */ #[Pure] public function getHeaders() {} /** * (PECL pecl_http >= 0.12.0)
    * Set headers * @link https://php.net/manual/en/function.httprequest-setheaders.php * @param null|array $headers [optional]

    * an associative array as parameter containing header name/value pairs; * if empty or omitted, all previously set headers will be unset *

    * @return bool true on success or false on failure. */ public function setHeaders(?array $headers = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Add cookies * @link https://php.net/manual/en/function.httprequest-addcookies.php * @param array $cookies

    * an associative array containing any cookie name/value pairs to add *

    * @return bool true on success or false on failure. */ public function addCookies(array $cookies) {} /** * (PECL pecl_http >= 0.10.0)
    * Get cookies * @link https://php.net/manual/en/function.httprequest-getcookies.php * @return array an associative array containing any previously set cookies. */ #[Pure] public function getCookies() {} /** * (PECL pecl_http >= 0.12.0)
    * Set cookies * @link https://php.net/manual/en/function.httprequest-setcookies.php * @param null|array $cookies [optional]

    * an associative array as parameter containing cookie name/value pairs; * if empty or omitted, all previously set cookies will be unset *

    * @return bool true on success or false on failure. */ public function setCookies(?array $cookies = null) {} /** * (PECL pecl_http >= 1.0.0)
    * Enable cookies * @link https://php.net/manual/en/function.httprequest-enablecookies.php * @return bool true on success or false on failure. */ public function enableCookies() {} /** * (PECL pecl_http >= 1.0.0)
    * Reset cookies * @link https://php.net/manual/en/function.httprequest-resetcookies.php * @param bool $session_only [optional]

    * whether only session cookies should be reset (needs libcurl >= v7.15.4, else libcurl >= v7.14.1) *

    * @return bool true on success or false on failure. */ public function resetCookies($session_only = null) {} public function flushCookies() {} /** * (PECL pecl_http >= 0.10.0)
    * Set method * @link https://php.net/manual/en/function.httprequest-setmethod.php * @param int $request_method

    * the request method to use *

    * @return bool true on success or false on failure. */ public function setMethod($request_method) {} /** * (PECL pecl_http >= 0.10.0)
    * Get method * @link https://php.net/manual/en/function.httprequest-getmethod.php * @return int the currently set request method. */ #[Pure] public function getMethod() {} /** * (PECL pecl_http >= 0.10.0)
    * Set URL * @link https://php.net/manual/en/function.httprequest-seturl.php * @param string $url

    * the request url *

    * @return bool true on success or false on failure. */ public function setUrl($url) {} /** * (PECL pecl_http >= 0.10.0)
    * Get url * @link https://php.net/manual/en/function.httprequest-geturl.php * @return string the currently set request url as string. */ #[Pure] public function getUrl() {} /** * (PECL pecl_http >= 0.10.0)
    * Set content type * @link https://php.net/manual/en/function.httprequest-setcontenttype.php * @param string $content_type

    * the content type of the request (primary/secondary) *

    * @return bool TRUE on success, or FALSE if the content type does not seem to * contain a primary and a secondary part. */ public function setContentType($content_type) {} /** * (PECL pecl_http >= 0.10.0)
    * Get content type * @link https://php.net/manual/en/function.httprequest-getcontenttype.php * @return string the previously set content type as string. */ #[Pure] public function getContentType() {} /** * (PECL pecl_http >= 0.10.0)
    * Set query data * @link https://php.net/manual/en/function.httprequest-setquerydata.php * @param mixed $query_data

    * a string or associative array parameter containing the pre-encoded * query string or to be encoded query fields; * if empty, the query data will be unset *

    * @return bool true on success or false on failure. */ public function setQueryData($query_data) {} /** * (PECL pecl_http >= 0.10.0)
    * Get query data * @link https://php.net/manual/en/function.httprequest-getquerydata.php * @return string a string containing the urlencoded query. */ #[Pure] public function getQueryData() {} /** * (PECL pecl_http >= 0.10.0)
    * Add query data * @link https://php.net/manual/en/function.httprequest-addquerydata.php * @param array $query_params

    * an associative array as parameter containing the query fields to add *

    * @return bool true on success or false on failure. */ public function addQueryData(array $query_params) {} /** * (PECL pecl_http >= 0.10.0)
    * Set post fields * @link https://php.net/manual/en/function.httprequest-setpostfields.php * @param array $post_data

    * an associative array containing the post fields; * if empty, the post data will be unset *

    * @return bool true on success or false on failure. */ public function setPostFields(array $post_data) {} /** * (PECL pecl_http >= 0.10.0)
    * Get post fields * @link https://php.net/manual/en/function.httprequest-getpostfields.php * @return array the currently set post fields as associative array. */ #[Pure] public function getPostFields() {} /** * (PECL pecl_http >= 0.10.0)
    * Add post fields * @link https://php.net/manual/en/function.httprequest-addpostfields.php * @param array $post_data

    * an associative array as parameter containing the post fields *

    * @return bool true on success or false on failure. */ public function addPostFields(array $post_data) {} /** * @param $request_body_data [optional] */ public function setBody($request_body_data) {} #[Pure] public function getBody() {} /** * @param $request_body_data */ public function addBody($request_body_data) {} /** * (PECL pecl_http 0.14.0-1.4.1)
    * Set raw post data * @link https://php.net/manual/en/function.httprequest-setrawpostdata.php * @param string $raw_post_data [optional]

    * raw post data *

    * @return bool true on success or false on failure. */ public function setRawPostData($raw_post_data = null) {} /** * (PECL pecl_http 0.14.0-1.4.1)
    * Get raw post data * @link https://php.net/manual/en/function.httprequest-getrawpostdata.php * @return string a string containing the currently set raw post data. */ #[Pure] public function getRawPostData() {} /** * (PECL pecl_http 0.14.0-1.4.1)
    * Add raw post data * @link https://php.net/manual/en/function.httprequest-addrawpostdata.php * @param string $raw_post_data

    * the raw post data to concatenate *

    * @return bool true on success or false on failure. */ public function addRawPostData($raw_post_data) {} /** * (PECL pecl_http >= 0.10.0)
    * Set post files * @link https://php.net/manual/en/function.httprequest-setpostfiles.php * @param array $post_files

    * an array containing the files to post; * if empty, the post files will be unset *

    * @return bool true on success or false on failure. */ public function setPostFiles(array $post_files) {} /** * (PECL pecl_http >= 0.10.0)
    * Add post file * @link https://php.net/manual/en/function.httprequest-addpostfile.php * @param string $name

    * the form element name *

    * @param string $file

    * the path to the file *

    * @param string $content_type [optional]

    * the content type of the file *

    * @return bool TRUE on success, or FALSE if the content type seems not to contain a * primary and a secondary content type part. */ public function addPostFile($name, $file, $content_type = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Get post files * @link https://php.net/manual/en/function.httprequest-getpostfiles.php * @return array an array containing currently set post files. */ #[Pure] public function getPostFiles() {} /** * (PECL pecl_http >= 0.10.0)
    * Set put file * @link https://php.net/manual/en/function.httprequest-setputfile.php * @param string $file [optional]

    * the path to the file to send; * if empty or omitted the put file will be unset *

    * @return bool true on success or false on failure. */ public function setPutFile($file = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Get put file * @link https://php.net/manual/en/function.httprequest-getputfile.php * @return string a string containing the path to the currently set put file. */ #[Pure] public function getPutFile() {} /** * (PECL pecl_http >= 0.25.0)
    * Set put data * @link https://php.net/manual/en/function.httprequest-setputdata.php * @param string $put_data [optional]

    * the data to upload *

    * @return bool true on success or false on failure. */ public function setPutData($put_data = null) {} /** * (PECL pecl_http >= 0.25.0)
    * Get put data * @link https://php.net/manual/en/function.httprequest-getputdata.php * @return string a string containing the currently set PUT data. */ #[Pure] public function getPutData() {} /** * (PECL pecl_http >= 0.25.0)
    * Add put data * @link https://php.net/manual/en/function.httprequest-addputdata.php * @param string $put_data

    * the data to concatenate *

    * @return bool true on success or false on failure. */ public function addPutData($put_data) {} /** * (PECL pecl_http >= 0.10.0)
    * Send request * @link https://php.net/manual/en/function.httprequest-send.php * @return HttpMessage the received response as HttpMessage object. */ public function send() {} /** * (PECL pecl_http >= 0.10.0)
    * Get response data * @link https://php.net/manual/en/function.httprequest-getresponsedata.php * @return array an associative array with the key "headers" containing an associative * array holding all response headers, as well as the key "body" containing a * string with the response body. */ #[Pure] public function getResponseData() {} /** * (PECL pecl_http >= 0.10.0)
    * Get response header(s) * @link https://php.net/manual/en/function.httprequest-getresponseheader.php * @param string $name [optional]

    * header to read; if empty, all response headers will be returned *

    * @return mixed either a string with the value of the header matching name if requested, * FALSE on failure, or an associative array containing all response headers. */ #[Pure] public function getResponseHeader($name = null) {} /** * (PECL pecl_http >= 0.23.0)
    * Get response cookie(s) * @link https://php.net/manual/en/function.httprequest-getresponsecookies.php * @param int $flags [optional]

    * http_parse_cookie flags *

    * @param null|array $allowed_extras [optional]

    * allowed keys treated as extra information instead of cookie names *

    * @return stdClass[] an array of stdClass objects like http_parse_cookie would return. */ #[Pure] public function getResponseCookies($flags = null, ?array $allowed_extras = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Get response code * @link https://php.net/manual/en/function.httprequest-getresponsecode.php * @return int an int representing the response code. */ #[Pure] public function getResponseCode() {} /** * (PECL pecl_http >= 0.23.0)
    * Get response status * @link https://php.net/manual/en/function.httprequest-getresponsestatus.php * @return string a string containing the response status text. */ #[Pure] public function getResponseStatus() {} /** * (PECL pecl_http >= 0.10.0)
    * Get response body * @link https://php.net/manual/en/function.httprequest-getresponsebody.php * @return string a string containing the response body. */ #[Pure] public function getResponseBody() {} /** * (PECL pecl_http >= 0.10.0)
    * Get response info * @link https://php.net/manual/en/function.httprequest-getresponseinfo.php * @param string $name [optional]

    * the info to read; if empty or omitted, an associative array containing * all available info will be returned *

    * @return mixed either a scalar containing the value of the info matching name if * requested, FALSE on failure, or an associative array containing all * available info. */ #[Pure] public function getResponseInfo($name = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Get response message * @link https://php.net/manual/en/function.httprequest-getresponsemessage.php * @return HttpMessage an HttpMessage object of the response. */ #[Pure] public function getResponseMessage() {} /** * (PECL pecl_http >= 0.21.0)
    * Get raw response message * @link https://php.net/manual/en/function.httprequest-getrawresponsemessage.php * @return string the complete web server response, including the headers in a form of a string. */ #[Pure] public function getRawResponseMessage() {} /** * (PECL pecl_http >= 0.11.0)
    * Get request message * @link https://php.net/manual/en/function.httprequest-getrequestmessage.php * @return HttpMessage an HttpMessage object representing the sent request. */ #[Pure] public function getRequestMessage() {} /** * (PECL pecl_http >= 0.21.0)
    * Get raw request message * @link https://php.net/manual/en/function.httprequest-getrawrequestmessage.php * @return string an HttpMessage in a form of a string. */ #[Pure] public function getRawRequestMessage() {} /** * (PECL pecl_http >= 0.15.0)
    * Get history * @link https://php.net/manual/en/function.httprequest-gethistory.php * @return HttpMessage an HttpMessage object representing the complete request/response history. */ #[Pure] public function getHistory() {} /** * (PECL pecl_http >= 0.15.0)
    * Clear history * @link https://php.net/manual/en/function.httprequest-clearhistory.php * @return void */ public function clearHistory() {} /** * @param $url [optional] * @param $method [optional] * @param $options [optional] * @param $class_name [optional] */ public static function factory($url, $method, $options, $class_name) {} /** * @param $url * @param $options [optional] * @param &$info [optional] */ public static function get($url, $options, &$info) {} /** * @param $url * @param $options [optional] * @param &$info [optional] */ public static function head($url, $options, &$info) {} /** * @param $url * @param $data * @param $options [optional] * @param &$info [optional] */ public static function postData($url, $data, $options, &$info) {} /** * @param $url * @param $data * @param $options [optional] * @param &$info [optional] */ public static function postFields($url, $data, $options, &$info) {} /** * @param $url * @param $data * @param $options [optional] * @param &$info [optional] */ public static function putData($url, $data, $options, &$info) {} /** * @param $url * @param $file * @param $options [optional] * @param &$info [optional] */ public static function putFile($url, $file, $options, &$info) {} /** * @param $url * @param $stream * @param $options [optional] * @param &$info [optional] */ public static function putStream($url, $stream, $options, &$info) {} /** * @param $method_name */ public static function methodRegister($method_name) {} /** * @param $method */ public static function methodUnregister($method) {} /** * @param $method_id */ public static function methodName($method_id) {} /** * @param $method */ public static function methodExists($method) {} /** * @param $fields * @param $files */ public static function encodeBody($fields, $files) {} } class HttpRequestDataShare implements Countable { private static $instance; public $cookie; public $dns; public $ssl; public $connect; public function __destruct() {} public function count() {} /** * @param HttpRequest $request */ public function attach(HttpRequest $request) {} /** * @param HttpRequest $request */ public function detach(HttpRequest $request) {} public function reset() {} /** * @param $global [optional] * @param $class_name [optional] */ public static function factory($global, $class_name) {} /** * @param $global [optional] */ public static function singleton($global) {} } /** * @link https://php.net/manual/en/class.httprequestpool.php */ class HttpRequestPool implements Countable, Iterator { /** * (PECL pecl_http >= 0.10.0)
    * HttpRequestPool constructor * @link https://php.net/manual/en/function.httprequestpool-construct.php * @param null|HttpRequest $request [optional]

    * HttpRequest object to attach *

    */ public function __construct(?HttpRequest $request = null) {} /** * (PECL pecl_http >= 0.10.0)
    * HttpRequestPool destructor * @link https://php.net/manual/en/function.httprequestpool-destruct.php * @return void */ public function __destruct() {} /** * (PECL pecl_http >= 0.10.0)
    * Attach HttpRequest * @link https://php.net/manual/en/function.httprequestpool-attach.php * @param HttpRequest $request

    * an HttpRequest object not already attached to any HttpRequestPool object *

    * @return bool true on success or false on failure. */ public function attach(HttpRequest $request) {} /** * (PECL pecl_http >= 0.10.0)
    * Detach HttpRequest * @link https://php.net/manual/en/function.httprequestpool-detach.php * @param HttpRequest $request

    * an HttpRequest object attached to this HttpRequestPool object *

    * @return bool true on success or false on failure. */ public function detach(HttpRequest $request) {} /** * (PECL pecl_http >= 0.10.0)
    * Send all requests * @link https://php.net/manual/en/function.httprequestpool-send.php * @return bool true on success or false on failure. */ public function send() {} /** * (PECL pecl_http >= 0.10.0)
    * Reset request pool * @link https://php.net/manual/en/function.httprequestpool-reset.php * @return void */ public function reset() {} /** * (PECL pecl_http >= 0.15.0)
    * Perform socket actions * @link https://php.net/manual/en/function.httprequestpool-socketperform.php * @return bool TRUE until each request has finished its transaction. */ protected function socketPerform() {} /** * (PECL pecl_http >= 0.10.0)
    * Perform socket select * @link https://php.net/manual/en/function.httprequestpool-socketselect.php * @return bool true on success or false on failure. */ protected function socketSelect() {} public function valid() {} public function current() {} public function key() {} public function next() {} public function rewind() {} public function count() {} /** * (PECL pecl_http >= 0.16.0)
    * Get attached requests * @link https://php.net/manual/en/function.httprequestpool-getattachedrequests.php * @return array an array containing all currently attached HttpRequest objects. */ #[Pure] public function getAttachedRequests() {} /** * (PECL pecl_http >= 0.16.0)
    * Get finished requests * @link https://php.net/manual/en/function.httprequestpool-getfinishedrequests.php * @return array an array containing all attached HttpRequest objects that already have finished their work. */ #[Pure] public function getFinishedRequests() {} /** * @param $enable [optional] */ public function enablePipelining($enable) {} /** * @param $enable [optional] */ public function enableEvents($enable) {} } /** * @link https://php.net/manual/en/class.httpresponse.php */ class HttpResponse { public const REDIRECT = 0; public const REDIRECT_PERM = 301; public const REDIRECT_FOUND = 302; public const REDIRECT_POST = 303; public const REDIRECT_PROXY = 305; public const REDIRECT_TEMP = 307; private static $sent; private static $catch; private static $mode; private static $stream; private static $file; private static $data; protected static $cache; protected static $gzip; protected static $eTag; protected static $lastModified; protected static $cacheControl; protected static $contentType; protected static $contentDisposition; protected static $bufferSize; protected static $throttleDelay; /** * (PECL pecl_http >= 0.12.0)
    * Set header * @link https://php.net/manual/en/function.httpresponse-setheader.php * @param string $name

    * the name of the header *

    * @param mixed $value [optional]

    * the value of the header; * if not set, no header with this name will be sent *

    * @param bool $replace [optional]

    * whether an existing header should be replaced *

    * @return bool true on success or false on failure. */ public static function setHeader($name, $value = null, $replace = null) {} /** * (PECL pecl_http >= 0.12.0)
    * Get header * @link https://php.net/manual/en/function.httpresponse-getheader.php * @param string $name [optional]

    * specifies the name of the header to read; * if empty or omitted, an associative array with all headers will be returned *

    * @return mixed either a string containing the value of the header matching name, * false on failure, or an associative array with all headers. */ public static function getHeader($name = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Set ETag * @link https://php.net/manual/en/function.httpresponse-setetag.php * @param string $etag

    * unquoted string as parameter containing the ETag *

    * @return bool true on success or false on failure. */ public static function setETag($etag) {} /** * (PECL pecl_http >= 0.10.0)
    * Get ETag * @link https://php.net/manual/en/function.httpresponse-getetag.php * @return string the calculated or previously set ETag as unquoted string. */ public static function getETag() {} /** * (PECL pecl_http >= 0.12.0)
    * Set last modified * @link https://php.net/manual/en/function.httpresponse-setlastmodified.php * @param int $timestamp

    * Unix timestamp representing the last modification time of the sent entity *

    * @return bool true on success or false on failure. */ public static function setLastModified($timestamp) {} /** * (PECL pecl_http >= 0.12.0)
    * Get last modified * @link https://php.net/manual/en/function.httpresponse-getlastmodified.php * @return int the calculated or previously set Unix timestamp. */ public static function getLastModified() {} /** * (PECL pecl_http >= 0.10.0)
    * Set content disposition * @link https://php.net/manual/en/function.httpresponse-setcontentdisposition.php * @param string $filename

    * the file name the "Save as..." dialog should display *

    * @param bool $inline [optional]

    * if set to true and the user agent knows how to handle the content type, * it will probably not cause the popup window to be shown *

    * @return bool true on success or false on failure. */ public static function setContentDisposition($filename, $inline = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Get content disposition * @link https://php.net/manual/en/function.httpresponse-getcontentdisposition.php * @return string the current content disposition as string like sent in a header. */ public static function getContentDisposition() {} /** * (PECL pecl_http >= 0.10.0)
    * Set content type * @link https://php.net/manual/en/function.httpresponse-setcontenttype.php * @param string $content_type

    * the content type of the sent entity (primary/secondary) *

    * @return bool true on success, or false if the content type does not seem to * contain a primary and secondary content type part. */ public static function setContentType($content_type) {} /** * (PECL pecl_http >= 0.10.0)
    * Get content type * @link https://php.net/manual/en/function.httpresponse-getcontenttype.php * @return string the currently set content type as string. */ public static function getContentType() {} /** * (PECL pecl_http >= 0.13.0)
    * Guess content type * @link https://php.net/manual/en/function.httpresponse-guesscontenttype.php * @param string $magic_file

    * specifies the magic.mime database to use *

    * @param int $magic_mode [optional]

    * flags for libmagic *

    * @return string|false the guessed content type on success or false on failure. */ public static function guessContentType($magic_file, $magic_mode = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Set cache * @link https://php.net/manual/en/function.httpresponse-setcache.php * @param bool $cache

    * whether caching should be attempted *

    * @return bool true on success or false on failure. */ public static function setCache($cache) {} /** * (PECL pecl_http >= 0.10.0)
    * Get cache * @link https://php.net/manual/en/function.httpresponse-getcache.php * @return bool true if caching should be attempted, else false. */ public static function getCache() {} /** * (PECL pecl_http >= 0.10.0)
    * Set cache control * @link https://php.net/manual/en/function.httpresponse-setcachecontrol.php * @param string $control

    * the primary cache control setting *

    * @param int $max_age [optional]

    * the max-age in seconds, suggesting how long the cache entry is valid on the client side *

    * @param bool $must_revalidate [optional]

    * whether the cached entity should be revalidated by the client for every request *

    * @return bool true on success, or false if control does not match one of public, private or no-cache. */ public static function setCacheControl($control, $max_age = null, $must_revalidate = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Get cache control * @link https://php.net/manual/en/function.httpresponse-getcachecontrol.php * @return string the current cache control setting as a string like sent in a header. */ public static function getCacheControl() {} /** * (PECL pecl_http >= 0.10.0)
    * Set gzip * @link https://php.net/manual/en/function.httpresponse-setgzip.php * @param bool $gzip

    * whether GZip compression should be enabled *

    * @return bool true on success or false on failure. */ public static function setGzip($gzip) {} /** * (PECL pecl_http >= 0.10.0)
    * Get gzip * @link https://php.net/manual/en/function.httpresponse-getgzip.php * @return bool true if GZip compression is enabled, else false. */ public static function getGzip() {} /** * (PECL pecl_http >= 0.10.0)
    * Set throttle delay * @link https://php.net/manual/en/function.httpresponse-setthrottledelay.php * @param float $seconds

    * seconds to sleep after each chunk sent *

    * @return bool true on success or false on failure. */ public static function setThrottleDelay($seconds) {} /** * (PECL pecl_http >= 0.10.0)
    * Get throttle delay * @link https://php.net/manual/en/function.httpresponse-getthrottledelay.php * @return float a float representing the throttle delay in seconds. */ public static function getThrottleDelay() {} /** * (PECL pecl_http >= 0.10.0)
    * Set buffer size * @link https://php.net/manual/en/function.httpresponse-setbuffersize.php * @param int $bytes

    * the chunk size in bytes *

    * @return bool true on success or false on failure. */ public static function setBufferSize($bytes) {} /** * (PECL pecl_http >= 0.10.0)
    * Get buffer size * @link https://php.net/manual/en/function.httpresponse-getbuffersize.php * @return int an int representing the current buffer size in bytes. */ public static function getBufferSize() {} /** * (PECL pecl_http >= 0.10.0)
    * Set data * @link https://php.net/manual/en/function.httpresponse-setdata.php * @param mixed $data

    * data to send *

    * @return bool true on success or false on failure. */ public static function setData($data) {} /** * (PECL pecl_http >= 0.10.0)
    * Get data * @link https://php.net/manual/en/function.httpresponse-getdata.php * @return string a string containing the previously set data to send. */ public static function getData() {} /** * (PECL pecl_http >= 0.10.0)
    * Set file * @link https://php.net/manual/en/function.httpresponse-setfile.php * @param string $file

    * the path to the file to send *

    * @return bool true on success or false on failure. */ public static function setFile($file) {} /** * (PECL pecl_http >= 0.10.0)
    * Get file * @link https://php.net/manual/en/function.httpresponse-getfile.php * @return string the previously set path to the file to send as string. */ public static function getFile() {} /** * (PECL pecl_http >= 0.10.0)
    * Set stream * @link https://php.net/manual/en/function.httpresponse-setstream.php * @param resource $stream

    * already opened stream from which the data to send will be read *

    * @return bool true on success or false on failure. */ public static function setStream($stream) {} /** * (PECL pecl_http >= 0.10.0)
    * Get Stream * @link https://php.net/manual/en/function.httpresponse-getstream.php * @return resource the previously set resource. */ public static function getStream() {} /** * (PECL pecl_http >= 0.10.0)
    * Send response * @link https://php.net/manual/en/function.httpresponse-send.php * @param bool $clean_ob [optional]

    * whether to destroy all previously started output handlers and their buffers *

    * @return bool true on success or false on failure. */ public static function send($clean_ob = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Capture script output * @link https://php.net/manual/en/function.httpresponse-capture.php * @return void */ public static function capture() {} /** * (PECL pecl_http >= 0.10.0)
    * Redirect * @link https://php.net/manual/en/function.httpresponse-redirect.php * @param null|string $url [optional] * @param null|array $params [optional] * @param null|bool $session [optional] * @param null|int $status [optional] * @return void */ public static function redirect($url = null, ?array $params = null, $session = null, $status = null) {} /** * (PECL pecl_http >= 0.12.0)
    * Send HTTP response status * @link https://php.net/manual/en/function.httpresponse-status.php * @param int $status * @return bool */ public static function status($status) {} /** * (PECL pecl_http >= 0.10.0)
    * Get request headers * @link https://php.net/manual/en/function.httpresponse-getrequestheaders.php * @return array */ public static function getRequestHeaders() {} /** * (PECL pecl_http >= 0.10.0)
    * Get request body * @link https://php.net/manual/en/function.httpresponse-getrequestbody.php * @return string */ public static function getRequestBody() {} /** * (PECL pecl_http >= 0.10.0)
    * Get request body stream * @link https://php.net/manual/en/function.httpresponse-getrequestbodystream.php * @return resource */ public static function getRequestBodyStream() {} } class HttpUtil { /** * @param $timestamp [optional] */ public static function date($timestamp) {} /** * @param $url * @param $parts [optional] * @param $flags [optional] * @param &$composed [optional] */ public static function buildUrl($url, $parts, $flags, &$composed) {} /** * @param $query * @param $prefix [optional] * @param $arg_sep [optional] */ public static function buildStr($query, $prefix, $arg_sep) {} /** * @param $supported * @param &$result [optional] */ public static function negotiateLanguage($supported, &$result) {} /** * @param $supported * @param &$result [optional] */ public static function negotiateCharset($supported, &$result) {} /** * @param $supported * @param &$result [optional] */ public static function negotiateContentType($supported, &$result) {} /** * @param $last_modified * @param $for_range [optional] */ public static function matchModified($last_modified, $for_range) {} /** * @param $plain_etag * @param $for_range [optional] */ public static function matchEtag($plain_etag, $for_range) {} /** * @param $header_name * @param $header_value * @param $case_sensitive [optional] */ public static function matchRequestHeader($header_name, $header_value, $case_sensitive) {} /** * @param $message_string */ public static function parseMessage($message_string) {} /** * @param $headers_string */ public static function parseHeaders($headers_string) {} /** * @param $cookie_string */ public static function parseCookie($cookie_string) {} /** * @param $cookie_array */ public static function buildCookie($cookie_array) {} /** * @param $param_string * @param $flags [optional] */ public static function parseParams($param_string, $flags) {} /** * @param $encoded_string */ public static function chunkedDecode($encoded_string) {} /** * @param $plain * @param $flags [optional] */ public static function deflate($plain, $flags) {} /** * @param $encoded */ public static function inflate($encoded) {} /** * @param $feature [optional] */ public static function support($feature) {} } /** * (PECL pecl_http >= 0.1.0)
    * Compose HTTP RFC compliant date * @link https://php.net/manual/en/function.http-date.php * @param int $timestamp [optional]

    * Unix timestamp; current time if omitted *

    * @return string the HTTP date as string. */ #[Pure] function http_date($timestamp = null) {} /** * (PECL pecl_http >= 0.21.0)
    * Build an URL * @link https://php.net/manual/en/function.http-build-url.php * @param mixed $url [optional]

    * (part(s) of) an URL in form of a string or associative array like parse_url returns *

    * @param mixed $parts [optional]

    * same as the first argument *

    * @param null|int $flags [optional]

    * a bitmask of binary or'ed HTTP_URL constants; * HTTP_URL_REPLACE is the default *

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

    * if set, it will be filled with the parts of the composed url like parse_url would return *

    * @return string|false the new URL as string on success or false on failure. */ function http_build_url($url = null, $parts = null, $flags = null, ?array &$new_url = null) {} /** * (PECL pecl_http >= 0.23.0)
    * Build query string * @link https://php.net/manual/en/function.http-build-str.php * @param array $query

    * associative array of query string parameters *

    * @param string $prefix [optional]

    * top level prefix *

    * @param string $arg_separator [optional]

    * argument separator to use (by default the INI setting arg_separator.output will be used, or "&" if neither is set *

    * @return string|false the built query as string on success or false on failure. */ #[Pure] function http_build_str(array $query, $prefix = null, $arg_separator = null) {} /** * (PECL pecl_http >= 0.1.0)
    * Negotiate clients preferred language * @link https://php.net/manual/en/function.http-negotiate-language.php * @param array $supported

    * array containing the supported languages as values *

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

    * will be filled with an array containing the negotiation results *

    * @return string the negotiated language or the default language (i.e. first array entry) if none match. */ function http_negotiate_language(array $supported, ?array &$result = null) {} /** * (PECL pecl_http >= 0.1.0)
    * Negotiate clients preferred character set * @link https://php.net/manual/en/function.http-negotiate-charset.php * @param array $supported

    * array containing the supported charsets as values *

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

    * will be filled with an array containing the negotiation results *

    * @return string the negotiated charset or the default charset (i.e. first array entry) if none match. */ function http_negotiate_charset(array $supported, ?array &$result = null) {} /** * (PECL pecl_http >= 0.19.0)
    * Negotiate clients preferred content type * @link https://php.net/manual/en/function.http-negotiate-content-type.php * @param array $supported

    * array containing the supported content types as values *

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

    * will be filled with an array containing the negotiation results *

    * @return string the negotiated content type or the default content type (i.e. first array entry) if none match. */ function http_negotiate_content_type(array $supported, ?array &$result = null) {} /** * (PECL pecl_http >= 0.1.0)
    * Issue HTTP redirect * @link https://php.net/manual/en/function.http-redirect.php * @param string $url [optional]

    * the URL to redirect to *

    * @param null|array $params [optional]

    * associative array of query parameters *

    * @param null|bool $session [optional]

    * whether to append session information *

    * @param null|int $status [optional]

    * custom response status code *

    * @return void|false returns false or exits with the specified redirection status code */ function http_redirect($url = null, ?array $params = null, $session = null, $status = null) {} /** * (PECL pecl_http >= 0.10.0)
    * HTTP throttling * @link https://php.net/manual/en/function.http-throttle.php * @param float $sec [optional]

    * seconds to sleep after each chunk sent *

    * @param int $bytes [optional]

    * the chunk size in bytes *

    * @return void */ function http_throttle($sec = null, $bytes = null) {} /** * (PECL pecl_http >= 0.1.0)
    * Send HTTP response status * @link https://php.net/manual/en/function.http-send-status.php * @param int $status

    * HTTP status code (100-599) *

    * @return bool true on success or false on failure. */ function http_send_status($status) {} /** * (PECL pecl_http >= 0.1.0)
    * Send Last-Modified * @link https://php.net/manual/en/function.http-send-last-modified.php * @param int $timestamp [optional]

    * a Unix timestamp, converted to a valid HTTP date; * if omitted, the current time will be sent *

    * @return bool true on success or false on failure. */ function http_send_last_modified($timestamp = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Send Content-Type * @link https://php.net/manual/en/function.http-send-content-type.php * @param string $content_type [optional]

    * the desired content type (primary/secondary) *

    * @return bool true on success or false on failure. */ function http_send_content_type($content_type = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Send Content-Disposition * @link https://php.net/manual/en/function.http-send-content-disposition.php * @param string $filename

    * the file name the "Save as..." dialog should display *

    * @param bool $inline [optional]

    * if set to true and the user agent knows how to handle the content type, * it will probably not cause the popup window to be shown *

    * @return bool true on success or false on failure. */ function http_send_content_disposition($filename, $inline = null) {} /** * (PECL pecl_http >= 0.1.0)
    * Match last modification * @link https://php.net/manual/en/function.http-match-modified.php * @param int $timestamp [optional]

    * Unix timestamp; current time, if omitted *

    * @param bool $for_range [optional]

    * if set to true, the header usually used to validate HTTP ranges will be checked *

    * @return bool true if timestamp represents an earlier date than the header, else false. */ #[Pure] function http_match_modified($timestamp = null, $for_range = null) {} /** * (PECL pecl_http >= 0.1.0)
    * Match ETag * @link https://php.net/manual/en/function.http-match-etag.php * @param string $etag

    * the ETag to match *

    * @param bool $for_range [optional]

    * if set to true, the header usually used to validate HTTP ranges will be checked *

    * @return bool true if ETag matches or the header contained the asterisk ("*"), else false. */ #[Pure] function http_match_etag($etag, $for_range = null) {} /** * (PECL pecl_http >= 0.1.0)
    * Caching by last modification * @link https://php.net/manual/en/function.http-cache-last-modified.php * @param int $timestamp_or_expires [optional]

    * Unix timestamp *

    * @return bool with 304 Not Modified if the entity is cached. * &see.http.configuration.force_exit; */ #[Pure] function http_cache_last_modified($timestamp_or_expires = null) {} /** * (PECL pecl_http >= 0.1.0)
    * Caching by ETag * @link https://php.net/manual/en/function.http-cache-etag.php * @param string $etag [optional]

    * custom ETag *

    * @return bool with 304 Not Modified if the entity is cached. * &see.http.configuration.force_exit; */ #[Pure] function http_cache_etag($etag = null) {} /** * (PECL pecl_http >= 0.1.0)
    * Send arbitrary data * @link https://php.net/manual/en/function.http-send-data.php * @param string $data

    * data to send *

    * @return bool true on success or false on failure. */ function http_send_data($data) {} /** * (PECL pecl_http >= 0.1.0)
    * Send file * @link https://php.net/manual/en/function.http-send-file.php * @param string $file

    * the file to send *

    * @return bool true on success or false on failure. */ function http_send_file($file) {} /** * (PECL pecl_http >= 0.1.0)
    * Send stream * @link https://php.net/manual/en/function.http-send-stream.php * @param resource $stream

    * stream to read from (must be seekable) *

    * @return bool true on success or false on failure. */ function http_send_stream($stream) {} /** * (PECL pecl_http >= 0.1.0)
    * Decode chunked-encoded data * @link https://php.net/manual/en/function.http-chunked-decode.php * @param string $encoded

    * chunked encoded string *

    * @return string|false the decoded string on success or false on failure. */ #[Pure] function http_chunked_decode($encoded) {} /** * (PECL pecl_http >= 0.12.0)
    * Parse HTTP messages * @link https://php.net/manual/en/function.http-parse-message.php * @param string $message

    * string containing a single HTTP message or several consecutive HTTP messages *

    * @return object a hierarchical object structure of the parsed messages. */ #[Pure] function http_parse_message($message) {} /** * (PECL pecl_http >= 0.10.0)
    * Parse HTTP headers * @link https://php.net/manual/en/function.http-parse-headers.php * @param string $header

    * string containing HTTP headers *

    * @return array|false an array on success or false on failure. */ #[Pure] function http_parse_headers($header) {} /** * (PECL pecl_http >= 0.20.0)
    * Parse HTTP cookie * @link https://php.net/manual/en/function.http-parse-cookie.php * @param string $cookie

    * string containing the value of a Set-Cookie response header *

    * @param int $flags [optional]

    * parse flags (HTTP_COOKIE_PARSE_RAW) *

    * @param null|array $allowed_extras [optional]

    * array containing recognized extra keys; * by default all unknown keys will be treated as cookie names *

    * @return stdClass|false a stdClass object on success or false on failure. */ #[Pure] function http_parse_cookie($cookie, $flags = null, ?array $allowed_extras = null) {} /** * (PECL pecl_http >= 1.2.0)
    * Build cookie string * @link https://php.net/manual/en/function.http-build-cookie.php * @param array $cookie

    * a cookie list like returned from http_parse_cookie *

    * @return string the cookie(s) as string. */ #[Pure] function http_build_cookie(array $cookie) {} /** * (PECL pecl_http >= 1.0.0)
    * Parse parameter list * @link https://php.net/manual/en/function.http-parse-params.php * @param string $param

    * Parameters *

    * @param int $flags [optional]

    * Parse flags *

    * @return stdClass parameter list as stdClass object. */ #[Pure] function http_parse_params($param, $flags = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Get request headers as array * @link https://php.net/manual/en/function.http-get-request-headers.php * @return array an associative array of incoming request headers. */ #[Pure] function http_get_request_headers() {} /** * (PECL pecl_http >= 0.10.0)
    * Get request body as string * @link https://php.net/manual/en/function.http-get-request-body.php * @return string|null the raw request body as string on success or NULL on failure. */ #[Pure] function http_get_request_body() {} /** * (PECL pecl_http >= 0.22.0)
    * Get request body as stream * @link https://php.net/manual/en/function.http-get-request-body-stream.php * @return resource|null the raw request body as stream on success or NULL on failure. */ #[Pure] function http_get_request_body_stream() {} /** * (PECL pecl_http >= 0.10.0)
    * Match any header * @link https://php.net/manual/en/function.http-match-request-header.php * @param string $header

    * the header name (case-insensitive) *

    * @param string $value

    * the header value that should be compared *

    * @param bool $match_case [optional]

    * whether the value should be compared case sensitively *

    * @return bool true if header value matches, else false. */ #[Pure] function http_match_request_header($header, $value, $match_case = null) {} /** * (PECL pecl_http >= 1.5.0)
    * Stat persistent handles * @link https://php.net/manual/en/function.http-persistent-handles-count.php * @return stdClass|false persistent handles statistics as stdClass object on success or false on failure. */ function http_persistent_handles_count() {} /** * (PECL pecl_http >= 1.5.0)
    * Clean up persistent handles * @link https://php.net/manual/en/function.http-persistent-handles-clean.php * @param string $ident [optional] * @return string */ function http_persistent_handles_clean($ident = null) {} /** * (PECL pecl_http >= 1.5.0)
    * Get/set ident of persistent handles * @link https://php.net/manual/en/function.http-persistent-handles-ident.php * @param string $ident

    * the identification string *

    * @return string|false the prior ident as string on success or false on failure. */ function http_persistent_handles_ident($ident) {} /** * (PECL pecl_http >= 0.1.0)
    * Perform GET request * @link https://php.net/manual/en/function.http-get.php * @param string $url

    * URL *

    * @param null|array $options [optional]

    *

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

    * Will be filled with request/response information *

    * @return string */ function http_get($url, ?array $options = null, ?array &$info = null) {} /** * (PECL pecl_http >= 0.1.0)
    * Perform HEAD request * @link https://php.net/manual/en/function.http-head.php * @param string $url [optional]

    * URL *

    * @param null|array $options [optional]

    *

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

    *

    * @return string */ function http_head($url = null, ?array $options = null, ?array &$info = null) {} /** * (PECL pecl_http >= 0.1.0)
    * Perform POST request with pre-encoded data * @link https://php.net/manual/en/function.http-post-data.php * @param string $url

    * URL *

    * @param string $data [optional]

    * String containing the pre-encoded post data *

    * @param null|array $options [optional]

    *

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

    *

    * @return string */ function http_post_data($url, $data = null, ?array $options = null, ?array &$info = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Perform POST request with data to be encoded * @link https://php.net/manual/en/function.http-post-fields.php * @param string $url

    * URL *

    * @param null|array $data [optional]

    * Associative array of POST values *

    * @param null|array $files [optional]

    * Array of files to post *

    * @param null|array $options [optional]

    *

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

    *

    * @return string */ function http_post_fields($url, ?array $data = null, ?array $files = null, ?array $options = null, ?array &$info = null) {} /** * (PECL pecl_http >= 0.25.0)
    * Perform PUT request with data * @link https://php.net/manual/en/function.http-put-data.php * @param string $url

    * URL *

    * @param null|string $data [optional]

    * PUT request body *

    * @param null|array $options [optional]

    *

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

    *

    * @return string */ function http_put_data($url, $data = null, ?array $options = null, ?array &$info = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Perform PUT request with file * @link https://php.net/manual/en/function.http-put-file.php * @param string $url

    * URL *

    * @param null|string $file [optional]

    * The file to put *

    * @param null|array $options [optional]

    *

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

    *

    * @return string */ function http_put_file($url, $file = null, ?array $options = null, ?array &$info = null) {} /** * (PECL pecl_http >= 0.10.0)
    * Perform PUT request with stream * @link https://php.net/manual/en/function.http-put-stream.php * @param string $url

    * URL *

    * @param null|resource $stream [optional]

    * The stream to read the PUT request body from *

    * @param null|array $options [optional]

    *

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

    *

    * @return string */ function http_put_stream($url, $stream = null, ?array $options = null, ?array &$info = null) {} /** * (PECL pecl_http >= 1.0.0)
    * Perform custom request * @link https://php.net/manual/en/function.http-request.php * @param int $method

    * Request method *

    * @param null|string $url [optional]

    * URL *

    * @param null|string $body [optional]

    * Request body *

    * @param null|array $options [optional]

    *

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

    *

    * @return string */ function http_request($method, $url = null, $body = null, ?array $options = null, ?array &$info = null) {} /** * (PECL pecl_http >= 1.0.0)
    * Encode request body * @link https://php.net/manual/en/function.http-request-body-encode.php * @param array $fields

    * POST fields *

    * @param array $files

    * POST files *

    * @return string|false encoded string on success or false on failure. */ #[Pure] function http_request_body_encode(array $fields, array $files) {} /** * (PECL pecl_http >= 0.10.0)
    * Register request method * @link https://php.net/manual/en/function.http-request-method-register.php * @param string $method

    * the request method name to register *

    * @return int|false the ID of the request method on success or false on failure. */ function http_request_method_register($method) {} /** * (PECL pecl_http >= 0.10.0)
    * Unregister request method * @link https://php.net/manual/en/function.http-request-method-unregister.php * @param mixed $method

    * The request method name or ID *

    * @return bool true on success or false on failure. */ function http_request_method_unregister($method) {} /** * (PECL pecl_http >= 0.10.0)
    * Check whether request method exists * @link https://php.net/manual/en/function.http-request-method-exists.php * @param mixed $method

    * request method name or ID *

    * @return bool true if the request method is known, else false. */ #[Pure] function http_request_method_exists($method) {} /** * (PECL pecl_http >= 0.10.0)
    * Get request method name * @link https://php.net/manual/en/function.http-request-method-name.php * @param int $method

    * request method ID *

    * @return string|false the request method name as string on success or false on failure. */ #[Pure] function http_request_method_name($method) {} /** * (PECL pecl_http >= 0.10.0)
    * ETag output handler * @link https://php.net/manual/en/function.ob-etaghandler.php * @param string $data * @param int $mode * @return string */ #[Pure] function ob_etaghandler($data, $mode) {} /** * (PECL pecl_http >= 0.15.0)
    * Deflate data * @link https://php.net/manual/en/function.http-deflate.php * @param string $data

    * String containing the data that should be encoded *

    * @param int $flags [optional]

    * deflate options *

    * @return string|null the encoded string on success, or NULL on failure. */ #[Pure] function http_deflate($data, $flags = null) {} /** * (PECL pecl_http >= 0.15.0)
    * Inflate data * @link https://php.net/manual/en/function.http-inflate.php * @param string $data

    * string containing the compressed data *

    * @return string|null the decoded string on success, or NULL on failure. */ #[Pure] function http_inflate($data) {} /** * (PECL pecl_http >= 0.21.0)
    * Deflate output handler * @link https://php.net/manual/en/function.ob-deflatehandler.php * @param string $data * @param int $mode * @return string */ function ob_deflatehandler($data, $mode) {} /** * (PECL pecl_http >= 0.21.0)
    * Inflate output handler * @link https://php.net/manual/en/function.ob-inflatehandler.php * @param string $data * @param int $mode * @return string */ function ob_inflatehandler($data, $mode) {} /** * (PECL pecl_http >= 0.15.0)
    * Check built-in HTTP support * @link https://php.net/manual/en/function.http-support.php * @param int $feature [optional]

    * feature to probe for *

    * @return int integer, whether requested feature is supported, * or a bitmask with all supported features if feature was omitted. */ #[Pure] function http_support($feature = null) {} /** * don't urldecode values * @link https://php.net/manual/en/http.constants.php */ define('HTTP_COOKIE_PARSE_RAW', 1); /** * whether "secure" was found in the cookie's parameters list * @link https://php.net/manual/en/http.constants.php */ define('HTTP_COOKIE_SECURE', 16); /** * whether "httpOnly" was found in the cookie's parameter list * @link https://php.net/manual/en/http.constants.php */ define('HTTP_COOKIE_HTTPONLY', 32); define('HTTP_DEFLATE_LEVEL_DEF', 0); define('HTTP_DEFLATE_LEVEL_MIN', 1); define('HTTP_DEFLATE_LEVEL_MAX', 9); define('HTTP_DEFLATE_TYPE_ZLIB', 0); define('HTTP_DEFLATE_TYPE_GZIP', 16); define('HTTP_DEFLATE_TYPE_RAW', 32); define('HTTP_DEFLATE_STRATEGY_DEF', 0); define('HTTP_DEFLATE_STRATEGY_FILT', 256); define('HTTP_DEFLATE_STRATEGY_HUFF', 512); define('HTTP_DEFLATE_STRATEGY_RLE', 768); define('HTTP_DEFLATE_STRATEGY_FIXED', 1024); /** * don't flush * @link https://php.net/manual/en/http.constants.php */ define('HTTP_ENCODING_STREAM_FLUSH_NONE', 0); /** * synchronized flush only * @link https://php.net/manual/en/http.constants.php */ define('HTTP_ENCODING_STREAM_FLUSH_SYNC', 1048576); /** * full data flush * @link https://php.net/manual/en/http.constants.php */ define('HTTP_ENCODING_STREAM_FLUSH_FULL', 2097152); /** * use "basic" authentication * @link https://php.net/manual/en/http.constants.php */ define('HTTP_AUTH_BASIC', 1); /** * use "digest" authentication * @link https://php.net/manual/en/http.constants.php */ define('HTTP_AUTH_DIGEST', 2); /** * use "NTLM" authentication * @link https://php.net/manual/en/http.constants.php */ define('HTTP_AUTH_NTLM', 8); /** * use "GSS-NEGOTIATE" authentication * @link https://php.net/manual/en/http.constants.php */ define('HTTP_AUTH_GSSNEG', 4); /** * try any authentication scheme * @link https://php.net/manual/en/http.constants.php */ define('HTTP_AUTH_ANY', -1); define('HTTP_VERSION_NONE', 0); /** * HTTP version 1.0 * @link https://php.net/manual/en/http.constants.php */ define('HTTP_VERSION_1_0', 1); /** * HTTP version 1.1 * @link https://php.net/manual/en/http.constants.php */ define('HTTP_VERSION_1_1', 2); /** * no specific HTTP protocol version * @link https://php.net/manual/en/http.constants.php */ define('HTTP_VERSION_ANY', 0); /** * use TLSv1 only * @link https://php.net/manual/en/http.constants.php */ define('HTTP_SSL_VERSION_TLSv1', 1); /** * use SSLv2 only * @link https://php.net/manual/en/http.constants.php */ define('HTTP_SSL_VERSION_SSLv2', 2); /** * use SSLv3 only * @link https://php.net/manual/en/http.constants.php */ define('HTTP_SSL_VERSION_SSLv3', 3); /** * no specific SSL protocol version * @link https://php.net/manual/en/http.constants.php */ define('HTTP_SSL_VERSION_ANY', 0); /** * use IPv4 only for name lookups * @link https://php.net/manual/en/http.constants.php */ define('HTTP_IPRESOLVE_V4', 1); /** * use IPv6 only for name lookups * @link https://php.net/manual/en/http.constants.php */ define('HTTP_IPRESOLVE_V6', 2); /** * use any IP mechanism only for name lookups * @link https://php.net/manual/en/http.constants.php */ define('HTTP_IPRESOLVE_ANY', 0); /** * the proxy is a SOCKS4 type proxy * @link https://php.net/manual/en/http.constants.php */ define('HTTP_PROXY_SOCKS4', 4); /** * the proxy is a SOCKS5 type proxy * @link https://php.net/manual/en/http.constants.php */ define('HTTP_PROXY_SOCKS5', 5); /** * standard HTTP proxy * @link https://php.net/manual/en/http.constants.php */ define('HTTP_PROXY_HTTP', 0); define('HTTP_METH_GET', 1); define('HTTP_METH_HEAD', 2); define('HTTP_METH_POST', 3); define('HTTP_METH_PUT', 4); define('HTTP_METH_DELETE', 5); define('HTTP_METH_OPTIONS', 6); define('HTTP_METH_TRACE', 7); define('HTTP_METH_CONNECT', 8); define('HTTP_METH_PROPFIND', 9); define('HTTP_METH_PROPPATCH', 10); define('HTTP_METH_MKCOL', 11); define('HTTP_METH_COPY', 12); define('HTTP_METH_MOVE', 13); define('HTTP_METH_LOCK', 14); define('HTTP_METH_UNLOCK', 15); define('HTTP_METH_VERSION_CONTROL', 16); define('HTTP_METH_REPORT', 17); define('HTTP_METH_CHECKOUT', 18); define('HTTP_METH_CHECKIN', 19); define('HTTP_METH_UNCHECKOUT', 20); define('HTTP_METH_MKWORKSPACE', 21); define('HTTP_METH_UPDATE', 22); define('HTTP_METH_LABEL', 23); define('HTTP_METH_MERGE', 24); define('HTTP_METH_BASELINE_CONTROL', 25); define('HTTP_METH_MKACTIVITY', 26); define('HTTP_METH_ACL', 27); /** * guess applicable redirect method * @link https://php.net/manual/en/http.constants.php */ define('HTTP_REDIRECT', 0); /** * permanent redirect (301 Moved permanently) * @link https://php.net/manual/en/http.constants.php */ define('HTTP_REDIRECT_PERM', 301); /** * standard redirect (302 Found) * RFC 1945 and RFC 2068 specify that the client is not allowed * to change the method on the redirected request. However, most * existing user agent implementations treat 302 as if it were a 303 * response, performing a GET on the Location field-value regardless * of the original request method. The status codes 303 and 307 have * been added for servers that wish to make unambiguously clear which * kind of reaction is expected of the client. * @link https://php.net/manual/en/http.constants.php */ define('HTTP_REDIRECT_FOUND', 302); /** * redirect applicable to POST requests (303 See other) * @link https://php.net/manual/en/http.constants.php */ define('HTTP_REDIRECT_POST', 303); /** * proxy redirect (305 Use proxy) * @link https://php.net/manual/en/http.constants.php */ define('HTTP_REDIRECT_PROXY', 305); /** * temporary redirect (307 Temporary Redirect) * @link https://php.net/manual/en/http.constants.php */ define('HTTP_REDIRECT_TEMP', 307); /** * querying for this constant will always return true * @link https://php.net/manual/en/http.constants.php */ define('HTTP_SUPPORT', 1); /** * whether support to issue HTTP requests is given, ie. libcurl support was compiled in * @link https://php.net/manual/en/http.constants.php */ define('HTTP_SUPPORT_REQUESTS', 2); /** * whether support to guess the Content-Type of HTTP messages is given, ie. libmagic support was compiled in * @link https://php.net/manual/en/http.constants.php */ define('HTTP_SUPPORT_MAGICMIME', 4); /** * whether support for zlib encodings is given, ie. libz support was compiled in * @link https://php.net/manual/en/http.constants.php */ define('HTTP_SUPPORT_ENCODINGS', 8); /** * whether support to issue HTTP requests over SSL is given, ie. linked libcurl was built with SSL support * @link https://php.net/manual/en/http.constants.php */ define('HTTP_SUPPORT_SSLREQUESTS', 32); define('HTTP_SUPPORT_EVENTS', 128); /** * allow commands additionally to semicolons as separator * @link https://php.net/manual/en/http.constants.php */ define('HTTP_PARAMS_ALLOW_COMMA', 1); /** * continue parsing after an error occurred * @link https://php.net/manual/en/http.constants.php */ define('HTTP_PARAMS_ALLOW_FAILURE', 2); /** * raise PHP warnings on parse errors * @link https://php.net/manual/en/http.constants.php */ define('HTTP_PARAMS_RAISE_ERROR', 4); /** * all three values above, bitwise or'ed * @link https://php.net/manual/en/http.constants.php */ define('HTTP_PARAMS_DEFAULT', 7); /** * replace every part of the first URL when there's one of the second URL * @link https://php.net/manual/en/http.constants.php */ define('HTTP_URL_REPLACE', 0); /** * join relative paths * @link https://php.net/manual/en/http.constants.php */ define('HTTP_URL_JOIN_PATH', 1); /** * join query strings * @link https://php.net/manual/en/http.constants.php */ define('HTTP_URL_JOIN_QUERY', 2); /** * strip any user authentication information * @link https://php.net/manual/en/http.constants.php */ define('HTTP_URL_STRIP_USER', 4); /** * strip any password authentication information * @link https://php.net/manual/en/http.constants.php */ define('HTTP_URL_STRIP_PASS', 8); /** * strip any authentication information * @link https://php.net/manual/en/http.constants.php */ define('HTTP_URL_STRIP_AUTH', 12); /** * strip explicit port numbers * @link https://php.net/manual/en/http.constants.php */ define('HTTP_URL_STRIP_PORT', 32); /** * strip complete path * @link https://php.net/manual/en/http.constants.php */ define('HTTP_URL_STRIP_PATH', 64); /** * strip query string * @link https://php.net/manual/en/http.constants.php */ define('HTTP_URL_STRIP_QUERY', 128); /** * strip any fragments (#identifier) * @link https://php.net/manual/en/http.constants.php */ define('HTTP_URL_STRIP_FRAGMENT', 256); /** * strip anything but scheme and host * @link https://php.net/manual/en/http.constants.php */ define('HTTP_URL_STRIP_ALL', 492); define('HTTP_URL_FROM_ENV', 4096); /** * runtime error * @link https://php.net/manual/en/http.constants.php */ define('HTTP_E_RUNTIME', 1); /** * an invalid parameter was passed * @link https://php.net/manual/en/http.constants.php */ define('HTTP_E_INVALID_PARAM', 2); /** * header() or similar operation failed * @link https://php.net/manual/en/http.constants.php */ define('HTTP_E_HEADER', 3); /** * HTTP header parse error * @link https://php.net/manual/en/http.constants.php */ define('HTTP_E_MALFORMED_HEADERS', 4); /** * unknown/invalid request method * @link https://php.net/manual/en/http.constants.php */ define('HTTP_E_REQUEST_METHOD', 5); /** * with operation incompatible message type * @link https://php.net/manual/en/http.constants.php */ define('HTTP_E_MESSAGE_TYPE', 6); /** * encoding/decoding error * @link https://php.net/manual/en/http.constants.php */ define('HTTP_E_ENCODING', 7); /** * request failure * @link https://php.net/manual/en/http.constants.php */ define('HTTP_E_REQUEST', 8); /** * request pool failure * @link https://php.net/manual/en/http.constants.php */ define('HTTP_E_REQUEST_POOL', 9); /** * socket exception * @link https://php.net/manual/en/http.constants.php */ define('HTTP_E_SOCKET', 10); /** * response failure * @link https://php.net/manual/en/http.constants.php */ define('HTTP_E_RESPONSE', 11); /** * invalid URL * @link https://php.net/manual/en/http.constants.php */ define('HTTP_E_URL', 12); /** * querystring operation failure * @link https://php.net/manual/en/http.constants.php */ define('HTTP_E_QUERYSTRING', 13); /** * the message is of no specific type * @link https://php.net/manual/en/http.constants.php */ define('HTTP_MSG_NONE', 0); /** * request style message * @link https://php.net/manual/en/http.constants.php */ define('HTTP_MSG_REQUEST', 1); /** * response style message * @link https://php.net/manual/en/http.constants.php */ define('HTTP_MSG_RESPONSE', 2); define('HTTP_QUERYSTRING_TYPE_BOOL', 3); define('HTTP_QUERYSTRING_TYPE_INT', 1); define('HTTP_QUERYSTRING_TYPE_FLOAT', 2); define('HTTP_QUERYSTRING_TYPE_STRING', 6); define('HTTP_QUERYSTRING_TYPE_ARRAY', 4); define('HTTP_QUERYSTRING_TYPE_OBJECT', 5); "value"]. * @throws \http\Exception\InvalidArgumentException * @return \http\Cookie self. */ public function addCookies(array $cookies) {} /** * Add an extra attribute to the cookie list. * See http\Cookie::setExtra(). * * @param string $extra_name The key of the extra attribute. * @param string $extra_value The value of the extra attribute. * @throws \http\Exception\InvalidArgumentException * @return \http\Cookie self. */ public function addExtra(string $extra_name, string $extra_value) {} /** * Add several extra attributes. * See http\Cookie::addExtra(). * * @param array $extras A list of extra attributes of the form ["key" => "value"]. * @throws \http\Exception\InvalidArgumentException * @return \http\Cookie self. */ public function addExtras(array $extras) {} /** * Retrieve a specific cookie value. * See http\Cookie::setCookie(). * * @param string $cookie_name The key of the cookie to look up. * @return string|null string the cookie value. * or NULL if $cookie_name could not be found. */ public function getCookie(string $cookie_name) {} /** * Get the list of cookies. * See http\Cookie::setCookies(). * * @return array the list of cookies of form ["name" => "value"]. */ public function getCookies() {} /** * Retrieve the effective domain of the cookie list. * See http\Cookie::setDomain(). * * @return string the effective domain. */ public function getDomain() {} /** * Get the currently set expires attribute. * See http\Cookie::setExpires(). * * ***NOTE:*** * A return value of -1 means that the attribute is not set. * * @return int the currently set expires attribute as seconds since the epoch. */ public function getExpires() {} /** * Retrieve an extra attribute. * See http\Cookie::setExtra(). * * @param string $name The key of the extra attribute. * @return string the value of the extra attribute. */ public function getExtra(string $name) {} /** * Retrieve the list of extra attributes. * See http\Cookie::setExtras(). * * @return array the list of extra attributes of the form ["key" => "value"]. */ public function getExtras() {} /** * Get the currently set flags. * See http\Cookie::SECURE and http\Cookie::HTTPONLY constants. * * @return int the currently set flags bitmask. */ public function getFlags() {} /** * Get the currently set max-age attribute of the cookie list. * See http\Cookie::setMaxAge(). * * ***NOTE:*** * A return value of -1 means that the attribute is not set. * * @return int the currently set max-age. */ public function getMaxAge() {} /** * Retrieve the path the cookie(s) of this cookie list are effective at. * See http\Cookie::setPath(). * * @return string the effective path. */ public function getPath() {} /** * (Re)set a cookie. * See http\Cookie::addCookie() and http\Cookie::setCookies(). * * ***NOTE:*** * The cookie will be deleted from the list if $cookie_value is NULL. * * @param string $cookie_name The key of the cookie. * @param string $cookie_value The value of the cookie. * @throws \http\Exception\InvalidArgumentException * @return \http\Cookie self. */ public function setCookie(string $cookie_name, string $cookie_value) {} /** * (Re)set the cookies. * See http\Cookie::addCookies(). * * @param array $cookies Set the cookies to this array. * @throws \http\Exception\InvalidArgumentException * @return \http\Cookie self. */ public function setCookies(?array $cookies = null) {} /** * Set the effective domain of the cookie list. * See http\Cookie::setPath(). * * @param string $value The domain the cookie(s) belong to. * @throws \http\Exception\InvalidArgumentException * @return \http\Cookie self. */ public function setDomain(?string $value = null) {} /** * Set the traditional expires timestamp. * See http\Cookie::setMaxAge() for a safer alternative. * * @param int $value The expires timestamp as seconds since the epoch. * @throws \http\Exception\InvalidArgumentException * @return \http\Cookie self. */ public function setExpires(int $value = -1) {} /** * (Re)set an extra attribute. * See http\Cookie::addExtra(). * * ***NOTE:*** * The attribute will be removed from the extras list if $extra_value is NULL. * * @param string $extra_name The key of the extra attribute. * @param string $extra_value The value of the extra attribute. * @throws \http\Exception\InvalidArgumentException * @return \http\Cookie self. */ public function setExtra(string $extra_name, ?string $extra_value = null) {} /** * (Re)set the extra attributes. * See http\Cookie::addExtras(). * * @param array $extras Set the extra attributes to this array. * @throws \http\Exception\InvalidArgumentException * @return \http\Cookie self. */ public function setExtras(?array $extras = null) {} /** * Set the flags to specified $value. * See http\Cookie::SECURE and http\Cookie::HTTPONLY constants. * * @param int $value The new flags bitmask. * @throws \http\Exception\InvalidArgumentException * @return \http\Cookie self. */ public function setFlags(int $value = 0) {} /** * Set the maximum age the cookie may have on the client side. * This is a client clock departure safe alternative to the "expires" attribute. * See http\Cookie::setExpires(). * * @param int $value The max-age in seconds. * @throws \http\Exception\InvalidArgumentException * @return \http\Cookie self. */ public function setMaxAge(int $value = -1) {} /** * Set the path the cookie(s) of this cookie list should be effective at. * See http\Cookie::setDomain(). * * @param string $path The URL path the cookie(s) should take effect within. * @throws \http\Exception\InvalidArgumentException * @return \http\Cookie self. */ public function setPath(?string $path = null) {} /** * Get the cookie list as array. * * @return array the cookie list as array. */ public function toArray() {} /** * Retrieve the string representation of the cookie list. * See http\Cookie::toArray(). * * @return string the cookie list as string. */ public function toString() {} } namespace http\Encoding; namespace http; /** * The http\Env class provides static methods to manipulate and inspect the server's current request's HTTP environment. */ class Env { /** * Retrieve the current HTTP request's body. * * @param string $body_class_name A user class extending http\Message\Body. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\UnexpectedValueException * @return \http\Message\Body instance representing the request body */ public function getRequestBody(?string $body_class_name = null) {} /** * Retrieve one or all headers of the current HTTP request. * * @param string $header_name The key of a header to retrieve. * @return string|null|array NULL if $header_name was not found * or string the compound header when $header_name was found * or array of all headers if $header_name was not specified */ public function getRequestHeader(?string $header_name = null) {} /** * Get the HTTP response code to send. * * @return int the HTTP response code. */ public function getResponseCode() {} /** * Get one or all HTTP response headers to be sent. * * @param string $header_name The name of the response header to retrieve. * @return string|array|null string the compound value of the response header to send * or NULL if the header was not found * or array of all response headers, if $header_name was not specified */ public function getResponseHeader(?string $header_name = null) {} /** * Retrieve a list of all known HTTP response status. * * @return array mapping of the form \[ * ... * int $code => string $status * ... * \] */ public function getResponseStatusForAllCodes() {} /** * Retrieve the string representation of specified HTTP response code. * * @param int $code The HTTP response code to get the string representation for. * @return string the HTTP response status message (may be empty, if no message for this code was found) */ public function getResponseStatusForCode(int $code) {} /** * Generic negotiator. For specific client negotiation see http\Env::negotiateContentType() and related methods. * * ***NOTE:*** * The first element of $supported serves as a default if no operand matches. * * @param string $params HTTP header parameter's value to negotiate. * @param array $supported List of supported negotiation operands. * @param string $prim_typ_sep A "primary type separator", i.e. that would be a hyphen for content language negotiation (en-US, de-DE, etc.). * @param array &$result Out parameter recording negotiation results. * @return string|null NULL if negotiation fails. * or string the closest match negotiated, or the default (first entry of $supported). */ public function negotiate(string $params, array $supported, ?string $prim_typ_sep = null, ?array &$result = null) {} /** * Negotiate the client's preferred character set. * * ***NOTE:*** * The first element of $supported character sets serves as a default if no character set matches. * * @param array $supported List of supported content character sets. * @param array &$result Out parameter recording negotiation results. * @return string|null NULL if negotiation fails. * or string the negotiated character set. */ public function negotiateCharset(array $supported, array &$result = null) {} /** * Negotiate the client's preferred MIME content type. * * ***NOTE:*** * The first element of $supported content types serves as a default if no content-type matches. * * @param array $supported List of supported MIME content types. * @param array &$result Out parameter recording negotiation results. * @return string|null NULL if negotiation fails. * or string the negotiated content type. */ public function negotiateContentType(array $supported, array &$result = null) {} /** * Negotiate the client's preferred encoding. * * ***NOTE:*** * The first element of $supported encodings serves as a default if no encoding matches. * * @param array $supported List of supported content encodings. * @param array &$result Out parameter recording negotiation results. * @return string|null NULL if negotiation fails. * or string the negotiated encoding. */ public function negotiateEncoding(array $supported, array &$result = null) {} /** * Negotiate the client's preferred language. * * ***NOTE:*** * The first element of $supported languages serves as a default if no language matches. * * @param array $supported List of supported content languages. * @param array &$result Out parameter recording negotiation results. * @return string|null NULL if negotiation fails. * or string the negotiated language. */ public function negotiateLanguage(array $supported, array &$result = null) {} /** * Set the HTTP response code to send. * * @param int $code The HTTP response status code. * @return bool Success. */ public function setResponseCode(int $code) {} /** * Set a response header, either replacing a prior set header, or appending the new header value, depending on $replace. * * If no $header_value is specified, or $header_value is NULL, then a previously set header with the same key will be deleted from the list. * * If $response_code is not 0, the response status code is updated accordingly. * * @param string $header_name * @param mixed $header_value * @param int $response_code * @param bool $replace * @return bool Success. */ public function setResponseHeader(string $header_name, $header_value = null, ?int $response_code = null, ?bool $replace = null) {} } /** * The http extension's Exception interface. * * Use it to catch any Exception thrown by pecl/http. * * The individual exception classes extend their equally named native PHP extensions, if such exist, and implement this empty interface. For example the http\Exception\BadMethodCallException extends SPL's BadMethodCallException. */ interface Exception {} /** * The http\Header class provides methods to manipulate, match, negotiate and serialize HTTP headers. */ class Header implements \Serializable { /** * None of the following match constraints applies. */ public const MATCH_LOOSE = 0; /** * Perform case sensitive matching. */ public const MATCH_CASE = 1; /** * Match only on word boundaries (according by CType alpha-numeric). */ public const MATCH_WORD = 16; /** * Match the complete string. */ public const MATCH_FULL = 32; /** * Case sensitively match the full string (same as MATCH_CASE|MATCH_FULL). */ public const MATCH_STRICT = 33; /** * The name of the HTTP header. * * @var string */ public $name = null; /** * The value of the HTTP header. * * @var mixed */ public $value = null; /** * Create an http\Header instance for use of simple matching or negotiation. If the value of the header is an array it may be compounded to a single comma separated string. * * @param string $name The HTTP header name. * @param mixed $value The value of the header. * * # Throws: */ public function __construct(?string $name = null, $value = null) {} /** * String cast handler. Alias of http\Header::serialize(). * * @return string the serialized form of the HTTP header (i.e. "Name: value"). */ public function __toString() {} /** * Create a parameter list out of the HTTP header value. * * @param mixed $ps The parameter separator(s). * @param mixed $as The argument separator(s). * @param mixed $vs The value separator(s). * @param int $flags The modus operandi. See http\Params constants. * @return \http\Params instance */ public function getParams($ps = null, $as = null, $vs = null, ?int $flags = null) {} /** * Match the HTTP header's value against provided $value according to $flags. * * @param string $value The comparison value. * @param int $flags The modus operandi. See http\Header constants. * @return bool whether $value matches the header value according to $flags. */ public function match(string $value, ?int $flags = null) {} /** * Negotiate the header's value against a list of supported values in $supported. * Negotiation operation is adopted according to the header name, i.e. if the * header being negotiated is Accept, then a slash is used as primary type * separator, and if the header is Accept-Language respectively, a hyphen is * used instead. * * ***NOTE:*** * The first element of $supported serves as a default if no operand matches. * * @param array $supported The list of supported values to negotiate. * @param array &$result Out parameter recording the negotiation results. * @return string|null NULL if negotiation fails. * or string the closest match negotiated, or the default (first entry of $supported). */ public function negotiate(array $supported, array &$result = null) {} /** * Parse HTTP headers. * See also http\Header\Parser. * * @param string $header The complete string of headers. * @param string $header_class A class extending http\Header. * @return array|false array of parsed headers, where the elements are instances of $header_class if specified. * or false if parsing fails. */ public function parse(string $header, ?string $header_class = null) {} /** * Implements Serializable. * * @return string serialized representation of HTTP header (i.e. "Name: value") */ public function serialize() {} /** * Convenience method. Alias of http\Header::serialize(). * * @return string the serialized form of the HTTP header (i.e. "Name: value"). */ public function toString() {} /** * Implements Serializable. * * @param string $serialized The serialized HTTP header (i.e. "Name: value") */ public function unserialize($serialized) {} } /** * The message class builds the foundation for any request and response message. * * See http\Client\Request and http\Client\Response, as well as http\Env\Request and http\Env\Response. */ class Message implements \Countable, \Serializable, \Iterator { /** * No specific type of message. */ public const TYPE_NONE = 0; /** * A request message. */ public const TYPE_REQUEST = 1; /** * A response message. */ public const TYPE_RESPONSE = 2; /** * The message type. See http\Message::TYPE_* constants. * * @var int */ protected $type = \http\Message::TYPE_NONE; /** * The message's body. * * @var \http\Message\Body */ protected $body = null; /** * The request method if the message is of type request. * * @var string */ protected $requestMethod = ""; /** * The request url if the message is of type request. * * @var string */ protected $requestUrl = ""; /** * The response status phrase if the message is of type response. * * @var string */ protected $responseStatus = ""; /** * The response code if the message is of type response. * * @var int */ protected $responseCode = 0; /** * A custom HTTP protocol version. * * @var string */ protected $httpVersion = null; /** * Any message headers. * * @var array */ protected $headers = null; /** * Any parent message. * * @var \http\Message */ protected $parentMessage; /** * Create a new HTTP message. * * @param mixed $message Either a resource or a string, representing the HTTP message. * @param bool $greedy Whether to read from a $message resource until EOF. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\BadMessageException */ public function __construct($message = null, bool $greedy = true) {} /** * Retrieve the message serialized to a string. * Alias of http\Message::toString(). * * @return string the single serialized HTTP message. */ public function __toString() {} /** * Append the data of $body to the message's body. * See http\Message::setBody() and http\Message\Body::append(). * * @param \http\Message\Body $body The message body to add. * @return \http\Message self. */ public function addBody(Message\Body $body) {} /** * Add an header, appending to already existing headers. * See http\Message::addHeaders() and http\Message::setHeader(). * * @param string $name The header name. * @param mixed $value The header value. * @return \http\Message self. */ public function addHeader(string $name, $value) {} /** * Add headers, optionally appending values, if header keys already exist. * See http\Message::addHeader() and http\Message::setHeaders(). * * @param array $headers The HTTP headers to add. * @param bool $append Whether to append values for existing headers. * @return \http\Message self. */ public function addHeaders(array $headers, bool $append = false) {} /** * Implements Countable. * * @return int the count of messages in the chain above the current message. */ public function count() {} /** * Implements iterator. * See http\Message::valid() and http\Message::rewind(). * * @return \http\Message the current message in the iterated message chain. */ public function current() {} /** * Detach a clone of this message from any message chain. * * @throws \http\Exception\InvalidArgumentException * @return \http\Message clone. */ public function detach() {} /** * Retrieve the message's body. * See http\Message::setBody(). * * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\UnexpectedValueException * @return \http\Message\Body the message body. */ public function getBody() {} /** * Retrieve a single header, optionally hydrated into a http\Header extending class. * * @param string $header The header's name. * @param string $into_class The name of a class extending http\Header. * @return mixed|\http\Header mixed the header value if $into_class is NULL. * or \http\Header descendant. */ public function getHeader(string $header, ?string $into_class = null) {} /** * Retrieve all message headers. * See http\Message::setHeaders() and http\Message::getHeader(). * * @return array the message's headers. */ public function getHeaders() {} /** * Retrieve the HTTP protocol version of the message. * See http\Message::setHttpVersion(). * * @return string the HTTP protocol version, e.g. "1.0"; defaults to "1.1". */ public function getHttpVersion() {} /** * Retrieve the first line of a request or response message. * See http\Message::setInfo and also: * * * http\Message::getType() * * http\Message::getHttpVersion() * * http\Message::getResponseCode() * * http\Message::getResponseStatus() * * http\Message::getRequestMethod() * * http\Message::getRequestUrl() * * @return string|null string the HTTP message information. * or NULL if the message is neither of type request nor response. */ public function getInfo() {} /** * Retrieve any parent message. * See http\Message::reverse(). * * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\BadMethodCallException * @return \http\Message the parent message. */ public function getParentMessage() {} /** * Retrieve the request method of the message. * See http\Message::setRequestMethod() and http\Message::getRequestUrl(). * * @return string|false string the request method. * or false if the message was not of type request. */ public function getRequestMethod() {} /** * Retrieve the request URL of the message. * See http\Message::setRequestUrl(). * * @return string|false string the request URL; usually the path and the querystring. * or false if the message was not of type request. */ public function getRequestUrl() {} /** * Retrieve the response code of the message. * See http\Message::setResponseCode() and http\Message::getResponseStatus(). * * @return int|false int the response status code. * or false if the message is not of type response. */ public function getResponseCode() {} /** * Retrieve the response status of the message. * See http\Message::setResponseStatus() and http\Message::getResponseCode(). * * @return string|false string the response status phrase. * or false if the message is not of type response. */ public function getResponseStatus() {} /** * Retrieve the type of the message. * See http\Message::setType() and http\Message::getInfo(). * * @return int the message type. See http\Message::TYPE_* constants. */ public function getType() {} /** * Check whether this message is a multipart message based on it's content type. * If the message is a multipart message and a reference $boundary is given, the boundary string of the multipart message will be stored in $boundary. * * See http\Message::splitMultipartBody(). * * @param string &$boundary A reference where the boundary string will be stored. * @return bool whether this is a message with a multipart "Content-Type". */ public function isMultipart(string &$boundary = null) {} /** * Implements Iterator. * See http\Message::current() and http\Message::rewind(). * * @return int a non-sequential integer key. */ public function key() {} /** * Implements Iterator. * See http\Message::valid() and http\Message::rewind(). */ public function next() {} /** * Prepend message(s) $message to this message, or the top most message of this message chain. * * ***NOTE:*** * The message chains must not overlap. * * @param \http\Message $message The message (chain) to prepend as parent messages. * @param bool $top Whether to prepend to the top-most parent message. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\UnexpectedValueException * @return \http\Message self. */ public function prepend(Message $message, bool $top = true) {} /** * Reverse the message chain and return the former top-most message. * * ***NOTE:*** * Message chains are ordered in reverse-parsed order by default, i.e. the last parsed message is the message you'll receive from any call parsing HTTP messages. * * This call re-orders the messages of the chain and returns the message that was parsed first with any later parsed messages re-parentized. * * @throws \http\Exception\InvalidArgumentException * @return \http\Message the other end of the message chain. */ public function reverse() {} /** * Implements Iterator. */ public function rewind() {} /** * Implements Serializable. * * @return string the serialized HTTP message. */ public function serialize() {} /** * Set the message's body. * See http\Message::getBody() and http\Message::addBody(). * * @param \http\Message\Body $body The new message body. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\UnexpectedValueException * @return \http\Message self. */ public function setBody(Message\Body $body) {} /** * Set a single header. * See http\Message::getHeader() and http\Message::addHeader(). * * ***NOTE:*** * Prior to v2.5.6/v3.1.0 headers with the same name were merged into a single * header with values concatenated by comma. * * @param string $header The header's name. * @param mixed $value The header's value. Removes the header if NULL. * @return \http\Message self. */ public function setHeader(string $header, $value = null) {} /** * Set the message headers. * See http\Message::getHeaders() and http\Message::addHeaders(). * * ***NOTE:*** * Prior to v2.5.6/v3.1.0 headers with the same name were merged into a single * header with values concatenated by comma. * * @param array $headers The message's headers. * @return \http\Message null. */ public function setHeaders(?array $headers = null) {} /** * Set the HTTP protocol version of the message. * See http\Message::getHttpVersion(). * * @param string $http_version The protocol version, e.g. "1.1", optionally prefixed by "HTTP/". * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\BadHeaderException * @return \http\Message self. */ public function setHttpVersion(string $http_version) {} /** * Set the complete message info, i.e. type and response resp. request information, at once. * See http\Message::getInfo(). * * @param string $http_info The message info (first line of an HTTP message). * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\BadHeaderException * @return \http\Message self. */ public function setInfo(string $http_info) {} /** * Set the request method of the message. * See http\Message::getRequestMethod() and http\Message::setRequestUrl(). * * @param string $method The request method. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\BadMethodCallException * @return \http\Message self. */ public function setRequestMethod(string $method) {} /** * Set the request URL of the message. * See http\Message::getRequestUrl() and http\Message::setRequestMethod(). * * @param string $url The request URL. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\BadMethodCallException * @return \http\Message self. */ public function setRequestUrl(string $url) {} /** * Set the response status code. * See http\Message::getResponseCode() and http\Message::setResponseStatus(). * * ***NOTE:*** * This method also resets the response status phrase to the default for that code. * * @param int $response_code The response code. * @param bool $strict Whether to check that the response code is between 100 and 599 inclusive. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\BadMethodCallException * @return \http\Message self. */ public function setResponseCode(int $response_code, bool $strict = true) {} /** * Set the response status phrase. * See http\Message::getResponseStatus() and http\Message::setResponseCode(). * * @param string $response_status The status phrase. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\BadMethodCallException * @return \http\Message self. */ public function setResponseStatus(string $response_status) {} /** * Set the message type and reset the message info. * See http\Message::getType() and http\Message::setInfo(). * * @param int $type The desired message type. See the http\Message::TYPE_* constants. * @return \http\Message self. */ public function setType(int $type) {} /** * Splits the body of a multipart message. * See http\Message::isMultipart() and http\Message\Body::addPart(). * * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\BadMethodCallException * @throws \http\Exception\BadMessageException * @return \http\Message a message chain of all messages of the multipart body. */ public function splitMultipartBody() {} /** * Stream the message through a callback. * * @param callable $callback The callback of the form function(http\Message $from, string $data). * @return \http\Message self. */ public function toCallback(callable $callback) {} /** * Stream the message into stream $stream, starting from $offset, streaming $maxlen at most. * * @param resource $stream The resource to write to. * @return \http\Message self. */ public function toStream($stream) {} /** * Retrieve the message serialized to a string. * * @param bool $include_parent Whether to include all parent messages. * @return string the HTTP message chain serialized to a string. */ public function toString(bool $include_parent = false) {} /** * Implements Serializable. * * @param string $data The serialized message. */ public function unserialize($data) {} /** * Implements Iterator. * See http\Message::current() and http\Message::rewind(). * * @return bool whether http\Message::current() would not return NULL. */ public function valid() {} } /** * Parse, interpret and compose HTTP (header) parameters. */ class Params implements \ArrayAccess { /** * The default parameter separator (","). */ public const DEF_PARAM_SEP = ','; /** * The default argument separator (";"). */ public const DEF_ARG_SEP = ';'; /** * The default value separator ("="). */ public const DEF_VAL_SEP = '='; /** * Empty param separator to parse cookies. */ public const COOKIE_PARAM_SEP = ''; /** * Do not interpret the parsed parameters. */ public const PARSE_RAW = 0; /** * Interpret input as default formatted parameters. */ public const PARSE_DEFAULT = 17; /** * Parse backslash escaped (quoted) strings. */ public const PARSE_ESCAPED = 1; /** * Urldecode single units of parameters, arguments and values. */ public const PARSE_URLENCODED = 4; /** * Parse sub dimensions indicated by square brackets. */ public const PARSE_DIMENSION = 8; /** * Parse URL querystring (same as http\Params::PARSE_URLENCODED|http\Params::PARSE_DIMENSION). */ public const PARSE_QUERY = 12; /** * Parse [RFC5987](http://tools.ietf.org/html/rfc5987) style encoded character set and language information embedded in HTTP header params. */ public const PARSE_RFC5987 = 16; /** * Parse [RFC5988](http://tools.ietf.org/html/rfc5988) (Web Linking) tags of Link headers. */ public const PARSE_RFC5988 = 32; /** * The (parsed) parameters. * * @var array */ public $params = null; /** * The parameter separator(s). * * @var array */ public $param_sep = \http\Params::DEF_PARAM_SEP; /** * The argument separator(s). * * @var array */ public $arg_sep = \http\Params::DEF_ARG_SEP; /** * The value separator(s). * * @var array */ public $val_sep = \http\Params::DEF_VAL_SEP; /** * The modus operandi of the parser. See http\Params::PARSE_* constants. * * @var int */ public $flags = \http\Params::PARSE_DEFAULT; /** * Instantiate a new HTTP (header) parameter set. * * @param mixed $params Pre-parsed parameters or a string to be parsed. * @param mixed $ps The parameter separator(s). * @param mixed $as The argument separator(s). * @param mixed $vs The value separator(s). * @param int $flags The modus operandi. See http\Params::PARSE_* constants. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\RuntimeException */ public function __construct($params = null, $ps = null, $as = null, $vs = null, ?int $flags = null) {} /** * String cast handler. Alias of http\Params::toString(). * Returns a stringified version of the parameters. * * @return string version of the parameters. */ public function __toString() {} /** * Implements ArrayAccess. * * @param string $name The offset to look after. * @return bool Existence. */ public function offsetExists($name) {} /** * Implements ArrayAccess. * * @param string $name The offset to retrieve. * @return mixed contents at offset. */ public function offsetGet($name) {} /** * Implements ArrayAccess. * * @param string $name The offset to modify. * @param mixed $value The value to set. */ public function offsetSet($name, $value) {} /** * Implements ArrayAccess. * * @param string $name The offset to delete. */ public function offsetUnset($name) {} /** * Convenience method that simply returns http\Params::$params. * * @return array of parameters. */ public function toArray() {} /** * Returns a stringified version of the parameters. * * @return string version of the parameters. */ public function toString() {} } /** * The http\QueryString class provides versatile facilities to retrieve, use and manipulate query strings and form data. */ class QueryString implements \Serializable, \ArrayAccess, \IteratorAggregate { /** * Cast requested value to bool. */ public const TYPE_BOOL = 16; /** * Cast requested value to int. */ public const TYPE_INT = 4; /** * Cast requested value to float. */ public const TYPE_FLOAT = 5; /** * Cast requested value to string. */ public const TYPE_STRING = 6; /** * Cast requested value to an array. */ public const TYPE_ARRAY = 7; /** * Cast requested value to an object. */ public const TYPE_OBJECT = 8; /** * The global instance. See http\QueryString::getGlobalInstance(). * * @var \http\QueryString */ private $instance = null; /** * The data. * * @var array */ private $queryArray = null; /** * Create an independent querystring instance. * * @param mixed $params The query parameters to use or parse. * @throws \http\Exception\BadQueryStringException */ public function __construct($params = null) {} /** * Get the string representation of the querystring (x-www-form-urlencoded). * * @return string the x-www-form-urlencoded querystring. */ public function __toString() {} /** * Retrieve an querystring value. * * See http\QueryString::TYPE_* constants. * * @param string $name The key to retrieve the value for. * @param mixed $type The type to cast the value to. See http\QueryString::TYPE_* constants. * @param mixed $defval The default value to return if the key $name does not exist. * @param bool $delete Whether to delete the entry from the querystring after retrieval. * @return \http\QueryString|string|mixed|mixed|string \http\QueryString if called without arguments. * or string the whole querystring if $name is of zero length. * or mixed $defval if the key $name does not exist. * or mixed the querystring value cast to $type if $type was specified and the key $name exists. * or string the querystring value if the key $name exists and $type is not specified or equals http\QueryString::TYPE_STRING. */ public function get(?string $name = null, $type = null, $defval = null, bool $delete = false) {} /** * Retrieve an array value with at offset $name. * * @param string $name The key to look up. * @param mixed $defval The default value to return if the offset $name does not exist. * @param bool $delete Whether to remove the key and value from the querystring after retrieval. * @return array|mixed array the (casted) value. * or mixed $defval if offset $name does not exist. */ public function getArray(string $name, $defval = null, bool $delete = false) {} /** * Retrieve a boolean value at offset $name. * * @param string $name The key to look up. * @param mixed $defval The default value to return if the offset $name does not exist. * @param bool $delete Whether to remove the key and value from the querystring after retrieval. * @return bool|mixed bool the (casted) value. * or mixed $defval if offset $name does not exist. */ public function getBool(string $name, $defval = null, bool $delete = false) {} /** * Retrieve a float value at offset $name. * * @param string $name The key to look up. * @param mixed $defval The default value to return if the offset $name does not exist. * @param bool $delete Whether to remove the key and value from the querystring after retrieval. * @return float|mixed float the (casted) value. * or mixed $defval if offset $name does not exist. */ public function getFloat(string $name, $defval = null, bool $delete = false) {} /** * Retrieve the global querystring instance referencing $_GET. * * @throws \http\Exception\UnexpectedValueException * @return \http\QueryString the http\QueryString::$instance */ public function getGlobalInstance() {} /** * Retrieve a int value at offset $name. * * @param string $name The key to look up. * @param mixed $defval The default value to return if the offset $name does not exist. * @param bool $delete Whether to remove the key and value from the querystring after retrieval. * @return int|mixed int the (casted) value. * or mixed $defval if offset $name does not exist. */ public function getInt(string $name, $defval = null, bool $delete = false) {} /** * Implements IteratorAggregate. * * @throws \http\Exception\InvalidArgumentException * @throws \InvalidArgumentException */ public function getIterator() {} /** * Retrieve a object value with at offset $name. * * @param string $name The key to look up. * @param mixed $defval The default value to return if the offset $name does not exist. * @param bool $delete Whether to remove the key and value from the querystring after retrieval. * @return object|mixed object the (casted) value. * or mixed $defval if offset $name does not exist. */ public function getObject(string $name, $defval = null, bool $delete = false) {} /** * Retrieve a string value with at offset $name. * * @param string $name The key to look up. * @param mixed $defval The default value to return if the offset $name does not exist. * @param bool $delete Whether to remove the key and value from the querystring after retrieval. * @return string|mixed string the (casted) value. * or mixed $defval if offset $name does not exist. */ public function getString(string $name, $defval = null, bool $delete = false) {} /** * Set additional $params to a clone of this instance. * See http\QueryString::set(). * * ***NOTE:*** * This method returns a clone (copy) of this instance. * * @param mixed $params Additional params as object, array or string to parse. * @throws \http\Exception\BadQueryStringException * @return \http\QueryString clone. */ public function mod($params = null) {} /** * Implements ArrayAccess. * * @param string $name The offset to look up. * @return bool whether the key $name isset. */ public function offsetExists($name) {} /** * Implements ArrayAccess. * * @param mixed $offset The offset to look up. * @return mixed|null mixed the value locate at offset $name. * or NULL if key $name could not be found. */ public function offsetGet($offset) {} /** * Implements ArrayAccess. * * @param string $name The key to set the value for. * @param mixed $data The data to place at offset $name. */ public function offsetSet($name, $data) {} /** * Implements ArrayAccess. * * @param string $name The offset to look up. */ public function offsetUnset($name) {} /** * Implements Serializable. * See http\QueryString::toString(). * * @return string the x-www-form-urlencoded querystring. */ public function serialize() {} /** * Set additional querystring entries. * * @param mixed $params Additional params as object, array or string to parse. * @return \http\QueryString self. */ public function set($params) {} /** * Simply returns http\QueryString::$queryArray. * * @return array the $queryArray property. */ public function toArray() {} /** * Get the string representation of the querystring (x-www-form-urlencoded). * * @return string the x-www-form-urlencoded querystring. */ public function toString() {} /** * Implements Serializable. * * @param string $serialized The x-www-form-urlencoded querystring. * @throws \http\Exception */ public function unserialize($serialized) {} /** * Translate character encodings of the querystring with ext/iconv. * * ***NOTE:*** * This method is only available when ext/iconv support was enabled at build time. * * @param string $from_enc The encoding to convert from. * @param string $to_enc The encoding to convert to. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\BadConversionException * @return \http\QueryString self. */ public function xlate(string $from_enc, string $to_enc) {} } /** * The http\Url class provides versatile means to parse, construct and manipulate URLs. */ class Url { /** * Replace parts of the old URL with parts of the new. */ public const REPLACE = 0; /** * Whether a relative path should be joined into the old path. */ public const JOIN_PATH = 1; /** * Whether the querystrings should be joined. */ public const JOIN_QUERY = 2; /** * Strip the user information from the URL. */ public const STRIP_USER = 4; /** * Strip the password from the URL. */ public const STRIP_PASS = 8; /** * Strip user and password information from URL (same as STRIP_USER|STRIP_PASS). */ public const STRIP_AUTH = 12; /** * Do not include the port. */ public const STRIP_PORT = 32; /** * Do not include the URL path. */ public const STRIP_PATH = 64; /** * Do not include the URL querystring. */ public const STRIP_QUERY = 128; /** * Strip the fragment (hash) from the URL. */ public const STRIP_FRAGMENT = 256; /** * Strip everything except scheme and host information. */ public const STRIP_ALL = 492; /** * Import initial URL parts from the SAPI environment. */ public const FROM_ENV = 4096; /** * Whether to sanitize the URL path (consolidate double slashes, directory jumps etc.) */ public const SANITIZE_PATH = 8192; /** * Parse UTF-8 encoded multibyte sequences. */ public const PARSE_MBUTF8 = 131072; /** * Parse locale encoded multibyte sequences (on systems with wide character support). */ public const PARSE_MBLOC = 65536; /** * Parse and convert multibyte hostnames according to IDNA (with IDNA support). */ public const PARSE_TOIDN = 1048576; /** * Explicitly request IDNA2003 implementation if available (libidn, idnkit or ICU). */ public const PARSE_TOIDN_2003 = 9437184; /** * Explicitly request IDNA2008 implementation if available (libidn2, idnkit2 or ICU). */ public const PARSE_TOIDN_2008 = 5242880; /** * Percent encode multibyte sequences in the userinfo, path, query and fragment parts of the URL. */ public const PARSE_TOPCT = 2097152; /** * Continue parsing when encountering errors. */ public const IGNORE_ERRORS = 268435456; /** * Suppress errors/exceptions. */ public const SILENT_ERRORS = 536870912; /** * Standard flags used by default internally for e.g. http\Message::setRequestUrl(). * Enables joining path and query, sanitizing path, multibyte/unicode, international domain names and transient percent encoding. */ public const STDFLAGS = 3350531; /** * The URL's scheme. * * @var string */ public $scheme = null; /** * Authenticating user. * * @var string */ public $user = null; /** * Authentication password. * * @var string */ public $pass = null; /** * Hostname/domain. * * @var string */ public $host = null; /** * Port. * * @var string */ public $port = null; /** * URL path. * * @var string */ public $path = null; /** * URL querystring. * * @var string */ public $query = null; /** * URL fragment (hash). * * @var string */ public $fragment = null; /** * Create an instance of an http\Url. * * ***NOTE:*** * Prior to v3.0.0, the default for the $flags parameter was http\Url::FROM_ENV. * * See also http\Env\Url. * * @param mixed $old_url Initial URL parts. Either an array, object, http\Url instance or string to parse. * @param mixed $new_url Overriding URL parts. Either an array, object, http\Url instance or string to parse. * @param int $flags The modus operandi of constructing the url. See http\Url constants. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\BadUrlException */ public function __construct($old_url = null, $new_url = null, int $flags = 0) {} /** * String cast handler. Alias of http\Url::toString(). * * @return string the URL as string. */ public function __toString() {} /** * Clone this URL and apply $parts to the cloned URL. * * ***NOTE:*** * This method returns a clone (copy) of this instance. * * @param mixed $parts New URL parts. * @param int $flags Modus operandi of URL construction. See http\Url constants. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\BadUrlException * @return \http\Url clone. */ public function mod($parts, int $flags = \http\Url::JOIN_PATH|\http\Url::JOIN_QUERY|\http\Url::SANITIZE_PATH) {} /** * Retrieve the URL parts as array. * * @return array the URL parts. */ public function toArray() {} /** * Get the string prepresentation of the URL. * * @return string the URL as string. */ public function toString() {} } /** * The http\Client\Curl namespace holds option value constants specific to the curl driver of the http\Client. */ namespace http\Client\Curl; /** * Bitmask of available libcurl features. * See http\Client\Curl\Features namespace. */ const FEATURES = 4179869; /** * List of library versions of or linked into libcurl, * e.g. "libcurl/7.50.0 OpenSSL/1.0.2h zlib/1.2.8 libidn/1.32 nghttp2/1.12.0". * See http\Client\Curl\Versions namespace. */ const VERSIONS = 'libcurl/7.64.0 OpenSSL/1.1.1b zlib/1.2.11 libidn2/2.0.5 libpsl/0.20.2 (+libidn2/2.0.5) libssh2/1.8.0 nghttp2/1.36.0 librtmp/2.3'; /** * Use HTTP/1.0 protocol version. */ const HTTP_VERSION_1_0 = 1; /** * Use HTTP/1.1 protocol version. */ const HTTP_VERSION_1_1 = 2; /** * Attempt to use HTTP/2 protocol version. Available if libcurl is v7.33.0 or more recent and was built with nghttp2 support. */ const HTTP_VERSION_2_0 = 3; /** * Attempt to use version 2 for HTTPS, version 1.1 for HTTP. Available if libcurl is v7.47.0 or more recent and was built with nghttp2 support. */ const HTTP_VERSION_2TLS = 4; /** * Use any HTTP protocol version. */ const HTTP_VERSION_ANY = 0; /** * Use TLS v1.0 encryption. */ const SSL_VERSION_TLSv1_0 = 4; /** * Use TLS v1.1 encryption. */ const SSL_VERSION_TLSv1_1 = 5; /** * Use TLS v1.2 encryption. */ const SSL_VERSION_TLSv1_2 = 6; /** * Use any TLS v1 encryption. */ const SSL_VERSION_TLSv1 = 1; /** * Use SSL v2 encryption. */ const SSL_VERSION_SSLv2 = 2; /** * Use SSL v3 encryption. */ const SSL_VERSION_SSLv3 = 3; /** * Use any encryption. */ const SSL_VERSION_ANY = 0; /** * Use TLS SRP authentication. Available if libcurl is v7.21.4 or more recent and was built with gnutls or openssl with TLS-SRP support. */ const TLSAUTH_SRP = 1; /** * Use IPv4 resolver. */ const IPRESOLVE_V4 = 1; /** * Use IPv6 resolver. */ const IPRESOLVE_V6 = 2; /** * Use any resolver. */ const IPRESOLVE_ANY = 0; /** * Use Basic authentication. */ const AUTH_BASIC = 1; /** * Use Digest authentication. */ const AUTH_DIGEST = 2; /** * Use IE (lower v7) quirks with Digest authentication. Available if libcurl is v7.19.3 or more recent. */ const AUTH_DIGEST_IE = 16; /** * Use NTLM authentication. */ const AUTH_NTLM = 8; /** * Use GSS-Negotiate authentication. */ const AUTH_GSSNEG = 4; /** * Use HTTP Netgotiate authentication (SPNEGO, RFC4559). Available if libcurl is v7.38.0 or more recent. */ const AUTH_SPNEGO = 4; /** * Use any authentication. */ const AUTH_ANY = -17; /** * Use SOCKSv4 proxy protocol. */ const PROXY_SOCKS4 = 4; /** * Use SOCKSv4a proxy protocol. */ const PROXY_SOCKS4A = 5; /** * Use SOCKS5h proxy protocol. */ const PROXY_SOCKS5_HOSTNAME = 5; /** * Use SOCKS5 proxy protoccol. */ const PROXY_SOCKS5 = 5; /** * Use HTTP/1.1 proxy protocol. */ const PROXY_HTTP = 0; /** * Use HTTP/1.0 proxy protocol. Available if libcurl is v7.19.4 or more recent. */ const PROXY_HTTP_1_0 = 1; /** * Keep POSTing on 301 redirects. Available if libcurl is v7.19.1 or more recent. */ const POSTREDIR_301 = 1; /** * Keep POSTing on 302 redirects. Available if libcurl is v7.19.1 or more recent. */ const POSTREDIR_302 = 2; /** * Keep POSTing on 303 redirects. Available if libcurl is v7.19.1 or more recent. */ const POSTREDIR_303 = 4; /** * Keep POSTing on any redirect. Available if libcurl is v7.19.1 or more recent. */ const POSTREDIR_ALL = 7; namespace http\Client; /** * The http\Client\Request class provides an HTTP message implementation tailored to represent a request message to be sent by the client. * * See http\Client::enqueue(). */ class Request extends \http\Message { /** * Array of options for this request, which override client options. * * @var array */ protected $options = null; /** * Create a new client request message to be enqueued and sent by http\Client. * * @param string $meth The request method. * @param string $url The request URL. * @param array $headers HTTP headers. * @param \http\Message\Body $body Request body. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\UnexpectedValueException */ public function __construct(?string $meth = null, ?string $url = null, ?array $headers = null, ?\http\Message\Body $body = null) {} /** * Add querystring data. * See http\Client\Request::setQuery() and http\Message::setRequestUrl(). * * @param mixed $query_data Additional querystring data. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\BadQueryStringException * @return \http\Client\Request self. */ public function addQuery($query_data) {} /** * Add specific SSL options. * See http\Client\Request::setSslOptions(), http\Client\Request::setOptions() and http\Client\Curl\$ssl options. * * @param array $ssl_options Add this SSL options. * @throws \http\Exception\InvalidArgumentException * @return \http\Client\Request self. */ public function addSslOptions(?array $ssl_options = null) {} /** * Extract the currently set "Content-Type" header. * See http\Client\Request::setContentType(). * * @return string|null string the currently set content type. * or NULL if no "Content-Type" header is set. */ public function getContentType() {} /** * Get priorly set options. * See http\Client\Request::setOptions(). * * @return array options. */ public function getOptions() {} /** * Retrieve the currently set querystring. * * @return string|null string the currently set querystring. * or NULL if no querystring is set. */ public function getQuery() {} /** * Retrieve priorly set SSL options. * See http\Client\Request::getOptions() and http\Client\Request::setSslOptions(). * * @return array SSL options. */ public function getSslOptions() {} /** * Set the MIME content type of the request message. * * @param string $content_type The MIME type used as "Content-Type". * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\UnexpectedValueException * @return \http\Client\Request self. */ public function setContentType(string $content_type) {} /** * Set client options. * See http\Client::setOptions() and http\Client\Curl. * * Request specific options override general options which were set in the client. * * ***NOTE:*** * Only options specified prior enqueueing a request are applied to the request. * * @param array $options The options to set. * @throws \http\Exception\InvalidArgumentException * @return \http\Client\Request self. */ public function setOptions(?array $options = null) {} /** * (Re)set the querystring. * See http\Client\Request::addQuery() and http\Message::setRequestUrl(). * * @param mixed $query_data * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\BadQueryStringException * @return \http\Client\Request self. */ public function setQuery($query_data) {} /** * Specifically set SSL options. * See http\Client\Request::setOptions() and http\Client\Curl\$ssl options. * * @param array $ssl_options Set SSL options to this array. * @throws \http\Exception\InvalidArgumentException * @return \http\Client\Request self. */ public function setSslOptions(?array $ssl_options = null) {} } /** * The http\Client\Response class represents an HTTP message the client returns as answer from a server to an http\Client\Request. */ class Response extends \http\Message { /** * Extract response cookies. * Parses any "Set-Cookie" response headers into an http\Cookie list. See http\Cookie::__construct(). * * @param int $flags Cookie parser flags. * @param array $allowed_extras List of keys treated as extras. * @return array list of http\Cookie instances. */ public function getCookies(int $flags = 0, ?array $allowed_extras = null) {} /** * Retrieve transfer related information after the request has completed. * See http\Client::getTransferInfo(). * * @param string $name A key to retrieve out of the transfer info. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\BadMethodCallException * @throws \http\Exception\UnexpectedValueException * @return object|mixed object stdClass instance with all transfer info if $name was not given. * or mixed the specific transfer info for $name. */ public function getTransferInfo(?string $name = null) {} } namespace http\Client\Curl; /** * Interface to an user event loop implementation for http\Client::configure()'s $use_eventloop option. * * ***NOTE:*** * This interface was added in v2.6.0, resp. v3.1.0. */ interface User { /** * No action. */ public const POLL_NONE = 0; /** * Poll for read readiness. */ public const POLL_IN = 1; /** * Poll for write readiness. */ public const POLL_OUT = 2; /** * Poll for read/write readiness. */ public const POLL_INOUT = 3; /** * Stop polling for activity on this descriptor. */ public const POLL_REMOVE = 4; /** * Initialize the event loop. * * @param callable $run as function(http\Client $c, resource $s = null, int $action = http\Client\Curl\User::POLL_NONE) : int * Internal callback returning the number of unfinished requests pending. * * * ***NOTE***: * The callback should be run when a timeout occurs or a watched socket needs action. */ public function init(callable $run); /** * Run the loop as long as it does not block. * * ***NOTE:*** * This method is called by http\Client::once(), so it does not need to have an actual implementation if http\Client::once() is never called. */ public function once(); /** * Run the loop. * * ***NOTE:*** * This method is called by http\Client::send(), so it does not need to have an actual implementation if http\Client::send() is never called. */ public function send(); /** * Register (or deregister) a socket watcher. * * @param resource $socket The socket descriptor to watch. * @param int $poll http\Client\Curl\User::POLL_* constant. */ public function socket($socket, int $poll); /** * Register a timeout watcher. * * @param int $timeout_ms Desired maximum timeout in milliseconds. */ public function timer(int $timeout_ms); /** * Wait/poll/select (block the loop) until events fire. * * ***NOTE:*** * This method is called by http\Client::wait(), so it does not need to have an actual implementation if http\Client::wait() is never called. * * @param int $timeout_ms Block for at most this milliseconds. */ public function wait(?int $timeout_ms = null); } /** * CURL feature constants. * * ***NOTE:*** * These constants have been added in v2.6.0, resp. v3.1.0. */ namespace http\Client\Curl\Features; /** * Whether libcurl supports asynchronous domain name resolution. */ const ASYNCHDNS = 128; /** * Whether libcurl supports the Generic Security Services Application Program Interface. Available if libcurl is v7.38.0 or more recent. */ const GSSAPI = 131072; /** * Whether libcurl supports HTTP Generic Security Services negotiation. */ const GSSNEGOTIATE = 32; /** * Whether libcurl supports the HTTP/2 protocol. Available if libcurl is v7.33.0 or more recent. */ const HTTP2 = 65536; /** * Whether libcurl supports international domain names. */ const IDN = 1024; /** * Whether libcurl supports IPv6. */ const IPV6 = 1; /** * Whether libcurl supports the old Kerberos protocol. */ const KERBEROS4 = 2; /** * Whether libcurl supports the more recent Kerberos v5 protocol. Available if libcurl is v7.40.0 or more recent. */ const KERBEROS5 = 262144; /** * Whether libcurl supports large files. */ const LARGEFILE = 512; /** * Whether libcurl supports gzip/deflate compression. */ const LIBZ = 8; /** * Whether libcurl supports the NT Lan Manager authentication. */ const NTLM = 16; /** * Whether libcurl supports NTLM delegation to a winbind helper. Available if libcurl is v7.22.0 or more recent. */ const NTLM_WB = 32768; /** * Whether libcurl supports the Public Suffix List for cookie host handling. Available if libcurl is v7.47.0 or more recent. */ const PSL = 1048576; /** * Whether libcurl supports the Simple and Protected GSSAPI Negotiation Mechanism. */ const SPNEGO = 256; /** * Whether libcurl supports SSL/TLS protocols. */ const SSL = 4; /** * Whether libcurl supports the Security Support Provider Interface. */ const SSPI = 2048; /** * Whether libcurl supports TLS Secure Remote Password authentication. Available if libcurl is v7.21.4 or more recent. */ const TLSAUTH_SRP = 16384; /** * Whether libcurl supports connections to unix sockets. Available if libcurl is v7.40.0 or more recent. */ const UNIX_SOCKETS = 524288; /** * CURL version constants. * * ***NOTE:*** * These constants have been added in v2.6.0, resp. v3.1.0. */ namespace http\Client\Curl\Versions; /** * Version string of libcurl, e.g. "7.50.0". */ const CURL = '7.64.0'; /** * Version string of the SSL/TLS library, e.g. "OpenSSL/1.0.2h". */ const SSL = 'OpenSSL/1.1.1b'; /** * Version string of the zlib compression library, e.g. "1.2.8". */ const LIBZ = '1.2.11'; /** * Version string of the c-ares library, e.g. "1.11.0". */ const ARES = null; /** * Version string of the IDN library, e.g. "1.32". */ const IDN = null; namespace http\Encoding; /** * Base class for encoding stream implementations. */ abstract class Stream { /** * Do no intermittent flushes. */ public const FLUSH_NONE = 0; /** * Flush at appropriate transfer points. */ public const FLUSH_SYNC = 1048576; /** * Flush at each IO operation. */ public const FLUSH_FULL = 2097152; /** * Base constructor for encoding stream implementations. * * @param int $flags See http\Encoding\Stream and implementation specific constants. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\RuntimeException */ public function __construct(int $flags = 0) {} /** * Check whether the encoding stream is already done. * * @return bool whether the encoding stream is completed. */ public function done() {} /** * Finish and reset the encoding stream. * Returns any pending data. * * @return string any pending data. */ public function finish() {} /** * Flush the encoding stream. * Returns any pending data. * * @return string any pending data. */ public function flush() {} /** * Update the encoding stream with more input. * * @param string $data The data to pass through the stream. * @return string processed data. */ public function update(string $data) {} } namespace http\Encoding\Stream; /** * A [brotli](https://brotli.org) decoding stream. * * ***NOTE:*** * This class has been added in v3.2.0. */ class Debrotli extends \http\Encoding\Stream { /** * Decode brotli encoded data. * * @param string $data The data to uncompress. * @return string the uncompressed data. */ public function decode(string $data) {} } /** * A stream decoding data encoded with chunked transfer encoding. */ class Dechunk extends \http\Encoding\Stream { /** * Decode chunked encoded data. * * @param string $data The data to decode. * @param int &$decoded_len Out parameter with the length of $data that's been decoded. * Should be ```strlen($data)``` if not truncated. * @return string|string|string|false string the decoded data. * or string the unencoded data. * or string the truncated decoded data. * or false if $data cannot be decoded. */ public function decode(string $data, int &$decoded_len = 0) {} } /** * A deflate stream supporting deflate, zlib and gzip encodings. */ class Deflate extends \http\Encoding\Stream { /** * Gzip encoding. RFC1952 */ public const TYPE_GZIP = 16; /** * Zlib encoding. RFC1950 */ public const TYPE_ZLIB = 0; /** * Deflate encoding. RFC1951 */ public const TYPE_RAW = 32; /** * Default compression level. */ public const LEVEL_DEF = 0; /** * Least compression level. */ public const LEVEL_MIN = 1; /** * Greatest compression level. */ public const LEVEL_MAX = 9; /** * Default compression strategy. */ public const STRATEGY_DEF = 0; /** * Filtered compression strategy. */ public const STRATEGY_FILT = 256; /** * Huffman strategy only. */ public const STRATEGY_HUFF = 512; /** * Run-length encoding strategy. */ public const STRATEGY_RLE = 768; /** * Encoding with fixed Huffman codes only. * * > **A note on the compression strategy:** * > * > The strategy parameter is used to tune the compression algorithm. * > * > Use the value DEFAULT_STRATEGY for normal data, FILTERED for data produced by a filter (or predictor), HUFFMAN_ONLY to force Huffman encoding only (no string match), or RLE to limit match distances to one (run-length encoding). * > * > Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better. The effect of FILTERED is to force more Huffman coding and less string matching; it is somewhat intermediate between DEFAULT_STRATEGY and HUFFMAN_ONLY. * > * > RLE is designed to be almost as fast as HUFFMAN_ONLY, but give better compression for PNG image data. * > * > FIXED prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. * > * > The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set appropriately. * > * >_Source: [zlib Manual](http://www.zlib.net/manual.html)_ */ public const STRATEGY_FIXED = 1024; /** * Encode data with deflate/zlib/gzip encoding. * * @param string $data The data to compress. * @param int $flags Any compression tuning flags. See http\Encoding\Stream\Deflate and http\Encoding\Stream constants. * @return string the compressed data. */ public function encode(string $data, int $flags = 0) {} } /** * A [brotli](https://brotli.org) encoding stream. * * ***NOTE:*** * This class has been added in v3.2.0. */ class Enbrotli extends \http\Encoding\Stream { /** * Default compression level. */ public const LEVEL_DEF = null; /** * Least compression level. */ public const LEVEL_MIN = null; /** * Greatest compression level. */ public const LEVEL_MAX = null; /** * Default window bits. */ public const WBITS_DEF = null; /** * Minimum window bits. */ public const WBITS_MIN = null; /** * Maximum window bits. */ public const WBITS_MAX = null; /** * Default compression mode. */ public const MODE_GENERIC = null; /** * Compression mode for UTF-8 formatted text. */ public const MODE_TEXT = null; /** * Compression mode used in WOFF 2.0. */ public const MODE_FONT = null; /** * Encode data with brotli encoding. * * @param string $data The data to compress. * @param int $flags Any compression tuning flags. See http\Encoding\Stream\Enbrotli and http\Encoding\Stream constants. * @return string the compressed data. */ public function encode(string $data, int $flags = 0) {} } /** * A inflate stream supporting deflate, zlib and gzip encodings. */ class Inflate extends \http\Encoding\Stream { /** * Decode deflate/zlib/gzip encoded data. * * @param string $data The data to uncompress. * @return string the uncompressed data. */ public function decode(string $data) {} } namespace http\Env; /** * The http\Env\Request class' instances represent the server's current HTTP request. * * See http\Message for inherited members. */ class Request extends \http\Message { /** * The request's query parameters. ($_GET) * * @var \http\QueryString */ protected $query = null; /** * The request's form parameters. ($_POST) * * @var \http\QueryString */ protected $form = null; /** * The request's form uploads. ($_FILES) * * @var array */ protected $files = null; /** * The request's cookies. ($_COOKIE) * * @var array */ protected $cookie = null; /** * Create an instance of the server's current HTTP request. * * Upon construction, the http\Env\Request acquires http\QueryString instances of query parameters ($\_GET) and form parameters ($\_POST). * * It also compiles an array of uploaded files ($\_FILES) more comprehensive than the original $\_FILES array, see http\Env\Request::getFiles() for that matter. * * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\UnexpectedValueException */ public function __construct() {} /** * Retrieve an URL query value ($_GET). * * See http\QueryString::get() and http\QueryString::TYPE_* constants. * * @param string $name The key to retrieve the value for. * @param mixed $type The type to cast the value to. See http\QueryString::TYPE_* constants. * @param mixed $defval The default value to return if the key $name does not exist. * @param bool $delete Whether to delete the entry from the querystring after retrieval. * @return \http\QueryString|string|mixed|mixed|string \http\QueryString if called without arguments. * or string the whole querystring if $name is of zero length. * or mixed $defval if the key $name does not exist. * or mixed the querystring value cast to $type if $type was specified and the key $name exists. * or string the querystring value if the key $name exists and $type is not specified or equals http\QueryString::TYPE_STRING. */ public function getCookie(?string $name = null, $type = null, $defval = null, bool $delete = false) {} /** * Retrieve the uploaded files list ($_FILES). * * @return array the consolidated upload files array. */ public function getFiles() {} /** * Retrieve a form value ($_POST). * * See http\QueryString::get() and http\QueryString::TYPE_* constants. * * @param string $name The key to retrieve the value for. * @param mixed $type The type to cast the value to. See http\QueryString::TYPE_* constants. * @param mixed $defval The default value to return if the key $name does not exist. * @param bool $delete Whether to delete the entry from the querystring after retrieval. * @return \http\QueryString|string|mixed|mixed|string \http\QueryString if called without arguments. * or string the whole querystring if $name is of zero length. * or mixed $defval if the key $name does not exist. * or mixed the querystring value cast to $type if $type was specified and the key $name exists. * or string the querystring value if the key $name exists and $type is not specified or equals http\QueryString::TYPE_STRING. */ public function getForm(?string $name = null, $type = null, $defval = null, bool $delete = false) {} /** * Retrieve an URL query value ($_GET). * * See http\QueryString::get() and http\QueryString::TYPE_* constants. * * @param string $name The key to retrieve the value for. * @param mixed $type The type to cast the value to. See http\QueryString::TYPE_* constants. * @param mixed $defval The default value to return if the key $name does not exist. * @param bool $delete Whether to delete the entry from the querystring after retrieval. * @return \http\QueryString|string|mixed|mixed|string \http\QueryString if called without arguments. * or string the whole querystring if $name is of zero length. * or mixed $defval if the key $name does not exist. * or mixed the querystring value cast to $type if $type was specified and the key $name exists. * or string the querystring value if the key $name exists and $type is not specified or equals http\QueryString::TYPE_STRING. */ public function getQuery(?string $name = null, $type = null, $defval = null, bool $delete = false) {} } /** * The http\Env\Response class' instances represent the server's current HTTP response. * * See http\Message for inherited members. */ class Response extends \http\Message { /** * Do not use content encoding. */ public const CONTENT_ENCODING_NONE = 0; /** * Support "Accept-Encoding" requests with gzip and deflate encoding. */ public const CONTENT_ENCODING_GZIP = 1; /** * No caching info available. */ public const CACHE_NO = 0; /** * The cache was hit. */ public const CACHE_HIT = 1; /** * The cache was missed. */ public const CACHE_MISS = 2; /** * A request instance which overrides the environments default request. * * @var \http\Env\Request */ protected $request = null; /** * The response's MIME content type. * * @var string */ protected $contentType = null; /** * The response's MIME content disposition. * * @var string */ protected $contentDisposition = null; /** * See http\Env\Response::CONTENT_ENCODING_* constants. * * @var int */ protected $contentEncoding = null; /** * How the client should treat this response in regards to caching. * * @var string */ protected $cacheControl = null; /** * A custom ETag. * * @var string */ protected $etag = null; /** * A "Last-Modified" time stamp. * * @var int */ protected $lastModified = null; /** * Any throttling delay. * * @var int */ protected $throttleDelay = null; /** * The chunk to send every $throttleDelay seconds. * * @var int */ protected $throttleChunk = null; /** * The response's cookies. * * @var array */ protected $cookies = null; /** * Create a new env response message instance. * * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\UnexpectedValueException */ public function __construct() {} /** * Output buffer handler. * Appends output data to the body. * * @param string $data The data output. * @param int $ob_flags Output buffering flags passed from the output buffering control layer. * @return bool success. */ public function __invoke(string $data, int $ob_flags = 0) {} /** * Manually test the header $header_name of the environment's request for a cache hit. * http\Env\Response::send() checks that itself, though. * * @param string $header_name The request header to test. * @return int a http\Env\Response::CACHE_* constant. */ public function isCachedByEtag(string $header_name = "If-None-Match") {} /** * Manually test the header $header_name of the environment's request for a cache hit. * http\Env\Response::send() checks that itself, though. * * @param string $header_name The request header to test. * @return int a http\Env\Response::CACHE_* constant. */ public function isCachedByLastModified(string $header_name = "If-Modified-Since") {} /** * Send the response through the SAPI or $stream. * Flushes all output buffers. * * @param resource $stream A writable stream to send the response through. * @return bool success. */ public function send($stream = null) {} /** * Make suggestions to the client how it should cache the response. * * @param string $cache_control (A) "Cache-Control" header value(s). * @throws \http\Exception\InvalidArgumentException * @return \http\Env\Response self. */ public function setCacheControl(string $cache_control) {} /** * Set the response's content disposition parameters. * * @param array $disposition_params MIME content disposition as http\Params array. * @throws \http\Exception\InvalidArgumentException * @return \http\Env\Response self. */ public function setContentDisposition(array $disposition_params) {} /** * Enable support for "Accept-Encoding" requests with deflate or gzip. * The response will be compressed if the client indicates support and wishes that. * * @param int $content_encoding See http\Env\Response::CONTENT_ENCODING_* constants. * @throws \http\Exception\InvalidArgumentException * @return \http\Env\Response self. */ public function setContentEncoding(int $content_encoding) {} /** * Set the MIME content type of the response. * * @param string $content_type The response's content type. * @throws \http\Exception\InvalidArgumentException * @return \http\Env\Response self. */ public function setContentType(string $content_type) {} /** * Add cookies to the response to send. * * @param mixed $cookie The cookie to send. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\UnexpectedValueException * @return \http\Env\Response self. */ public function setCookie($cookie) {} /** * Override the environment's request. * * @param \http\Message $env_request The overriding request message. * @throws \http\Exception\InvalidArgumentException * @return \http\Env\Response self. */ public function setEnvRequest(\http\Message $env_request) {} /** * Set a custom ETag. * * ***NOTE:*** * This will be used for caching and pre-condition checks. * * @param string $etag A ETag. * @throws \http\Exception\InvalidArgumentException * @return \http\Env\Response self. */ public function setEtag(string $etag) {} /** * Set a custom last modified time stamp. * * ***NOTE:*** * This will be used for caching and pre-condition checks. * * @param int $last_modified A unix timestamp. * @throws \http\Exception\InvalidArgumentException * @return \http\Env\Response self. */ public function setLastModified(int $last_modified) {} /** * Enable throttling. * Send $chunk_size bytes every $delay seconds. * * ***NOTE:*** * If you need throttling by regular means, check for other options in your stack, because this method blocks the executing process/thread until the response has completely been sent. * * @param int $chunk_size Bytes to send. * @param float $delay Seconds to sleep. * @return \http\Env\Response self. */ public function setThrottleRate(int $chunk_size, float $delay = 1) {} } /** * URL class using the HTTP environment by default. * * ***NOTE:*** * This class has been added in v3.0.0. * * Always adds http\Url::FROM_ENV to the $flags constructor argument. See also http\Url. */ class Url extends \http\Url {} namespace http\Exception; /** * A bad conversion (e.g. character conversion) was encountered. */ class BadConversionException extends \DomainException implements \http\Exception {} /** * A bad HTTP header was encountered. */ class BadHeaderException extends \DomainException implements \http\Exception {} /** * A bad HTTP message was encountered. */ class BadMessageException extends \DomainException implements \http\Exception {} /** * A method was called on an object, which was in an invalid or unexpected state. */ class BadMethodCallException extends \BadMethodCallException implements \http\Exception {} /** * A bad querystring was encountered. */ class BadQueryStringException extends \DomainException implements \http\Exception {} /** * A bad HTTP URL was encountered. */ class BadUrlException extends \DomainException implements \http\Exception {} /** * One or more invalid arguments were passed to a method. */ class InvalidArgumentException extends \InvalidArgumentException implements \http\Exception {} /** * A generic runtime exception. */ class RuntimeException extends \RuntimeException implements \http\Exception {} /** * An unexpected value was encountered. */ class UnexpectedValueException extends \UnexpectedValueException implements \http\Exception {} namespace http\Header; /** * The parser which is underlying http\Header and http\Message. * * ***NOTE:*** * This class has been added in v2.3.0. */ class Parser { /** * Finish up parser at end of (incomplete) input. */ public const CLEANUP = 1; /** * Parse failure. */ public const STATE_FAILURE = -1; /** * Expecting HTTP info (request/response line) or headers. */ public const STATE_START = 0; /** * Expecting a key or already parsing a key. */ public const STATE_KEY = 1; /** * Expecting a value or already parsing the value. */ public const STATE_VALUE = 2; /** * At EOL of an header, checking whether a folded header line follows. */ public const STATE_VALUE_EX = 3; /** * A header was completed. */ public const STATE_HEADER_DONE = 4; /** * Finished parsing the headers. * * ***NOTE:*** * Most of this states won't be returned to the user, because the parser immediately jumps to the next expected state. */ public const STATE_DONE = 5; /** * Retrieve the current state of the parser. * See http\Header\Parser::STATE_* constants. * * @throws \http\Exception\InvalidArgumentException * @return int http\Header\Parser::STATE_* constant. */ public function getState() {} /** * Parse a string. * * @param string $data The (part of the) header to parse. * @param int $flags Any combination of [parser flags](http/Header/Parser#Parser.flags:). * @param array &$header Successfully parsed headers. * @throws \http\Exception\InvalidArgumentException * @return int http\Header\Parser::STATE_* constant. */ public function parse(string $data, int $flags, array &$header = null) {} /** * Parse a stream. * * @param resource $stream The header stream to parse from. * @param int $flags Any combination of [parser flags](http/Header/Parser#Parser.flags:). * @param array &$headers The headers parsed. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\UnexpectedValueException * @return int http\Header\Parser::STATE_* constant. */ public function stream($stream, int $flags, array &$headers) {} } namespace http\Message; /** * The message body, represented as a PHP (temporary) stream. * * ***NOTE:*** * Currently, http\Message\Body::addForm() creates multipart/form-data bodies. */ class Body implements \Serializable { /** * Create a new message body, optionally referencing $stream. * * @param resource $stream A stream to be used as message body. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\UnexpectedValueException */ public function __construct($stream = null) {} /** * String cast handler. * * @return string the message body. */ public function __toString() {} /** * Add form fields and files to the message body. * * ***NOTE:*** * Currently, http\Message\Body::addForm() creates "multipart/form-data" bodies. * * @param array $fields List of form fields to add. * @param array $files List of form files to add. * * $fields must look like: * * [ * "field_name" => "value", * "multi_field" => [ * "value1", * "value2" * ] * ] * * $files must look like: * * [ * [ * "name" => "field_name", * "type" => "content/type", * "file" => "/path/to/file.ext" * ], [ * "name" => "field_name2", * "type" => "text/plain", * "file" => "file.ext", * "data" => "string" * ], [ * "name" => "field_name3", * "type" => "image/jpeg", * "file" => "file.ext", * "data" => fopen("/home/mike/Pictures/mike.jpg","r") * ] * * As you can see, a file structure must contain a "file" entry, which holds a file path, and an optional "data" entry, which may either contain a resource to read from or the actual data as string. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\RuntimeException * @return \http\Message\Body self. */ public function addForm(?array $fields = null, ?array $files = null) {} /** * Add a part to a multipart body. * * @param \http\Message $part The message part. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\RuntimeException * @return \http\Message\Body self. */ public function addPart(\http\Message $part) {} /** * Append plain bytes to the message body. * * @param string $data The data to append to the body. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\RuntimeException * @return \http\Message\Body self. */ public function append(string $data) {} /** * Retrieve the ETag of the body. * * @return string|string|false string an Apache style ETag of inode, mtime and size in hex concatenated by hyphens if the message body stream is stat-able. * or string a content hash (which algorithm is determined by INI http.etag.mode) if the stream is not stat-able. * or false if http.etag.mode is not a known hash algorithm. */ public function etag() {} /** * Retrieve any boundary of the message body. * See http\Message::splitMultipartBody(). * * @return string|null string the message body boundary. * or NULL if this message body has no boundary. */ public function getBoundary() {} /** * Retrieve the underlying stream resource. * * @return resource the underlying stream. */ public function getResource() {} /** * Implements Serializable. * Alias of http\Message\Body::__toString(). * * @return string serialized message body. */ public function serialize() {} /** * Stat size, atime, mtime and/or ctime. * * @param string $field A single stat field to retrieve. * @return int|object int the requested stat field. * or object stdClass instance holding all four stat fields. */ public function stat(?string $field = null) {} /** * Stream the message body through a callback. * * @param callable $callback The callback of the form function(http\Message\Body $from, string $data). * @param int $offset Start to stream from this offset. * @param int $maxlen Stream at most $maxlen bytes, or all if $maxlen is less than 1. * @return \http\Message\Body self. */ public function toCallback(callable $callback, int $offset = 0, int $maxlen = 0) {} /** * Stream the message body into another stream $stream, starting from $offset, streaming $maxlen at most. * * @param resource $stream The resource to write to. * @param int $offset The starting offset. * @param int $maxlen The maximum amount of data to stream. All content if less than 1. * @return \http\Message\Body self. */ public function toStream($stream, int $offset = 0, int $maxlen = 0) {} /** * Retrieve the message body serialized to a string. * Alias of http\Message\Body::__toString(). * * @return string message body. */ public function toString() {} /** * Implements Serializable. * * @param string $serialized The serialized message body. */ public function unserialize($serialized) {} } /** * The parser which is underlying http\Message. * * ***NOTE:*** * This class was added in v2.2.0. */ class Parser { /** * Finish up parser at end of (incomplete) input. */ public const CLEANUP = 1; /** * Soak up the rest of input if no entity length is deducible. */ public const DUMB_BODIES = 2; /** * Redirect messages do not contain any body despite of indication of such. */ public const EMPTY_REDIRECTS = 4; /** * Continue parsing while input is available. */ public const GREEDY = 8; /** * Parse failure. */ public const STATE_FAILURE = -1; /** * Expecting HTTP info (request/response line) or headers. */ public const STATE_START = 0; /** * Parsing headers. */ public const STATE_HEADER = 1; /** * Completed parsing headers. */ public const STATE_HEADER_DONE = 2; /** * Parsing the body. */ public const STATE_BODY = 3; /** * Soaking up all input as body. */ public const STATE_BODY_DUMB = 4; /** * Reading body as indicated by `Content-Length` or `Content-Range`. */ public const STATE_BODY_LENGTH = 5; /** * Parsing `chunked` encoded body. */ public const STATE_BODY_CHUNKED = 6; /** * Finished parsing the body. */ public const STATE_BODY_DONE = 7; /** * Updating Content-Length based on body size. */ public const STATE_UPDATE_CL = 8; /** * Finished parsing the message. * * ***NOTE:*** * Most of this states won't be returned to the user, because the parser immediately jumps to the next expected state. */ public const STATE_DONE = 9; /** * Retrieve the current state of the parser. * See http\Message\Parser::STATE_* constants. * * @throws \http\Exception\InvalidArgumentException * @return int http\Message\Parser::STATE_* constant. */ public function getState() {} /** * Parse a string. * * @param string $data The (part of the) message to parse. * @param int $flags Any combination of [parser flags](http/Message/Parser#Parser.flags:). * @param \http\Message $message The current state of the message parsed. * @throws \http\Exception\InvalidArgumentException * @return int http\Message\Parser::STATE_* constant. */ public function parse(string $data, int $flags, \http\Message $message) {} /** * Parse a stream. * * @param resource $stream The message stream to parse from. * @param int $flags Any combination of [parser flags](http/Message/Parser#Parser.flags:). * @param \http\Message $message The current state of the message parsed. * @throws \http\Exception\InvalidArgumentException * @throws \http\Exception\UnexpectedValueException * @return int http\Message\Parser::STATE_* constant. */ public function stream($stream, int $flags, \http\Message $message) {} } * 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 = -1) {} /** * 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 = -1): 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 = -1): 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 = -1): 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 = -1): 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 input charset. *

    * @param string $to_encoding

    * The output charset. *

    *

    * If you append the string //TRANSLIT to * out_charset transliteration is activated. This * means that when a character can't be represented in the target charset, * it can be approximated through one or several similarly looking * characters. If you append the string //IGNORE, * characters that cannot be represented in the target charset are silently * discarded. Otherwise, str is cut from the first * illegal character and an E_NOTICE is generated. *

    * @param string $string

    * The string to be converted. *

    * @return string|false the converted string or FALSE on failure. */ #[Pure] function iconv(string $from_encoding, string $to_encoding, string $string): string|false {} /** * Convert character encoding as output buffer handler * @link https://php.net/manual/en/function.ob-iconv-handler.php * @param string $contents * @param int $status * @return string See ob_start for information about this handler * return values. */ #[Pure] function ob_iconv_handler(string $contents, int $status): string {} /** * Retrieve internal configuration variables of iconv extension * @link https://php.net/manual/en/function.iconv-get-encoding.php * @param string $type [optional]

    * The value of the optional type can be: * all * input_encoding * output_encoding * internal_encoding *

    * @return string|string[]|false the current value of the internal configuration variable if * successful or FALSE on failure. *

    * If type is omitted or set to "all", * iconv_get_encoding returns an array that * stores all these variables. *

    */ #[Pure] #[ArrayShape(["input_encoding" => "string", "output_encoding" => "string", "internal_encoding" => "string"])] function iconv_get_encoding(string $type = "all"): array|string|false {} /** * Set current setting for character encoding conversion * @link https://php.net/manual/en/function.iconv-set-encoding.php * @param string $type

    * The value of type can be any one of these: * input_encoding * output_encoding * internal_encoding *

    * @param string $encoding

    * The character set. *

    * @return bool TRUE on success or FALSE on failure. */ function iconv_set_encoding(string $type, string $encoding): bool {} /** * Returns the character count of string * @link https://php.net/manual/en/function.iconv-strlen.php * @param string $string

    * The string. *

    * @param string|null $encoding

    * If charset parameter is omitted, * str is assumed to be encoded in * iconv.internal_encoding. *

    * @return int|false the character count of str, as an integer. False on error. */ #[Pure] function iconv_strlen(string $string, ?string $encoding = null): int|false {} /** * Cut out part of a string * @link https://php.net/manual/en/function.iconv-substr.php * @param string $string

    * The original string. *

    * @param int $offset

    * If offset is non-negative, * iconv_substr cuts the portion out of * str beginning at offset'th * character, counting from zero. *

    *

    * If offset is negative, * iconv_substr cuts out the portion beginning * at the position, offset characters * away from the end of str. *

    * @param int|null $length [optional]

    * If length is given and is positive, the return * value will contain at most length characters * of the portion that begins at offset * (depending on the length of string). *

    *

    * If negative length is passed, * iconv_substr cuts the portion out of * str from the offset'th * character up to the character that is * length characters away from the end of the string. * In case offset is also negative, the start position * is calculated beforehand according to the rule explained above. *

    * @param string|null $encoding

    * If charset parameter is omitted, * string are assumed to be encoded in * iconv.internal_encoding. *

    *

    * Note that offset and length * parameters are always deemed to represent offsets that are * calculated on the basis of the character set determined by * charset, whilst the counterpart * substr always takes these for byte offsets. *

    * @return string|false the portion of str specified by the * offset and length parameters. *

    * If str is shorter than offset * characters long, FALSE will be returned. *

    */ #[Pure] function iconv_substr(string $string, int $offset, ?int $length = null, ?string $encoding = null): string|false {} /** * Finds position of first occurrence of a needle within a haystack * @link https://php.net/manual/en/function.iconv-strpos.php * @param string $haystack

    * The entire string. *

    * @param string $needle

    * The searched substring. *

    * @param int $offset [optional]

    * The optional offset parameter specifies * the position from which the search should be performed. *

    * @param string|null $encoding

    * If charset parameter is omitted, * string are assumed to be encoded in * iconv.internal_encoding. *

    * @return int<0,max>|false the numeric position of the first occurrence of * needle in haystack. *

    * If needle is not found, * iconv_strpos will return FALSE. *

    */ #[Pure] function iconv_strpos(string $haystack, string $needle, int $offset = 0, ?string $encoding = null): int|false {} /** * Finds the last occurrence of a needle within a haystack * @link https://php.net/manual/en/function.iconv-strrpos.php * @param string $haystack

    * The entire string. *

    * @param string $needle

    * The searched substring. *

    * @param string|null $encoding

    * If charset parameter is omitted, * string are assumed to be encoded in * iconv.internal_encoding. *

    * @return int|false the numeric position of the last occurrence of * needle in haystack. *

    * If needle is not found, * iconv_strrpos will return FALSE. *

    */ #[Pure] function iconv_strrpos(string $haystack, string $needle, ?string $encoding = null): int|false {} /** * Composes a MIME header field * @link https://php.net/manual/en/function.iconv-mime-encode.php * @param string $field_name

    * The field name. *

    * @param string $field_value

    * The field value. *

    * @param array $options

    * You can control the behaviour of iconv_mime_encode * by specifying an associative array that contains configuration items * to the optional third parameter preferences. * The items supported by iconv_mime_encode are * listed below. Note that item names are treated case-sensitive. * * Configuration items supported by iconv_mime_encode * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    ItemTypeDescriptionDefault valueExample
    schemestring * Specifies the method to encode a field value by. The value of * this item may be either "B" or "Q", where "B" stands for * base64 encoding scheme and "Q" stands for * quoted-printable encoding scheme. * BB
    input-charsetstring * Specifies the character set in which the first parameter * field_name and the second parameter * field_value are presented. If not given, * iconv_mime_encode assumes those parameters * are presented to it in the * iconv.internal_encoding * ini setting. * * iconv.internal_encoding * ISO-8859-1
    output-charsetstring * Specifies the character set to use to compose the * MIME header. * * iconv.internal_encoding * UTF-8
    line-lengthinteger * Specifies the maximum length of the header lines. The resulting * header is "folded" to a set of multiple lines in case * the resulting header field would be longer than the value of this * parameter, according to * RFC2822 - Internet Message Format. * If not given, the length will be limited to 76 characters. * 76996
    line-break-charsstring * Specifies the sequence of characters to append to each line * as an end-of-line sign when "folding" is performed on a long header * field. If not given, this defaults to "\r\n" * (CR LF). Note that * this parameter is always treated as an ASCII string regardless * of the value of input-charset. * \r\n\n
    *

    * @return string|false an encoded MIME field on success, * or FALSE if an error occurs during the encoding. */ #[Pure] function iconv_mime_encode(string $field_name, string $field_value, array $options = []): string|false {} /** * Decodes a MIME header field * @link https://php.net/manual/en/function.iconv-mime-decode.php * @param string $string

    * The encoded header, as a string. *

    * @param int $mode [optional]

    * mode determines the behaviour in the event * iconv_mime_decode encounters a malformed * MIME header field. You can specify any combination * of the following bitmasks. * * Bitmasks acceptable to iconv_mime_decode * * * * * * * * * * * * * * * *
    ValueConstantDescription
    1ICONV_MIME_DECODE_STRICT * If set, the given header is decoded in full conformance with the * standards defined in RFC2047. * This option is disabled by default because there are a lot of * broken mail user agents that don't follow the specification and don't * produce correct MIME headers. *
    2ICONV_MIME_DECODE_CONTINUE_ON_ERROR * If set, iconv_mime_decode_headers * attempts to ignore any grammatical errors and continue to process * a given header. *
    *

    * @param string|null $encoding

    * The optional charset parameter specifies the * character set to represent the result by. If omitted, * iconv.internal_encoding * will be used. *

    * @return string|false a decoded MIME field on success, * or FALSE if an error occurs during the decoding. */ #[Pure] function iconv_mime_decode(string $string, int $mode = 0, ?string $encoding = null): string|false {} /** * Decodes multiple MIME header fields at once * @link https://php.net/manual/en/function.iconv-mime-decode-headers.php * @param string $headers

    * The encoded headers, as a string. *

    * @param int $mode [optional]

    * mode determines the behaviour in the event * iconv_mime_decode_headers encounters a malformed * MIME header field. You can specify any combination * of the following bitmasks. *
    * Bitmasks acceptable to iconv_mime_decode_headers

    * * * * * * * * * * * * * * * * *
    ValueConstantDescription
    1ICONV_MIME_DECODE_STRICT * If set, the given header is decoded in full conformance with the * standards defined in RFC2047. * This option is disabled by default because there are a lot of * broken mail user agents that don't follow the specification and don't * produce correct MIME headers. *
    2ICONV_MIME_DECODE_CONTINUE_ON_ERROR * If set, iconv_mime_decode_headers * attempts to ignore any grammatical errors and continue to process * a given header. *
    * @param string|null $encoding

    * The optional charset parameter specifies the * character set to represent the result by. If omitted, * iconv.internal_encoding * will be used. *

    * @return array|false an associative array that holds a whole set of * MIME header fields specified by * encoded_headers on success, or FALSE * if an error occurs during the decoding. *

    * Each key of the return value represents an individual * field name and the corresponding element represents a field value. * If more than one field of the same name are present, * iconv_mime_decode_headers automatically incorporates * them into a numerically indexed array in the order of occurrence. *

    */ #[Pure] function iconv_mime_decode_headers(string $headers, int $mode = 0, ?string $encoding = null): array|false {} /** * string * @link https://php.net/manual/en/iconv.constants.php */ define('ICONV_IMPL', "libiconv"); /** * string * @link https://php.net/manual/en/iconv.constants.php */ define('ICONV_VERSION', 2.17); /** * integer * @link https://php.net/manual/en/iconv.constants.php */ define('ICONV_MIME_DECODE_STRICT', 1); /** * integer * @link https://php.net/manual/en/iconv.constants.php */ define('ICONV_MIME_DECODE_CONTINUE_ON_ERROR', 2); // End of iconv v. 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 Makes an exact copy of the Imagick object * @link https://php.net/manual/en/class.imagick.php */ class Imagick implements Iterator, Countable { // Constants available in Imagick 7.1 // https://im7.phpimagick.com/Imagick/constants public const ALIGN_CENTER = 2; public const ALIGN_LEFT = 1; public const ALIGN_RIGHT = 3; public const ALIGN_UNDEFINED = 0; public const ALPHACHANNEL_ACTIVATE = 1; public const ALPHACHANNEL_ASSOCIATE = 2; public const ALPHACHANNEL_BACKGROUND = 3; public const ALPHACHANNEL_COPY = 4; public const ALPHACHANNEL_DEACTIVATE = 5; public const ALPHACHANNEL_DISCRETE = 6; public const ALPHACHANNEL_DISSOCIATE = 7; public const ALPHACHANNEL_EXTRACT = 8; public const ALPHACHANNEL_OFF = 9; public const ALPHACHANNEL_ON = 10; public const ALPHACHANNEL_OPAQUE = 11; public const ALPHACHANNEL_REMOVE = 12; public const ALPHACHANNEL_SET = 13; public const ALPHACHANNEL_SHAPE = 14; public const ALPHACHANNEL_TRANSPARENT = 15; public const ALPHACHANNEL_UNDEFINED = 0; public const AUTO_THRESHOLD_KAPUR = 1; public const AUTO_THRESHOLD_OTSU = 2; public const AUTO_THRESHOLD_TRIANGLE = 3; public const CHANNEL_ALL = 134217727; public const CHANNEL_ALPHA = 16; public const CHANNEL_BLACK = 8; public const CHANNEL_BLUE = 4; public const CHANNEL_COMPOSITES = 31; public const CHANNEL_COMPOSITE_MASK = 512; public const CHANNEL_CYAN = 1; public const CHANNEL_DEFAULT = 134217727; public const CHANNEL_GRAY = 1; public const CHANNEL_GRAY_CHANNELS = 1024; public const CHANNEL_GREEN = 2; public const CHANNEL_INDEX = 32; public const CHANNEL_MAGENTA = 2; public const CHANNEL_META = 256; public const CHANNEL_OPACITY = 16; public const CHANNEL_READ_MASK = 64; public const CHANNEL_RED = 1; public const CHANNEL_RGBA = 23; public const CHANNEL_RGBS = 512; public const CHANNEL_SYNC = 131072; public const CHANNEL_TRUEALPHA = 256; public const CHANNEL_UNDEFINED = 0; public const CHANNEL_WRITE_MASK = 128; public const CHANNEL_YELLOW = 4; public const COLORSPACE_ADOBE98 = 36; public const COLORSPACE_CMY = 1; public const COLORSPACE_CMYK = 2; public const COLORSPACE_DISPLAYP3 = 35; public const COLORSPACE_GRAY = 3; public const COLORSPACE_HCL = 4; public const COLORSPACE_HCLP = 5; public const COLORSPACE_HSB = 6; public const COLORSPACE_HSI = 7; public const COLORSPACE_HSL = 8; public const COLORSPACE_HSV = 9; public const COLORSPACE_HWB = 10; public const COLORSPACE_JZAZBZ = 34; public const COLORSPACE_LCH = 12; public const COLORSPACE_LCHAB = 13; public const COLORSPACE_LCHUV = 14; public const COLORSPACE_LINEARGRAY = 33; public const COLORSPACE_LMS = 16; public const COLORSPACE_LOG = 15; public const COLORSPACE_LUV = 17; public const COLORSPACE_OHTA = 18; public const COLORSPACE_PROPHOTO = 37; public const COLORSPACE_REC601YCBCR = 19; public const COLORSPACE_REC709YCBCR = 20; public const COLORSPACE_RGB = 21; public const COLORSPACE_SCRGB = 22; public const COLORSPACE_SRGB = 23; public const COLORSPACE_TRANSPARENT = 24; public const COLORSPACE_UNDEFINED = 0; public const COLORSPACE_XYY = 25; public const COLORSPACE_XYZ = 26; public const COLORSPACE_YCBCR = 27; public const COLORSPACE_YCC = 28; public const COLORSPACE_YDBDR = 29; public const COLORSPACE_YIQ = 30; public const COLORSPACE_YPBPR = 31; public const COLORSPACE_YUV = 32; public const COLOR_ALPHA = 18; public const COLOR_BLACK = 11; public const COLOR_BLUE = 12; public const COLOR_CYAN = 13; public const COLOR_FUZZ = 19; public const COLOR_GREEN = 14; public const COLOR_MAGENTA = 17; public const COLOR_RED = 15; public const COLOR_YELLOW = 16; public const COMPLEX_OPERATOR_ADD = 1; public const COMPLEX_OPERATOR_CONJUGATE = 2; public const COMPLEX_OPERATOR_DIVIDE = 3; public const COMPLEX_OPERATOR_MAGNITUDEPHASE = 4; public const COMPLEX_OPERATOR_MULTIPLY = 5; public const COMPLEX_OPERATOR_REALIMAGINARY = 6; public const COMPLEX_OPERATOR_SUBTRACT = 7; public const COMPOSITE_ATOP = 2; public const COMPOSITE_BLEND = 3; public const COMPOSITE_BLUR = 4; public const COMPOSITE_BUMPMAP = 5; public const COMPOSITE_CHANGEMASK = 6; public const COMPOSITE_CLEAR = 7; public const COMPOSITE_COLORBURN = 8; public const COMPOSITE_COLORDODGE = 9; public const COMPOSITE_COLORIZE = 10; public const COMPOSITE_COPY = 13; public const COMPOSITE_COPYALPHA = 17; public const COMPOSITE_COPYBLACK = 11; public const COMPOSITE_COPYBLUE = 12; public const COMPOSITE_COPYCYAN = 14; public const COMPOSITE_COPYGREEN = 15; public const COMPOSITE_COPYMAGENTA = 16; public const COMPOSITE_COPYOPACITY = 17; public const COMPOSITE_COPYRED = 18; public const COMPOSITE_COPYYELLOW = 19; public const COMPOSITE_DARKEN = 20; public const COMPOSITE_DARKENINTENSITY = 21; public const COMPOSITE_DEFAULT = 54; public const COMPOSITE_DIFFERENCE = 22; public const COMPOSITE_DISPLACE = 23; public const COMPOSITE_DISSOLVE = 24; public const COMPOSITE_DISTORT = 25; public const COMPOSITE_DIVIDEDST = 26; public const COMPOSITE_DIVIDESRC = 27; public const COMPOSITE_DST = 29; public const COMPOSITE_DSTATOP = 28; public const COMPOSITE_DSTIN = 30; public const COMPOSITE_DSTOUT = 31; public const COMPOSITE_DSTOVER = 32; public const COMPOSITE_EXCLUSION = 33; public const COMPOSITE_FREEZE = 72; public const COMPOSITE_HARDLIGHT = 34; public const COMPOSITE_HARDMIX = 35; public const COMPOSITE_HUE = 36; public const COMPOSITE_IN = 37; public const COMPOSITE_INTERPOLATE = 73; public const COMPOSITE_LIGHTEN = 39; public const COMPOSITE_LIGHTENINTENSITY = 40; public const COMPOSITE_LINEARBURN = 41; public const COMPOSITE_LINEARDODGE = 42; public const COMPOSITE_LINEARLIGHT = 43; public const COMPOSITE_LUMINIZE = 44; public const COMPOSITE_MATHEMATICS = 45; public const COMPOSITE_MINUSDST = 46; public const COMPOSITE_MINUSSRC = 47; public const COMPOSITE_MODULATE = 48; public const COMPOSITE_MODULUSADD = 49; public const COMPOSITE_MODULUSSUBTRACT = 50; public const COMPOSITE_MULTIPLY = 51; public const COMPOSITE_NEGATE = 74; public const COMPOSITE_NO = 52; public const COMPOSITE_OUT = 53; public const COMPOSITE_OVER = 54; public const COMPOSITE_OVERLAY = 55; public const COMPOSITE_PEGTOPLIGHT = 56; public const COMPOSITE_PINLIGHT = 57; public const COMPOSITE_PLUS = 58; public const COMPOSITE_REFLECT = 75; public const COMPOSITE_REPLACE = 59; public const COMPOSITE_RMSE = 79; public const COMPOSITE_SALIENCY_BLEND = 80; public const COMPOSITE_SEAMLESS_BLEND = 81; public const COMPOSITE_SATURATE = 60; public const COMPOSITE_SCREEN = 61; public const COMPOSITE_SOFTBURN = 76; public const COMPOSITE_SOFTDODGE = 77; public const COMPOSITE_SOFTLIGHT = 62; public const COMPOSITE_SRC = 64; public const COMPOSITE_SRCATOP = 63; public const COMPOSITE_SRCIN = 65; public const COMPOSITE_SRCOUT = 66; public const COMPOSITE_SRCOVER = 67; public const COMPOSITE_STAMP = 78; public const COMPOSITE_STEREO = 71; public const COMPOSITE_THRESHOLD = 68; public const COMPOSITE_UNDEFINED = 0; public const COMPOSITE_VIVIDLIGHT = 69; public const COMPOSITE_XOR = 70; public const COMPRESSION_B44 = 2; public const COMPRESSION_B44A = 1; public const COMPRESSION_BZIP = 3; public const COMPRESSION_DWAA = 24; public const COMPRESSION_DWAB = 25; public const COMPRESSION_DXT1 = 4; public const COMPRESSION_DXT3 = 5; public const COMPRESSION_DXT5 = 6; public const COMPRESSION_FAX = 7; public const COMPRESSION_GROUP4 = 8; public const COMPRESSION_JBIG1 = 9; public const COMPRESSION_JBIG2 = 10; public const COMPRESSION_JPEG = 12; public const COMPRESSION_JPEG2000 = 11; public const COMPRESSION_LOSSLESSJPEG = 13; public const COMPRESSION_LZMA = 14; public const COMPRESSION_LZW = 15; public const COMPRESSION_NO = 16; public const COMPRESSION_PIZ = 17; public const COMPRESSION_PXR24 = 18; public const COMPRESSION_RLE = 19; public const COMPRESSION_UNDEFINED = 0; public const COMPRESSION_WEBP = 23; public const COMPRESSION_ZIP = 20; public const COMPRESSION_ZIPS = 21; public const COMPRESSION_ZSTD = 22; public const DECORATION_LINETHROUGH = 4; public const DECORATION_LINETROUGH = 4; public const DECORATION_NO = 1; public const DECORATION_OVERLINE = 3; public const DECORATION_UNDERLINE = 2; public const DIRECTION_LEFT_TO_RIGHT = 2; public const DIRECTION_RIGHT_TO_LEFT = 1; public const DISPOSE_BACKGROUND = 2; public const DISPOSE_NONE = 1; public const DISPOSE_PREVIOUS = 3; public const DISPOSE_UNDEFINED = 0; public const DISPOSE_UNRECOGNIZED = 0; public const DISTORTION_AFFINE = 1; public const DISTORTION_AFFINEPROJECTION = 2; public const DISTORTION_ARC = 9; public const DISTORTION_BARREL = 14; public const DISTORTION_BARRELINVERSE = 15; public const DISTORTION_BILINEAR = 6; public const DISTORTION_BILINEARFORWARD = 6; public const DISTORTION_BILINEARREVERSE = 7; public const DISTORTION_CYLINDER2PLANE = 12; public const DISTORTION_DEPOLAR = 11; public const DISTORTION_PERSPECTIVE = 4; public const DISTORTION_PERSPECTIVEPROJECTION = 5; public const DISTORTION_PLANE2CYLINDER = 13; public const DISTORTION_POLAR = 10; public const DISTORTION_POLYNOMIAL = 8; public const DISTORTION_RESIZE = 17; public const DISTORTION_RIGID_AFFINE = 19; public const DISTORTION_SCALEROTATETRANSLATE = 3; public const DISTORTION_SENTINEL = 18; public const DISTORTION_SHEPARDS = 16; public const DISTORTION_UNDEFINED = 0; public const DITHERMETHOD_FLOYDSTEINBERG = 3; public const DITHERMETHOD_NO = 1; public const DITHERMETHOD_RIEMERSMA = 2; public const DITHERMETHOD_UNDEFINED = 0; public const EVALUATE_ABS = 1; public const EVALUATE_ADD = 2; public const EVALUATE_ADDMODULUS = 3; public const EVALUATE_AND = 4; public const EVALUATE_COSINE = 5; public const EVALUATE_DIVIDE = 6; public const EVALUATE_EXPONENTIAL = 7; public const EVALUATE_GAUSSIANNOISE = 8; public const EVALUATE_IMPULSENOISE = 9; public const EVALUATE_INVERSE_LOG = 33; public const EVALUATE_LAPLACIANNOISE = 10; public const EVALUATE_LEFTSHIFT = 11; public const EVALUATE_LOG = 12; public const EVALUATE_MAX = 13; public const EVALUATE_MEAN = 14; public const EVALUATE_MEDIAN = 15; public const EVALUATE_MIN = 16; public const EVALUATE_MULTIPLICATIVENOISE = 17; public const EVALUATE_MULTIPLY = 18; public const EVALUATE_OR = 19; public const EVALUATE_POISSONNOISE = 20; public const EVALUATE_POW = 21; public const EVALUATE_RIGHTSHIFT = 22; public const EVALUATE_ROOT_MEAN_SQUARE = 23; public const EVALUATE_SET = 24; public const EVALUATE_SINE = 25; public const EVALUATE_SUBTRACT = 26; public const EVALUATE_SUM = 27; public const EVALUATE_THRESHOLD = 29; public const EVALUATE_THRESHOLDBLACK = 28; public const EVALUATE_THRESHOLDWHITE = 30; public const EVALUATE_UNDEFINED = 0; public const EVALUATE_UNIFORMNOISE = 31; public const EVALUATE_XOR = 32; public const FILLRULE_EVENODD = 1; public const FILLRULE_NONZERO = 2; public const FILLRULE_UNDEFINED = 0; public const FILTER_BARTLETT = 20; public const FILTER_BESSEL = 13; public const FILTER_BLACKMAN = 7; public const FILTER_BOHMAN = 19; public const FILTER_BOX = 2; public const FILTER_CATROM = 11; public const FILTER_COSINE = 28; public const FILTER_CUBIC = 10; public const FILTER_CUBIC_SPLINE = 31; public const FILTER_GAUSSIAN = 8; public const FILTER_HAMMING = 6; public const FILTER_HANN = 5; public const FILTER_HANNING = 5; public const FILTER_HERMITE = 4; public const FILTER_JINC = 13; public const FILTER_KAISER = 16; public const FILTER_LAGRANGE = 21; public const FILTER_LANCZOS = 22; public const FILTER_LANCZOS2 = 24; public const FILTER_LANCZOS2SHARP = 25; public const FILTER_LANCZOSRADIUS = 30; public const FILTER_LANCZOSSHARP = 23; public const FILTER_MITCHELL = 12; public const FILTER_PARZEN = 18; public const FILTER_POINT = 1; public const FILTER_QUADRATIC = 9; public const FILTER_ROBIDOUX = 26; public const FILTER_ROBIDOUXSHARP = 27; public const FILTER_SENTINEL = 34; public const FILTER_SINC = 14; public const FILTER_SINCFAST = 15; public const FILTER_SPLINE = 29; public const FILTER_TRIANGLE = 3; public const FILTER_UNDEFINED = 0; public const FILTER_WELCH = 17; public const FILTER_WELSH = 17; public const FUNCTION_ARCSIN = 1; public const FUNCTION_ARCTAN = 2; public const FUNCTION_POLYNOMIAL = 3; public const FUNCTION_SINUSOID = 4; public const FUNCTION_UNDEFINED = 0; public const GRAVITY_CENTER = 5; public const GRAVITY_EAST = 6; public const GRAVITY_FORGET = 0; public const GRAVITY_NORTH = 2; public const GRAVITY_NORTHEAST = 3; public const GRAVITY_NORTHWEST = 1; public const GRAVITY_SOUTH = 8; public const GRAVITY_SOUTHEAST = 9; public const GRAVITY_SOUTHWEST = 7; public const GRAVITY_WEST = 4; public const IMAGE_TYPE_BILEVEL = 1; public const IMAGE_TYPE_COLOR_SEPARATION = 8; public const IMAGE_TYPE_COLOR_SEPARATION_ALPHA = 9; public const IMAGE_TYPE_GRAYSCALE = 2; public const IMAGE_TYPE_GRAYSCALE_ALPHA = 3; public const IMAGE_TYPE_OPTIMIZE = 10; public const IMAGE_TYPE_PALETTE = 4; public const IMAGE_TYPE_PALETTE_ALPHA = 5; public const IMAGE_TYPE_PALETTE_BILEVEL_ALPHA = 11; public const IMAGE_TYPE_TRUE_COLOR = 6; public const IMAGE_TYPE_TRUE_COLOR_ALPHA = 7; public const IMAGICK_EXTNUM = 30800; public const IMAGICK_EXTVER = "3.8.0"; public const IMGTYPE_BILEVEL = 1; public const IMGTYPE_COLORSEPARATION = 8; public const IMGTYPE_COLORSEPARATIONALPHA = 9; public const IMGTYPE_COLORSEPARATIONMATTE = 9; public const IMGTYPE_GRAYSCALE = 2; public const IMGTYPE_GRAYSCALEALPHA = 3; public const IMGTYPE_GRAYSCALEMATTE = 3; public const IMGTYPE_OPTIMIZE = 10; public const IMGTYPE_PALETTE = 4; public const IMGTYPE_PALETTEALPHA = 5; public const IMGTYPE_PALETTEBILEVELALPHA = 11; public const IMGTYPE_PALETTEBILEVELMATTE = 11; public const IMGTYPE_PALETTEMATTE = 5; public const IMGTYPE_TRUECOLOR = 6; public const IMGTYPE_TRUECOLORALPHA = 7; public const IMGTYPE_TRUECOLORMATTE = 7; public const IMGTYPE_UNDEFINED = 0; public const INTERLACE_GIF = 5; public const INTERLACE_JPEG = 6; public const INTERLACE_LINE = 2; public const INTERLACE_NO = 1; public const INTERLACE_PARTITION = 4; public const INTERLACE_PLANE = 3; public const INTERLACE_PNG = 7; public const INTERLACE_UNDEFINED = 0; public const INTERPOLATE_AVERAGE = 1; public const INTERPOLATE_AVERAGE_16 = 3; public const INTERPOLATE_AVERAGE_9 = 2; public const INTERPOLATE_BACKGROUND_COLOR = 4; public const INTERPOLATE_BILINEAR = 5; public const INTERPOLATE_BLEND = 6; public const INTERPOLATE_CATROM = 7; public const INTERPOLATE_INTEGER = 8; public const INTERPOLATE_MESH = 9; public const INTERPOLATE_NEAREST_PIXEL = 10; public const INTERPOLATE_SPLINE = 11; public const INTERPOLATE_UNDEFINED = 0; public const KERNEL_BINOMIAL = 7; public const KERNEL_BLUR = 5; public const KERNEL_CHEBYSHEV = 33; public const KERNEL_COMET = 6; public const KERNEL_COMPASS = 13; public const KERNEL_CONVEX_HULL = 30; public const KERNEL_CORNERS = 25; public const KERNEL_CROSS = 21; public const KERNEL_DIAGONALS = 26; public const KERNEL_DIAMOND = 15; public const KERNEL_DIFFERENCE_OF_GAUSSIANS = 3; public const KERNEL_DISK = 19; public const KERNEL_EDGES = 24; public const KERNEL_EUCLIDEAN = 36; public const KERNEL_FREI_CHEN = 10; public const KERNEL_GAUSSIAN = 2; public const KERNEL_KIRSCH = 14; public const KERNEL_LAPLACIAN = 8; public const KERNEL_LAPLACIAN_OF_GAUSSIANS = 4; public const KERNEL_LINE_ENDS = 27; public const KERNEL_LINE_JUNCTIONS = 28; public const KERNEL_MANHATTAN = 34; public const KERNEL_OCTAGON = 18; public const KERNEL_OCTAGONAL = 35; public const KERNEL_PEAKS = 23; public const KERNEL_PLUS = 20; public const KERNEL_PREWITT = 12; public const KERNEL_RECTANGLE = 17; public const KERNEL_RIDGES = 29; public const KERNEL_RING = 22; public const KERNEL_ROBERTS = 11; public const KERNEL_SKELETON = 32; public const KERNEL_SOBEL = 9; public const KERNEL_SQUARE = 16; public const KERNEL_THIN_SE = 31; public const KERNEL_UNITY = 1; public const KERNEL_USER_DEFINED = 37; public const LAYERMETHOD_COALESCE = 1; public const LAYERMETHOD_COMPAREANY = 2; public const LAYERMETHOD_COMPARECLEAR = 3; public const LAYERMETHOD_COMPAREOVERLAY = 4; public const LAYERMETHOD_COMPOSITE = 12; public const LAYERMETHOD_DISPOSE = 5; public const LAYERMETHOD_FLATTEN = 14; public const LAYERMETHOD_MERGE = 13; public const LAYERMETHOD_MOSAIC = 15; public const LAYERMETHOD_OPTIMIZE = 6; public const LAYERMETHOD_OPTIMIZEIMAGE = 7; public const LAYERMETHOD_OPTIMIZEPLUS = 8; public const LAYERMETHOD_OPTIMIZETRANS = 9; public const LAYERMETHOD_REMOVEDUPS = 10; public const LAYERMETHOD_REMOVEZERO = 11; public const LAYERMETHOD_TRIMBOUNDS = 16; public const LAYERMETHOD_UNDEFINED = 0; public const LINECAP_BUTT = 1; public const LINECAP_ROUND = 2; public const LINECAP_SQUARE = 3; public const LINECAP_UNDEFINED = 0; public const LINEJOIN_BEVEL = 3; public const LINEJOIN_MITER = 1; public const LINEJOIN_ROUND = 2; public const LINEJOIN_UNDEFINED = 0; public const METRIC_ABSOLUTEERRORMETRIC = 1; public const METRIC_FUZZERROR = 2; public const METRIC_MEANABSOLUTEERROR = 3; public const METRIC_MEANERRORPERPIXELMETRIC = 4; public const METRIC_MEANSQUAREERROR = 5; public const METRIC_NORMALIZEDCROSSCORRELATIONERRORMETRIC = 6; public const METRIC_PEAKABSOLUTEERROR = 7; public const METRIC_PEAKSIGNALTONOISERATIO = 8; public const METRIC_PERCEPTUALHASH_ERROR = 9; public const METRIC_ROOTMEANSQUAREDERROR = 10; public const METRIC_STRUCTURAL_DISSIMILARITY_ERROR = 12; public const METRIC_STRUCTURAL_SIMILARITY_ERROR = 11; public const MONTAGEMODE_CONCATENATE = 3; public const MONTAGEMODE_FRAME = 1; public const MONTAGEMODE_UNFRAME = 2; public const MORPHOLOGY_BOTTOM_HAT = 17; public const MORPHOLOGY_CLOSE = 9; public const MORPHOLOGY_CLOSE_INTENSITY = 11; public const MORPHOLOGY_CONVOLVE = 1; public const MORPHOLOGY_CORRELATE = 2; public const MORPHOLOGY_DILATE = 4; public const MORPHOLOGY_DILATE_INTENSITY = 6; public const MORPHOLOGY_DISTANCE = 21; public const MORPHOLOGY_EDGE = 15; public const MORPHOLOGY_EDGE_IN = 13; public const MORPHOLOGY_EDGE_OUT = 14; public const MORPHOLOGY_ERODE = 3; public const MORPHOLOGY_ERODE_INTENSITY = 5; public const MORPHOLOGY_HIT_AND_MISS = 18; public const MORPHOLOGY_ITERATIVE = 7; public const MORPHOLOGY_OPEN = 8; public const MORPHOLOGY_OPEN_INTENSITY = 10; public const MORPHOLOGY_SMOOTH = 12; public const MORPHOLOGY_THICKEN = 20; public const MORPHOLOGY_THINNING = 19; public const MORPHOLOGY_TOP_HAT = 16; public const MORPHOLOGY_VORONOI = 22; public const NOISE_GAUSSIAN = 2; public const NOISE_IMPULSE = 4; public const NOISE_LAPLACIAN = 5; public const NOISE_MULTIPLICATIVEGAUSSIAN = 3; public const NOISE_POISSON = 6; public const NOISE_RANDOM = 7; public const NOISE_UNIFORM = 1; public const NORMALIZE_KERNEL_CORRELATE = 65536; public const NORMALIZE_KERNEL_NONE = 0; public const NORMALIZE_KERNEL_PERCENT = 4096; public const NORMALIZE_KERNEL_VALUE = 8192; public const ORIENTATION_BOTTOMLEFT = 4; public const ORIENTATION_BOTTOMRIGHT = 3; public const ORIENTATION_LEFTBOTTOM = 8; public const ORIENTATION_LEFTTOP = 5; public const ORIENTATION_RIGHTBOTTOM = 7; public const ORIENTATION_RIGHTTOP = 6; public const ORIENTATION_TOPLEFT = 1; public const ORIENTATION_TOPRIGHT = 2; public const ORIENTATION_UNDEFINED = 0; public const PAINT_FILLTOBORDER = 4; public const PAINT_FLOODFILL = 3; public const PAINT_POINT = 1; public const PAINT_REPLACE = 2; public const PAINT_RESET = 5; public const PATHUNITS_OBJECTBOUNDINGBOX = 3; public const PATHUNITS_UNDEFINED = 0; public const PATHUNITS_USERSPACE = 1; public const PATHUNITS_USERSPACEONUSE = 2; public const PIXELMASK_COMPOSITE = 4; public const PIXELMASK_READ = 1; public const PIXELMASK_WRITE = 2; public const PIXELSTORAGE_CHAR = 1; public const PIXELSTORAGE_DOUBLE = 2; public const PIXELSTORAGE_FLOAT = 3; public const PIXELSTORAGE_LONG = 4; public const PIXELSTORAGE_QUANTUM = 6; public const PIXELSTORAGE_SHORT = 7; public const PIXEL_CHAR = 1; public const PIXEL_DOUBLE = 2; public const PIXEL_FLOAT = 3; public const PIXEL_LONG = 4; public const PIXEL_QUANTUM = 6; public const PIXEL_SHORT = 7; public const PREVIEW_ADDNOISE = 14; public const PREVIEW_BLUR = 16; public const PREVIEW_BRIGHTNESS = 6; public const PREVIEW_CHARCOALDRAWING = 28; public const PREVIEW_DESPECKLE = 12; public const PREVIEW_DULL = 9; public const PREVIEW_EDGEDETECT = 18; public const PREVIEW_GAMMA = 7; public const PREVIEW_GRAYSCALE = 10; public const PREVIEW_HUE = 4; public const PREVIEW_IMPLODE = 25; public const PREVIEW_JPEG = 29; public const PREVIEW_OILPAINT = 27; public const PREVIEW_QUANTIZE = 11; public const PREVIEW_RAISE = 22; public const PREVIEW_REDUCENOISE = 13; public const PREVIEW_ROLL = 3; public const PREVIEW_ROTATE = 1; public const PREVIEW_SATURATION = 5; public const PREVIEW_SEGMENT = 23; public const PREVIEW_SHADE = 21; public const PREVIEW_SHARPEN = 15; public const PREVIEW_SHEAR = 2; public const PREVIEW_SOLARIZE = 20; public const PREVIEW_SPIFF = 8; public const PREVIEW_SPREAD = 19; public const PREVIEW_SWIRL = 24; public const PREVIEW_THRESHOLD = 17; public const PREVIEW_UNDEFINED = 0; public const PREVIEW_WAVE = 26; public const QUANTUM_RANGE = 65535; public const RENDERINGINTENT_ABSOLUTE = 3; public const RENDERINGINTENT_PERCEPTUAL = 2; public const RENDERINGINTENT_RELATIVE = 4; public const RENDERINGINTENT_SATURATION = 1; public const RENDERINGINTENT_UNDEFINED = 0; public const RESOLUTION_PIXELSPERCENTIMETER = 2; public const RESOLUTION_PIXELSPERINCH = 1; public const RESOLUTION_UNDEFINED = 0; public const RESOURCETYPE_AREA = 1; public const RESOURCETYPE_DISK = 2; public const RESOURCETYPE_FILE = 3; public const RESOURCETYPE_HEIGHT = 4; public const RESOURCETYPE_LISTLENGTH = 11; public const RESOURCETYPE_MAP = 5; public const RESOURCETYPE_MEMORY = 6; public const RESOURCETYPE_THREAD = 7; public const RESOURCETYPE_THROTTLE = 8; public const RESOURCETYPE_TIME = 9; public const RESOURCETYPE_UNDEFINED = 0; public const RESOURCETYPE_WIDTH = 10; public const SPARSECOLORMETHOD_BARYCENTRIC = 1; public const SPARSECOLORMETHOD_BILINEAR = 7; public const SPARSECOLORMETHOD_INVERSE = 19; public const SPARSECOLORMETHOD_MANHATTAN = 20; public const SPARSECOLORMETHOD_POLYNOMIAL = 8; public const SPARSECOLORMETHOD_SPEPARDS = 16; public const SPARSECOLORMETHOD_UNDEFINED = 0; public const SPARSECOLORMETHOD_VORONOI = 18; public const STATISTIC_CONTRAST = 10; public const STATISTIC_GRADIENT = 1; public const STATISTIC_MAXIMUM = 2; public const STATISTIC_MEAN = 3; public const STATISTIC_MEDIAN = 4; public const STATISTIC_MINIMUM = 5; public const STATISTIC_MODE = 6; public const STATISTIC_NONPEAK = 7; public const STATISTIC_ROOT_MEAN_SQUARE = 8; public const STATISTIC_STANDARD_DEVIATION = 9; public const STRETCH_ANY = 10; public const STRETCH_CONDENSED = 4; public const STRETCH_EXPANDED = 7; public const STRETCH_EXTRACONDENSED = 3; public const STRETCH_EXTRAEXPANDED = 8; public const STRETCH_NORMAL = 1; public const STRETCH_SEMICONDENSED = 5; public const STRETCH_SEMIEXPANDED = 6; public const STRETCH_ULTRACONDENSED = 2; public const STRETCH_ULTRAEXPANDED = 9; public const STYLE_ANY = 4; public const STYLE_BOLD = 5; public const STYLE_ITALIC = 2; public const STYLE_NORMAL = 1; public const STYLE_OBLIQUE = 3; public const USE_ZEND_MM = 0; public const VIRTUALPIXELMETHOD_BACKGROUND = 1; public const VIRTUALPIXELMETHOD_BLACK = 9; public const VIRTUALPIXELMETHOD_CHECKERTILE = 16; public const VIRTUALPIXELMETHOD_DITHER = 2; public const VIRTUALPIXELMETHOD_EDGE = 3; public const VIRTUALPIXELMETHOD_GRAY = 10; public const VIRTUALPIXELMETHOD_HORIZONTALTILE = 12; public const VIRTUALPIXELMETHOD_HORIZONTALTILEEDGE = 14; public const VIRTUALPIXELMETHOD_MASK = 8; public const VIRTUALPIXELMETHOD_MIRROR = 4; public const VIRTUALPIXELMETHOD_RANDOM = 5; public const VIRTUALPIXELMETHOD_TILE = 6; public const VIRTUALPIXELMETHOD_TRANSPARENT = 7; public const VIRTUALPIXELMETHOD_UNDEFINED = 0; public const VIRTUALPIXELMETHOD_VERTICALTILE = 13; public const VIRTUALPIXELMETHOD_VERTICALTILEEDGE = 15; public const VIRTUALPIXELMETHOD_WHITE = 11; /** * (PECL imagick 2.0.0)
    * Removes repeated portions of images to optimize * @link https://php.net/manual/en/imagick.optimizeimagelayers.php * @return bool TRUE on success. * @throws ImagickException on error. */ public function optimizeImageLayers() {} /** * (PECL imagick 2.0.0)
    * Returns the maximum bounding region between images * @link https://php.net/manual/en/imagick.compareimagelayers.php * @param int $method

    * One of the layer method constants. *

    * @return Imagick TRUE on success. * @throws ImagickException on error. */ public function compareImageLayers($method) {} /** * (PECL imagick 2.0.0)
    * Quickly fetch attributes * @link https://php.net/manual/en/imagick.pingimageblob.php * @param string $image

    * A string containing the image. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function pingImageBlob($image) {} /** * (PECL imagick 2.0.0)
    * Get basic image attributes in a lightweight manner * @link https://php.net/manual/en/imagick.pingimagefile.php * @param resource $filehandle

    * An open filehandle to the image. *

    * @param string $fileName [optional]

    * Optional filename for this image. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function pingImageFile($filehandle, $fileName = null) {} /** * (PECL imagick 2.0.0)
    * Creates a vertical mirror image * @link https://php.net/manual/en/imagick.transposeimage.php * @return bool TRUE on success. * @throws ImagickException on error. */ public function transposeImage() {} /** * (PECL imagick 2.0.0)
    * Creates a horizontal mirror image * @link https://php.net/manual/en/imagick.transverseimage.php * @return bool TRUE on success. * @throws ImagickException on error. */ public function transverseImage() {} /** * (PECL imagick 2.0.0)
    * Remove edges from the image * @link https://php.net/manual/en/imagick.trimimage.php * @param float $fuzz

    * By default target must match a particular pixel color exactly. * However, in many cases two colors may differ by a small amount. * The fuzz member of image defines how much tolerance is acceptable * to consider two colors as the same. This parameter represents the variation * on the quantum range. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function trimImage($fuzz) {} /** * (PECL imagick 2.0.0)
    * Applies wave filter to the image * @link https://php.net/manual/en/imagick.waveimage.php * @param float $amplitude

    * The amplitude of the wave. *

    * @param float $length

    * The length of the wave. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function waveImage($amplitude, $length) {} /** * (PECL imagick 2.0.0)
    * Adds vignette filter to the image * @link https://php.net/manual/en/imagick.vignetteimage.php * @param float $blackPoint

    * The black point. *

    * @param float $whitePoint

    * The white point *

    * @param int $x

    * X offset of the ellipse *

    * @param int $y

    * Y offset of the ellipse *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function vignetteImage($blackPoint, $whitePoint, $x, $y) {} /** * (PECL imagick 2.0.0)
    * Discards all but one of any pixel color * @link https://php.net/manual/en/imagick.uniqueimagecolors.php * @return bool TRUE on success. * @throws ImagickException on error. */ public function uniqueImageColors() {} /** * (PECL imagick 2.0.0)
    * Return if the image has a matte channel * @link https://php.net/manual/en/imagick.getimagematte.php * @return bool TRUE on success or FALSE on failure. * @throws ImagickException on error. */ #[Deprecated] #[Pure] public function getImageMatte() {} /** * (PECL imagick 2.0.0)
    * Sets the image matte channel * @link https://php.net/manual/en/imagick.setimagematte.php * @param bool $matte

    * True activates the matte channel and false disables it. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageMatte($matte) {} /** * Adaptively resize image with data dependent triangulation * * If legacy is true, the calculations are done with the small rounding bug that existed in Imagick before 3.4.0.
    * If false, the calculations should produce the same results as ImageMagick CLI does.
    *
    * Note: The behavior of the parameter bestfit changed in Imagick 3.0.0. Before this version given dimensions 400x400 an image of dimensions 200x150 would be left untouched. * In Imagick 3.0.0 and later the image would be scaled up to size 400x300 as this is the "best fit" for the given dimensions. If bestfit parameter is used both width and height must be given. * @link https://php.net/manual/en/imagick.adaptiveresizeimage.php * @param int $columns The number of columns in the scaled image. * @param int $rows The number of rows in the scaled image. * @param bool $bestfit [optional] Whether to fit the image inside a bounding box.
    * The behavior of the parameter bestfit changed in Imagick 3.0.0. Before this version given dimensions 400x400 an image of dimensions 200x150 would be left untouched. In Imagick 3.0.0 and later the image would be scaled up to size 400x300 as this is the "best fit" for the given dimensions. If bestfit parameter is used both width and height must be given. * @param bool $legacy [optional] Added since 3.4.0. Default value FALSE * @return bool TRUE on success * @throws ImagickException Throws ImagickException on error * @since 2.0.0 */ public function adaptiveResizeImage($columns, $rows, $bestfit = false, $legacy = false) {} /** * (PECL imagick 2.0.0)
    * Simulates a pencil sketch * @link https://php.net/manual/en/imagick.sketchimage.php * @param float $radius

    * The radius of the Gaussian, in pixels, not counting the center pixel *

    * @param float $sigma

    * The standard deviation of the Gaussian, in pixels. *

    * @param float $angle

    * Apply the effect along this angle. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function sketchImage($radius, $sigma, $angle) {} /** * (PECL imagick 2.0.0)
    * Creates a 3D effect * @link https://php.net/manual/en/imagick.shadeimage.php * @param bool $gray

    * A value other than zero shades the intensity of each pixel. *

    * @param float $azimuth

    * Defines the light source direction. *

    * @param float $elevation

    * Defines the light source direction. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function shadeImage($gray, $azimuth, $elevation) {} /** * (PECL imagick 2.0.0)
    * Returns the size offset * @link https://php.net/manual/en/imagick.getsizeoffset.php * @return int the size offset associated with the Imagick object. * @throws ImagickException on error. */ #[Pure] public function getSizeOffset() {} /** * (PECL imagick 2.0.0)
    * Sets the size and offset of the Imagick object * @link https://php.net/manual/en/imagick.setsizeoffset.php * @param int $columns

    * The width in pixels. *

    * @param int $rows

    * The height in pixels. *

    * @param int $offset

    * The image offset. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setSizeOffset($columns, $rows, $offset) {} /** * (PECL imagick 2.0.0)
    * Adds adaptive blur filter to image * @link https://php.net/manual/en/imagick.adaptiveblurimage.php * @param float $radius

    * The radius of the Gaussian, in pixels, not counting the center pixel. * Provide a value of 0 and the radius will be chosen automagically. *

    * @param float $sigma

    * The standard deviation of the Gaussian, in pixels. *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channel constants using bitwise operators. Defaults to Imagick::CHANNEL_DEFAULT. Refer to this list of channel constants *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function adaptiveBlurImage($radius, $sigma, $channel = Imagick::CHANNEL_DEFAULT) {} /** * (PECL imagick 2.0.0)
    * Enhances the contrast of a color image * @link https://php.net/manual/en/imagick.contraststretchimage.php * @param float $black_point

    * The black point. *

    * @param float $white_point

    * The white point. *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Imagick::CHANNEL_ALL. Refer to this * list of channel constants. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function contrastStretchImage($black_point, $white_point, $channel = Imagick::CHANNEL_ALL) {} /** * (PECL imagick 2.0.0)
    * Adaptively sharpen the image * @link https://php.net/manual/en/imagick.adaptivesharpenimage.php * @param float $radius

    * The radius of the Gaussian, in pixels, not counting the center pixel. Use 0 for auto-select. *

    * @param float $sigma

    * The standard deviation of the Gaussian, in pixels. *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channel constants using bitwise operators. Defaults to Imagick::CHANNEL_DEFAULT. Refer to this list of channel constants *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function adaptiveSharpenImage($radius, $sigma, $channel = Imagick::CHANNEL_DEFAULT) {} /** * (PECL imagick 2.0.0)
    * Creates a high-contrast, two-color image * @link https://php.net/manual/en/imagick.randomthresholdimage.php * @param float $low

    * The low point *

    * @param float $high

    * The high point *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function randomThresholdImage($low, $high, $channel = Imagick::CHANNEL_ALL) {} /** * @param $xRounding * @param $yRounding * @param $strokeWidth [optional] * @param $displace [optional] * @param $sizeCorrection [optional] * @throws ImagickException on error. */ public function roundCornersImage($xRounding, $yRounding, $strokeWidth, $displace, $sizeCorrection) {} /** * (PECL imagick 2.0.0)
    * Rounds image corners * Alias to {@see Imagick::roundCornersImage} * @link https://php.net/manual/en/imagick.roundcorners.php * @param float $x_rounding

    * x rounding *

    * @param float $y_rounding

    * y rounding *

    * @param float $stroke_width [optional]

    * stroke width *

    * @param float $displace [optional]

    * image displace *

    * @param float $size_correction [optional]

    * size correction *

    * @return bool TRUE on success. * @throws ImagickException on error. */ #[Deprecated(replacement: "%class%->roundCornersImage(%parametersList%)")] public function roundCorners($x_rounding, $y_rounding, $stroke_width = 10.0, $displace = 5.0, $size_correction = -6.0) {} /** * (PECL imagick 2.0.0)
    * Set the iterator position * @link https://php.net/manual/en/imagick.setiteratorindex.php * @param int $index

    * The position to set the iterator to *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setIteratorIndex($index) {} /** * (PECL imagick 2.0.0)
    * Gets the index of the current active image * @link https://php.net/manual/en/imagick.getiteratorindex.php * @return int an integer containing the index of the image in the stack. */ #[Pure] public function getIteratorIndex() {} /** * (PECL imagick 2.0.0)
    * Convenience method for setting crop size and the image geometry * @link https://php.net/manual/en/imagick.transformimage.php * @param string $crop

    * A crop geometry string. This geometry defines a subregion of the image to crop. *

    * @param string $geometry

    * An image geometry string. This geometry defines the final size of the image. *

    * @return Imagick TRUE on success. * @throws ImagickException on error. */ public function transformImage($crop, $geometry) {} /** * (PECL imagick 2.0.0)
    * Sets the image opacity level * @link https://php.net/manual/en/imagick.setimageopacity.php * @param float $opacity

    * The level of transparency: 1.0 is fully opaque and 0.0 is fully * transparent. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageOpacity($opacity) {} /** * (PECL imagick 2.2.2)
    * Performs an ordered dither * @link https://php.net/manual/en/imagick.orderedposterizeimage.php * @param string $threshold_map

    * A string containing the name of the threshold dither map to use *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function orderedPosterizeImage($threshold_map, $channel = Imagick::CHANNEL_ALL) {} /** * (PECL imagick 2.0.0)
    * Simulates a Polaroid picture * @link https://php.net/manual/en/imagick.polaroidimage.php * @param ImagickDraw $properties

    * The polaroid properties *

    * @param float $angle

    * The polaroid angle *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function polaroidImage(ImagickDraw $properties, $angle) {} /** * (PECL imagick 2.0.0)
    * Returns the named image property * @link https://php.net/manual/en/imagick.getimageproperty.php * @param string $name

    * name of the property (for example Exif:DateTime) *

    * @return string|false a string containing the image property, false if a * property with the given name does not exist. * @throws ImagickException on error. */ #[Pure] public function getImageProperty($name) {} /** * (PECL imagick 2.0.0)
    * Sets an image property * @link https://php.net/manual/en/imagick.setimageproperty.php * @param string $name * @param string $value * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageProperty($name, $value) {} /** * (PECL imagick 2.0.0)
    * Sets the image interpolate pixel method * @link https://php.net/manual/en/imagick.setimageinterpolatemethod.php * @param int $method

    * The method is one of the Imagick::INTERPOLATE_* constants *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageInterpolateMethod($method) {} /** * (PECL imagick 2.0.0)
    * Returns the interpolation method * @link https://php.net/manual/en/imagick.getimageinterpolatemethod.php * @return int the interpolate method on success. * @throws ImagickException on error. */ #[Pure] public function getImageInterpolateMethod() {} /** * (PECL imagick 2.0.0)
    * Stretches with saturation the image intensity * @link https://php.net/manual/en/imagick.linearstretchimage.php * @param float $blackPoint

    * The image black point *

    * @param float $whitePoint

    * The image white point *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function linearStretchImage($blackPoint, $whitePoint) {} /** * (PECL imagick 2.0.0)
    * Returns the image length in bytes * @link https://php.net/manual/en/imagick.getimagelength.php * @return int an int containing the current image size. * @throws ImagickException on error. */ #[Pure] public function getImageLength() {} /** * (No version information available, might only be in SVN)
    * Set image size * @link https://php.net/manual/en/imagick.extentimage.php * @param int $width

    * The new width *

    * @param int $height

    * The new height *

    * @param int $x

    * X position for the new size *

    * @param int $y

    * Y position for the new size *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function extentImage($width, $height, $x, $y) {} /** * (PECL imagick 2.0.0)
    * Gets the image orientation * @link https://php.net/manual/en/imagick.getimageorientation.php * @return int an int on success. * @throws ImagickException on error. */ #[Pure] public function getImageOrientation() {} /** * (PECL imagick 2.0.0)
    * Sets the image orientation * @link https://php.net/manual/en/imagick.setimageorientation.php * @param int $orientation

    * One of the orientation constants *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageOrientation($orientation) {} /** * (PECL imagick 2.1.0)
    * Changes the color value of any pixel that matches target * @link https://php.net/manual/en/imagick.paintfloodfillimage.php * @param mixed $fill

    * ImagickPixel object or a string containing the fill color *

    * @param float $fuzz

    * The amount of fuzz. For example, set fuzz to 10 and the color red at * intensities of 100 and 102 respectively are now interpreted as the * same color for the purposes of the floodfill. *

    * @param mixed $bordercolor

    * ImagickPixel object or a string containing the border color *

    * @param int $x

    * X start position of the floodfill *

    * @param int $y

    * Y start position of the floodfill *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channel constants using bitwise operators. Defaults to Imagick::CHANNEL_DEFAULT. Refer to this list of channel constants *

    * @return bool TRUE on success. * @throws ImagickException on error. */ #[Deprecated] public function paintFloodfillImage($fill, $fuzz, $bordercolor, $x, $y, $channel = Imagick::CHANNEL_ALL) {} /** * (PECL imagick 2.0.0)
    * Replaces colors in the image from a color lookup table. Optional second parameter to replace colors in a specific channel. This method is available if Imagick has been compiled against ImageMagick version 6.3.6 or newer. * @link https://php.net/manual/en/imagick.clutimage.php * @param Imagick $lookup_table

    * Imagick object containing the color lookup table *

    * @param int $channel [optional]

    * The Channeltype * constant. When not supplied, default channels are replaced. *

    * @return bool TRUE on success. * @throws ImagickException on error. * @since 2.0.0 */ public function clutImage(Imagick $lookup_table, $channel = Imagick::CHANNEL_DEFAULT) {} /** * (PECL imagick 2.0.0)
    * Returns the image properties * @link https://php.net/manual/en/imagick.getimageproperties.php * @param string $pattern [optional]

    * The pattern for property names. *

    * @param bool $only_names [optional]

    * Whether to return only property names. If FALSE then also the values are returned *

    * @return array an array containing the image properties or property names. * @throws ImagickException on error. */ #[Pure] public function getImageProperties($pattern = "*", $only_names = true) {} /** * (PECL imagick 2.2.0)
    * Returns the image profiles * @link https://php.net/manual/en/imagick.getimageprofiles.php * @param string $pattern [optional]

    * The pattern for profile names. *

    * @param bool $include_values [optional]

    * Whether to return only profile names. If FALSE then only profile names will be returned. *

    * @return array an array containing the image profiles or profile names. * @throws ImagickException on error. */ #[Pure] public function getImageProfiles($pattern = "*", $include_values = true) {} /** * (PECL imagick 2.0.1)
    * Distorts an image using various distortion methods * @link https://php.net/manual/en/imagick.distortimage.php * @param int $method

    * The method of image distortion. See distortion constants *

    * @param array $arguments

    * The arguments for this distortion method *

    * @param bool $bestfit

    * Attempt to resize destination to fit distorted source *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function distortImage($method, array $arguments, $bestfit) {} /** * (No version information available, might only be in SVN)
    * Writes an image to a filehandle * @link https://php.net/manual/en/imagick.writeimagefile.php * @param resource $filehandle

    * Filehandle where to write the image *

    * @param string|null $format

    * The image format. The list of valid format specifiers depends on the compiled feature set of ImageMagick, and can be queried at runtime via Imagick::queryFormats(). *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function writeImageFile($filehandle, ?string $format = null) {} /** * (No version information available, might only be in SVN)
    * Writes frames to a filehandle * @link https://php.net/manual/en/imagick.writeimagesfile.php * @param resource $filehandle

    * Filehandle where to write the images *

    * @param string|null $format

    * The image format. The list of valid format specifiers depends on the compiled feature set of ImageMagick, and can be queried at runtime via Imagick::queryFormats(). *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function writeImagesFile($filehandle, ?string $format = null) {} /** * (No version information available, might only be in SVN)
    * Reset image page * @link https://php.net/manual/en/imagick.resetimagepage.php * @param string $page

    * The page definition. For example 7168x5147+0+0 *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function resetImagePage($page) {} /** * (No version information available, might only be in SVN)
    * Sets image clip mask * @link https://php.net/manual/en/imagick.setimageclipmask.php * @param Imagick $clip_mask

    * The Imagick object containing the clip mask *

    * @return bool TRUE on success. */ public function setImageClipMask(Imagick $clip_mask) {} /** * (No version information available, might only be in SVN)
    * Gets image clip mask * @link https://php.net/manual/en/imagick.getimageclipmask.php * @return Imagick an Imagick object containing the clip mask. * @throws ImagickException on error. */ #[Pure] public function getImageClipMask() {} /** * (No version information available, might only be in SVN)
    * Animates an image or images * @link https://php.net/manual/en/imagick.animateimages.php * @param string $x_server

    * X server address *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function animateImages($x_server) {} /** * (No version information available, might only be in SVN)
    * Recolors image * @link https://php.net/manual/en/imagick.recolorimage.php * @param array $matrix

    * The matrix containing the color values *

    * @return bool TRUE on success. * @throws ImagickException on error. */ #[Deprecated] public function recolorImage(array $matrix) {} /** * (PECL imagick 2.1.0)
    * Sets font * @link https://php.net/manual/en/imagick.setfont.php * @param string $font

    * Font name or a filename *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setFont($font) {} /** * (PECL imagick 2.1.0)
    * Gets font * @link https://php.net/manual/en/imagick.getfont.php * @return string|false the string containing the font name or FALSE if not font is set. */ #[Pure] public function getFont() {} /** * (PECL imagick 2.1.0)
    * Sets point size * @link https://php.net/manual/en/imagick.setpointsize.php * @param float $point_size

    * Point size *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setPointSize($point_size) {} /** * (No version information available, might only be in SVN)
    * Gets point size * @link https://php.net/manual/en/imagick.getpointsize.php * @return float a float containing the point size. */ #[Pure] public function getPointSize() {} /** * (PECL imagick 2.1.0)
    * Merges image layers * @link https://php.net/manual/en/imagick.mergeimagelayers.php * @param int $layer_method

    * One of the Imagick::LAYERMETHOD_* constants *

    * @return Imagick Returns an Imagick object containing the merged image. * @throws ImagickException */ public function mergeImageLayers($layer_method) {} /** * (No version information available, might only be in SVN)
    * Sets image alpha channel * @link https://php.net/manual/en/imagick.setimagealphachannel.php * @param int $mode

    * One of the Imagick::ALPHACHANNEL_* constants *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageAlphaChannel($mode) {} /** * (No version information available, might only be in SVN)
    * Changes the color value of any pixel that matches target * @link https://php.net/manual/en/imagick.floodfillpaintimage.php * @param mixed $fill

    * ImagickPixel object or a string containing the fill color *

    * @param float $fuzz

    * The amount of fuzz. For example, set fuzz to 10 and the color red at intensities of 100 and 102 respectively are now interpreted as the same color. *

    * @param mixed $target

    * ImagickPixel object or a string containing the target color to paint *

    * @param int $x

    * X start position of the floodfill *

    * @param int $y

    * Y start position of the floodfill *

    * @param bool $invert

    * If TRUE paints any pixel that does not match the target color. *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channel constants using bitwise operators. Defaults to Imagick::CHANNEL_DEFAULT. Refer to this list of channel constants *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function floodFillPaintImage($fill, $fuzz, $target, $x, $y, $invert, $channel = Imagick::CHANNEL_DEFAULT) {} /** * (No version information available, might only be in SVN)
    * Changes the color value of any pixel that matches target * @link https://php.net/manual/en/imagick.opaquepaintimage.php * @param mixed $target

    * ImagickPixel object or a string containing the color to change *

    * @param mixed $fill

    * The replacement color *

    * @param float $fuzz

    * The amount of fuzz. For example, set fuzz to 10 and the color red at intensities of 100 and 102 respectively are now interpreted as the same color. *

    * @param bool $invert

    * If TRUE paints any pixel that does not match the target color. *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channel constants using bitwise operators. Defaults to Imagick::CHANNEL_DEFAULT. Refer to this list of channel constants *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function opaquePaintImage($target, $fill, $fuzz, $invert, $channel = Imagick::CHANNEL_DEFAULT) {} /** * (No version information available, might only be in SVN)
    * Paints pixels transparent * @link https://php.net/manual/en/imagick.transparentpaintimage.php * @param mixed $target

    * The target color to paint *

    * @param float $alpha

    * The level of transparency: 1.0 is fully opaque and 0.0 is fully transparent. *

    * @param float $fuzz

    * The amount of fuzz. For example, set fuzz to 10 and the color red at intensities of 100 and 102 respectively are now interpreted as the same color. *

    * @param bool $invert

    * If TRUE paints any pixel that does not match the target color. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function transparentPaintImage($target, $alpha, $fuzz, $invert) {} /** * (No version information available, might only be in SVN)
    * Animates an image or images * @link https://php.net/manual/en/imagick.liquidrescaleimage.php * @param int $width

    * The width of the target size *

    * @param int $height

    * The height of the target size *

    * @param float $delta_x

    * How much the seam can traverse on x-axis. * Passing 0 causes the seams to be straight. *

    * @param float $rigidity

    * Introduces a bias for non-straight seams. This parameter is * typically 0. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function liquidRescaleImage($width, $height, $delta_x, $rigidity) {} /** * (No version information available, might only be in SVN)
    * Enciphers an image * @link https://php.net/manual/en/imagick.encipherimage.php * @param string $passphrase

    * The passphrase *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function encipherImage($passphrase) {} /** * (No version information available, might only be in SVN)
    * Deciphers an image * @link https://php.net/manual/en/imagick.decipherimage.php * @param string $passphrase

    * The passphrase *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function decipherImage($passphrase) {} /** * (No version information available, might only be in SVN)
    * Sets the gravity * @link https://php.net/manual/en/imagick.setgravity.php * @param int $gravity

    * The gravity property. Refer to the list of * gravity constants. *

    * @return bool No value is returned. * @throws ImagickException on error. */ public function setGravity($gravity) {} /** * (No version information available, might only be in SVN)
    * Gets the gravity * @link https://php.net/manual/en/imagick.getgravity.php * @return int the gravity property. Refer to the list of * gravity constants. */ #[Pure] public function getGravity() {} /** * (PECL imagick 2.2.1)
    * Gets channel range * @link https://php.net/manual/en/imagick.getimagechannelrange.php * @param int $channel

    * Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channel constants using bitwise operators. Defaults to Imagick::CHANNEL_DEFAULT. Refer to this list of channel constants *

    * @return float[] an array containing minima and maxima values of the channel(s). * @throws ImagickException on error. */ #[ArrayShape(["minima" => "float", "maxima" => "float"])] #[Pure] public function getImageChannelRange($channel) {} /** * (No version information available, might only be in SVN)
    * Gets the image alpha channel * @link https://php.net/manual/en/imagick.getimagealphachannel.php * @return bool a constant defining the current alpha channel value. Refer to this * list of alpha channel constants. * @throws ImagickException on error. */ #[Pure] public function getImageAlphaChannel() {} /** * (No version information available, might only be in SVN)
    * Gets channel distortions * @link https://php.net/manual/en/imagick.getimagechanneldistortions.php * @param Imagick $reference

    * Imagick object containing the reference image *

    * @param int $metric

    * Refer to this list of metric type constants. *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channel constants using bitwise operators. Defaults to Imagick::CHANNEL_DEFAULT. Refer to this list of channel constants *

    * @return float a float describing the channel distortion. * @throws ImagickException on error. */ #[Pure] public function getImageChannelDistortions(Imagick $reference, $metric, $channel = Imagick::CHANNEL_DEFAULT) {} /** * (No version information available, might only be in SVN)
    * Sets the image gravity * @link https://php.net/manual/en/imagick.setimagegravity.php * @param int $gravity

    * The gravity property. Refer to the list of * gravity constants. *

    * @return bool No value is returned. * @throws ImagickException on error. */ public function setImageGravity($gravity) {} /** * (No version information available, might only be in SVN)
    * Gets the image gravity * @link https://php.net/manual/en/imagick.getimagegravity.php * @return int the images gravity property. Refer to the list of * gravity constants. * @throws ImagickException on error. */ #[Pure] public function getImageGravity() {} /** * (No version information available, might only be in SVN)
    * Imports image pixels * @link https://php.net/manual/en/imagick.importimagepixels.php * @param int $x

    * The image x position *

    * @param int $y

    * The image y position *

    * @param int $width

    * The image width *

    * @param int $height

    * The image height *

    * @param string $map

    * Map of pixel ordering as a string. This can be for example RGB. * The value can be any combination or order of R = red, G = green, B = blue, A = alpha (0 is transparent), * O = opacity (0 is opaque), C = cyan, Y = yellow, M = magenta, K = black, I = intensity (for grayscale), P = pad. *

    * @param int $storage

    * The pixel storage method. * Refer to this list of pixel constants. *

    * @param array $pixels

    * The array of pixels *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function importImagePixels($x, $y, $width, $height, $map, $storage, array $pixels) {} /** * (No version information available, might only be in SVN)
    * Removes skew from the image * @link https://php.net/manual/en/imagick.deskewimage.php * @param float $threshold

    * Deskew threshold *

    * @return bool * @throws ImagickException on error. */ public function deskewImage($threshold) {} /** * (No version information available, might only be in SVN)
    * Segments an image * @link https://php.net/manual/en/imagick.segmentimage.php * @param int $COLORSPACE

    * One of the COLORSPACE constants. *

    * @param float $cluster_threshold

    * A percentage describing minimum number of pixels * contained in hexedra before it is considered valid. *

    * @param float $smooth_threshold

    * Eliminates noise from the histogram. *

    * @param bool $verbose [optional]

    * Whether to output detailed information about recognised classes. *

    * @return bool * @throws ImagickException on error. */ public function segmentImage($COLORSPACE, $cluster_threshold, $smooth_threshold, $verbose = false) {} /** * (No version information available, might only be in SVN)
    * Interpolates colors * @link https://php.net/manual/en/imagick.sparsecolorimage.php * @param int $SPARSE_METHOD

    * Refer to this list of sparse method constants *

    * @param array $arguments

    * An array containing the coordinates. * The array is in format array(1,1, 2,45) *

    * @param int $channel [optional] * @return bool TRUE on success. * @throws ImagickException on error. */ public function sparseColorImage($SPARSE_METHOD, array $arguments, $channel = Imagick::CHANNEL_DEFAULT) {} /** * (No version information available, might only be in SVN)
    * Remaps image colors * @link https://php.net/manual/en/imagick.remapimage.php * @param Imagick $replacement

    * An Imagick object containing the replacement colors *

    * @param int $DITHER

    * Refer to this list of dither method constants *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function remapImage(Imagick $replacement, $DITHER) {} /** * (No version information available, might only be in SVN)
    * Exports raw image pixels * @link https://php.net/manual/en/imagick.exportimagepixels.php * @param int $x

    * X-coordinate of the exported area *

    * @param int $y

    * Y-coordinate of the exported area *

    * @param int $width

    * Width of the exported aread *

    * @param int $height

    * Height of the exported area *

    * @param string $map

    * Ordering of the exported pixels. For example "RGB". * Valid characters for the map are R, G, B, A, O, C, Y, M, K, I and P. *

    * @param int $STORAGE

    * Refer to this list of pixel type constants *

    * @return int[] an array containing the pixels values. * @throws ImagickException on error. */ public function exportImagePixels($x, $y, $width, $height, $map, $STORAGE) {} /** * (No version information available, might only be in SVN)
    * The getImageChannelKurtosis purpose * @link https://php.net/manual/en/imagick.getimagechannelkurtosis.php * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channel constants using bitwise operators. Defaults to Imagick::CHANNEL_DEFAULT. Refer to this list of channel constants *

    * @return float[] an array with kurtosis and skewness * members. * @throws ImagickException on error. */ #[ArrayShape(["kurtosis" => "float", "skewness" => "float"])] #[Pure] public function getImageChannelKurtosis($channel = Imagick::CHANNEL_DEFAULT) {} /** * (No version information available, might only be in SVN)
    * Applies a function on the image * @link https://php.net/manual/en/imagick.functionimage.php * @param int $function

    * Refer to this list of function constants *

    * @param array $arguments

    * Array of arguments to pass to this function. *

    * @param int $channel [optional] * @return bool TRUE on success. * @throws ImagickException on error. */ public function functionImage($function, array $arguments, $channel = Imagick::CHANNEL_DEFAULT) {} /** * Transform image colorspace * @param $COLORSPACE * @return bool TRUE on success. * @throws ImagickException on error. */ public function transformImageColorspace($COLORSPACE) {} /** * (No version information available, might only be in SVN)
    * Replaces colors in the image * @link https://php.net/manual/en/imagick.haldclutimage.php * @param Imagick $clut

    * Imagick object containing the Hald lookup image. *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channel constants using bitwise operators. Defaults to Imagick::CHANNEL_DEFAULT. Refer to this list of channel constants *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function haldClutImage(Imagick $clut, $channel = Imagick::CHANNEL_DEFAULT) {} /** * Adjusts the levels of a particular image channel by scaling the minimum and maximum values to the full quantum range. * @param $CHANNEL [optional] * @return bool TRUE on success. * @throws ImagickException on error. */ public function autoLevelImage($CHANNEL) {} /** * @link https://www.php.net/manual/en/imagick.blueshiftimage.php * @param float $factor [optional] * @return bool * @throws ImagickException on error. */ public function blueShiftImage($factor = 1.5) {} /** * (No version information available, might only be in SVN)
    * Get image artifact * @link https://php.net/manual/en/imagick.getimageartifact.php * @param string $artifact

    * The name of the artifact *

    * @return string the artifact value on success. * @throws ImagickException on error. */ #[Pure] public function getImageArtifact($artifact) {} /** * (No version information available, might only be in SVN)
    * Set image artifact * @link https://php.net/manual/en/imagick.setimageartifact.php * @param string $artifact

    * The name of the artifact *

    * @param string $value

    * The value of the artifact *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageArtifact($artifact, $value) {} /** * (No version information available, might only be in SVN)
    * Delete image artifact * @link https://php.net/manual/en/imagick.deleteimageartifact.php * @param string $artifact

    * The name of the artifact to delete *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function deleteImageArtifact($artifact) {} /** * (PECL imagick 0.9.10-0.9.9)
    * Gets the colorspace * @link https://php.net/manual/en/imagick.getcolorspace.php * @return int an integer which can be compared against COLORSPACE constants. */ #[Pure] public function getColorspace() {} /** * (No version information available, might only be in SVN)
    * Set colorspace * @link https://php.net/manual/en/imagick.setcolorspace.php * @param int $COLORSPACE

    * One of the COLORSPACE constants *

    * @return bool TRUE on success. */ public function setColorspace($COLORSPACE) {} /** * @param $CHANNEL [optional] * @throws ImagickException on error. */ public function clampImage($CHANNEL) {} /** * @param bool $stack * @param int $offset * @return Imagick * @throws ImagickException on error. */ public function smushImages($stack, $offset) {} /** * (PECL imagick 2.0.0)
    * The Imagick constructor * @link https://php.net/manual/en/imagick.construct.php * @param mixed $files

    * The path to an image to load or an array of paths. Paths can include * wildcards for file names, or can be URLs. *

    * @throws ImagickException Throws ImagickException on error. */ public function __construct($files = null) {} /** * @return string */ public function __toString() {} public function count() {} /** * (PECL imagick 2.0.0)
    * Returns a MagickPixelIterator * @link https://php.net/manual/en/imagick.getpixeliterator.php * @return ImagickPixelIterator an ImagickPixelIterator on success. * @throws ImagickException on error. * @throws ImagickPixelIteratorException on error. */ #[Pure] public function getPixelIterator() {} /** * (PECL imagick 2.0.0)
    * Get an ImagickPixelIterator for an image section * @link https://php.net/manual/en/imagick.getpixelregioniterator.php * @param int $x

    * The x-coordinate of the region. *

    * @param int $y

    * The y-coordinate of the region. *

    * @param int $columns

    * The width of the region. *

    * @param int $rows

    * The height of the region. *

    * @return ImagickPixelIterator an ImagickPixelIterator for an image section. * @throws ImagickException on error. * @throws ImagickPixelIteratorException on error. */ #[Pure] public function getPixelRegionIterator($x, $y, $columns, $rows) {} /** * (PECL imagick 0.9.0-0.9.9)
    * Reads image from filename * @link https://php.net/manual/en/imagick.readimage.php * @param string $filename * @return bool TRUE on success. * @throws ImagickException Throws ImagickException on error. */ public function readImage($filename) {} /** * @param $filenames * @throws ImagickException Throws ImagickException on error. */ public function readImages($filenames) {} /** * (PECL imagick 2.0.0)
    * Reads image from a binary string * @link https://php.net/manual/en/imagick.readimageblob.php * @param string $image * @param string $filename [optional] * @return bool TRUE on success. * @throws ImagickException Throws ImagickException on error. */ public function readImageBlob($image, $filename = null) {} /** * (PECL imagick 2.0.0)
    * Sets the format of a particular image * @link https://php.net/manual/en/imagick.setimageformat.php * @param string $format

    * String presentation of the image format. Format support * depends on the ImageMagick installation. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageFormat($format) {} /** * Scales the size of an image to the given dimensions. Passing zero as either of the arguments will preserve dimension while scaling.
    * If legacy is true, the calculations are done with the small rounding bug that existed in Imagick before 3.4.0.
    * If false, the calculations should produce the same results as ImageMagick CLI does. * @link https://php.net/manual/en/imagick.scaleimage.php * @param int $columns * @param int $rows * @param bool $bestfit [optional] The behavior of the parameter bestfit changed in Imagick 3.0.0. Before this version given dimensions 400x400 an image of dimensions 200x150 would be left untouched. In Imagick 3.0.0 and later the image would be scaled up to size 400x300 as this is the "best fit" for the given dimensions. If bestfit parameter is used both width and height must be given. * @param bool $legacy [optional] Added since 3.4.0. Default value FALSE * @return bool TRUE on success. * @throws ImagickException Throws ImagickException on error * @since 2.0.0 */ public function scaleImage($columns, $rows, $bestfit = false, $legacy = false) {} /** * (PECL imagick 0.9.0-0.9.9)
    * Writes an image to the specified filename * @link https://php.net/manual/en/imagick.writeimage.php * @param string $filename [optional]

    * Filename where to write the image. The extension of the filename * defines the type of the file. * Format can be forced regardless of file extension using format: prefix, * for example "jpg:test.png". *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function writeImage($filename = null) {} /** * (PECL imagick 0.9.0-0.9.9)
    * Writes an image or image sequence * @link https://php.net/manual/en/imagick.writeimages.php * @param string $filename * @param bool $adjoin * @return bool TRUE on success. * @throws ImagickException on error. */ public function writeImages($filename, $adjoin) {} /** * (PECL imagick 2.0.0)
    * Adds blur filter to image * @link https://php.net/manual/en/imagick.blurimage.php * @param float $radius

    * Blur radius *

    * @param float $sigma

    * Standard deviation *

    * @param int $channel [optional]

    * The Channeltype * constant. When not supplied, all channels are blurred. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function blurImage($radius, $sigma, $channel = null) {} /** * Changes the size of an image to the given dimensions and removes any associated profiles.
    * If legacy is true, the calculations are done with the small rounding bug that existed in Imagick before 3.4.0.
    * If false, the calculations should produce the same results as ImageMagick CLI does.
    *
    * Note: The behavior of the parameter bestfit changed in Imagick 3.0.0. Before this version given dimensions 400x400 an image of dimensions 200x150 would be left untouched. In Imagick 3.0.0 and later the image would be scaled up to size 400x300 as this is the "best fit" for the given dimensions. If bestfit parameter is used both width and height must be given. * @link https://php.net/manual/en/imagick.thumbnailimage.php * @param int $columns

    * Image width *

    * @param int $rows

    * Image height *

    * @param bool $bestfit [optional]

    * Whether to force maximum values *

    * The behavior of the parameter bestfit changed in Imagick 3.0.0. Before this version given dimensions 400x400 an image of dimensions 200x150 would be left untouched. In Imagick 3.0.0 and later the image would be scaled up to size 400x300 as this is the "best fit" for the given dimensions. If bestfit parameter is used both width and height must be given. * @param bool $fill [optional] * @param bool $legacy [optional] Added since 3.4.0. Default value FALSE * @return bool TRUE on success. * @throws ImagickException on error. * @since 2.0.0 */ public function thumbnailImage($columns, $rows, $bestfit = false, $fill = false, $legacy = false) {} /** * Creates a cropped thumbnail at the requested size. * If legacy is true, uses the incorrect behaviour that was present until Imagick 3.4.0. * If false it uses the correct behaviour. * @link https://php.net/manual/en/imagick.cropthumbnailimage.php * @param int $width The width of the thumbnail * @param int $height The Height of the thumbnail * @param bool $legacy [optional] Added since 3.4.0. Default value FALSE * @return bool TRUE on succes * @throws ImagickException Throws ImagickException on error * @since 2.0.0 */ public function cropThumbnailImage($width, $height, $legacy = false) {} /** * (PECL imagick 2.0.0)
    * Returns the filename of a particular image in a sequence * @link https://php.net/manual/en/imagick.getimagefilename.php * @return string a string with the filename of the image. * @throws ImagickException on error. */ #[Pure] public function getImageFilename() {} /** * (PECL imagick 2.0.0)
    * Sets the filename of a particular image * @link https://php.net/manual/en/imagick.setimagefilename.php * @param string $filename * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageFilename($filename) {} /** * (PECL imagick 2.0.0)
    * Returns the format of a particular image in a sequence * @link https://php.net/manual/en/imagick.getimageformat.php * @return string a string containing the image format on success. * @throws ImagickException on error. */ #[Pure] public function getImageFormat() {} /** * @link https://secure.php.net/manual/en/imagick.getimagemimetype.php * @return string Returns the image mime-type. * @throws ImagickException on error. */ #[Pure] public function getImageMimeType() {} /** * (PECL imagick 2.0.0)
    * Removes an image from the image list * @link https://php.net/manual/en/imagick.removeimage.php * @return bool TRUE on success. * @throws ImagickException on error. */ public function removeImage() {} /** * (PECL imagick 2.0.0)
    * Destroys the Imagick object * @link https://php.net/manual/en/imagick.destroy.php * @return bool TRUE on success. */ #[Deprecated(replacement: "%class%->clear()")] public function destroy() {} /** * (PECL imagick 2.0.0)
    * Clears all resources associated to Imagick object * @link https://php.net/manual/en/imagick.clear.php * @return bool TRUE on success. */ public function clear() {} /** * (PECL imagick 2.0.0)
    * Returns the image length in bytes * @link https://php.net/manual/en/imagick.getimagesize.php * @return int an int containing the current image size. * @throws ImagickException on error. */ #[Deprecated(replacement: "%class%->getImageLength()")] #[Pure] public function getImageSize() {} /** * (PECL imagick 2.0.0)
    * Returns the image sequence as a blob * @link https://php.net/manual/en/imagick.getimageblob.php * @return string a string containing the image. * @throws ImagickException on error. */ #[Pure] public function getImageBlob() {} /** * (PECL imagick 2.0.0)
    * Returns all image sequences as a blob * @link https://php.net/manual/en/imagick.getimagesblob.php * @return string a string containing the images. On failure, throws ImagickException on failure * @throws ImagickException on failure */ #[Pure] public function getImagesBlob() {} /** * (PECL imagick 2.0.0)
    * Sets the Imagick iterator to the first image * @link https://php.net/manual/en/imagick.setfirstiterator.php * @return bool TRUE on success. */ public function setFirstIterator() {} /** * (PECL imagick 2.0.1)
    * Sets the Imagick iterator to the last image * @link https://php.net/manual/en/imagick.setlastiterator.php * @return bool TRUE on success. */ public function setLastIterator() {} public function resetIterator() {} /** * (PECL imagick 2.0.0)
    * Move to the previous image in the object * @link https://php.net/manual/en/imagick.previousimage.php * @return bool TRUE on success. */ public function previousImage() {} /** * (PECL imagick 2.0.0)
    * Moves to the next image * @link https://php.net/manual/en/imagick.nextimage.php * @return bool TRUE on success. */ public function nextImage() {} /** * (PECL imagick 2.0.0)
    * Checks if the object has a previous image * @link https://php.net/manual/en/imagick.haspreviousimage.php * @return bool TRUE if the object has more images when traversing the list in the * reverse direction, returns FALSE if there are none. */ public function hasPreviousImage() {} /** * (PECL imagick 2.0.0)
    * Checks if the object has more images * @link https://php.net/manual/en/imagick.hasnextimage.php * @return bool TRUE if the object has more images when traversing the list in the * forward direction, returns FALSE if there are none. */ public function hasNextImage() {} /** * (PECL imagick 2.0.0)
    * Set the iterator position * @link https://php.net/manual/en/imagick.setimageindex.php * @param int $index

    * The position to set the iterator to *

    * @return bool TRUE on success. * @throws ImagickException on error. */ #[Deprecated] public function setImageIndex($index) {} /** * (PECL imagick 2.0.0)
    * Gets the index of the current active image * @link https://php.net/manual/en/imagick.getimageindex.php * @return int an integer containing the index of the image in the stack. */ #[Deprecated] #[Pure] public function getImageIndex() {} /** * (PECL imagick 2.0.0)
    * Adds a comment to your image * @link https://php.net/manual/en/imagick.commentimage.php * @param string $comment

    * The comment to add *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function commentImage($comment) {} /** * (PECL imagick 2.0.0)
    * Extracts a region of the image * @link https://php.net/manual/en/imagick.cropimage.php * @param int $width

    * The width of the crop *

    * @param int $height

    * The height of the crop *

    * @param int $x

    * The X coordinate of the cropped region's top left corner *

    * @param int $y

    * The Y coordinate of the cropped region's top left corner *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function cropImage($width, $height, $x, $y) {} /** * (PECL imagick 2.0.0)
    * Adds a label to an image * @link https://php.net/manual/en/imagick.labelimage.php * @param string $label

    * The label to add *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function labelImage($label) {} /** * (PECL imagick 2.0.0)
    * Gets the width and height as an associative array * @link https://php.net/manual/en/imagick.getimagegeometry.php * @return int[] an array with the width/height of the image. * @throws ImagickException on error. */ #[ArrayShape(["width" => "int", "height" => "int"])] #[Pure] public function getImageGeometry() {} /** * (PECL imagick 2.0.0)
    * Renders the ImagickDraw object on the current image * @link https://php.net/manual/en/imagick.drawimage.php * @param ImagickDraw $draw

    * The drawing operations to render on the image. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function drawImage(ImagickDraw $draw) {} /** * (No version information available, might only be in SVN)
    * Sets the image compression quality * @link https://php.net/manual/en/imagick.setimagecompressionquality.php * @param int $quality

    * The image compression quality as an integer *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageCompressionQuality($quality) {} /** * (PECL imagick 2.2.2)
    * Gets the current image's compression quality * @link https://php.net/manual/en/imagick.getimagecompressionquality.php * @return int integer describing the images compression quality */ #[Pure] public function getImageCompressionQuality() {} /** * (PECL imagick 2.0.0)
    * Annotates an image with text * @link https://php.net/manual/en/imagick.annotateimage.php * @param ImagickDraw $draw_settings

    * The ImagickDraw object that contains settings for drawing the text *

    * @param float $x

    * Horizontal offset in pixels to the left of text *

    * @param float $y

    * Vertical offset in pixels to the baseline of text *

    * @param float $angle

    * The angle at which to write the text *

    * @param string $text

    * The string to draw *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function annotateImage(ImagickDraw $draw_settings, $x, $y, $angle, $text) {} /** * (PECL imagick 2.0.0)
    * Composite one image onto another * @link https://php.net/manual/en/imagick.compositeimage.php * @param Imagick $composite_object

    * Imagick object which holds the composite image *

    * @param int $composite Composite operator * @param int $x

    * The column offset of the composited image *

    * @param int $y

    * The row offset of the composited image *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this list of channel constants. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function compositeImage(Imagick $composite_object, $composite, $x, $y, $channel = Imagick::CHANNEL_ALL) {} /** * (PECL imagick 2.0.0)
    * Control the brightness, saturation, and hue * @link https://php.net/manual/en/imagick.modulateimage.php * @param float $brightness * @param float $saturation * @param float $hue * @return bool TRUE on success. * @throws ImagickException on error. */ public function modulateImage($brightness, $saturation, $hue) {} /** * (PECL imagick 2.0.0)
    * Gets the number of unique colors in the image * @link https://php.net/manual/en/imagick.getimagecolors.php * @return int TRUE on success. * @throws ImagickException on error. */ #[Pure] public function getImageColors() {} /** * (PECL imagick 2.0.0)
    * Creates a composite image * @link https://php.net/manual/en/imagick.montageimage.php * @param ImagickDraw $draw

    * The font name, size, and color are obtained from this object. *

    * @param string $tile_geometry

    * The number of tiles per row and page (e.g. 6x4+0+0). *

    * @param string $thumbnail_geometry

    * Preferred image size and border size of each thumbnail * (e.g. 120x120+4+3>). *

    * @param int $mode

    * Thumbnail framing mode, see Montage Mode constants. *

    * @param string $frame

    * Surround the image with an ornamental border (e.g. 15x15+3+3). The * frame color is that of the thumbnail's matte color. *

    * @return Imagick TRUE on success. * @throws ImagickException on error. */ public function montageImage(ImagickDraw $draw, $tile_geometry, $thumbnail_geometry, $mode, $frame) {} /** * (PECL imagick 2.0.0)
    * Identifies an image and fetches attributes * @link https://php.net/manual/en/imagick.identifyimage.php * @param bool $appendRawOutput [optional] * @return array Identifies an image and returns the attributes. Attributes include * the image width, height, size, and others. * @throws ImagickException on error. */ public function identifyImage($appendRawOutput = false) {} /** * (PECL imagick 2.0.0)
    * Changes the value of individual pixels based on a threshold * @link https://php.net/manual/en/imagick.thresholdimage.php * @param float $threshold * @param int $channel [optional] * @return bool TRUE on success. * @throws ImagickException on error. */ public function thresholdImage($threshold, $channel = Imagick::CHANNEL_ALL) {} /** * (PECL imagick 2.0.0)
    * Selects a threshold for each pixel based on a range of intensity * @link https://php.net/manual/en/imagick.adaptivethresholdimage.php * @param int $width

    * Width of the local neighborhood. *

    * @param int $height

    * Height of the local neighborhood. *

    * @param int $offset

    * The mean offset *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function adaptiveThresholdImage($width, $height, $offset) {} /** * (PECL imagick 2.0.0)
    * Forces all pixels below the threshold into black * @link https://php.net/manual/en/imagick.blackthresholdimage.php * @param mixed $threshold

    * The threshold below which everything turns black *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function blackThresholdImage($threshold) {} /** * (PECL imagick 2.0.0)
    * Force all pixels above the threshold into white * @link https://php.net/manual/en/imagick.whitethresholdimage.php * @param mixed $threshold * @return bool TRUE on success. * @throws ImagickException on error. */ public function whiteThresholdImage($threshold) {} /** * (PECL imagick 2.0.0)
    * Append a set of images * @link https://php.net/manual/en/imagick.appendimages.php * @param bool $stack [optional]

    * Whether to stack the images vertically. * By default (or if FALSE is specified) images are stacked left-to-right. * If stack is TRUE, images are stacked top-to-bottom. *

    * @return Imagick Imagick instance on success. * @throws ImagickException on error. */ public function appendImages($stack = false) {} /** * (PECL imagick 2.0.0)
    * Simulates a charcoal drawing * @link https://php.net/manual/en/imagick.charcoalimage.php * @param float $radius

    * The radius of the Gaussian, in pixels, not counting the center pixel *

    * @param float $sigma

    * The standard deviation of the Gaussian, in pixels *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function charcoalImage($radius, $sigma) {} /** * (PECL imagick 2.0.0)
    * Enhances the contrast of a color image * @link https://php.net/manual/en/imagick.normalizeimage.php * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function normalizeImage($channel = Imagick::CHANNEL_ALL) {} /** * (PECL imagick 2.0.0)
    * Simulates an oil painting * @link https://php.net/manual/en/imagick.oilpaintimage.php * @param float $radius

    * The radius of the circular neighborhood. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function oilPaintImage($radius) {} /** * (PECL imagick 2.0.0)
    * Reduces the image to a limited number of color level * @link https://php.net/manual/en/imagick.posterizeimage.php * @param int $levels * @param bool $dither * @return bool TRUE on success. * @throws ImagickException on error. */ public function posterizeImage($levels, $dither) {} /** * (PECL imagick 2.0.0)
    * Radial blurs an image * @link https://php.net/manual/en/imagick.radialblurimage.php * @param float $angle * @param int $channel [optional] * @return bool TRUE on success. * @throws ImagickException on error. */ public function radialBlurImage($angle, $channel = Imagick::CHANNEL_ALL) {} /** * (PECL imagick 2.0.0)
    * Creates a simulated 3d button-like effect * @link https://php.net/manual/en/imagick.raiseimage.php * @param int $width * @param int $height * @param int $x * @param int $y * @param bool $raise * @return bool TRUE on success. * @throws ImagickException on error. */ public function raiseImage($width, $height, $x, $y, $raise) {} /** * (PECL imagick 2.0.0)
    * Resample image to desired resolution * @link https://php.net/manual/en/imagick.resampleimage.php * @param float $x_resolution * @param float $y_resolution * @param int $filter * @param float $blur * @return bool TRUE on success. * @throws ImagickException on error. */ public function resampleImage($x_resolution, $y_resolution, $filter, $blur) {} /** * Scales an image to the desired dimensions with one of these filters:
    * If legacy is true, the calculations are done with the small rounding bug that existed in Imagick before 3.4.0.
    * If false, the calculations should produce the same results as ImageMagick CLI does.
    *
    * Note: The behavior of the parameter bestfit changed in Imagick 3.0.0. Before this version given dimensions 400x400 an image of dimensions 200x150 would be left untouched.
    * In Imagick 3.0.0 and later the image would be scaled up to size 400x300 as this is the "best fit" for the given dimensions. If bestfit parameter is used both width and height must be given. * @link https://php.net/manual/en/imagick.resizeimage.php * @param int $columns Width of the image * @param int $rows Height of the image * @param int $filter Refer to the list of filter constants. * @param float $blur The blur factor where > 1 is blurry, < 1 is sharp. * @param bool $bestfit [optional] Added since 2.1.0. Added optional fit parameter. This method now supports proportional scaling. Pass zero as either parameter for proportional scaling * @param bool $legacy [optional] Added since 3.4.0. Default value FALSE * @return bool TRUE on success * @throws ImagickException on error. * @since 2.0.0 */ public function resizeImage($columns, $rows, $filter, $blur, $bestfit = false, $legacy = false) {} /** * (PECL imagick 2.0.0)
    * Offsets an image * @link https://php.net/manual/en/imagick.rollimage.php * @param int $x

    * The X offset. *

    * @param int $y

    * The Y offset. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function rollImage($x, $y) {} /** * (PECL imagick 2.0.0)
    * Rotates an image * @link https://php.net/manual/en/imagick.rotateimage.php * @param mixed $background

    * The background color *

    * @param float $degrees

    * The number of degrees to rotate the image *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function rotateImage($background, $degrees) {} /** * (PECL imagick 2.0.0)
    * Scales an image with pixel sampling * @link https://php.net/manual/en/imagick.sampleimage.php * @param int $columns * @param int $rows * @return bool TRUE on success. * @throws ImagickException on error. */ public function sampleImage($columns, $rows) {} /** * (PECL imagick 2.0.0)
    * Applies a solarizing effect to the image * @link https://php.net/manual/en/imagick.solarizeimage.php * @param int $threshold * @return bool TRUE on success. * @throws ImagickException on error. */ public function solarizeImage($threshold) {} /** * (PECL imagick 2.0.0)
    * Simulates an image shadow * @link https://php.net/manual/en/imagick.shadowimage.php * @param float $opacity * @param float $sigma * @param int $x * @param int $y * @return bool TRUE on success. * @throws ImagickException on error. */ public function shadowImage($opacity, $sigma, $x, $y) {} /** * @param string $key * @param string $value * @return bool * @throws ImagickException on error. */ #[Deprecated] public function setImageAttribute($key, $value) {} /** * (PECL imagick 2.0.0)
    * Sets the image background color * @link https://php.net/manual/en/imagick.setimagebackgroundcolor.php * @param mixed $background * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageBackgroundColor($background) {} /** * (PECL imagick 2.0.0)
    * Sets the image composite operator * @link https://php.net/manual/en/imagick.setimagecompose.php * @param int $compose * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageCompose($compose) {} /** * (PECL imagick 2.0.0)
    * Sets the image compression * @link https://php.net/manual/en/imagick.setimagecompression.php * @param int $compression

    * One of the COMPRESSION constants *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageCompression($compression) {} /** * (PECL imagick 2.0.0)
    * Sets the image delay * @link https://php.net/manual/en/imagick.setimagedelay.php * @param int $delay

    * The amount of time expressed in 'ticks' that the image should be * displayed for. For animated GIFs there are 100 ticks per second, so a * value of 20 would be 20/100 of a second aka 1/5th of a second. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageDelay($delay) {} /** * (PECL imagick 2.0.0)
    * Sets the image depth * @link https://php.net/manual/en/imagick.setimagedepth.php * @param int $depth * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageDepth($depth) {} /** * (PECL imagick 2.0.0)
    * Sets the image gamma * @link https://php.net/manual/en/imagick.setimagegamma.php * @param float $gamma * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageGamma($gamma) {} /** * (PECL imagick 2.0.0)
    * Sets the image iterations * @link https://php.net/manual/en/imagick.setimageiterations.php * @param int $iterations

    * The number of iterations the image should loop over. Set to '0' to loop * continuously. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageIterations($iterations) {} /** * (PECL imagick 2.0.0)
    * Sets the image matte color * @link https://php.net/manual/en/imagick.setimagemattecolor.php * @param mixed $matte * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageMatteColor($matte) {} /** * (PECL imagick 2.0.0)
    * Sets the page geometry of the image * @link https://php.net/manual/en/imagick.setimagepage.php * @param int $width * @param int $height * @param int $x * @param int $y * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImagePage($width, $height, $x, $y) {} /** * @param $filename * @throws ImagickException on error. */ public function setImageProgressMonitor($filename) {} /** * (PECL imagick 2.0.0)
    * Sets the image resolution * @link https://php.net/manual/en/imagick.setimageresolution.php * @param float $x_resolution * @param float $y_resolution * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageResolution($x_resolution, $y_resolution) {} /** * (PECL imagick 2.0.0)
    * Sets the image scene * @link https://php.net/manual/en/imagick.setimagescene.php * @param int $scene * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageScene($scene) {} /** * (PECL imagick 2.0.0)
    * Sets the image ticks-per-second * @link https://php.net/manual/en/imagick.setimagetickspersecond.php * @param int $ticks_per_second

    * The duration for which an image should be displayed expressed in ticks * per second. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageTicksPerSecond($ticks_per_second) {} /** * (PECL imagick 2.0.0)
    * Sets the image type * @link https://php.net/manual/en/imagick.setimagetype.php * @param int $image_type * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageType($image_type) {} /** * (PECL imagick 2.0.0)
    * Sets the image units of resolution * @link https://php.net/manual/en/imagick.setimageunits.php * @param int $units * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageUnits($units) {} /** * (PECL imagick 2.0.0)
    * Sharpens an image * @link https://php.net/manual/en/imagick.sharpenimage.php * @param float $radius * @param float $sigma * @param int $channel [optional] * @return bool TRUE on success. * @throws ImagickException on error. */ public function sharpenImage($radius, $sigma, $channel = Imagick::CHANNEL_ALL) {} /** * (PECL imagick 2.0.0)
    * Shaves pixels from the image edges * @link https://php.net/manual/en/imagick.shaveimage.php * @param int $columns * @param int $rows * @return bool TRUE on success. * @throws ImagickException on error. */ public function shaveImage($columns, $rows) {} /** * (PECL imagick 2.0.0)
    * Creating a parallelogram * @link https://php.net/manual/en/imagick.shearimage.php * @param mixed $background

    * The background color *

    * @param float $x_shear

    * The number of degrees to shear on the x axis *

    * @param float $y_shear

    * The number of degrees to shear on the y axis *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function shearImage($background, $x_shear, $y_shear) {} /** * (PECL imagick 2.0.0)
    * Splices a solid color into the image * @link https://php.net/manual/en/imagick.spliceimage.php * @param int $width * @param int $height * @param int $x * @param int $y * @return bool TRUE on success. * @throws ImagickException on error. */ public function spliceImage($width, $height, $x, $y) {} /** * (PECL imagick 2.0.0)
    * Fetch basic attributes about the image * @link https://php.net/manual/en/imagick.pingimage.php * @param string $filename

    * The filename to read the information from. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function pingImage($filename) {} /** * (PECL imagick 2.0.0)
    * Reads image from open filehandle * @link https://php.net/manual/en/imagick.readimagefile.php * @param resource $filehandle * @param string $fileName [optional] * @return bool TRUE on success. * @throws ImagickException on error. */ public function readImageFile($filehandle, $fileName = null) {} /** * (PECL imagick 2.0.0)
    * Displays an image * @link https://php.net/manual/en/imagick.displayimage.php * @param string $servername

    * The X server name *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function displayImage($servername) {} /** * (PECL imagick 2.0.0)
    * Displays an image or image sequence * @link https://php.net/manual/en/imagick.displayimages.php * @param string $servername

    * The X server name *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function displayImages($servername) {} /** * (PECL imagick 2.0.0)
    * Randomly displaces each pixel in a block * @link https://php.net/manual/en/imagick.spreadimage.php * @param float $radius * @return bool TRUE on success. * @throws ImagickException on error. */ public function spreadImage($radius) {} /** * (PECL imagick 2.0.0)
    * Swirls the pixels about the center of the image * @link https://php.net/manual/en/imagick.swirlimage.php * @param float $degrees * @return bool TRUE on success. * @throws ImagickException on error. */ public function swirlImage($degrees) {} /** * (PECL imagick 2.0.0)
    * Strips an image of all profiles and comments * @link https://php.net/manual/en/imagick.stripimage.php * @return bool TRUE on success. * @throws ImagickException on error. */ public function stripImage() {} /** * (PECL imagick 2.0.0)
    * Returns formats supported by Imagick * @link https://php.net/manual/en/imagick.queryformats.php * @param string $pattern [optional] * @return array an array containing the formats supported by Imagick. */ public static function queryFormats($pattern = "*") {} /** * (PECL imagick 2.0.0)
    * Returns the configured fonts * @link https://php.net/manual/en/imagick.queryfonts.php * @param string $pattern [optional]

    * The query pattern *

    * @return array an array containing the configured fonts. */ public static function queryFonts($pattern = "*") {} /** * (PECL imagick 2.0.0)
    * Returns an array representing the font metrics * @link https://php.net/manual/en/imagick.queryfontmetrics.php * @param ImagickDraw $properties

    * ImagickDraw object containing font properties *

    * @param string $text

    * The text *

    * @param bool $multiline [optional]

    * Multiline parameter. If left empty it is autodetected *

    * @return array a multi-dimensional array representing the font metrics. * @throws ImagickException on error. */ public function queryFontMetrics(ImagickDraw $properties, $text, $multiline = null) {} /** * (PECL imagick 2.0.0)
    * Hides a digital watermark within the image * @link https://php.net/manual/en/imagick.steganoimage.php * @param Imagick $watermark_wand * @param int $offset * @return Imagick TRUE on success. * @throws ImagickException on error. */ public function steganoImage(Imagick $watermark_wand, $offset) {} /** * (PECL imagick 2.0.0)
    * Adds random noise to the image * @link https://php.net/manual/en/imagick.addnoiseimage.php * @param int $noise_type

    * The type of the noise. Refer to this list of * noise constants. *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channel constants using bitwise operators. Defaults to Imagick::CHANNEL_DEFAULT. Refer to this list of channel constants *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function addNoiseImage($noise_type, $channel = Imagick::CHANNEL_DEFAULT) {} /** * (PECL imagick 2.0.0)
    * Simulates motion blur * @link https://php.net/manual/en/imagick.motionblurimage.php * @param float $radius

    * The radius of the Gaussian, in pixels, not counting the center pixel. *

    * @param float $sigma

    * The standard deviation of the Gaussian, in pixels. *

    * @param float $angle

    * Apply the effect along this angle. *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. * The channel argument affects only if Imagick is compiled against ImageMagick version * 6.4.4 or greater. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function motionBlurImage($radius, $sigma, $angle, $channel = Imagick::CHANNEL_DEFAULT) {} /** * (PECL imagick 2.0.0)
    * Forms a mosaic from images * @link https://php.net/manual/en/imagick.mosaicimages.php * @return Imagick TRUE on success. * @throws ImagickException on error. */ #[Deprecated] public function mosaicImages() {} /** * (PECL imagick 2.0.0)
    * Method morphs a set of images * @link https://php.net/manual/en/imagick.morphimages.php * @param int $number_frames

    * The number of in-between images to generate. *

    * @return Imagick This method returns a new Imagick object on success. * Throw an ImagickException on error. * @throws ImagickException on error * @throws ImagickException on error. */ public function morphImages($number_frames) {} /** * (PECL imagick 2.0.0)
    * Scales an image proportionally to half its size * @link https://php.net/manual/en/imagick.minifyimage.php * @return bool TRUE on success. * @throws ImagickException on error. */ public function minifyImage() {} /** * (PECL imagick 2.0.0)
    * Transforms an image * @link https://php.net/manual/en/imagick.affinetransformimage.php * @param ImagickDraw $matrix

    * The affine matrix *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function affineTransformImage(ImagickDraw $matrix) {} /** * (PECL imagick 2.0.0)
    * Average a set of images * @link https://php.net/manual/en/imagick.averageimages.php * @return Imagick a new Imagick object on success. * @throws ImagickException on error. */ #[Deprecated] public function averageImages() {} /** * (PECL imagick 2.0.0)
    * Surrounds the image with a border * @link https://php.net/manual/en/imagick.borderimage.php * @param mixed $bordercolor

    * ImagickPixel object or a string containing the border color *

    * @param int $width

    * Border width *

    * @param int $height

    * Border height *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function borderImage($bordercolor, $width, $height) {} /** * (PECL imagick 2.0.0)
    * Removes a region of an image and trims * @link https://php.net/manual/en/imagick.chopimage.php * @param int $width

    * Width of the chopped area *

    * @param int $height

    * Height of the chopped area *

    * @param int $x

    * X origo of the chopped area *

    * @param int $y

    * Y origo of the chopped area *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function chopImage($width, $height, $x, $y) {} /** * (PECL imagick 2.0.0)
    * Clips along the first path from the 8BIM profile * @link https://php.net/manual/en/imagick.clipimage.php * @return bool TRUE on success. * @throws ImagickException on error. */ public function clipImage() {} /** * (PECL imagick 2.0.0)
    * Clips along the named paths from the 8BIM profile * @link https://php.net/manual/en/imagick.clippathimage.php * @param string $pathname

    * The name of the path *

    * @param bool $inside

    * If TRUE later operations take effect inside clipping path. * Otherwise later operations take effect outside clipping path. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function clipPathImage($pathname, $inside) {} /** * Alias to {@see Imagick::clipPathImage} * @param string $pathname * @param string $inside * @throws ImagickException on error. */ public function clipImagePath($pathname, $inside) {} /** * (PECL imagick 2.0.0)
    * Composites a set of images * @link https://php.net/manual/en/imagick.coalesceimages.php * @return Imagick a new Imagick object on success. * @throws ImagickException on error. */ public function coalesceImages() {} /** * (PECL imagick 2.0.0)
    * Changes the color value of any pixel that matches target * @link https://php.net/manual/en/imagick.colorfloodfillimage.php * @param mixed $fill

    * ImagickPixel object containing the fill color *

    * @param float $fuzz

    * The amount of fuzz. For example, set fuzz to 10 and the color red at * intensities of 100 and 102 respectively are now interpreted as the * same color for the purposes of the floodfill. *

    * @param mixed $bordercolor

    * ImagickPixel object containing the border color *

    * @param int $x

    * X start position of the floodfill *

    * @param int $y

    * Y start position of the floodfill *

    * @return bool TRUE on success. * @throws ImagickException on error. */ #[Deprecated] public function colorFloodfillImage($fill, $fuzz, $bordercolor, $x, $y) {} /** * Blends the fill color with each pixel in the image. The 'opacity' color is a per channel strength factor for how strongly the color should be applied.
    * If legacy is true, the behaviour of this function is incorrect, but consistent with how it behaved before Imagick version 3.4.0 * @link https://php.net/manual/en/imagick.colorizeimage.php * @param mixed $colorize

    * ImagickPixel object or a string containing the colorize color *

    * @param mixed $opacity

    * ImagickPixel object or an float containing the opacity value. * 1.0 is fully opaque and 0.0 is fully transparent. *

    * @param bool $legacy [optional] Added since 3.4.0. Default value FALSE * @return bool TRUE on success. * @throws ImagickException Throws ImagickException on error * @since 2.0.0 */ public function colorizeImage($colorize, $opacity, $legacy = false) {} /** * (PECL imagick 2.0.0)
    * Returns the difference in one or more images * @link https://php.net/manual/en/imagick.compareimagechannels.php * @param Imagick $image

    * Imagick object containing the image to compare. *

    * @param int $channelType

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. *

    * @param int $metricType

    * One of the metric type constants. *

    * @return array Array consisting of new_wand and * distortion. * @throws ImagickException on error. */ public function compareImageChannels(Imagick $image, $channelType, $metricType) {} /** * (PECL imagick 2.0.0)
    * Compares an image to a reconstructed image * @link https://php.net/manual/en/imagick.compareimages.php * @param Imagick $compare

    * An image to compare to. *

    * @param int $metric

    * Provide a valid metric type constant. Refer to this * list of metric constants. *

    * @return array Array consisting of an Imagick object of the * reconstructed image and a float representing the difference. * @throws ImagickException Throws ImagickException on error. */ public function compareImages(Imagick $compare, $metric) {} /** * (PECL imagick 2.0.0)
    * Change the contrast of the image * @link https://php.net/manual/en/imagick.contrastimage.php * @param bool $sharpen

    * The sharpen value *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function contrastImage($sharpen) {} /** * (PECL imagick 2.0.0)
    * Combines one or more images into a single image * @link https://php.net/manual/en/imagick.combineimages.php * @param int $channelType

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. *

    * @return Imagick TRUE on success. * @throws ImagickException on error. */ public function combineImages($channelType) {} /** * (PECL imagick 2.0.0)
    * Applies a custom convolution kernel to the image * @link https://php.net/manual/en/imagick.convolveimage.php * @param array $kernel

    * The convolution kernel *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function convolveImage(array $kernel, $channel = Imagick::CHANNEL_ALL) {} /** * (PECL imagick 2.0.0)
    * Displaces an image's colormap * @link https://php.net/manual/en/imagick.cyclecolormapimage.php * @param int $displace

    * The amount to displace the colormap. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function cycleColormapImage($displace) {} /** * (PECL imagick 2.0.0)
    * Returns certain pixel differences between images * @link https://php.net/manual/en/imagick.deconstructimages.php * @return Imagick a new Imagick object on success. * @throws ImagickException on error. */ public function deconstructImages() {} /** * (PECL imagick 2.0.0)
    * Reduces the speckle noise in an image * @link https://php.net/manual/en/imagick.despeckleimage.php * @return bool TRUE on success. * @throws ImagickException on error. */ public function despeckleImage() {} /** * (PECL imagick 2.0.0)
    * Enhance edges within the image * @link https://php.net/manual/en/imagick.edgeimage.php * @param float $radius

    * The radius of the operation. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function edgeImage($radius) {} /** * (PECL imagick 2.0.0)
    * Returns a grayscale image with a three-dimensional effect * @link https://php.net/manual/en/imagick.embossimage.php * @param float $radius

    * The radius of the effect *

    * @param float $sigma

    * The sigma of the effect *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function embossImage($radius, $sigma) {} /** * (PECL imagick 2.0.0)
    * Improves the quality of a noisy image * @link https://php.net/manual/en/imagick.enhanceimage.php * @return bool TRUE on success. * @throws ImagickException on error. */ public function enhanceImage() {} /** * (PECL imagick 2.0.0)
    * Equalizes the image histogram * @link https://php.net/manual/en/imagick.equalizeimage.php * @return bool TRUE on success. * @throws ImagickException on error. */ public function equalizeImage() {} /** * (PECL imagick 2.0.0)
    * Applies an expression to an image * @link https://php.net/manual/en/imagick.evaluateimage.php * @param int $op

    * The evaluation operator *

    * @param float $constant

    * The value of the operator *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function evaluateImage($op, $constant, $channel = Imagick::CHANNEL_ALL) {} /** * Merges a sequence of images. This is useful for combining Photoshop layers into a single image. * This is replaced by: *
         * $im = $im->mergeImageLayers(\Imagick::LAYERMETHOD_FLATTEN)
         * 
    * @link https://php.net/manual/en/imagick.flattenimages.php * @return Imagick Returns an Imagick object containing the merged image. * @throws ImagickException Throws ImagickException on error. * @since 2.0.0 */ #[Deprecated] public function flattenImages() {} /** * (PECL imagick 2.0.0)
    * Creates a vertical mirror image * @link https://php.net/manual/en/imagick.flipimage.php * @return bool TRUE on success. * @throws ImagickException on error. */ public function flipImage() {} /** * (PECL imagick 2.0.0)
    * Creates a horizontal mirror image * @link https://php.net/manual/en/imagick.flopimage.php * @return bool TRUE on success. * @throws ImagickException on error. */ public function flopImage() {} /** * (PECL imagick 2.0.0)
    * Adds a simulated three-dimensional border * @link https://php.net/manual/en/imagick.frameimage.php * @param mixed $matte_color

    * ImagickPixel object or a string representing the matte color *

    * @param int $width

    * The width of the border *

    * @param int $height

    * The height of the border *

    * @param int $inner_bevel

    * The inner bevel width *

    * @param int $outer_bevel

    * The outer bevel width *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function frameImage($matte_color, $width, $height, $inner_bevel, $outer_bevel) {} /** * (PECL imagick 2.0.0)
    * Evaluate expression for each pixel in the image * @link https://php.net/manual/en/imagick.fximage.php * @param string $expression

    * The expression. *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. *

    * @return Imagick TRUE on success. * @throws ImagickException on error. */ public function fxImage($expression, $channel = Imagick::CHANNEL_ALL) {} /** * (PECL imagick 2.0.0)
    * Gamma-corrects an image * @link https://php.net/manual/en/imagick.gammaimage.php * @param float $gamma

    * The amount of gamma-correction. *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function gammaImage($gamma, $channel = Imagick::CHANNEL_ALL) {} /** * (PECL imagick 2.0.0)
    * Blurs an image * @link https://php.net/manual/en/imagick.gaussianblurimage.php * @param float $radius

    * The radius of the Gaussian, in pixels, not counting the center pixel. *

    * @param float $sigma

    * The standard deviation of the Gaussian, in pixels. *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function gaussianBlurImage($radius, $sigma, $channel = Imagick::CHANNEL_ALL) {} /** * @link https://www.php.net/manual/en/imagick.getimageattribute.php * @param string $key

    The key of the attribute to get.

    * @return string */ #[Deprecated] #[Pure] public function getImageAttribute($key) {} /** * (PECL imagick 2.0.0)
    * Returns the image background color * @link https://php.net/manual/en/imagick.getimagebackgroundcolor.php * @return ImagickPixel an ImagickPixel set to the background color of the image. * @throws ImagickException on error. */ #[Pure] public function getImageBackgroundColor() {} /** * (PECL imagick 2.0.0)
    * Returns the chromaticy blue primary point * @link https://php.net/manual/en/imagick.getimageblueprimary.php * @return float[] Array consisting of "x" and "y" coordinates of point. * @throws ImagickException on error. */ #[ArrayShape(["x" => "float", "y" => "float"])] #[Pure] public function getImageBluePrimary() {} /** * (PECL imagick 2.0.0)
    * Returns the image border color * @link https://php.net/manual/en/imagick.getimagebordercolor.php * @return ImagickPixel TRUE on success. * @throws ImagickException on error. */ #[Pure] public function getImageBorderColor() {} /** * (PECL imagick 2.0.0)
    * Gets the depth for a particular image channel * @link https://php.net/manual/en/imagick.getimagechanneldepth.php * @param int $channel

    * Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channel constants using bitwise operators. Defaults to Imagick::CHANNEL_DEFAULT. Refer to this list of channel constants *

    * @return int TRUE on success. * @throws ImagickException on error. */ #[Pure] public function getImageChannelDepth($channel) {} /** * (PECL imagick 2.0.0)
    * Compares image channels of an image to a reconstructed image * @link https://php.net/manual/en/imagick.getimagechanneldistortion.php * @param Imagick $reference

    * Imagick object to compare to. *

    * @param int $channel

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. *

    * @param int $metric

    * One of the metric type constants. *

    * @return float TRUE on success. * @throws ImagickException on error. */ #[Pure] public function getImageChannelDistortion(Imagick $reference, $channel, $metric) {} /** * (PECL imagick 2.0.0)
    * Gets the extrema for one or more image channels * @link https://php.net/manual/en/imagick.getimagechannelextrema.php * @param int $channel

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. *

    * @return int[] * @throws ImagickException on error. */ #[ArrayShape(["minima" => "int", "maxima" => "int"])] #[Deprecated] #[Pure] public function getImageChannelExtrema($channel) {} /** * (PECL imagick 2.0.0)
    * Gets the mean and standard deviation * @link https://php.net/manual/en/imagick.getimagechannelmean.php * @param int $channel

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. *

    * @return float[] * @throws ImagickException on error. */ #[ArrayShape(["mean" => "float", "standardDeviation" => "float"])] #[Pure] public function getImageChannelMean($channel) {} /** * (PECL imagick 2.0.0)
    * Returns statistics for each channel in the image * @link https://php.net/manual/en/imagick.getimagechannelstatistics.php * @return array * @throws ImagickException on error. */ #[Pure] public function getImageChannelStatistics() {} /** * (PECL imagick 2.0.0)
    * Returns the color of the specified colormap index * @link https://php.net/manual/en/imagick.getimagecolormapcolor.php * @param int $index

    * The offset into the image colormap. *

    * @return ImagickPixel TRUE on success. * @throws ImagickException on error. */ #[Pure] public function getImageColormapColor($index) {} /** * (PECL imagick 2.0.0)
    * Gets the image colorspace * @link https://php.net/manual/en/imagick.getimagecolorspace.php * @return int TRUE on success. * @throws ImagickException on error. */ #[Pure] public function getImageColorspace() {} /** * (PECL imagick 2.0.0)
    * Returns the composite operator associated with the image * @link https://php.net/manual/en/imagick.getimagecompose.php * @return int TRUE on success. * @throws ImagickException on error. */ #[Pure] public function getImageCompose() {} /** * (PECL imagick 2.0.0)
    * Gets the image delay * @link https://php.net/manual/en/imagick.getimagedelay.php * @return int the image delay. * @throws ImagickException on error. */ #[Pure] public function getImageDelay() {} /** * (PECL imagick 0.9.1-0.9.9)
    * Gets the image depth * @link https://php.net/manual/en/imagick.getimagedepth.php * @return int The image depth. * @throws ImagickException on error. */ #[Pure] public function getImageDepth() {} /** * (PECL imagick 2.0.0)
    * Compares an image to a reconstructed image * @link https://php.net/manual/en/imagick.getimagedistortion.php * @param Imagick $reference

    * Imagick object to compare to. *

    * @param int $metric

    * One of the metric type constants. *

    * @return float the distortion metric used on the image (or the best guess * thereof). * @throws ImagickException on error. */ #[Pure] public function getImageDistortion(Imagick $reference, $metric) {} /** * (PECL imagick 2.0.0)
    * Gets the extrema for the image * @link https://php.net/manual/en/imagick.getimageextrema.php * @return int[] an associative array with the keys "min" and "max". * @throws ImagickException on error. */ #[ArrayShape(["min" => "int", "max" => "int"])] #[Deprecated] #[Pure] public function getImageExtrema() {} /** * (PECL imagick 2.0.0)
    * Gets the image disposal method * @link https://php.net/manual/en/imagick.getimagedispose.php * @return int the dispose method on success. * @throws ImagickException on error. */ #[Pure] public function getImageDispose() {} /** * (PECL imagick 2.0.0)
    * Gets the image gamma * @link https://php.net/manual/en/imagick.getimagegamma.php * @return float the image gamma on success. * @throws ImagickException on error. */ #[Pure] public function getImageGamma() {} /** * (PECL imagick 2.0.0)
    * Returns the chromaticy green primary point * @link https://php.net/manual/en/imagick.getimagegreenprimary.php * @return float[] an array with the keys "x" and "y" on success, throws an ImagickException on failure. * @throws ImagickException on failure * @throws ImagickException on error. */ #[ArrayShape(["x" => "float", "y" => "float"])] #[Pure] public function getImageGreenPrimary() {} /** * (PECL imagick 2.0.0)
    * Returns the image height * @link https://php.net/manual/en/imagick.getimageheight.php * @return int the image height in pixels. * @throws ImagickException on error. */ #[Pure] public function getImageHeight() {} /** * (PECL imagick 2.0.0)
    * Gets the image histogram * @link https://php.net/manual/en/imagick.getimagehistogram.php * @return array the image histogram as an array of ImagickPixel objects. * @throws ImagickException on error. */ #[Pure] public function getImageHistogram() {} /** * (PECL imagick 2.0.0)
    * Gets the image interlace scheme * @link https://php.net/manual/en/imagick.getimageinterlacescheme.php * @return int the interlace scheme as an integer on success. * Trhow an ImagickException on error. * @throws ImagickException on error */ #[Deprecated] #[Pure] public function getImageInterlaceScheme() {} /** * (PECL imagick 2.0.0)
    * Gets the image iterations * @link https://php.net/manual/en/imagick.getimageiterations.php * @return int the image iterations as an integer. * @throws ImagickException on error. */ #[Pure] public function getImageIterations() {} /** * (PECL imagick 2.0.0)
    * Returns the image matte color * @link https://php.net/manual/en/imagick.getimagemattecolor.php * @return ImagickPixel ImagickPixel object on success. * @throws ImagickException on error. */ #[Pure] public function getImageMatteColor() {} /** * (PECL imagick 2.0.0)
    * Returns the page geometry * @link https://php.net/manual/en/imagick.getimagepage.php * @return int[] the page geometry associated with the image in an array with the * keys "width", "height", "x", and "y". * @throws ImagickException on error. */ #[ArrayShape(["width" => "int", "height" => "int", "x" => "int", "y" => "int"])] #[Pure] public function getImagePage() {} /** * (PECL imagick 2.0.0)
    * Returns the color of the specified pixel * @link https://php.net/manual/en/imagick.getimagepixelcolor.php * @param int $x

    * The x-coordinate of the pixel *

    * @param int $y

    * The y-coordinate of the pixel *

    * @return ImagickPixel an ImagickPixel instance for the color at the coordinates given. * @throws ImagickException on error. */ #[Pure] public function getImagePixelColor($x, $y) {} /** * (PECL imagick 2.0.0)
    * Returns the named image profile * @link https://php.net/manual/en/imagick.getimageprofile.php * @param string $name

    * The name of the profile to return. *

    * @return string a string containing the image profile. * @throws ImagickException on error. */ #[Pure] public function getImageProfile($name) {} /** * (PECL imagick 2.0.0)
    * Returns the chromaticity red primary point * @link https://php.net/manual/en/imagick.getimageredprimary.php * @return float[] the chromaticity red primary point as an array with the keys "x" * and "y". * Throw an ImagickException on error. * @throws ImagickException on error */ #[ArrayShape(["x" => "float", "y" => "float"])] #[Pure] public function getImageRedPrimary() {} /** * (PECL imagick 2.0.0)
    * Gets the image rendering intent * @link https://php.net/manual/en/imagick.getimagerenderingintent.php * @return int the image rendering intent. * @throws ImagickException on error. */ #[Pure] public function getImageRenderingIntent() {} /** * (PECL imagick 2.0.0)
    * Gets the image X and Y resolution * @link https://php.net/manual/en/imagick.getimageresolution.php * @return float[] the resolution as an array. * @throws ImagickException on error. */ #[ArrayShape(["x" => "float", "y" => "float"])] #[Pure] public function getImageResolution() {} /** * (PECL imagick 2.0.0)
    * Gets the image scene * @link https://php.net/manual/en/imagick.getimagescene.php * @return int the image scene. * @throws ImagickException on error. */ #[Pure] public function getImageScene() {} /** * (PECL imagick 2.0.0)
    * Generates an SHA-256 message digest * @link https://php.net/manual/en/imagick.getimagesignature.php * @return string a string containing the SHA-256 hash of the file. * @throws ImagickException on error. */ #[Pure] public function getImageSignature() {} /** * (PECL imagick 2.0.0)
    * Gets the image ticks-per-second * @link https://php.net/manual/en/imagick.getimagetickspersecond.php * @return int the image ticks-per-second. * @throws ImagickException on error. */ #[Pure] public function getImageTicksPerSecond() {} /** * (PECL imagick 0.9.10-0.9.9)
    * Gets the potential image type * @link https://php.net/manual/en/imagick.getimagetype.php * @return int the potential image type. * imagick::IMGTYPE_UNDEFINED * imagick::IMGTYPE_BILEVEL * imagick::IMGTYPE_GRAYSCALE * imagick::IMGTYPE_GRAYSCALEMATTE * imagick::IMGTYPE_PALETTE * imagick::IMGTYPE_PALETTEMATTE * imagick::IMGTYPE_TRUECOLOR * imagick::IMGTYPE_TRUECOLORMATTE * imagick::IMGTYPE_COLORSEPARATION * imagick::IMGTYPE_COLORSEPARATIONMATTE * imagick::IMGTYPE_OPTIMIZE * @throws ImagickException on error. */ #[Pure] public function getImageType() {} /** * (PECL imagick 2.0.0)
    * Gets the image units of resolution * @link https://php.net/manual/en/imagick.getimageunits.php * @return int the image units of resolution. * @throws ImagickException on error. */ #[Pure] public function getImageUnits() {} /** * (PECL imagick 2.0.0)
    * Returns the virtual pixel method * @link https://php.net/manual/en/imagick.getimagevirtualpixelmethod.php * @return int the virtual pixel method on success. * @throws ImagickException on error. */ #[Pure] public function getImageVirtualPixelMethod() {} /** * (PECL imagick 2.0.0)
    * Returns the chromaticity white point * @link https://php.net/manual/en/imagick.getimagewhitepoint.php * @return float[] the chromaticity white point as an associative array with the keys * "x" and "y". * @throws ImagickException on error. */ #[ArrayShape(["x" => "float", "y" => "float"])] #[Pure] public function getImageWhitePoint() {} /** * (PECL imagick 2.0.0)
    * Returns the image width * @link https://php.net/manual/en/imagick.getimagewidth.php * @return int the image width. * @throws ImagickException on error. */ #[Pure] public function getImageWidth() {} /** * (PECL imagick 2.0.0)
    * Returns the number of images in the object * @link https://php.net/manual/en/imagick.getnumberimages.php * @return int the number of images associated with Imagick object. */ #[Pure] public function getNumberImages() {} /** * (PECL imagick 2.0.0)
    * Gets the image total ink density * @link https://php.net/manual/en/imagick.getimagetotalinkdensity.php * @return float the image total ink density of the image. * Throw an ImagickException on error. * @throws ImagickException on error * @throws ImagickException on error. */ #[Pure] public function getImageTotalInkDensity() {} /** * (PECL imagick 2.0.0)
    * Extracts a region of the image * @link https://php.net/manual/en/imagick.getimageregion.php * @param int $width

    * The width of the extracted region. *

    * @param int $height

    * The height of the extracted region. *

    * @param int $x

    * X-coordinate of the top-left corner of the extracted region. *

    * @param int $y

    * Y-coordinate of the top-left corner of the extracted region. *

    * @return Imagick Extracts a region of the image and returns it as a new wand. * @throws ImagickException on error. */ #[Pure] public function getImageRegion($width, $height, $x, $y) {} /** * (PECL imagick 2.0.0)
    * Creates a new image as a copy * @link https://php.net/manual/en/imagick.implodeimage.php * @param float $radius

    * The radius of the implode *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function implodeImage($radius) {} /** * (PECL imagick 2.0.0)
    * Adjusts the levels of an image * @link https://php.net/manual/en/imagick.levelimage.php * @param float $blackPoint

    * The image black point *

    * @param float $gamma

    * The gamma value *

    * @param float $whitePoint

    * The image white point *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function levelImage($blackPoint, $gamma, $whitePoint, $channel = Imagick::CHANNEL_ALL) {} /** * (PECL imagick 2.0.0)
    * Scales an image proportionally 2x * @link https://php.net/manual/en/imagick.magnifyimage.php * @return bool TRUE on success. * @throws ImagickException on error. */ public function magnifyImage() {} /** * (PECL imagick 2.0.0)
    * Replaces the colors of an image with the closest color from a reference image. * @link https://php.net/manual/en/imagick.mapimage.php * @param Imagick $map * @param bool $dither * @return bool TRUE on success. * @throws ImagickException on error. */ #[Deprecated] public function mapImage(Imagick $map, $dither) {} /** * (PECL imagick 2.0.0)
    * Changes the transparency value of a color * @link https://php.net/manual/en/imagick.mattefloodfillimage.php * @param float $alpha

    * The level of transparency: 1.0 is fully opaque and 0.0 is fully * transparent. *

    * @param float $fuzz

    * The fuzz member of image defines how much tolerance is acceptable to * consider two colors as the same. *

    * @param mixed $bordercolor

    * An ImagickPixel object or string representing the border color. *

    * @param int $x

    * The starting x coordinate of the operation. *

    * @param int $y

    * The starting y coordinate of the operation. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ #[Deprecated] public function matteFloodfillImage($alpha, $fuzz, $bordercolor, $x, $y) {} /** * (PECL imagick 2.0.0)
    * Applies a digital filter * @link https://php.net/manual/en/imagick.medianfilterimage.php * @param float $radius

    * The radius of the pixel neighborhood. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ #[Deprecated] public function medianFilterImage($radius) {} /** * (PECL imagick 2.0.0)
    * Negates the colors in the reference image * @link https://php.net/manual/en/imagick.negateimage.php * @param bool $gray

    * Whether to only negate grayscale pixels within the image. *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function negateImage($gray, $channel = Imagick::CHANNEL_ALL) {} /** * (PECL imagick 2.0.0)
    * Change any pixel that matches color * @link https://php.net/manual/en/imagick.paintopaqueimage.php * @param mixed $target

    * Change this target color to the fill color within the image. An * ImagickPixel object or a string representing the target color. *

    * @param mixed $fill

    * An ImagickPixel object or a string representing the fill color. *

    * @param float $fuzz

    * The fuzz member of image defines how much tolerance is acceptable to * consider two colors as the same. *

    * @param int $channel [optional]

    * Provide any channel constant that is valid for your channel mode. To * apply to more than one channel, combine channeltype constants using * bitwise operators. Refer to this * list of channel constants. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ #[Deprecated] public function paintOpaqueImage($target, $fill, $fuzz, $channel = Imagick::CHANNEL_ALL) {} /** * (PECL imagick 2.0.0)
    * Changes any pixel that matches color with the color defined by fill * @link https://php.net/manual/en/imagick.painttransparentimage.php * @param mixed $target

    * Change this target color to specified opacity value within the image. *

    * @param float $alpha

    * The level of transparency: 1.0 is fully opaque and 0.0 is fully * transparent. *

    * @param float $fuzz

    * The fuzz member of image defines how much tolerance is acceptable to * consider two colors as the same. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ #[Deprecated] public function paintTransparentImage($target, $alpha, $fuzz) {} /** * (PECL imagick 2.0.0)
    * Quickly pin-point appropriate parameters for image processing * @link https://php.net/manual/en/imagick.previewimages.php * @param int $preview

    * Preview type. See Preview type constants *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function previewImages($preview) {} /** * (PECL imagick 2.0.0)
    * Adds or removes a profile from an image * @link https://php.net/manual/en/imagick.profileimage.php * @param string $name * @param string $profile * @return bool TRUE on success. * @throws ImagickException on error. */ public function profileImage($name, $profile) {} /** * (PECL imagick 2.0.0)
    * Analyzes the colors within a reference image * @link https://php.net/manual/en/imagick.quantizeimage.php * @param int $numberColors * @param int $colorspace * @param int $treedepth * @param bool $dither * @param bool $measureError * @return bool TRUE on success. * @throws ImagickException on error. */ public function quantizeImage($numberColors, $colorspace, $treedepth, $dither, $measureError) {} /** * (PECL imagick 2.0.0)
    * Analyzes the colors within a sequence of images * @link https://php.net/manual/en/imagick.quantizeimages.php * @param int $numberColors * @param int $colorspace * @param int $treedepth * @param bool $dither * @param bool $measureError * @return bool TRUE on success. * @throws ImagickException on error. */ public function quantizeImages($numberColors, $colorspace, $treedepth, $dither, $measureError) {} /** * (PECL imagick 2.0.0)
    * Smooths the contours of an image * @link https://php.net/manual/en/imagick.reducenoiseimage.php * @param float $radius * @return bool TRUE on success. * @throws ImagickException on error. */ #[Deprecated] public function reduceNoiseImage($radius) {} /** * (PECL imagick 2.0.0)
    * Removes the named image profile and returns it * @link https://php.net/manual/en/imagick.removeimageprofile.php * @param string $name * @return string a string containing the profile of the image. * @throws ImagickException on error. */ public function removeImageProfile($name) {} /** * (PECL imagick 2.0.0)
    * Separates a channel from the image * @link https://php.net/manual/en/imagick.separateimagechannel.php * @param int $channel * @return bool TRUE on success. * @throws ImagickException on error. */ public function separateImageChannel($channel) {} /** * (PECL imagick 2.0.0)
    * Sepia tones an image * @link https://php.net/manual/en/imagick.sepiatoneimage.php * @param float $threshold * @return bool TRUE on success. * @throws ImagickException on error. */ public function sepiaToneImage($threshold) {} /** * (PECL imagick 2.0.0)
    * Sets the image bias for any method that convolves an image * @link https://php.net/manual/en/imagick.setimagebias.php * @param float $bias * @return bool TRUE on success. */ public function setImageBias($bias) {} /** * (PECL imagick 2.0.0)
    * Sets the image chromaticity blue primary point * @link https://php.net/manual/en/imagick.setimageblueprimary.php * @param float $x * @param float $y * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageBluePrimary($x, $y) {} /** * (PECL imagick 2.0.0)
    * Sets the image border color * @link https://php.net/manual/en/imagick.setimagebordercolor.php * @param mixed $border

    * The border color *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageBorderColor($border) {} /** * (PECL imagick 2.0.0)
    * Sets the depth of a particular image channel * @link https://php.net/manual/en/imagick.setimagechanneldepth.php * @param int $channel * @param int $depth * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageChannelDepth($channel, $depth) {} /** * (PECL imagick 2.0.0)
    * Sets the color of the specified colormap index * @link https://php.net/manual/en/imagick.setimagecolormapcolor.php * @param int $index * @param ImagickPixel $color * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageColormapColor($index, ImagickPixel $color) {} /** * (PECL imagick 2.0.0)
    * Sets the image colorspace * @link https://php.net/manual/en/imagick.setimagecolorspace.php * @param int $colorspace

    * One of the COLORSPACE constants *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageColorspace($colorspace) {} /** * (PECL imagick 2.0.0)
    * Sets the image disposal method * @link https://php.net/manual/en/imagick.setimagedispose.php * @param int $dispose * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageDispose($dispose) {} /** * (PECL imagick 2.0.0)
    * Sets the image size * @link https://php.net/manual/en/imagick.setimageextent.php * @param int $columns * @param int $rows * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageExtent($columns, $rows) {} /** * (PECL imagick 2.0.0)
    * Sets the image chromaticity green primary point * @link https://php.net/manual/en/imagick.setimagegreenprimary.php * @param float $x * @param float $y * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageGreenPrimary($x, $y) {} /** * (PECL imagick 2.0.0)
    * Sets the image compression * @link https://php.net/manual/en/imagick.setimageinterlacescheme.php * @param int $interlace_scheme * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageInterlaceScheme($interlace_scheme) {} /** * (PECL imagick 2.0.0)
    * Adds a named profile to the Imagick object * @link https://php.net/manual/en/imagick.setimageprofile.php * @param string $name * @param string $profile * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageProfile($name, $profile) {} /** * (PECL imagick 2.0.0)
    * Sets the image chromaticity red primary point * @link https://php.net/manual/en/imagick.setimageredprimary.php * @param float $x * @param float $y * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageRedPrimary($x, $y) {} /** * (PECL imagick 2.0.0)
    * Sets the image rendering intent * @link https://php.net/manual/en/imagick.setimagerenderingintent.php * @param int $rendering_intent * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageRenderingIntent($rendering_intent) {} /** * (PECL imagick 2.0.0)
    * Sets the image virtual pixel method * @link https://php.net/manual/en/imagick.setimagevirtualpixelmethod.php * @param int $method * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageVirtualPixelMethod($method) {} /** * (PECL imagick 2.0.0)
    * Sets the image chromaticity white point * @link https://php.net/manual/en/imagick.setimagewhitepoint.php * @param float $x * @param float $y * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImageWhitePoint($x, $y) {} /** * (PECL imagick 2.0.0)
    * Adjusts the contrast of an image * @link https://php.net/manual/en/imagick.sigmoidalcontrastimage.php * @param bool $sharpen * @param float $alpha * @param float $beta * @param int $channel [optional] * @return bool TRUE on success. * @throws ImagickException on error. */ public function sigmoidalContrastImage($sharpen, $alpha, $beta, $channel = Imagick::CHANNEL_ALL) {} /** * (PECL imagick 2.0.0)
    * Composites two images * @link https://php.net/manual/en/imagick.stereoimage.php * @param Imagick $offset_wand * @return bool TRUE on success. * @throws ImagickException on error. */ public function stereoImage(Imagick $offset_wand) {} /** * (PECL imagick 2.0.0)
    * Repeatedly tiles the texture image * @link https://php.net/manual/en/imagick.textureimage.php * @param Imagick $texture_wand * @return Imagick a new Imagick object that has the repeated texture applied. * @throws ImagickException on error. */ public function textureImage(Imagick $texture_wand) {} /** * pplies a color vector to each pixel in the image. The 'opacity' color is a per channel strength factor for how strongly the color should be applied. * If legacy is true, the behaviour of this function is incorrect, but consistent with how it behaved before Imagick version 3.4.0 * @link https://php.net/manual/en/imagick.tintimage.php * @param mixed $tint * @param mixed $opacity * @param bool $legacy [optional] * @return bool TRUE on success. * @throws ImagickException Throws ImagickException on error * @since 2.0.0 */ public function tintImage($tint, $opacity, $legacy = false) {} /** * (PECL imagick 2.0.0)
    * Sharpens an image * @link https://php.net/manual/en/imagick.unsharpmaskimage.php * @param float $radius * @param float $sigma * @param float $amount * @param float $threshold * @param int $channel [optional] * @return bool TRUE on success. * @throws ImagickException on error. */ public function unsharpMaskImage($radius, $sigma, $amount, $threshold, $channel = Imagick::CHANNEL_ALL) {} /** * (PECL imagick 2.0.0)
    * Returns a new Imagick object * @link https://php.net/manual/en/imagick.getimage.php * @return Imagick a new Imagick object with the current image sequence. * @throws ImagickException on error. */ #[Pure] public function getImage() {} /** * (PECL imagick 2.0.0)
    * Adds new image to Imagick object image list * @link https://php.net/manual/en/imagick.addimage.php * @param Imagick $source

    * The source Imagick object *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function addImage(Imagick $source) {} /** * (PECL imagick 2.0.0)
    * Replaces image in the object * @link https://php.net/manual/en/imagick.setimage.php * @param Imagick $replace

    * The replace Imagick object *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setImage(Imagick $replace) {} /** * (PECL imagick 2.0.0)
    * Creates a new image * @link https://php.net/manual/en/imagick.newimage.php * @param int $cols

    * Columns in the new image *

    * @param int $rows

    * Rows in the new image *

    * @param mixed $background

    * The background color used for this image *

    * @param string $format [optional]

    * Image format. This parameter was added in Imagick version 2.0.1. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function newImage($cols, $rows, $background, $format = null) {} /** * (PECL imagick 2.0.0)
    * Creates a new image * @link https://php.net/manual/en/imagick.newpseudoimage.php * @param int $columns

    * columns in the new image *

    * @param int $rows

    * rows in the new image *

    * @param string $pseudoString

    * string containing pseudo image definition. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function newPseudoImage($columns, $rows, $pseudoString) {} /** * (PECL imagick 2.0.0)
    * Gets the object compression type * @link https://php.net/manual/en/imagick.getcompression.php * @return int the compression constant */ #[Pure] public function getCompression() {} /** * (PECL imagick 2.0.0)
    * Gets the object compression quality * @link https://php.net/manual/en/imagick.getcompressionquality.php * @return int integer describing the compression quality */ #[Pure] public function getCompressionQuality() {} /** * (PECL imagick 2.0.0)
    * Returns the ImageMagick API copyright as a string * @link https://php.net/manual/en/imagick.getcopyright.php * @return string a string containing the copyright notice of Imagemagick and * Magickwand C API. */ public static function getCopyright() {} /** * (PECL imagick 2.0.0)
    * The filename associated with an image sequence * @link https://php.net/manual/en/imagick.getfilename.php * @return string a string on success. */ #[Pure] public function getFilename() {} /** * (PECL imagick 2.0.0)
    * Returns the format of the Imagick object * @link https://php.net/manual/en/imagick.getformat.php * @return string the format of the image. */ #[Pure] public function getFormat() {} /** * (PECL imagick 2.0.0)
    * Returns the ImageMagick home URL * @link https://php.net/manual/en/imagick.gethomeurl.php * @return string a link to the imagemagick homepage. */ public static function getHomeURL() {} /** * (PECL imagick 2.0.0)
    * Gets the object interlace scheme * @link https://php.net/manual/en/imagick.getinterlacescheme.php * @return int Gets the wand interlace * scheme. */ #[Pure] public function getInterlaceScheme() {} /** * (PECL imagick 2.0.0)
    * Returns a value associated with the specified key * @link https://php.net/manual/en/imagick.getoption.php * @param string $key

    * The name of the option *

    * @return string a value associated with a wand and the specified key. */ #[Pure] public function getOption($key) {} /** * (PECL imagick 2.0.0)
    * Returns the ImageMagick package name * @link https://php.net/manual/en/imagick.getpackagename.php * @return string the ImageMagick package name as a string. */ public static function getPackageName() {} /** * (PECL imagick 2.0.0)
    * Returns the page geometry * @link https://php.net/manual/en/imagick.getpage.php * @return int[] the page geometry associated with the Imagick object in * an associative array with the keys "width", "height", "x", and "y", * throwing ImagickException on error. * @throws ImagickException on error */ //width:int, height:int, x:int, y:int #[ArrayShape(["width" => "int", "height" => "int", "x" => "int", "y" => "int"])] #[Pure] public function getPage() {} /** * (PECL imagick 2.0.0)
    * Gets the quantum depth * @link https://php.net/manual/en/imagick.getquantumdepth.php * @return array the Imagick quantum depth as a string. */ // quantumDepthLong:int, quantumDepthString:string #[ArrayShape(["quantumDepthLong" => "int", "quantumDepthString" => "string"])] public static function getQuantumDepth() {} /** * (PECL imagick 2.0.0)
    * Returns the Imagick quantum range * @link https://php.net/manual/en/imagick.getquantumrange.php * @return array the Imagick quantum range as a string. */ #[ArrayShape(["quantumRangeLong" => "int", "quantumRangeString" => "string"])] public static function getQuantumRange() {} /** * (PECL imagick 2.0.0)
    * Returns the ImageMagick release date * @link https://php.net/manual/en/imagick.getreleasedate.php * @return string the ImageMagick release date as a string. */ public static function getReleaseDate() {} /** * (PECL imagick 2.0.0)
    * Returns the specified resource's memory usage * @link https://php.net/manual/en/imagick.getresource.php * @param int $type

    * Refer to the list of resourcetype constants. *

    * @return int the specified resource's memory usage in megabytes. */ public static function getResource($type) {} /** * (PECL imagick 2.0.0)
    * Returns the specified resource limit * @link https://php.net/manual/en/imagick.getresourcelimit.php * @param int $type

    * Refer to the list of resourcetype constants. *

    * @return int the specified resource limit in megabytes. */ public static function getResourceLimit($type) {} /** * (PECL imagick 2.0.0)
    * Gets the horizontal and vertical sampling factor * @link https://php.net/manual/en/imagick.getsamplingfactors.php * @return array an associative array with the horizontal and vertical sampling * factors of the image. */ #[Pure] public function getSamplingFactors() {} /** * (PECL imagick 2.0.0)
    * Returns the size associated with the Imagick object * @link https://php.net/manual/en/imagick.getsize.php * @return int[] the size associated with the Imagick object as an array with the * keys "columns" and "rows". * @throws ImagickException on error. */ #[ArrayShape(["columns" => "int", "rows" => "int"])] #[Pure] public function getSize() {} /** * (PECL imagick 2.0.0)
    * Returns the ImageMagick API version * @link https://php.net/manual/en/imagick.getversion.php * @return array the ImageMagick API version as a string and as a number. */ #[ArrayShape(["versionNumber" => "int", "versionString" => "string"])] public static function getVersion() {} /** * (PECL imagick 2.0.0)
    * Sets the object's default background color * @link https://php.net/manual/en/imagick.setbackgroundcolor.php * @param mixed $background * @return bool TRUE on success. * @throws ImagickException on error. */ public function setBackgroundColor($background) {} /** * (PECL imagick 2.0.0)
    * Sets the object's default compression type * @link https://php.net/manual/en/imagick.setcompression.php * @param int $compression * @return bool TRUE on success. * @throws ImagickException on error. */ public function setCompression($compression) {} /** * (PECL imagick 0.9.10-0.9.9)
    * Sets the object's default compression quality * @link https://php.net/manual/en/imagick.setcompressionquality.php * @param int $quality * @return bool TRUE on success. * @throws ImagickException on error. */ public function setCompressionQuality($quality) {} /** * (PECL imagick 2.0.0)
    * Sets the filename before you read or write the image * @link https://php.net/manual/en/imagick.setfilename.php * @param string $filename * @return bool TRUE on success. * @throws ImagickException on error. */ public function setFilename($filename) {} /** * (PECL imagick 2.0.0)
    * Sets the format of the Imagick object * @link https://php.net/manual/en/imagick.setformat.php * @param string $format * @return bool TRUE on success. * @throws ImagickException on error. */ public function setFormat($format) {} /** * (PECL imagick 2.0.0)
    * Sets the image compression * @link https://php.net/manual/en/imagick.setinterlacescheme.php * @param int $interlace_scheme * @return bool TRUE on success. * @throws ImagickException on error. */ public function setInterlaceScheme($interlace_scheme) {} /** * (PECL imagick 2.0.0)
    * Set an option * @link https://php.net/manual/en/imagick.setoption.php * @param string $key * @param string $value * @return bool TRUE on success. * @throws ImagickException on error. */ public function setOption($key, $value) {} /** * (PECL imagick 2.0.0)
    * Sets the page geometry of the Imagick object * @link https://php.net/manual/en/imagick.setpage.php * @param int $width * @param int $height * @param int $x * @param int $y * @return bool TRUE on success. * @throws ImagickException on error. */ public function setPage($width, $height, $x, $y) {} /** * (PECL imagick 2.0.0)
    * Sets the limit for a particular resource in megabytes * @link https://php.net/manual/en/imagick.setresourcelimit.php * @param int $type

    * Refer to the list of resourcetype constants. *

    * @param int $limit

    * The resource limit. The unit depends on the type of the resource being limited. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public static function setResourceLimit($type, $limit) {} /** * (PECL imagick 2.0.0)
    * Sets the image resolution * @link https://php.net/manual/en/imagick.setresolution.php * @param float $x_resolution

    * The horizontal resolution. *

    * @param float $y_resolution

    * The vertical resolution. *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function setResolution($x_resolution, $y_resolution) {} /** * (PECL imagick 2.0.0)
    * Sets the image sampling factors * @link https://php.net/manual/en/imagick.setsamplingfactors.php * @param array $factors * @return bool TRUE on success. * @throws ImagickException on error. */ public function setSamplingFactors(array $factors) {} /** * (PECL imagick 2.0.0)
    * Sets the size of the Imagick object * @link https://php.net/manual/en/imagick.setsize.php * @param int $columns * @param int $rows * @return bool TRUE on success. * @throws ImagickException on error. */ public function setSize($columns, $rows) {} /** * (PECL imagick 2.0.0)
    * Sets the image type attribute * @link https://php.net/manual/en/imagick.settype.php * @param int $image_type * @return bool TRUE on success. * @throws ImagickException on error. */ public function setType($image_type) {} public function key() {} public function next() {} public function rewind() {} /** * (PECL imagick 2.0.0)
    * Checks if the current item is valid * @link https://php.net/manual/en/imagick.valid.php * @return bool TRUE on success. * @throws ImagickException on error. */ public function valid() {} /** * (PECL imagick 2.0.0)
    * Returns a reference to the current Imagick object * @link https://php.net/manual/en/imagick.current.php * @return Imagick self on success. */ public function current() {} /** * Change the brightness and/or contrast of an image. It converts the brightness and contrast parameters into slope and intercept and calls a polynomical function to apply to the image. * @link https://php.net/manual/en/imagick.brightnesscontrastimage.php * @param float $brightness * @param float $contrast * @param int $CHANNEL [optional] * @return void * @throws ImagickException on error. * @since 3.3.0 */ public function brightnessContrastImage($brightness, $contrast, $CHANNEL = Imagick::CHANNEL_DEFAULT) {} /** * Applies a user supplied kernel to the image according to the given morphology method. * @link https://php.net/manual/en/imagick.morphology.php * @param int $morphologyMethod Which morphology method to use one of the \Imagick::MORPHOLOGY_* constants. * @param int $iterations The number of iteration to apply the morphology function. A value of -1 means loop until no change found. How this is applied may depend on the morphology method. Typically this is a value of 1. * @param ImagickKernel $ImagickKernel * @param int $CHANNEL [optional] * @return void * @throws ImagickException on error. * @throws ImagickKernelException on error. * @since 3.3.0 */ public function morphology($morphologyMethod, $iterations, ImagickKernel $ImagickKernel, $CHANNEL = Imagick::CHANNEL_DEFAULT) {} /** * Applies a custom convolution kernel to the image. * @link https://php.net/manual/en/imagick.filter.php * @param ImagickKernel $ImagickKernel An instance of ImagickKernel that represents either a single kernel or a linked series of kernels. * @param int $CHANNEL [optional] Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channel constants using bitwise operators. Defaults to Imagick::CHANNEL_DEFAULT. Refer to this list of channel constants * @return void * @throws ImagickException on error. * @since 3.3.0 */ public function filter(ImagickKernel $ImagickKernel, $CHANNEL = Imagick::CHANNEL_DEFAULT) {} /** * Apply color transformation to an image. The method permits saturation changes, hue rotation, luminance to alpha, and various other effects. Although variable-sized transformation matrices can be used, typically one uses a 5x5 matrix for an RGBA image and a 6x6 for CMYKA (or RGBA with offsets). * The matrix is similar to those used by Adobe Flash except offsets are in column 6 rather than 5 (in support of CMYKA images) and offsets are normalized (divide Flash offset by 255) * @link https://php.net/manual/en/imagick.colormatriximage.php * @param array $color_matrix * @return void * @throws ImagickException on error. * @since 3.3.0 */ public function colorMatrixImage($color_matrix = Imagick::CHANNEL_DEFAULT) {} /** * Deletes an image property. * @link https://php.net/manual/en/imagick.deleteimageproperty.php * @param string $name The name of the property to delete. * @return void * @throws ImagickException on error. * @since 3.3.0 */ public function deleteImageProperty($name) {} /** * Implements the discrete Fourier transform (DFT) of the image either as a magnitude / phase or real / imaginary image pair. * @link https://php.net/manual/en/imagick.forwardfouriertransformimage.php * @param bool $magnitude If true, return as magnitude / phase pair otherwise a real / imaginary image pair. * @return void * @throws ImagickException on error. * @since 3.3.0 */ public function forwardFourierTransformimage($magnitude) {} /** * Gets the current image's compression type. * @link https://php.net/manual/en/imagick.getimagecompression.php * @return int * @since 3.3.0 */ #[Pure] public function getImageCompression() {} /** * Get the StringRegistry entry for the named key or false if not set. * @link https://php.net/manual/en/imagick.getregistry.php * @param string $key * @return string|false * @throws ImagickException Since version >= 3.4.3. Throws an exception if the key does not exist, rather than terminating the program. * @since 3.3.0 */ public static function getRegistry($key) {} /** * Returns the ImageMagick quantum range as an integer. * @link https://php.net/manual/en/imagick.getquantum.php * @return int * @since 3.3.0 */ public static function getQuantum() {} /** * Replaces any embedded formatting characters with the appropriate image property and returns the interpreted text. See https://www.imagemagick.org/script/escape.php for escape sequences. * @link https://php.net/manual/en/imagick.identifyformat.php * @see https://www.imagemagick.org/script/escape.php * @param string $embedText A string containing formatting sequences e.g. "Trim box: %@ number of unique colors: %k". * @return bool * @throws ImagickException on error. * @since 3.3.0 */ public function identifyFormat($embedText) {} /** * Implements the inverse discrete Fourier transform (DFT) of the image either as a magnitude / phase or real / imaginary image pair. * @link https://php.net/manual/en/imagick.inversefouriertransformimage.php * @param Imagick $complement The second image to combine with this one to form either the magnitude / phase or real / imaginary image pair. * @param bool $magnitude If true, combine as magnitude / phase pair otherwise a real / imaginary image pair. * @return void * @throws ImagickException on error. * @since 3.3.0 */ public function inverseFourierTransformImage($complement, $magnitude) {} /** * List all the registry settings. Returns an array of all the key/value pairs in the registry * @link https://php.net/manual/en/imagick.listregistry.php * @return array An array containing the key/values from the registry. * @since 3.3.0 */ public static function listRegistry() {} /** * Rotational blurs an image. * @link https://php.net/manual/en/imagick.rotationalblurimage.php * @param float $angle * @param int $CHANNEL * @return void * @throws ImagickException on error. * @since 3.3.0 */ public function rotationalBlurImage($angle, $CHANNEL = Imagick::CHANNEL_DEFAULT) {} /** * Selectively blur an image within a contrast threshold. It is similar to the unsharpen mask that sharpens everything with contrast above a certain threshold. * @link https://php.net/manual/en/imagick.selectiveblurimage.php * @param float $radius * @param float $sigma * @param float $threshold * @param int $CHANNEL Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channel constants using bitwise operators. Defaults to Imagick::CHANNEL_DEFAULT. Refer to this list of channel constants * @return void * @throws ImagickException on error. * @since 3.3.0 */ public function selectiveBlurImage($radius, $sigma, $threshold, $CHANNEL = Imagick::CHANNEL_DEFAULT) {} /** * Set whether antialiasing should be used for operations. On by default. * @param bool $antialias * @return int * @throws ImagickException on error. * @since 3.3.0 */ public function setAntiAlias($antialias) {} /** * @link https://php.net/manual/en/imagick.setimagebiasquantum.php * @param string $bias * @return void * @since 3.3.0 */ public function setImageBiasQuantum($bias) {} /** * Set a callback that will be called during the processing of the Imagick image. * @link https://php.net/manual/en/imagick.setprogressmonitor.php * @param callable $callback The progress function to call. It should return true if image processing should continue, or false if it should be cancelled. * The offset parameter indicates the progress and the span parameter indicates the total amount of work needed to be done. *
     bool callback ( mixed $offset , mixed $span ) 
    * Caution * The values passed to the callback function are not consistent. In particular the span parameter can increase during image processing. Because of this calculating the percentage complete of an image operation is not trivial. * @return void * @throws ImagickException on error. * @since 3.3.0 */ public function setProgressMonitor($callback) {} /** * Sets the ImageMagick registry entry named key to value. This is most useful for setting "temporary-path" which controls where ImageMagick creates temporary images e.g. while processing PDFs. * @link https://php.net/manual/en/imagick.setregistry.php * @param string $key * @param string $value * @return void * @since 3.3.0 */ public static function setRegistry($key, $value) {} /** * Replace each pixel with corresponding statistic from the neighborhood of the specified width and height. * @link https://php.net/manual/en/imagick.statisticimage.php * @param int $type * @param int $width * @param int $height * @param int $channel [optional] * @return void * @throws ImagickException on error. * @since 3.3.0 */ public function statisticImage($type, $width, $height, $channel = Imagick::CHANNEL_DEFAULT) {} /** * Searches for a subimage in the current image and returns a similarity image such that an exact match location is * completely white and if none of the pixels match, black, otherwise some gray level in-between. * You can also pass in the optional parameters bestMatch and similarity. After calling the function similarity will * be set to the 'score' of the similarity between the subimage and the matching position in the larger image, * bestMatch will contain an associative array with elements x, y, width, height that describe the matching region. * * @link https://php.net/manual/en/imagick.subimagematch.php * @param Imagick $imagick * @param array &$bestMatch [optional] * @param float &$similarity [optional] A new image that displays the amount of similarity at each pixel. * @param float $similarity_threshold [optional] Only used if compiled with ImageMagick (library) > 7 * @param int $metric [optional] Only used if compiled with ImageMagick (library) > 7 * @return Imagick * @throws ImagickException on error. * @since 3.3.0 */ public function subImageMatch(Imagick $imagick, array &$bestMatch, &$similarity, $similarity_threshold, $metric) {} /** * Is an alias of Imagick::subImageMatch * * @param Imagick $imagick * @param array &$bestMatch [optional] * @param float &$similarity [optional] A new image that displays the amount of similarity at each pixel. * @param float $similarity_threshold [optional] * @param int $metric [optional] * @return Imagick * @throws ImagickException on error. * @see Imagick::subImageMatch() This function is an alias of subImageMatch() * @since 3.4.0 */ public function similarityImage(Imagick $imagick, array &$bestMatch, &$similarity, $similarity_threshold, $metric) {} /** * Returns any ImageMagick configure options that match the specified pattern (e.g. "*" for all). Options include NAME, VERSION, LIB_VERSION, etc. * @return array * @since 3.4.0 */ #[Pure] public static function getConfigureOptions() {} /** * GetFeatures() returns the ImageMagick features that have been compiled into the runtime. * @return string * @since 3.4.0 */ #[Pure] public function getFeatures() {} /** * @return int * @since 3.4.0 */ #[Pure] public function getHDRIEnabled() {} /** * Sets the image channel mask. Returns the previous set channel mask. * Only works with Imagick >= 7 * @param int $channel * @throws ImagickException on error. * @since 3.4.0 */ public function setImageChannelMask($channel) {} /** * Merge multiple images of the same size together with the selected operator. https://www.imagemagick.org/Usage/layers/#evaluate-sequence * @param int $EVALUATE_CONSTANT * @return bool * @see https://www.imagemagick.org/Usage/layers/#evaluate-sequence * @throws ImagickException on error. * @since 3.4.0 */ public function evaluateImages($EVALUATE_CONSTANT) {} /** * Extracts the 'mean' from the image and adjust the image to try make set its gamma appropriately. * @param int $channel [optional] Default value Imagick::CHANNEL_ALL * @return bool * @throws ImagickException on error. * @since 3.4.1 */ public function autoGammaImage($channel = Imagick::CHANNEL_ALL) {} /** * Adjusts an image so that its orientation is suitable $ for viewing (i.e. top-left orientation). * @return bool * @throws ImagickException on error. * @since 3.4.1 */ public function autoOrient() {} /** * Composite one image onto another using the specified gravity. * * @param Imagick $imagick * @param int $COMPOSITE_CONSTANT * @param int $GRAVITY_CONSTANT * @return bool * @throws ImagickException on error. * @since 3.4.1 */ public function compositeImageGravity(Imagick $imagick, $COMPOSITE_CONSTANT, $GRAVITY_CONSTANT) {} /** * Attempts to increase the appearance of large-scale light-dark transitions. * * @param float $radius * @param float $strength * @return bool * @throws ImagickException on error. * @since 3.4.1 */ public function localContrastImage($radius, $strength) {} /** * Identifies the potential image type, returns one of the Imagick::IMGTYPE_* constants * @return int * @throws ImagickException on error. * @since 3.4.3 */ public function identifyImageType() {} /** * Sets the image to the specified alpha level. Will replace ImagickDraw::setOpacity() * * @param float $alpha * @return bool * @throws ImagickException on error. * @since 3.4.3 */ public function setImageAlpha($alpha) {} } /** * @method ImagickDraw clone() (PECL imagick 2.0.0)
    Makes an exact copy of the specified ImagickDraw object * @link https://php.net/manual/en/class.imagickdraw.php */ class ImagickDraw { public function resetVectorGraphics() {} #[Pure] public function getTextKerning() {} /** * @param float $kerning */ public function setTextKerning($kerning) {} #[Pure] public function getTextInterWordSpacing() {} /** * @param $spacing */ public function setTextInterWordSpacing($spacing) {} #[Pure] public function getTextInterLineSpacing() {} /** * @param $spacing */ public function setTextInterLineSpacing($spacing) {} /** * (PECL imagick 2.0.0)
    * The ImagickDraw constructor * @link https://php.net/manual/en/imagickdraw.construct.php */ public function __construct() {} /** * (PECL imagick 2.0.0)
    * Sets the fill color to be used for drawing filled objects * @link https://php.net/manual/en/imagickdraw.setfillcolor.php * @param ImagickPixel $fill_pixel

    * ImagickPixel to use to set the color *

    * @return bool No value is returned. * @throws ImagickDrawException on error. */ public function setFillColor(ImagickPixel $fill_pixel) {} /** * (PECL imagick 2.0.0)
    * Sets the opacity to use when drawing using the fill color or fill texture * @link https://php.net/manual/en/imagickdraw.setfillalpha.php * @param float $opacity

    * fill alpha *

    * @return bool No value is returned. */ #[Deprecated] public function setFillAlpha($opacity) {} /** * Sets the image resolution * @param float $x_resolution

    The horizontal resolution.

    * @param float $y_resolution

    The vertical resolution.

    * @return bool * @throws ImagickDrawException on error. */ public function setResolution($x_resolution, $y_resolution) {} /** * (PECL imagick 2.0.0)
    * Sets the color used for stroking object outlines * @link https://php.net/manual/en/imagickdraw.setstrokecolor.php * @param ImagickPixel $stroke_pixel

    * the stroke color *

    * @return bool No value is returned. * @throws ImagickDrawException on error. */ public function setStrokeColor(ImagickPixel $stroke_pixel) {} /** * (PECL imagick 2.0.0)
    * Specifies the opacity of stroked object outlines * @link https://php.net/manual/en/imagickdraw.setstrokealpha.php * @param float $opacity

    * opacity *

    * @return bool No value is returned. */ #[Deprecated] public function setStrokeAlpha($opacity) {} /** * (PECL imagick 2.0.0)
    * Sets the width of the stroke used to draw object outlines * @link https://php.net/manual/en/imagickdraw.setstrokewidth.php * @param float $stroke_width

    * stroke width *

    * @return bool No value is returned. */ public function setStrokeWidth($stroke_width) {} /** * (PECL imagick 2.0.0)
    * Clears the ImagickDraw * @link https://php.net/manual/en/imagickdraw.clear.php * @return bool an ImagickDraw object. */ public function clear() {} /** * (PECL imagick 2.0.0)
    * Draws a circle * @link https://php.net/manual/en/imagickdraw.circle.php * @param float $ox

    * origin x coordinate *

    * @param float $oy

    * origin y coordinate *

    * @param float $px

    * perimeter x coordinate *

    * @param float $py

    * perimeter y coordinate *

    * @return bool No value is returned. */ public function circle($ox, $oy, $px, $py) {} /** * (PECL imagick 2.0.0)
    * Draws text on the image * @link https://php.net/manual/en/imagickdraw.annotation.php * @param float $x

    * The x coordinate where text is drawn *

    * @param float $y

    * The y coordinate where text is drawn *

    * @param string $text

    * The text to draw on the image *

    * @return bool No value is returned. * @throws ImagickDrawException on error. */ public function annotation($x, $y, $text) {} /** * (PECL imagick 2.0.0)
    * Controls whether text is antialiased * @link https://php.net/manual/en/imagickdraw.settextantialias.php * @param bool $antiAlias * @return bool No value is returned. */ public function setTextAntialias($antiAlias) {} /** * (PECL imagick 2.0.0)
    * Specifies specifies the text code set * @link https://php.net/manual/en/imagickdraw.settextencoding.php * @param string $encoding

    * the encoding name *

    * @return bool No value is returned. */ public function setTextEncoding($encoding) {} /** * (PECL imagick 2.0.0)
    * Sets the fully-specified font to use when annotating with text * @link https://php.net/manual/en/imagickdraw.setfont.php * @param string $font_name * @return bool TRUE on success. * @throws ImagickDrawException on error. * @throws ImagickException on error. */ public function setFont($font_name) {} /** * (PECL imagick 2.0.0)
    * Sets the font family to use when annotating with text * @link https://php.net/manual/en/imagickdraw.setfontfamily.php * @param string $font_family

    * the font family *

    * @return bool TRUE on success. * @throws ImagickDrawException on error. * @throws ImagickException on error. */ public function setFontFamily($font_family) {} /** * (PECL imagick 2.0.0)
    * Sets the font pointsize to use when annotating with text * @link https://php.net/manual/en/imagickdraw.setfontsize.php * @param float $pointsize

    * the point size *

    * @return bool No value is returned. */ public function setFontSize($pointsize) {} /** * (PECL imagick 2.0.0)
    * Sets the font style to use when annotating with text * @link https://php.net/manual/en/imagickdraw.setfontstyle.php * @param int $style

    * STYLETYPE_ constant *

    * @return bool No value is returned. */ public function setFontStyle($style) {} /** * (PECL imagick 2.0.0)
    * Sets the font weight * @link https://php.net/manual/en/imagickdraw.setfontweight.php * @param int $font_weight * @return bool * @throws ImagickDrawException on error. */ public function setFontWeight($font_weight) {} /** * (PECL imagick 2.0.0)
    * Returns the font * @link https://php.net/manual/en/imagickdraw.getfont.php * @return string|false a string on success and false if no font is set. */ #[Pure] public function getFont() {} /** * (PECL imagick 2.0.0)
    * Returns the font family * @link https://php.net/manual/en/imagickdraw.getfontfamily.php * @return string|false the font family currently selected or false if font family is not set. */ #[Pure] public function getFontFamily() {} /** * (PECL imagick 2.0.0)
    * Returns the font pointsize * @link https://php.net/manual/en/imagickdraw.getfontsize.php * @return float the font size associated with the current ImagickDraw object. */ #[Pure] public function getFontSize() {} /** * (PECL imagick 2.0.0)
    * Returns the font style * @link https://php.net/manual/en/imagickdraw.getfontstyle.php * @return int the font style constant (STYLE_) associated with the ImagickDraw object * or 0 if no style is set. */ #[Pure] public function getFontStyle() {} /** * (PECL imagick 2.0.0)
    * Returns the font weight * @link https://php.net/manual/en/imagickdraw.getfontweight.php * @return int an int on success and 0 if no weight is set. */ #[Pure] public function getFontWeight() {} /** * (PECL imagick 2.0.0)
    * Frees all associated resources * @link https://php.net/manual/en/imagickdraw.destroy.php * @return bool No value is returned. */ public function destroy() {} /** * (PECL imagick 2.0.0)
    * Draws a rectangle * @link https://php.net/manual/en/imagickdraw.rectangle.php * @param float $x1

    * x coordinate of the top left corner *

    * @param float $y1

    * y coordinate of the top left corner *

    * @param float $x2

    * x coordinate of the bottom right corner *

    * @param float $y2

    * y coordinate of the bottom right corner *

    * @return bool No value is returned. */ public function rectangle($x1, $y1, $x2, $y2) {} /** * (PECL imagick 2.0.0)
    * Draws a rounded rectangle * @link https://php.net/manual/en/imagickdraw.roundrectangle.php * @param float $x1

    * x coordinate of the top left corner *

    * @param float $y1

    * y coordinate of the top left corner *

    * @param float $x2

    * x coordinate of the bottom right *

    * @param float $y2

    * y coordinate of the bottom right *

    * @param float $rx

    * x rounding *

    * @param float $ry

    * y rounding *

    * @return bool No value is returned. */ public function roundRectangle($x1, $y1, $x2, $y2, $rx, $ry) {} /** * (PECL imagick 2.0.0)
    * Draws an ellipse on the image * @link https://php.net/manual/en/imagickdraw.ellipse.php * @param float $ox * @param float $oy * @param float $rx * @param float $ry * @param float $start * @param float $end * @return bool No value is returned. */ public function ellipse($ox, $oy, $rx, $ry, $start, $end) {} /** * (PECL imagick 2.0.0)
    * Skews the current coordinate system in the horizontal direction * @link https://php.net/manual/en/imagickdraw.skewx.php * @param float $degrees

    * degrees to skew *

    * @return bool No value is returned. */ public function skewX($degrees) {} /** * (PECL imagick 2.0.0)
    * Skews the current coordinate system in the vertical direction * @link https://php.net/manual/en/imagickdraw.skewy.php * @param float $degrees

    * degrees to skew *

    * @return bool No value is returned. */ public function skewY($degrees) {} /** * (PECL imagick 2.0.0)
    * Applies a translation to the current coordinate system * @link https://php.net/manual/en/imagickdraw.translate.php * @param float $x

    * horizontal translation *

    * @param float $y

    * vertical translation *

    * @return bool No value is returned. */ public function translate($x, $y) {} /** * (PECL imagick 2.0.0)
    * Draws a line * @link https://php.net/manual/en/imagickdraw.line.php * @param float $sx

    * starting x coordinate *

    * @param float $sy

    * starting y coordinate *

    * @param float $ex

    * ending x coordinate *

    * @param float $ey

    * ending y coordinate *

    * @return bool No value is returned. */ public function line($sx, $sy, $ex, $ey) {} /** * (PECL imagick 2.0.0)
    * Draws an arc * @link https://php.net/manual/en/imagickdraw.arc.php * @param float $sx

    * Starting x ordinate of bounding rectangle *

    * @param float $sy

    * starting y ordinate of bounding rectangle *

    * @param float $ex

    * ending x ordinate of bounding rectangle *

    * @param float $ey

    * ending y ordinate of bounding rectangle *

    * @param float $sd

    * starting degrees of rotation *

    * @param float $ed

    * ending degrees of rotation *

    * @return bool No value is returned. */ public function arc($sx, $sy, $ex, $ey, $sd, $ed) {} /** * (PECL imagick 2.0.0)
    * Paints on the image's opacity channel * @link https://php.net/manual/en/imagickdraw.matte.php * @param float $x

    * x coordinate of the matte *

    * @param float $y

    * y coordinate of the matte *

    * @param int $paintMethod

    * PAINT_ constant *

    * @return bool TRUE on success or FALSE on failure. */ public function matte($x, $y, $paintMethod) {} /** * (PECL imagick 2.0.0)
    * Draws a polygon * @link https://php.net/manual/en/imagickdraw.polygon.php * @param array $coordinates

    * multidimensional array like array( array( 'x' => 3, 'y' => 4 ), array( 'x' => 2, 'y' => 6 ) ); *

    * @return bool TRUE on success. * @throws ImagickDrawException on error. */ public function polygon(array $coordinates) {} /** * (PECL imagick 2.0.0)
    * Draws a point * @link https://php.net/manual/en/imagickdraw.point.php * @param float $x

    * point's x coordinate *

    * @param float $y

    * point's y coordinate *

    * @return bool No value is returned. */ public function point($x, $y) {} /** * (PECL imagick 2.0.0)
    * Returns the text decoration * @link https://php.net/manual/en/imagickdraw.gettextdecoration.php * @return int one of the DECORATION_ constants * and 0 if no decoration is set. */ #[Pure] public function getTextDecoration() {} /** * (PECL imagick 2.0.0)
    * Returns the code set used for text annotations * @link https://php.net/manual/en/imagickdraw.gettextencoding.php * @return string a string specifying the code set * or false if text encoding is not set. */ #[Pure] public function getTextEncoding() {} #[Pure] public function getFontStretch() {} /** * (PECL imagick 2.0.0)
    * Sets the font stretch to use when annotating with text * @link https://php.net/manual/en/imagickdraw.setfontstretch.php * @param int $fontStretch

    * STRETCH_ constant *

    * @return bool No value is returned. */ public function setFontStretch($fontStretch) {} /** * (PECL imagick 2.0.0)
    * Controls whether stroked outlines are antialiased * @link https://php.net/manual/en/imagickdraw.setstrokeantialias.php * @param bool $stroke_antialias

    * the antialias setting *

    * @return bool No value is returned. */ public function setStrokeAntialias($stroke_antialias) {} /** * (PECL imagick 2.0.0)
    * Specifies a text alignment * @link https://php.net/manual/en/imagickdraw.settextalignment.php * @param int $alignment

    * ALIGN_ constant *

    * @return bool No value is returned. */ public function setTextAlignment($alignment) {} /** * (PECL imagick 2.0.0)
    * Specifies a decoration * @link https://php.net/manual/en/imagickdraw.settextdecoration.php * @param int $decoration

    * DECORATION_ constant *

    * @return bool No value is returned. */ public function setTextDecoration($decoration) {} /** * (PECL imagick 2.0.0)
    * Specifies the color of a background rectangle * @link https://php.net/manual/en/imagickdraw.settextundercolor.php * @param ImagickPixel $under_color

    * the under color *

    * @return bool No value is returned. * @throws ImagickDrawException on error. */ public function setTextUnderColor(ImagickPixel $under_color) {} /** * (PECL imagick 2.0.0)
    * Sets the overall canvas size * @link https://php.net/manual/en/imagickdraw.setviewbox.php * @param int $x1

    * left x coordinate *

    * @param int $y1

    * left y coordinate *

    * @param int $x2

    * right x coordinate *

    * @param int $y2

    * right y coordinate *

    * @return bool No value is returned. */ public function setViewbox($x1, $y1, $x2, $y2) {} /** * (PECL imagick 2.0.0)
    * Adjusts the current affine transformation matrix * @link https://php.net/manual/en/imagickdraw.affine.php * @param array $affine

    * Affine matrix parameters *

    * @return bool No value is returned. * @throws ImagickDrawException on error. */ public function affine(array $affine) {} /** * (PECL imagick 2.0.0)
    * Draws a bezier curve * @link https://php.net/manual/en/imagickdraw.bezier.php * @param array $coordinates

    * Multidimensional array like array( array( 'x' => 1, 'y' => 2 ), * array( 'x' => 3, 'y' => 4 ) ) *

    * @return bool No value is returned. * @throws ImagickDrawException on error. */ public function bezier(array $coordinates) {} /** * (PECL imagick 2.0.0)
    * Composites an image onto the current image * @link https://php.net/manual/en/imagickdraw.composite.php * @param int $compose

    * composition operator. One of COMPOSITE_ constants *

    * @param float $x

    * x coordinate of the top left corner *

    * @param float $y

    * y coordinate of the top left corner *

    * @param float $width

    * width of the composition image *

    * @param float $height

    * height of the composition image *

    * @param Imagick $compositeWand

    * the Imagick object where composition image is taken from *

    * @return bool TRUE on success. * @throws ImagickException on error. */ public function composite($compose, $x, $y, $width, $height, Imagick $compositeWand) {} /** * (PECL imagick 2.0.0)
    * Draws color on image * @link https://php.net/manual/en/imagickdraw.color.php * @param float $x

    * x coordinate of the paint *

    * @param float $y

    * y coordinate of the paint *

    * @param int $paintMethod

    * one of the PAINT_ constants *

    * @return bool No value is returned. */ public function color($x, $y, $paintMethod) {} /** * (PECL imagick 2.0.0)
    * Adds a comment * @link https://php.net/manual/en/imagickdraw.comment.php * @param string $comment

    * The comment string to add to vector output stream *

    * @return bool No value is returned. */ public function comment($comment) {} /** * (PECL imagick 2.0.0)
    * Obtains the current clipping path ID * @link https://php.net/manual/en/imagickdraw.getclippath.php * @return string|false a string containing the clip path ID or false if no clip path exists. */ #[Pure] public function getClipPath() {} /** * (PECL imagick 2.0.0)
    * Returns the current polygon fill rule * @link https://php.net/manual/en/imagickdraw.getcliprule.php * @return int one of the FILLRULE_ constants. */ #[Pure] public function getClipRule() {} /** * (PECL imagick 2.0.0)
    * Returns the interpretation of clip path units * @link https://php.net/manual/en/imagickdraw.getclipunits.php * @return int an int on success. */ #[Pure] public function getClipUnits() {} /** * (PECL imagick 2.0.0)
    * Returns the fill color * @link https://php.net/manual/en/imagickdraw.getfillcolor.php * @return ImagickPixel an ImagickPixel object. */ #[Pure] public function getFillColor() {} /** * (PECL imagick 2.0.0)
    * Returns the opacity used when drawing * @link https://php.net/manual/en/imagickdraw.getfillopacity.php * @return float The opacity. */ #[Pure] public function getFillOpacity() {} /** * (PECL imagick 2.0.0)
    * Returns the fill rule * @link https://php.net/manual/en/imagickdraw.getfillrule.php * @return int a FILLRULE_ constant */ #[Pure] public function getFillRule() {} /** * (PECL imagick 2.0.0)
    * Returns the text placement gravity * @link https://php.net/manual/en/imagickdraw.getgravity.php * @return int a GRAVITY_ constant on success and 0 if no gravity is set. */ #[Pure] public function getGravity() {} /** * (PECL imagick 2.0.0)
    * Returns the current stroke antialias setting * @link https://php.net/manual/en/imagickdraw.getstrokeantialias.php * @return bool TRUE if antialiasing is on and false if it is off. */ #[Pure] public function getStrokeAntialias() {} /** * (PECL imagick 2.0.0)
    * Returns the color used for stroking object outlines * @link https://php.net/manual/en/imagickdraw.getstrokecolor.php * @return ImagickPixel an ImagickPixel object which describes the color. */ #[Pure] public function getStrokeColor() {} /** * (PECL imagick 2.0.0)
    * Returns an array representing the pattern of dashes and gaps used to stroke paths * @link https://php.net/manual/en/imagickdraw.getstrokedasharray.php * @return array an array on success and empty array if not set. */ #[Pure] public function getStrokeDashArray() {} /** * (PECL imagick 2.0.0)
    * Returns the offset into the dash pattern to start the dash * @link https://php.net/manual/en/imagickdraw.getstrokedashoffset.php * @return float a float representing the offset and 0 if it's not set. */ #[Pure] public function getStrokeDashOffset() {} /** * (PECL imagick 2.0.0)
    * Returns the shape to be used at the end of open subpaths when they are stroked * @link https://php.net/manual/en/imagickdraw.getstrokelinecap.php * @return int one of the LINECAP_ constants or 0 if stroke linecap is not set. */ #[Pure] public function getStrokeLineCap() {} /** * (PECL imagick 2.0.0)
    * Returns the shape to be used at the corners of paths when they are stroked * @link https://php.net/manual/en/imagickdraw.getstrokelinejoin.php * @return int one of the LINEJOIN_ constants or 0 if stroke line join is not set. */ #[Pure] public function getStrokeLineJoin() {} /** * (PECL imagick 2.0.0)
    * Returns the stroke miter limit * @link https://php.net/manual/en/imagickdraw.getstrokemiterlimit.php * @return int an int describing the miter limit * and 0 if no miter limit is set. */ #[Pure] public function getStrokeMiterLimit() {} /** * (PECL imagick 2.0.0)
    * Returns the opacity of stroked object outlines * @link https://php.net/manual/en/imagickdraw.getstrokeopacity.php * @return float a float describing the opacity. */ #[Pure] public function getStrokeOpacity() {} /** * (PECL imagick 2.0.0)
    * Returns the width of the stroke used to draw object outlines * @link https://php.net/manual/en/imagickdraw.getstrokewidth.php * @return float a float describing the stroke width. */ #[Pure] public function getStrokeWidth() {} /** * (PECL imagick 2.0.0)
    * Returns the text alignment * @link https://php.net/manual/en/imagickdraw.gettextalignment.php * @return int one of the ALIGN_ constants and 0 if no align is set. */ #[Pure] public function getTextAlignment() {} /** * (PECL imagick 2.0.0)
    * Returns the current text antialias setting * @link https://php.net/manual/en/imagickdraw.gettextantialias.php * @return bool TRUE if text is antialiased and false if not. */ #[Pure] public function getTextAntialias() {} /** * (PECL imagick 2.0.0)
    * Returns a string containing vector graphics * @link https://php.net/manual/en/imagickdraw.getvectorgraphics.php * @return string a string containing the vector graphics. */ #[Pure] public function getVectorGraphics() {} /** * (PECL imagick 2.0.0)
    * Returns the text under color * @link https://php.net/manual/en/imagickdraw.gettextundercolor.php * @return ImagickPixel an ImagickPixel object describing the color. * @throws ImagickDrawException on error. */ #[Pure] public function getTextUnderColor() {} /** * (PECL imagick 2.0.0)
    * Adds a path element to the current path * @link https://php.net/manual/en/imagickdraw.pathclose.php * @return bool No value is returned. */ public function pathClose() {} /** * (PECL imagick 2.0.0)
    * Draws a cubic Bezier curve * @link https://php.net/manual/en/imagickdraw.pathcurvetoabsolute.php * @param float $x1

    * x coordinate of the first control point *

    * @param float $y1

    * y coordinate of the first control point *

    * @param float $x2

    * x coordinate of the second control point *

    * @param float $y2

    * y coordinate of the first control point *

    * @param float $x

    * x coordinate of the curve end *

    * @param float $y

    * y coordinate of the curve end *

    * @return bool No value is returned. */ public function pathCurveToAbsolute($x1, $y1, $x2, $y2, $x, $y) {} /** * (PECL imagick 2.0.0)
    * Draws a cubic Bezier curve * @link https://php.net/manual/en/imagickdraw.pathcurvetorelative.php * @param float $x1

    * x coordinate of starting control point *

    * @param float $y1

    * y coordinate of starting control point *

    * @param float $x2

    * x coordinate of ending control point *

    * @param float $y2

    * y coordinate of ending control point *

    * @param float $x

    * ending x coordinate *

    * @param float $y

    * ending y coordinate *

    * @return bool No value is returned. */ public function pathCurveToRelative($x1, $y1, $x2, $y2, $x, $y) {} /** * (PECL imagick 2.0.0)
    * Draws a quadratic Bezier curve * @link https://php.net/manual/en/imagickdraw.pathcurvetoquadraticbezierabsolute.php * @param float $x1

    * x coordinate of the control point *

    * @param float $y1

    * y coordinate of the control point *

    * @param float $x

    * x coordinate of the end point *

    * @param float $y

    * y coordinate of the end point *

    * @return bool No value is returned. */ public function pathCurveToQuadraticBezierAbsolute($x1, $y1, $x, $y) {} /** * (PECL imagick 2.0.0)
    * Draws a quadratic Bezier curve * @link https://php.net/manual/en/imagickdraw.pathcurvetoquadraticbezierrelative.php * @param float $x1

    * starting x coordinate *

    * @param float $y1

    * starting y coordinate *

    * @param float $x

    * ending x coordinate *

    * @param float $y

    * ending y coordinate *

    * @return bool No value is returned. */ public function pathCurveToQuadraticBezierRelative($x1, $y1, $x, $y) {} /** * (PECL imagick 2.0.0)
    * Draws a quadratic Bezier curve * @link https://php.net/manual/en/imagickdraw.pathcurvetoquadraticbeziersmoothabsolute.php * @param float $x

    * ending x coordinate *

    * @param float $y

    * ending y coordinate *

    * @return bool No value is returned. */ public function pathCurveToQuadraticBezierSmoothAbsolute($x, $y) {} /** * (PECL imagick 2.0.0)
    * Draws a quadratic Bezier curve * @link https://php.net/manual/en/imagickdraw.pathcurvetoquadraticbeziersmoothrelative.php * @param float $x

    * ending x coordinate *

    * @param float $y

    * ending y coordinate *

    * @return bool No value is returned. */ public function pathCurveToQuadraticBezierSmoothRelative($x, $y) {} /** * (PECL imagick 2.0.0)
    * Draws a cubic Bezier curve * @link https://php.net/manual/en/imagickdraw.pathcurvetosmoothabsolute.php * @param float $x2

    * x coordinate of the second control point *

    * @param float $y2

    * y coordinate of the second control point *

    * @param float $x

    * x coordinate of the ending point *

    * @param float $y

    * y coordinate of the ending point *

    * @return bool No value is returned. */ public function pathCurveToSmoothAbsolute($x2, $y2, $x, $y) {} /** * (PECL imagick 2.0.0)
    * Draws a cubic Bezier curve * @link https://php.net/manual/en/imagickdraw.pathcurvetosmoothrelative.php * @param float $x2

    * x coordinate of the second control point *

    * @param float $y2

    * y coordinate of the second control point *

    * @param float $x

    * x coordinate of the ending point *

    * @param float $y

    * y coordinate of the ending point *

    * @return bool No value is returned. */ public function pathCurveToSmoothRelative($x2, $y2, $x, $y) {} /** * (PECL imagick 2.0.0)
    * Draws an elliptical arc * @link https://php.net/manual/en/imagickdraw.pathellipticarcabsolute.php * @param float $rx

    * x radius *

    * @param float $ry

    * y radius *

    * @param float $x_axis_rotation

    * x axis rotation *

    * @param bool $large_arc_flag

    * large arc flag *

    * @param bool $sweep_flag

    * sweep flag *

    * @param float $x

    * x coordinate *

    * @param float $y

    * y coordinate *

    * @return bool No value is returned. */ public function pathEllipticArcAbsolute($rx, $ry, $x_axis_rotation, $large_arc_flag, $sweep_flag, $x, $y) {} /** * (PECL imagick 2.0.0)
    * Draws an elliptical arc * @link https://php.net/manual/en/imagickdraw.pathellipticarcrelative.php * @param float $rx

    * x radius *

    * @param float $ry

    * y radius *

    * @param float $x_axis_rotation

    * x axis rotation *

    * @param bool $large_arc_flag

    * large arc flag *

    * @param bool $sweep_flag

    * sweep flag *

    * @param float $x

    * x coordinate *

    * @param float $y

    * y coordinate *

    * @return bool No value is returned. */ public function pathEllipticArcRelative($rx, $ry, $x_axis_rotation, $large_arc_flag, $sweep_flag, $x, $y) {} /** * (PECL imagick 2.0.0)
    * Terminates the current path * @link https://php.net/manual/en/imagickdraw.pathfinish.php * @return bool No value is returned. */ public function pathFinish() {} /** * (PECL imagick 2.0.0)
    * Draws a line path * @link https://php.net/manual/en/imagickdraw.pathlinetoabsolute.php * @param float $x

    * starting x coordinate *

    * @param float $y

    * ending x coordinate *

    * @return bool No value is returned. */ public function pathLineToAbsolute($x, $y) {} /** * (PECL imagick 2.0.0)
    * Draws a line path * @link https://php.net/manual/en/imagickdraw.pathlinetorelative.php * @param float $x

    * starting x coordinate *

    * @param float $y

    * starting y coordinate *

    * @return bool No value is returned. */ public function pathLineToRelative($x, $y) {} /** * (PECL imagick 2.0.0)
    * Draws a horizontal line path * @link https://php.net/manual/en/imagickdraw.pathlinetohorizontalabsolute.php * @param float $x

    * x coordinate *

    * @return bool No value is returned. */ public function pathLineToHorizontalAbsolute($x) {} /** * (PECL imagick 2.0.0)
    * Draws a horizontal line * @link https://php.net/manual/en/imagickdraw.pathlinetohorizontalrelative.php * @param float $x

    * x coordinate *

    * @return bool No value is returned. */ public function pathLineToHorizontalRelative($x) {} /** * (PECL imagick 2.0.0)
    * Draws a vertical line * @link https://php.net/manual/en/imagickdraw.pathlinetoverticalabsolute.php * @param float $y

    * y coordinate *

    * @return bool No value is returned. */ public function pathLineToVerticalAbsolute($y) {} /** * (PECL imagick 2.0.0)
    * Draws a vertical line path * @link https://php.net/manual/en/imagickdraw.pathlinetoverticalrelative.php * @param float $y

    * y coordinate *

    * @return bool No value is returned. */ public function pathLineToVerticalRelative($y) {} /** * (PECL imagick 2.0.0)
    * Starts a new sub-path * @link https://php.net/manual/en/imagickdraw.pathmovetoabsolute.php * @param float $x

    * x coordinate of the starting point *

    * @param float $y

    * y coordinate of the starting point *

    * @return bool No value is returned. */ public function pathMoveToAbsolute($x, $y) {} /** * (PECL imagick 2.0.0)
    * Starts a new sub-path * @link https://php.net/manual/en/imagickdraw.pathmovetorelative.php * @param float $x

    * target x coordinate *

    * @param float $y

    * target y coordinate *

    * @return bool No value is returned. */ public function pathMoveToRelative($x, $y) {} /** * (PECL imagick 2.0.0)
    * Declares the start of a path drawing list * @link https://php.net/manual/en/imagickdraw.pathstart.php * @return bool No value is returned. */ public function pathStart() {} /** * (PECL imagick 2.0.0)
    * Draws a polyline * @link https://php.net/manual/en/imagickdraw.polyline.php * @param array $coordinates

    * array of x and y coordinates: array( array( 'x' => 4, 'y' => 6 ), array( 'x' => 8, 'y' => 10 ) ) *

    * @return bool TRUE on success. * @throws ImagickDrawException on error. */ public function polyline(array $coordinates) {} /** * (PECL imagick 2.0.0)
    * Terminates a clip path definition * @link https://php.net/manual/en/imagickdraw.popclippath.php * @return bool No value is returned. */ public function popClipPath() {} /** * (PECL imagick 2.0.0)
    * Terminates a definition list * @link https://php.net/manual/en/imagickdraw.popdefs.php * @return bool No value is returned. */ public function popDefs() {} /** * (PECL imagick 2.0.0)
    * Terminates a pattern definition * @link https://php.net/manual/en/imagickdraw.poppattern.php * @return bool TRUE on success or FALSE on failure. * @throws ImagickException on error. */ public function popPattern() {} /** * (PECL imagick 2.0.0)
    * Starts a clip path definition * @link https://php.net/manual/en/imagickdraw.pushclippath.php * @param string $clip_mask_id

    * Clip mask Id *

    * @return bool No value is returned. */ public function pushClipPath($clip_mask_id) {} /** * (PECL imagick 2.0.0)
    * Indicates that following commands create named elements for early processing * @link https://php.net/manual/en/imagickdraw.pushdefs.php * @return bool No value is returned. */ public function pushDefs() {} /** * (PECL imagick 2.0.0)
    * Indicates that subsequent commands up to a ImagickDraw::opPattern() command comprise the definition of a named pattern * @link https://php.net/manual/en/imagickdraw.pushpattern.php * @param string $pattern_id

    * the pattern Id *

    * @param float $x

    * x coordinate of the top-left corner *

    * @param float $y

    * y coordinate of the top-left corner *

    * @param float $width

    * width of the pattern *

    * @param float $height

    * height of the pattern *

    * @return bool TRUE on success or FALSE on failure. */ public function pushPattern($pattern_id, $x, $y, $width, $height) {} /** * (PECL imagick 2.0.0)
    * Renders all preceding drawing commands onto the image * @link https://php.net/manual/en/imagickdraw.render.php * @return bool TRUE on success or FALSE on failure. * @throws ImagickException on error. */ public function render() {} /** * (PECL imagick 2.0.0)
    * Applies the specified rotation to the current coordinate space * @link https://php.net/manual/en/imagickdraw.rotate.php * @param float $degrees

    * degrees to rotate *

    * @return bool No value is returned. */ public function rotate($degrees) {} /** * (PECL imagick 2.0.0)
    * Adjusts the scaling factor * @link https://php.net/manual/en/imagickdraw.scale.php * @param float $x

    * horizontal factor *

    * @param float $y

    * vertical factor *

    * @return bool No value is returned. */ public function scale($x, $y) {} /** * (PECL imagick 2.0.0)
    * Associates a named clipping path with the image * @link https://php.net/manual/en/imagickdraw.setclippath.php * @param string $clip_mask

    * the clipping path name *

    * @return bool No value is returned. * @throws ImagickException on error. */ public function setClipPath($clip_mask) {} /** * (PECL imagick 2.0.0)
    * Set the polygon fill rule to be used by the clipping path * @link https://php.net/manual/en/imagickdraw.setcliprule.php * @param int $fill_rule

    * FILLRULE_ constant *

    * @return bool No value is returned. */ public function setClipRule($fill_rule) {} /** * (PECL imagick 2.0.0)
    * Sets the interpretation of clip path units * @link https://php.net/manual/en/imagickdraw.setclipunits.php * @param int $clip_units

    * the number of clip units *

    * @return bool No value is returned. */ public function setClipUnits($clip_units) {} /** * (PECL imagick 2.0.0)
    * Sets the opacity to use when drawing using the fill color or fill texture * @link https://php.net/manual/en/imagickdraw.setfillopacity.php * @param float $fillOpacity

    * the fill opacity *

    * @return bool No value is returned. */ public function setFillOpacity($fillOpacity) {} /** * (PECL imagick 2.0.0)
    * Sets the URL to use as a fill pattern for filling objects * @link https://php.net/manual/en/imagickdraw.setfillpatternurl.php * @param string $fill_url

    * URL to use to obtain fill pattern. *

    * @return bool TRUE on success or FALSE on failure. * @throws ImagickException on error. */ public function setFillPatternURL($fill_url) {} /** * (PECL imagick 2.0.0)
    * Sets the fill rule to use while drawing polygons * @link https://php.net/manual/en/imagickdraw.setfillrule.php * @param int $fill_rule

    * FILLRULE_ constant *

    * @return bool No value is returned. */ public function setFillRule($fill_rule) {} /** * (PECL imagick 2.0.0)
    * Sets the text placement gravity * @link https://php.net/manual/en/imagickdraw.setgravity.php * @param int $gravity

    * GRAVITY_ constant *

    * @return bool No value is returned. */ public function setGravity($gravity) {} /** * (PECL imagick 2.0.0)
    * Sets the pattern used for stroking object outlines * @link https://php.net/manual/en/imagickdraw.setstrokepatternurl.php * @param string $stroke_url

    * stroke URL *

    * @return bool imagick.imagickdraw.return.success; * @throws ImagickException on error. */ public function setStrokePatternURL($stroke_url) {} /** * (PECL imagick 2.0.0)
    * Specifies the offset into the dash pattern to start the dash * @link https://php.net/manual/en/imagickdraw.setstrokedashoffset.php * @param float $dash_offset

    * dash offset *

    * @return bool No value is returned. */ public function setStrokeDashOffset($dash_offset) {} /** * (PECL imagick 2.0.0)
    * Specifies the shape to be used at the end of open subpaths when they are stroked * @link https://php.net/manual/en/imagickdraw.setstrokelinecap.php * @param int $linecap

    * LINECAP_ constant *

    * @return bool No value is returned. */ public function setStrokeLineCap($linecap) {} /** * (PECL imagick 2.0.0)
    * Specifies the shape to be used at the corners of paths when they are stroked * @link https://php.net/manual/en/imagickdraw.setstrokelinejoin.php * @param int $linejoin

    * LINEJOIN_ constant *

    * @return bool No value is returned. */ public function setStrokeLineJoin($linejoin) {} /** * (PECL imagick 2.0.0)
    * Specifies the miter limit * @link https://php.net/manual/en/imagickdraw.setstrokemiterlimit.php * @param int $miterlimit

    * the miter limit *

    * @return bool No value is returned. */ public function setStrokeMiterLimit($miterlimit) {} /** * (PECL imagick 2.0.0)
    * Specifies the opacity of stroked object outlines * @link https://php.net/manual/en/imagickdraw.setstrokeopacity.php * @param float $stroke_opacity

    * stroke opacity. 1.0 is fully opaque *

    * @return bool No value is returned. */ public function setStrokeOpacity($stroke_opacity) {} /** * (PECL imagick 2.0.0)
    * Sets the vector graphics * @link https://php.net/manual/en/imagickdraw.setvectorgraphics.php * @param string $xml

    * xml containing the vector graphics *

    * @return bool TRUE on success or FALSE on failure. */ public function setVectorGraphics($xml) {} /** * (PECL imagick 2.0.0)
    * Destroys the current ImagickDraw in the stack, and returns to the previously pushed ImagickDraw * @link https://php.net/manual/en/imagickdraw.pop.php * @return bool TRUE on success and false on failure. * @throws ImagickException on error. */ public function pop() {} /** * (PECL imagick 2.0.0)
    * Clones the current ImagickDraw and pushes it to the stack * @link https://php.net/manual/en/imagickdraw.push.php * @return bool TRUE on success or FALSE on failure. * @throws ImagickException on error. */ public function push() {} /** * (PECL imagick 2.0.0)
    * Specifies the pattern of dashes and gaps used to stroke paths * @link https://php.net/manual/en/imagickdraw.setstrokedasharray.php * @param array|null $dashArray

    * array of floats, use NULL to reset *

    * @return bool TRUE on success. */ public function setStrokeDashArray(?array $dashArray) {} /** * Sets the opacity to use when drawing using the fill or stroke color or texture. Fully opaque is 1.0. * * @param float $opacity * @return void * @since 3.4.1 */ public function setOpacity($opacity) {} /** * Returns the opacity used when drawing with the fill or stroke color or texture. Fully opaque is 1.0. * * @return float * @since 3.4.1 */ #[Pure] public function getOpacity() {} /** * Sets the image font resolution. * * @param float $x * @param float $y * @return bool * @throws ImagickException on error. * @since 3.4.1 */ public function setFontResolution($x, $y) {} /** * Gets the image X and Y resolution. * * @return array * @throws ImagickException on error. * @since 3.4.1 */ #[Pure] public function getFontResolution() {} /** * Returns the direction that will be used when annotating with text. * @return bool * @since 3.4.1 */ #[Pure] public function getTextDirection() {} /** * Sets the font style to use when annotating with text. The AnyStyle enumeration acts as a wild-card "don't care" option. * * @param int $direction * @return bool * @since 3.4.1 */ public function setTextDirection($direction) {} /** * Returns the border color used for drawing bordered objects. * * @return ImagickPixel * @since 3.4.1 */ #[Pure] public function getBorderColor() {} /** * Sets the border color to be used for drawing bordered objects. * @param ImagickPixel $color * @return bool * @throws ImagickDrawException on error. * @since 3.4.1 */ public function setBorderColor(ImagickPixel $color) {} /** * Obtains the vertical and horizontal resolution. * * @return string|null * @since 3.4.1 */ #[Pure] public function getDensity() {} /** * Sets the vertical and horizontal resolution. * @param string $density_string * @return bool * @throws ImagickException on error. * @since 3.4.1 */ public function setDensity($density_string) {} } /** * @link https://php.net/manual/en/class.imagickpixeliterator.php */ class ImagickPixelIterator implements Iterator { /** * (PECL imagick 2.0.0)
    * The ImagickPixelIterator constructor * @link https://php.net/manual/en/imagickpixeliterator.construct.php * @param Imagick $wand * @throws ImagickPixelIteratorException on error. * @throws ImagickException on error. */ public function __construct(Imagick $wand) {} /** * (PECL imagick 2.0.0)
    * Returns a new pixel iterator * @link https://php.net/manual/en/imagickpixeliterator.newpixeliterator.php * @param Imagick $wand * @return bool TRUE on success. Throwing ImagickPixelIteratorException. * @throws ImagickPixelIteratorException * @throws ImagickException */ #[Deprecated(replacement: "%class%->getPixelIterator(%parametersList%)")] public function newPixelIterator(Imagick $wand) {} /** * (PECL imagick 2.0.0)
    * Returns a new pixel iterator * @link https://php.net/manual/en/imagickpixeliterator.newpixelregioniterator.php * @param Imagick $wand * @param int $x * @param int $y * @param int $columns * @param int $rows * @return bool a new ImagickPixelIterator on success; on failure, throws ImagickPixelIteratorException * @throws ImagickPixelIteratorException * @throws ImagickException */ #[Deprecated(replacement: "%class%->getPixelRegionIterator(%parametersList%)")] public function newPixelRegionIterator(Imagick $wand, $x, $y, $columns, $rows) {} /** * (PECL imagick 2.0.0)
    * Returns the current pixel iterator row * @link https://php.net/manual/en/imagickpixeliterator.getiteratorrow.php * @return int the integer offset of the row, throwing ImagickPixelIteratorException on error. * @throws ImagickPixelIteratorException on error */ #[Pure] public function getIteratorRow() {} /** * (PECL imagick 2.0.0)
    * Set the pixel iterator row * @link https://php.net/manual/en/imagickpixeliterator.setiteratorrow.php * @param int $row * @return bool TRUE on success. * @throws ImagickPixelIteratorException on error. */ public function setIteratorRow($row) {} /** * (PECL imagick 2.0.0)
    * Sets the pixel iterator to the first pixel row * @link https://php.net/manual/en/imagickpixeliterator.setiteratorfirstrow.php * @return bool TRUE on success. * @throws ImagickPixelIteratorException on error. */ public function setIteratorFirstRow() {} /** * (PECL imagick 2.0.0)
    * Sets the pixel iterator to the last pixel row * @link https://php.net/manual/en/imagickpixeliterator.setiteratorlastrow.php * @return bool TRUE on success. * @throws ImagickPixelIteratorException on error. */ public function setIteratorLastRow() {} /** * (PECL imagick 2.0.0)
    * Returns the previous row * @link https://php.net/manual/en/imagickpixeliterator.getpreviousiteratorrow.php * @return array the previous row as an array of ImagickPixelWand objects from the * ImagickPixelIterator, throwing ImagickPixelIteratorException on error. * @throws ImagickPixelIteratorException on error */ #[Pure] public function getPreviousIteratorRow() {} /** * (PECL imagick 2.0.0)
    * Returns the current row of ImagickPixel objects * @link https://php.net/manual/en/imagickpixeliterator.getcurrentiteratorrow.php * @return array a row as an array of ImagickPixel objects that can themselves be iterated. * @throws ImagickPixelIteratorException on error. */ #[Pure] public function getCurrentIteratorRow() {} /** * (PECL imagick 2.0.0)
    * Returns the next row of the pixel iterator * @link https://php.net/manual/en/imagickpixeliterator.getnextiteratorrow.php * @return array the next row as an array of ImagickPixel objects, throwing * ImagickPixelIteratorException on error. * @throws ImagickPixelIteratorException on error */ #[Pure] public function getNextIteratorRow() {} /** * (PECL imagick 2.0.0)
    * Resets the pixel iterator * @link https://php.net/manual/en/imagickpixeliterator.resetiterator.php * @return bool TRUE on success. * @throws ImagickPixelIteratorException on error. */ public function resetIterator() {} /** * (PECL imagick 2.0.0)
    * Syncs the pixel iterator * @link https://php.net/manual/en/imagickpixeliterator.synciterator.php * @return bool TRUE on success. * @throws ImagickPixelIteratorException on error. */ public function syncIterator() {} /** * (PECL imagick 2.0.0)
    * Deallocates resources associated with a PixelIterator * @link https://php.net/manual/en/imagickpixeliterator.destroy.php * @return bool TRUE on success. * @throws ImagickPixelIteratorException on error. */ public function destroy() {} /** * (PECL imagick 2.0.0)
    * Clear resources associated with a PixelIterator * @link https://php.net/manual/en/imagickpixeliterator.clear.php * @return bool TRUE on success. * @throws ImagickPixelIteratorException on error. */ public function clear() {} /** * @param Imagick $Imagick * @throws ImagickPixelIteratorException on error. * @throws ImagickException on error. */ public static function getpixeliterator(Imagick $Imagick) {} /** * @param Imagick $Imagick * @param $x * @param $y * @param $columns * @param $rows * @throws ImagickPixelIteratorException on error. * @throws ImagickException on error. */ public static function getpixelregioniterator(Imagick $Imagick, $x, $y, $columns, $rows) {} /** * @throws ImagickPixelIteratorException on error. */ public function key() {} /** * @throws ImagickPixelIteratorException on error. */ public function next() {} /** * @throws ImagickPixelIteratorException on error. */ public function rewind() {} /** * @throws ImagickPixelIteratorException on error. */ public function current() {} /** * @throws ImagickPixelIteratorException on error. */ public function valid() {} } /** * @method clone() * @link https://php.net/manual/en/class.imagickpixel.php */ class ImagickPixel { /** * (PECL imagick 2.0.0)
    * Returns the normalized HSL color of the ImagickPixel object * @link https://php.net/manual/en/imagickpixel.gethsl.php * @return float[] the HSL value in an array with the keys "hue", * "saturation", and "luminosity". Throws ImagickPixelException on failure. * @throws ImagickPixelException on failure */ #[ArrayShape(["hue" => "float", "saturation" => "float", "luminosity" => "float"])] #[Pure] public function getHSL() {} /** * (PECL imagick 2.0.0)
    * Sets the normalized HSL color * @link https://php.net/manual/en/imagickpixel.sethsl.php * @param float $hue

    * The normalized value for hue, described as a fractional arc * (between 0 and 1) of the hue circle, where the zero value is * red. *

    * @param float $saturation

    * The normalized value for saturation, with 1 as full saturation. *

    * @param float $luminosity

    * The normalized value for luminosity, on a scale from black at * 0 to white at 1, with the full HS value at 0.5 luminosity. *

    * @return bool TRUE on success. * @throws ImagickPixelException on failure */ public function setHSL($hue, $saturation, $luminosity) {} /** * @throws ImagickPixelException on failure */ #[Pure] public function getColorValueQuantum() {} /** * @param $color_value * @throws ImagickPixelException on failure */ public function setColorValueQuantum($color_value) {} /** * Gets the colormap index of the pixel wand. * @throws ImagickPixelException on failure */ #[Pure] public function getIndex() {} /** * @param int $index * @throws ImagickPixelException on failure */ public function setIndex($index) {} /** * (PECL imagick 2.0.0)
    * The ImagickPixel constructor * @link https://php.net/manual/en/imagickpixel.construct.php * @param string $color [optional]

    * The optional color string to use as the initial value of this object. *

    * @throws ImagickPixelException on failure */ public function __construct($color = null) {} /** * (PECL imagick 2.0.0)
    * Sets the color * @link https://php.net/manual/en/imagickpixel.setcolor.php * @param string $color

    * The color definition to use in order to initialise the * ImagickPixel object. *

    * @return bool TRUE if the specified color was set, FALSE otherwise. * @throws ImagickPixelException on failure */ public function setColor($color) {} /** * (PECL imagick 2.0.0)
    * Sets the normalized value of one of the channels * @link https://php.net/manual/en/imagickpixel.setcolorvalue.php * @param int $color

    * One of the Imagick color constants e.g. \Imagick::COLOR_GREEN or \Imagick::COLOR_ALPHA. *

    * @param float $value

    * The value to set this channel to, ranging from 0 to 1. *

    * @return bool TRUE on success. * @throws ImagickPixelException on failure */ public function setColorValue($color, $value) {} /** * (PECL imagick 2.0.0)
    * Gets the normalized value of the provided color channel * @link https://php.net/manual/en/imagickpixel.getcolorvalue.php * @param int $color

    * The color to get the value of, specified as one of the Imagick color * constants. This can be one of the RGB colors, CMYK colors, alpha and * opacity e.g (Imagick::COLOR_BLUE, Imagick::COLOR_MAGENTA). *

    * @return float The value of the channel, as a normalized floating-point number, throwing * ImagickPixelException on error. * @throws ImagickPixelException on error */ #[Pure] public function getColorValue($color) {} /** * (PECL imagick 2.0.0)
    * Clears resources associated with this object * @link https://php.net/manual/en/imagickpixel.clear.php * @return bool TRUE on success. * @throws ImagickPixelException on failure */ public function clear() {} /** * (PECL imagick 2.0.0)
    * Deallocates resources associated with this object * @link https://php.net/manual/en/imagickpixel.destroy.php * @return bool TRUE on success. * @throws ImagickPixelException on failure */ public function destroy() {} /** * (PECL imagick 2.0.0)
    * Check the distance between this color and another * @link https://php.net/manual/en/imagickpixel.issimilar.php * @param ImagickPixel $color

    * The ImagickPixel object to compare this object against. *

    * @param float $fuzz

    * The maximum distance within which to consider these colors as similar. * The theoretical maximum for this value is the square root of three * (1.732). *

    * @return bool TRUE on success. * @throws ImagickPixelException on failure */ public function isSimilar(ImagickPixel $color, $fuzz) {} /** * (No version information available, might only be in SVN)
    * Check the distance between this color and another * @link https://php.net/manual/en/imagickpixel.ispixelsimilar.php * @param ImagickPixel $color

    * The ImagickPixel object to compare this object against. *

    * @param float $fuzz

    * The maximum distance within which to consider these colors as similar. * The theoretical maximum for this value is the square root of three * (1.732). *

    * @return bool TRUE on success. * @throws ImagickPixelException on failure */ public function isPixelSimilar(ImagickPixel $color, $fuzz) {} /** * (PECL imagick 2.0.0)
    * Returns the color * @link https://php.net/manual/en/imagickpixel.getcolor.php * @param int $normalized [optional]

    * Normalize the color values *

    * @return array An array of channel values, each normalized if TRUE is given as param. Throws * ImagickPixelException on error. * @throws ImagickPixelException on error. */ #[ArrayShape(["r" => "int|float", "g" => "int|float", "b" => "int|float", "a" => "int|float"])] #[Pure] public function getColor($normalized = 0) {} /** * (PECL imagick 2.1.0)
    * Returns the color as a string * @link https://php.net/manual/en/imagickpixel.getcolorasstring.php * @return string the color of the ImagickPixel object as a string. * @throws ImagickPixelException on failure */ #[Pure] public function getColorAsString() {} /** * (PECL imagick 2.0.0)
    * Returns the color count associated with this color * @link https://php.net/manual/en/imagickpixel.getcolorcount.php * @return int the color count as an integer on success, throws * ImagickPixelException on failure. * @throws ImagickPixelException on failure. */ #[Pure] public function getColorCount() {} /** * @param int $colorCount * @throws ImagickPixelException on failure */ public function setColorCount($colorCount) {} /** * Returns true if the distance between two colors is less than the specified distance. The fuzz value should be in the range 0-QuantumRange.
    * The maximum value represents the longest possible distance in the colorspace. e.g. from RGB(0, 0, 0) to RGB(255, 255, 255) for the RGB colorspace * @link https://php.net/manual/en/imagickpixel.ispixelsimilarquantum.php * @param string $color * @param string $fuzz * @return bool * @throws ImagickPixelException on failure * @since 3.3.0 */ public function isPixelSimilarQuantum($color, $fuzz) {} /** * Returns the color of the pixel in an array as Quantum values. If ImageMagick was compiled as HDRI these will be floats, otherwise they will be integers. * @link https://php.net/manual/en/imagickpixel.getcolorquantum.php * @return mixed The quantum value of the color element. Float if ImageMagick was compiled with HDRI, otherwise an int. * @throws ImagickPixelException on failure * @since 3.3.0 */ #[Pure] public function getColorQuantum() {} /** * Sets the color count associated with this color from another ImagickPixel object. * * @param ImagickPixel $srcPixel * @return bool * @throws ImagickPixelException on failure * @since 3.4.1 */ public function setColorFromPixel(ImagickPixel $srcPixel) {} } // End of imagick v.3.2.0RC1 // Start of Imagick v3.3.0RC1 /** * @link https://php.net/manual/en/class.imagickkernel.php */ class ImagickKernel { /** * Attach another kernel to this kernel to allow them to both be applied in a single morphology or filter function. Returns the new combined kernel. * @link https://php.net/manual/en/imagickkernel.addkernel.php * @param ImagickKernel $imagickKernel * @return void * @throws ImagickKernelException on error * @since 3.3.0 */ public function addKernel(ImagickKernel $imagickKernel) {} /** * Adds a given amount of the 'Unity' Convolution Kernel to the given pre-scaled and normalized Kernel. This in effect adds that amount of the original image into the resulting convolution kernel. The resulting effect is to convert the defined kernels into blended soft-blurs, unsharp kernels or into sharpening kernels. * @link https://php.net/manual/en/imagickkernel.addunitykernel.php * @return void * @throws ImagickKernelException on error * @since 3.3.0 */ public function addUnityKernel() {} /** * Create a kernel from a builtin in kernel. See https://www.imagemagick.org/Usage/morphology/#kernel for examples.
    * Currently the 'rotation' symbols are not supported. Example: $diamondKernel = ImagickKernel::fromBuiltIn(\Imagick::KERNEL_DIAMOND, "2"); * @link https://php.net/manual/en/imagickkernel.frombuiltin.php * @param int $kernelType The type of kernel to build e.g. \Imagick::KERNEL_DIAMOND * @param string $kernelString A string that describes the parameters e.g. "4,2.5" * @return ImagickKernel * @since 3.3.0 */ public static function fromBuiltin($kernelType, $kernelString) {} /** * Create a kernel from a builtin in kernel. See https://www.imagemagick.org/Usage/morphology/#kernel for examples.
    * Currently the 'rotation' symbols are not supported. Example: $diamondKernel = ImagickKernel::fromBuiltIn(\Imagick::KERNEL_DIAMOND, "2"); * @link https://php.net/manual/en/imagickkernel.frombuiltin.php * @see https://www.imagemagick.org/Usage/morphology/#kernel * @param array $matrix A matrix (i.e. 2d array) of values that define the kernel. Each element should be either a float value, or FALSE if that element shouldn't be used by the kernel. * @param array $origin [optional] Which element of the kernel should be used as the origin pixel. e.g. For a 3x3 matrix specifying the origin as [2, 2] would specify that the bottom right element should be the origin pixel. * @return ImagickKernel * @throws ImagickKernelException on error * @since 3.3.0 */ public static function fromMatrix($matrix, $origin) {} /** * Get the 2d matrix of values used in this kernel. The elements are either float for elements that are used or 'false' if the element should be skipped. * @link https://php.net/manual/en/imagickkernel.getmatrix.php * @return array A matrix (2d array) of the values that represent the kernel. * @throws ImagickKernelException on error * @since 3.3.0 */ #[Pure] public function getMatrix() {} /** * ScaleKernelInfo() scales the given kernel list by the given amount, with or without normalization of the sum of the kernel values (as per given flags).
    * The exact behaviour of this function depends on the normalization type being used please see https://www.imagemagick.org/api/morphology.php#ScaleKernelInfo for details.
    * Flag should be one of Imagick::NORMALIZE_KERNEL_VALUE, Imagick::NORMALIZE_KERNEL_CORRELATE, Imagick::NORMALIZE_KERNEL_PERCENT or not set. * @link https://php.net/manual/en/imagickkernel.scale.php * @see https://www.imagemagick.org/api/morphology.php#ScaleKernelInfo * @return void * @throws ImagickKernelException on error * @since 3.3.0 */ public function scale() {} /** * Separates a linked set of kernels and returns an array of ImagickKernels. * @link https://php.net/manual/en/imagickkernel.separate.php * @return void * @throws ImagickKernelException on error * @since 3.3.0 */ public function seperate() {} } * 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); * Add a watch to an initialized inotify instance * * @link https://php.net/manual/en/function.inotify-add-watch.php * * @param resource $inotify_instance

    resource returned by {@link https://php.net/manual/en/function.inotify-init.php inotify_init()}

    * @param string $pathname

    File or directory to watch

    * @param int $mask

    Events to watch for. See {@link https://php.net/manual/en/inotify.constants.php Predefined Constants}.

    * * @return int a unique (inotify instance-wide) watch descriptor. */ function inotify_add_watch($inotify_instance, $pathname, $mask) {} /** * (PHP >= 5.2.0, PECL inotify >= 0.1.2)
    * Initialize an inotify instance for use with {@see inotify_add_watch} * * @link https://php.net/manual/en/function.inotify-init.php * @return resource|false a stream resource or FALSE on error. */ function inotify_init() {} /** * (PHP >= 5.2.0, PECL inotify >= 0.1.2)
    * This function allows to know if {@see inotify_read} will block or not. * If a number upper than zero is returned, there are pending events * and {@see inotify_read} will not block. * * @link https://php.net/manual/en/function.inotify-queue-len.php * * @param resource $inotify_instance

    resource returned by {@link https://php.net/manual/en/function.inotify-init.php inotify_init()}

    * * @return int a number greater than zero if events are pending, otherwise zero. */ function inotify_queue_len($inotify_instance) {} /** * (PHP >= 5.2.0, PECL inotify >= 0.1.2)
    * Read inotify events from an inotify instance. * * @link https://php.net/manual/en/function.inotify-read.php * * @param resource $inotify_instance

    resource returned by {@link https://php.net/manual/en/function.inotify-init.php inotify_init()}

    * * @return array|false an array of inotify events or FALSE if no events * were pending and inotify_instance is non-blocking. Each event * is an array with the following keys: * *
      *
    • wd is a watch descriptor returned by inotify_add_watch()
    • *
    • mask is a bit mask of events
    • *
    • cookie is a unique id to connect related events (e.g. IN_MOVE_FROM and IN_MOVE_TO)
    • *
    • name is the name of a file (e.g. if a file was modified in a watched directory)
    • *
    */ function inotify_read($inotify_instance) {} /** * (PHP >= 5.2.0, PECL inotify >= 0.1.2)
    * Removes the watch $watch_descriptor from the inotify instance $inotify_instance. * * @link https://secure.php.net/manual/en/function.inotify-rm-watch.php * * @param resource $inotify_instance

    resource returned by {@link https://php.net/manual/en/function.inotify-init.php inotify_init()}

    * @param int $mask

    watch to remove from the instance

    * * @return bool TRUE on success or FALSE on failure. */ function inotify_rm_watch($inotify_instance, $mask) {} /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_ACCESS = 1; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_MODIFY = 2; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_ATTRIB = 4; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_CLOSE_WRITE = 8; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_CLOSE_NOWRITE = 16; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_OPEN = 32; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_MOVED_FROM = 64; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_MOVED_TO = 128; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_CREATE = 256; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_DELETE = 512; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_DELETE_SELF = 1024; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_MOVE_SELF = 2048; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_UNMOUNT = 8192; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_Q_OVERFLOW = 16384; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_IGNORED = 32768; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_CLOSE = 24; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_MOVE = 192; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_ALL_EVENTS = 4095; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_ONLYDIR = 16777216; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_DONT_FOLLOW = 33554432; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_MASK_ADD = 536870912; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_ISDIR = 1073741824; /** * @link https://php.net/manual/en/inotify.constants.php */ const IN_ONESHOT = 2147483648; // End of inotify v.0.1.6 * The database argument has to be a valid path to * database file on the server it resides on. If the server is not local, * it must be prefixed with either 'hostname:' (TCP/IP), '//hostname/' * (NetBEUI) or 'hostname@' (IPX/SPX), depending on the connection * protocol used. *

    * @param string $username [optional]

    * The user name. Can be set with the * ibase.default_user &php.ini; directive. *

    * @param string $password [optional]

    * The password for username. Can be set with the * ibase.default_password &php.ini; directive. *

    * @param string $charset [optional]

    * charset is the default character set for a * database. *

    * @param int $buffers [optional]

    * buffers is the number of database buffers to * allocate for the server-side cache. If 0 or omitted, server chooses * its own default. *

    * @param int $dialect [optional]

    * dialect selects the default SQL dialect for any * statement executed within a connection, and it defaults to the highest * one supported by client libraries. Functional only with InterBase 6 * and up. *

    * @param string $role [optional]

    * Functional only with InterBase 5 and up. *

    * @param int $sync [optional]

    *

    * @return resource|false an InterBase link identifier on success, or false on error. */ function ibase_connect($database = null, $username = null, $password = null, $charset = null, $buffers = null, $dialect = null, $role = null, $sync = null) {} /** * Open a persistent connection to an InterBase database * @link https://php.net/manual/en/function.ibase-pconnect.php * @param string $database [optional]

    * The database argument has to be a valid path to * database file on the server it resides on. If the server is not local, * it must be prefixed with either 'hostname:' (TCP/IP), '//hostname/' * (NetBEUI) or 'hostname@' (IPX/SPX), depending on the connection * protocol used. *

    * @param string $username [optional]

    * The user name. Can be set with the * ibase.default_user &php.ini; directive. *

    * @param string $password [optional]

    * The password for username. Can be set with the * ibase.default_password &php.ini; directive. *

    * @param string $charset [optional]

    * charset is the default character set for a * database. *

    * @param int $buffers [optional]

    * buffers is the number of database buffers to * allocate for the server-side cache. If 0 or omitted, server chooses * its own default. *

    * @param int $dialect [optional]

    * dialect selects the default SQL dialect for any * statement executed within a connection, and it defaults to the highest * one supported by client libraries. Functional only with InterBase 6 * and up. *

    * @param string $role [optional]

    * Functional only with InterBase 5 and up. *

    * @param int $sync [optional]

    *

    * @return resource|false an InterBase link identifier on success, or false on error. */ function ibase_pconnect($database = null, $username = null, $password = null, $charset = null, $buffers = null, $dialect = null, $role = null, $sync = null) {} /** * Close a connection to an InterBase database * @link https://php.net/manual/en/function.ibase-close.php * @param resource $connection_id [optional]

    * An InterBase link identifier returned from * ibase_connect. If omitted, the last opened link * is assumed. *

    * @return bool true on success or false on failure. */ function ibase_close($connection_id = null) {} /** * Drops a database * @link https://php.net/manual/en/function.ibase-drop-db.php * @param resource $connection [optional]

    * An InterBase link identifier. If omitted, the last opened link is * assumed. *

    * @return bool true on success or false on failure. */ function ibase_drop_db($connection = null) {} /** * Execute a query on an InterBase database * @link https://php.net/manual/en/function.ibase-query.php * @param resource $link_identifier [optional]

    * An InterBase link identifier. If omitted, the last opened link is * assumed. *

    * @param string $query

    * An InterBase query. *

    * @param int $bind_args [optional]

    *

    * @return resource|bool If the query raises an error, returns false. If it is successful and * there is a (possibly empty) result set (such as with a SELECT query), * returns a result identifier. If the query was successful and there were * no results, returns true. *

    *

    * In PHP 5.0.0 and up, this function will return the number of rows * affected by the query for INSERT, UPDATE and DELETE statements. In order * to retain backward compatibility, it will return true for these * statements if the query succeeded without affecting any rows. */ function ibase_query($link_identifier = null, $query, $bind_args = null) {} /** * Fetch a row from an InterBase database * @link https://php.net/manual/en/function.ibase-fetch-row.php * @param resource $result_identifier

    * An InterBase result identifier. *

    * @param int $fetch_flag [optional]

    * fetch_flag is a combination of the constants * IBASE_TEXT and IBASE_UNIXTIME * ORed together. Passing IBASE_TEXT will cause this * function to return BLOB contents instead of BLOB ids. Passing * IBASE_UNIXTIME will cause this function to return * date/time values as Unix timestamps instead of as formatted strings. *

    * @return array|false an array that corresponds to the fetched row, or false if there * are no more rows. Each result column is stored in an array offset, * starting at offset 0. */ function ibase_fetch_row($result_identifier, $fetch_flag = null) {} /** * Fetch a result row from a query as an associative array * @link https://php.net/manual/en/function.ibase-fetch-assoc.php * @param resource $result

    * The result handle. *

    * @param int $fetch_flag [optional]

    * fetch_flag is a combination of the constants * IBASE_TEXT and IBASE_UNIXTIME * ORed together. Passing IBASE_TEXT will cause this * function to return BLOB contents instead of BLOB ids. Passing * IBASE_UNIXTIME will cause this function to return * date/time values as Unix timestamps instead of as formatted strings. *

    * @return array|false an associative array that corresponds to the fetched row. * Subsequent calls will return the next row in the result set, or false if * there are no more rows. */ function ibase_fetch_assoc($result, $fetch_flag = null) {} /** * Get an object from a InterBase database * @link https://php.net/manual/en/function.ibase-fetch-object.php * @param resource $result_id

    * An InterBase result identifier obtained either by * ibase_query or ibase_execute. *

    * @param int $fetch_flag [optional]

    * fetch_flag is a combination of the constants * IBASE_TEXT and IBASE_UNIXTIME * ORed together. Passing IBASE_TEXT will cause this * function to return BLOB contents instead of BLOB ids. Passing * IBASE_UNIXTIME will cause this function to return * date/time values as Unix timestamps instead of as formatted strings. *

    * @return object|false an object with the next row information, or false if there are * no more rows. */ function ibase_fetch_object($result_id, $fetch_flag = null) {} /** * Free a result set * @link https://php.net/manual/en/function.ibase-free-result.php * @param resource $result_identifier

    * A result set created by ibase_query or * ibase_execute. *

    * @return bool true on success or false on failure. */ function ibase_free_result($result_identifier) {} /** * Assigns a name to a result set * @link https://php.net/manual/en/function.ibase-name-result.php * @param resource $result

    * An InterBase result set. *

    * @param string $name

    * The name to be assigned. *

    * @return bool true on success or false on failure. */ function ibase_name_result($result, $name) {} /** * Prepare a query for later binding of parameter placeholders and execution * @link https://php.net/manual/en/function.ibase-prepare.php * @param string $query

    * An InterBase query. *

    * @return resource|false a prepared query handle, or false on error. */ function ibase_prepare($query) {} /** * Execute a previously prepared query * @link https://php.net/manual/en/function.ibase-execute.php * @param resource $query

    * An InterBase query prepared by ibase_prepare. *

    * @param mixed ...$bind_arg [optional]

    *

    * @return resource|bool If the query raises an error, returns false. If it is successful and * there is a (possibly empty) result set (such as with a SELECT query), * returns a result identifier. If the query was successful and there were * no results, returns true. *

    *

    * In PHP 5.0.0 and up, this function returns the number of rows affected by * the query (if > 0 and applicable to the statement type). A query that * succeeded, but did not affect any rows (e.g. an UPDATE of a non-existent * record) will return true. */ function ibase_execute($query, ...$bind_arg) {} /** * Free memory allocated by a prepared query * @link https://php.net/manual/en/function.ibase-free-query.php * @param resource $query

    * A query prepared with ibase_prepare. *

    * @return bool true on success or false on failure. */ function ibase_free_query($query) {} /** * Increments the named generator and returns its new value * @link https://php.net/manual/en/function.ibase-gen-id.php * @param string $generator * @param int $increment [optional] * @param resource $link_identifier [optional] * @return mixed new generator value as integer, or as string if the value is too big. */ function ibase_gen_id($generator, $increment = null, $link_identifier = null) {} /** * Get the number of fields in a result set * @link https://php.net/manual/en/function.ibase-num-fields.php * @param resource $result_id

    * An InterBase result identifier. *

    * @return int the number of fields as an integer. */ function ibase_num_fields($result_id) {} /** * Return the number of parameters in a prepared query * @link https://php.net/manual/en/function.ibase-num-params.php * @param resource $query

    * The prepared query handle. *

    * @return int the number of parameters as an integer. */ function ibase_num_params($query) {} /** * Return the number of rows that were affected by the previous query * @link https://php.net/manual/en/function.ibase-affected-rows.php * @param resource $link_identifier [optional]

    * A transaction context. If link_identifier is a * connection resource, its default transaction is used. *

    * @return int the number of rows as an integer. */ function ibase_affected_rows($link_identifier = null) {} /** * Get information about a field * @link https://php.net/manual/en/function.ibase-field-info.php * @param resource $result

    * An InterBase result identifier. *

    * @param int $field_number

    * Field offset. *

    * @return array an array with the following keys: name, * alias, relation, * length and type. */ function ibase_field_info($result, $field_number) {} /** * Return information about a parameter in a prepared query * @link https://php.net/manual/en/function.ibase-param-info.php * @param resource $query

    * An InterBase prepared query handle. *

    * @param int $param_number

    * Parameter offset. *

    * @return array an array with the following keys: name, * alias, relation, * length and type. */ function ibase_param_info($query, $param_number) {} /** * Begin a transaction * @link https://php.net/manual/en/function.ibase-trans.php * @param int $trans_args [optional]

    * trans_args can be a combination of * IBASE_READ, * IBASE_WRITE, * IBASE_COMMITTED, * IBASE_CONSISTENCY, * IBASE_CONCURRENCY, * IBASE_REC_VERSION, * IBASE_REC_NO_VERSION, * IBASE_WAIT and * IBASE_NOWAIT. *

    * @param resource $link_identifier [optional]

    * An InterBase link identifier. If omitted, the last opened link is * assumed. *

    * @return resource|false a transaction handle, or false on error. */ function ibase_trans($trans_args = null, $link_identifier = null) {} /** * Commit a transaction * @link https://php.net/manual/en/function.ibase-commit.php * @param resource $link_or_trans_identifier [optional]

    * If called without an argument, this function commits the default * transaction of the default link. If the argument is a connection * identifier, the default transaction of the corresponding connection * will be committed. If the argument is a transaction identifier, the * corresponding transaction will be committed. *

    * @return bool true on success or false on failure. */ function ibase_commit($link_or_trans_identifier = null) {} /** * Roll back a transaction * @link https://php.net/manual/en/function.ibase-rollback.php * @param resource $link_or_trans_identifier [optional]

    * If called without an argument, this function rolls back the default * transaction of the default link. If the argument is a connection * identifier, the default transaction of the corresponding connection * will be rolled back. If the argument is a transaction identifier, the * corresponding transaction will be rolled back. *

    * @return bool true on success or false on failure. */ function ibase_rollback($link_or_trans_identifier = null) {} /** * Commit a transaction without closing it * @link https://php.net/manual/en/function.ibase-commit-ret.php * @param resource $link_or_trans_identifier [optional]

    * If called without an argument, this function commits the default * transaction of the default link. If the argument is a connection * identifier, the default transaction of the corresponding connection * will be committed. If the argument is a transaction identifier, the * corresponding transaction will be committed. The transaction context * will be retained, so statements executed from within this transaction * will not be invalidated. *

    * @return bool true on success or false on failure. */ function ibase_commit_ret($link_or_trans_identifier = null) {} /** * Roll back a transaction without closing it * @link https://php.net/manual/en/function.ibase-rollback-ret.php * @param resource $link_or_trans_identifier [optional]

    * If called without an argument, this function rolls back the default * transaction of the default link. If the argument is a connection * identifier, the default transaction of the corresponding connection * will be rolled back. If the argument is a transaction identifier, the * corresponding transaction will be rolled back. The transaction context * will be retained, so statements executed from within this transaction * will not be invalidated. *

    * @return bool true on success or false on failure. */ function ibase_rollback_ret($link_or_trans_identifier = null) {} /** * Return blob length and other useful info * @link https://php.net/manual/en/function.ibase-blob-info.php * @param resource $link_identifier

    * An InterBase link identifier. If omitted, the last opened link is * assumed. *

    * @param string $blob_id

    * A BLOB id. *

    * @return array an array containing information about a BLOB. The information returned * consists of the length of the BLOB, the number of segments it contains, the size * of the largest segment, and whether it is a stream BLOB or a segmented BLOB. */ function ibase_blob_info($link_identifier, $blob_id) {} /** * Create a new blob for adding data * @link https://php.net/manual/en/function.ibase-blob-create.php * @param resource $link_identifier [optional]

    * An InterBase link identifier. If omitted, the last opened link is * assumed. *

    * @return resource|false a BLOB handle for later use with * ibase_blob_add or false on failure. */ function ibase_blob_create($link_identifier = null) {} /** * Add data into a newly created blob * @link https://php.net/manual/en/function.ibase-blob-add.php * @param resource $blob_handle

    * A blob handle opened with ibase_blob_create. *

    * @param string $data

    * The data to be added. *

    * @return void */ function ibase_blob_add($blob_handle, $data) {} /** * Cancel creating blob * @link https://php.net/manual/en/function.ibase-blob-cancel.php * @param resource $blob_handle

    * A BLOB handle opened with ibase_blob_create. *

    * @return bool true on success or false on failure. */ function ibase_blob_cancel($blob_handle) {} /** * Close blob * @link https://php.net/manual/en/function.ibase-blob-close.php * @param resource $blob_handle

    * A BLOB handle opened with ibase_blob_create or * ibase_blob_open. *

    * @return mixed If the BLOB was being read, this function returns true on success, if * the BLOB was being written to, this function returns a string containing * the BLOB id that has been assigned to it by the database. On failure, this * function returns false. */ function ibase_blob_close($blob_handle) {} /** * Open blob for retrieving data parts * @link https://php.net/manual/en/function.ibase-blob-open.php * @param resource $link_identifier

    * An InterBase link identifier. If omitted, the last opened link is * assumed. *

    * @param string $blob_id

    * A BLOB id. *

    * @return resource|false a BLOB handle for later use with * ibase_blob_get or false on failure. */ function ibase_blob_open($link_identifier, $blob_id) {} /** * Get len bytes data from open blob * @link https://php.net/manual/en/function.ibase-blob-get.php * @param resource $blob_handle

    * A BLOB handle opened with ibase_blob_open. *

    * @param int $len

    * Size of returned data. *

    * @return string|false at most len bytes from the BLOB, or false * on failure. */ function ibase_blob_get($blob_handle, $len) {} /** * Output blob contents to browser * @link https://php.net/manual/en/function.ibase-blob-echo.php * @param string $blob_id

    *

    * @return bool true on success or false on failure. */ function ibase_blob_echo($blob_id) {} /** * Create blob, copy file in it, and close it * @link https://php.net/manual/en/function.ibase-blob-import.php * @param resource $link_identifier

    * An InterBase link identifier. If omitted, the last opened link is * assumed. *

    * @param resource $file_handle

    * The file handle is a handle returned by fopen. *

    * @return string|false the BLOB id on success, or false on error. */ function ibase_blob_import($link_identifier, $file_handle) {} /** * Return error messages * @link https://php.net/manual/en/function.ibase-errmsg.php * @return string|false the error message as a string, or false if no error occurred. */ function ibase_errmsg() {} /** * Return an error code * @link https://php.net/manual/en/function.ibase-errcode.php * @return int|false the error code as an integer, or false if no error occurred. */ function ibase_errcode() {} /** * Add a user to a security database (only for IB6 or later) * @link https://php.net/manual/en/function.ibase-add-user.php * @param resource $service_handle * @param string $user_name * @param string $password * @param string $first_name [optional] * @param string $middle_name [optional] * @param string $last_name [optional] * @return bool true on success or false on failure. */ function ibase_add_user($service_handle, $user_name, $password, $first_name = null, $middle_name = null, $last_name = null) {} /** * Modify a user to a security database (only for IB6 or later) * @link https://php.net/manual/en/function.ibase-modify-user.php * @param resource $service_handle * @param string $user_name * @param string $password * @param string $first_name [optional] * @param string $middle_name [optional] * @param string $last_name [optional] * @return bool true on success or false on failure. */ function ibase_modify_user($service_handle, $user_name, $password, $first_name = null, $middle_name = null, $last_name = null) {} /** * Delete a user from a security database (only for IB6 or later) * @link https://php.net/manual/en/function.ibase-delete-user.php * @param resource $service_handle * @param string $user_name * @return bool true on success or false on failure. */ function ibase_delete_user($service_handle, $user_name) {} /** * Connect to the service manager * @link https://php.net/manual/en/function.ibase-service-attach.php * @param string $host * @param string $dba_username * @param string $dba_password * @return resource|false */ function ibase_service_attach($host, $dba_username, $dba_password) {} /** * Disconnect from the service manager * @link https://php.net/manual/en/function.ibase-service-detach.php * @param resource $service_handle * @return bool true on success or false on failure. */ function ibase_service_detach($service_handle) {} /** * Initiates a backup task in the service manager and returns immediately * @link https://php.net/manual/en/function.ibase-backup.php * @param resource $service_handle * @param string $source_db * @param string $dest_file * @param int $options [optional] * @param bool $verbose [optional] * @return mixed */ function ibase_backup($service_handle, $source_db, $dest_file, $options = null, $verbose = null) {} /** * Initiates a restore task in the service manager and returns immediately * @link https://php.net/manual/en/function.ibase-restore.php * @param resource $service_handle * @param string $source_file * @param string $dest_db * @param int $options [optional] * @param bool $verbose [optional] * @return mixed */ function ibase_restore($service_handle, $source_file, $dest_db, $options = null, $verbose = null) {} /** * Execute a maintenance command on the database server * @link https://php.net/manual/en/function.ibase-maintain-db.php * @param resource $service_handle * @param string $db * @param int $action * @param int $argument [optional] * @return bool true on success or false on failure. */ function ibase_maintain_db($service_handle, $db, $action, $argument = null) {} /** * Request statistics about a database * @link https://php.net/manual/en/function.ibase-db-info.php * @param resource $service_handle * @param string $db * @param int $action * @param int $argument [optional] * @return string */ function ibase_db_info($service_handle, $db, $action, $argument = null) {} /** * Request information about a database server * @link https://php.net/manual/en/function.ibase-server-info.php * @param resource $service_handle * @param int $action * @return string */ function ibase_server_info($service_handle, $action) {} /** * Wait for an event to be posted by the database * @link https://php.net/manual/en/function.ibase-wait-event.php * @param string $event_name1

    * The event name. *

    * @param string $event_name2 [optional]

    *

    * @param string ...$_ [optional] * @return string the name of the event that was posted. */ function ibase_wait_event($event_name1, $event_name2 = null, ...$_) {} /** * Register a callback function to be called when events are posted * @link https://php.net/manual/en/function.ibase-set-event-handler.php * @param callable $event_handler

    * The callback is called with the event name and the link resource as * arguments whenever one of the specified events is posted by the * database. *

    *

    * The callback must return false if the event handler should be * canceled. Any other return value is ignored. This function accepts up * to 15 event arguments. *

    * @param string $event_name1

    * An event name. *

    * @param string $event_name2 [optional]

    * At most 15 events allowed. *

    * @param string ...$_ [optional] * @return resource The return value is an event resource. This resource can be used to free * the event handler using ibase_free_event_handler. */ function ibase_set_event_handler($event_handler, $event_name1, $event_name2 = null, ...$_) {} /** * Cancels a registered event handler * @link https://php.net/manual/en/function.ibase-free-event-handler.php * @param resource $event

    * An event resource, created by * ibase_set_event_handler. *

    * @return bool true on success or false on failure. */ function ibase_free_event_handler($event) {} /** * This is an alias of ibase_connect * Open a connection to an InterBase database * @link https://php.net/manual/en/function.fbird-connect.php * @param string $database [optional]

    * The database argument has to be a valid path to * database file on the server it resides on. If the server is not local, * it must be prefixed with either 'hostname:' (TCP/IP), '//hostname/' * (NetBEUI) or 'hostname@' (IPX/SPX), depending on the connection * protocol used. *

    * @param string $username [optional]

    * The user name. Can be set with the * fbird.default_user &php.ini; directive. *

    * @param string $password [optional]

    * The password for username. Can be set with the * fbird.default_password &php.ini; directive. *

    * @param string $charset [optional]

    * charset is the default character set for a * database. *

    * @param int $buffers [optional]

    * buffers is the number of database buffers to * allocate for the server-side cache. If 0 or omitted, server chooses * its own default. *

    * @param int $dialect [optional]

    * dialect selects the default SQL dialect for any * statement executed within a connection, and it defaults to the highest * one supported by client libraries. Functional only with InterBase 6 * and up. *

    * @param string $role [optional]

    * Functional only with InterBase 5 and up. *

    * @param int $sync [optional]

    *

    * @return resource|false an InterBase link identifier on success, or false on error. */ function fbird_connect($database = null, $username = null, $password = null, $charset = null, $buffers = null, $dialect = null, $role = null, $sync = null) {} /** * This is an alias of ibase_pconnect * Open a persistent connection to an InterBase database * @link https://php.net/manual/en/function.fbird-pconnect.php * @param string $database [optional]

    * The database argument has to be a valid path to * database file on the server it resides on. If the server is not local, * it must be prefixed with either 'hostname:' (TCP/IP), '//hostname/' * (NetBEUI) or 'hostname@' (IPX/SPX), depending on the connection * protocol used. *

    * @param string $username [optional]

    * The user name. Can be set with the * fbird.default_user &php.ini; directive. *

    * @param string $password [optional]

    * The password for username. Can be set with the * fbird.default_password &php.ini; directive. *

    * @param string $charset [optional]

    * charset is the default character set for a * database. *

    * @param int $buffers [optional]

    * buffers is the number of database buffers to * allocate for the server-side cache. If 0 or omitted, server chooses * its own default. *

    * @param int $dialect [optional]

    * dialect selects the default SQL dialect for any * statement executed within a connection, and it defaults to the highest * one supported by client libraries. Functional only with InterBase 6 * and up. *

    * @param string $role [optional]

    * Functional only with InterBase 5 and up. *

    * @param int $sync [optional]

    *

    * @return resource|false an InterBase link identifier on success, or false on error. */ function fbird_pconnect($database = null, $username = null, $password = null, $charset = null, $buffers = null, $dialect = null, $role = null, $sync = null) {} /** * This is an alias of ibase_close * Close a connection to an InterBase database * @link https://php.net/manual/en/function.fbird-close.php * @param resource $connection_id [optional]

    * An InterBase link identifier returned from * fbird_connect. If omitted, the last opened link * is assumed. *

    * @return bool true on success or false on failure. */ function fbird_close($connection_id = null) {} /** * This is an alias of ibase_drop_db * Drops a database * @link https://php.net/manual/en/function.fbird-drop-db.php * @param resource $connection [optional]

    * An InterBase link identifier. If omitted, the last opened link is * assumed. *

    * @return bool true on success or false on failure. */ function fbird_drop_db($connection = null) {} /** * This is an alias of ibase_query * Execute a query on an InterBase database * @link https://php.net/manual/en/function.fbird-query.php * @param resource $link_identifier [optional]

    * An InterBase link identifier. If omitted, the last opened link is * assumed. *

    * @param string $query

    * An InterBase query. *

    * @param int $bind_args [optional]

    *

    * @return resource|bool If the query raises an error, returns false. If it is successful and * there is a (possibly empty) result set (such as with a SELECT query), * returns a result identifier. If the query was successful and there were * no results, returns true. *

    *

    * In PHP 5.0.0 and up, this function will return the number of rows * affected by the query for INSERT, UPDATE and DELETE statements. In order * to retain backward compatibility, it will return true for these * statements if the query succeeded without affecting any rows. */ function fbird_query($link_identifier = null, $query, $bind_args = null) {} /** * This is an alias of ibase_fetch_row * Fetch a row from an InterBase database * @link https://php.net/manual/en/function.fbird-fetch-row.php * @param resource $result_identifier

    * An InterBase result identifier. *

    * @param int $fetch_flag [optional]

    * fetch_flag is a combination of the constants * IBASE_TEXT and IBASE_UNIXTIME * ORed together. Passing IBASE_TEXT will cause this * function to return BLOB contents instead of BLOB ids. Passing * IBASE_UNIXTIME will cause this function to return * date/time values as Unix timestamps instead of as formatted strings. *

    * @return array|false an array that corresponds to the fetched row, or false if there * are no more rows. Each result column is stored in an array offset, * starting at offset 0. */ function fbird_fetch_row($result_identifier, $fetch_flag = null) {} /** * This is an alias of ibase_fetch_assoc * Fetch a result row from a query as an associative array * @link https://php.net/manual/en/function.fbird-fetch-assoc.php * @param resource $result

    * The result handle. *

    * @param int $fetch_flag [optional]

    * fetch_flag is a combination of the constants * IBASE_TEXT and IBASE_UNIXTIME * ORed together. Passing IBASE_TEXT will cause this * function to return BLOB contents instead of BLOB ids. Passing * IBASE_UNIXTIME will cause this function to return * date/time values as Unix timestamps instead of as formatted strings. *

    * @return array|false an associative array that corresponds to the fetched row. * Subsequent calls will return the next row in the result set, or false if * there are no more rows. */ function fbird_fetch_assoc($result, $fetch_flag = null) {} /** * This is an alias of ibase_fetch_object * Get an object from a InterBase database * @link https://php.net/manual/en/function.fbird-fetch-object.php * @param resource $result_id

    * An InterBase result identifier obtained either by * fbird_query or fbird_execute. *

    * @param int $fetch_flag [optional]

    * fetch_flag is a combination of the constants * IBASE_TEXT and IBASE_UNIXTIME * ORed together. Passing IBASE_TEXT will cause this * function to return BLOB contents instead of BLOB ids. Passing * IBASE_UNIXTIME will cause this function to return * date/time values as Unix timestamps instead of as formatted strings. *

    * @return object|false an object with the next row information, or false if there are * no more rows. */ function fbird_fetch_object($result_id, $fetch_flag = null) {} /** * This is an alias of ibase_free_result * Free a result set * @link https://php.net/manual/en/function.fbird-free-result.php * @param resource $result_identifier

    * A result set created by fbird_query or * fbird_execute. *

    * @return bool true on success or false on failure. */ function fbird_free_result($result_identifier) {} /** * This is an alias of ibase_name_result * Assigns a name to a result set * @link https://php.net/manual/en/function.fbird-name-result.php * @param resource $result

    * An InterBase result set. *

    * @param string $name

    * The name to be assigned. *

    * @return bool true on success or false on failure. */ function fbird_name_result($result, $name) {} /** * This is an alias of ibase_prepare * Prepare a query for later binding of parameter placeholders and execution * @link https://php.net/manual/en/function.fbird-prepare.php * @param string $query

    * An InterBase query. *

    * @return resource|false a prepared query handle, or false on error. */ function fbird_prepare($query) {} /** * This is an alias of ibase_execute * Execute a previously prepared query * @link https://php.net/manual/en/function.fbird-execute.php * @param resource $query

    * An InterBase query prepared by fbird_prepare. *

    * @param mixed ...$bind_arg [optional] * @return resource|bool

    If the query raises an error, returns false. If it is successful and * there is a (possibly empty) result set (such as with a SELECT query), * returns a result identifier. If the query was successful and there were * no results, returns true. *

    *

    * In PHP 5.0.0 and up, this function returns the number of rows affected by * the query (if > 0 and applicable to the statement type). A query that * succeeded, but did not affect any rows (e.g. an UPDATE of a non-existent * record) will return true.

    */ function fbird_execute($query, ...$bind_arg) {} /** * This is an alias of ibase_free_query * Free memory allocated by a prepared query * @link https://php.net/manual/en/function.fbird-free-query.php * @param resource $query

    * A query prepared with fbird_prepare. *

    * @return bool true on success or false on failure. */ function fbird_free_query($query) {} /** * This is an alias of ibase_gen_id * Increments the named generator and returns its new value * @link https://php.net/manual/en/function.fbird-gen-id.php * @param string $generator * @param int $increment [optional] * @param resource $link_identifier [optional] * @return mixed new generator value as integer, or as string if the value is too big. */ function fbird_gen_id($generator, $increment = null, $link_identifier = null) {} /** * This is an alias of ibase_num_fields * Get the number of fields in a result set * @link https://php.net/manual/en/function.fbird-num-fields.php * @param resource $result_id

    * An InterBase result identifier. *

    * @return int the number of fields as an integer. */ function fbird_num_fields($result_id) {} /** * This is an alias of ibase_num_params * Return the number of parameters in a prepared query * @link https://php.net/manual/en/function.fbird-num-params.php * @param resource $query

    * The prepared query handle. *

    * @return int the number of parameters as an integer. */ function fbird_num_params($query) {} /** * This is an alias of ibase_affected_rows * Return the number of rows that were affected by the previous query * @link https://php.net/manual/en/function.fbird-affected-rows.php * @param resource $link_identifier [optional]

    * A transaction context. If link_identifier is a * connection resource, its default transaction is used. *

    * @return int the number of rows as an integer. */ function fbird_affected_rows($link_identifier = null) {} /** * This is an alias of ibase_field_info * Get information about a field * @link https://php.net/manual/en/function.fbird-field-info.php * @param resource $result

    * An InterBase result identifier. *

    * @param int $field_number

    * Field offset. *

    * @return array an array with the following keys: name, * alias, relation, * length and type. */ function fbird_field_info($result, $field_number) {} /** * This is an alias of ibase_param_info * Return information about a parameter in a prepared query * @link https://php.net/manual/en/function.fbird-param-info.php * @param resource $query

    * An InterBase prepared query handle. *

    * @param int $param_number

    * Parameter offset. *

    * @return array an array with the following keys: name, * alias, relation, * length and type. */ function fbird_param_info($query, $param_number) {} /** * This is an alias of ibase_trans * Begin a transaction * @link https://php.net/manual/en/function.fbird-trans.php * @param int $trans_args [optional]

    * trans_args can be a combination of * IBASE_READ, * IBASE_WRITE, * IBASE_COMMITTED, * IBASE_CONSISTENCY, * IBASE_CONCURRENCY, * IBASE_REC_VERSION, * IBASE_REC_NO_VERSION, * IBASE_WAIT and * IBASE_NOWAIT. *

    * @param resource $link_identifier [optional]

    * An InterBase link identifier. If omitted, the last opened link is * assumed. *

    * @return resource|false a transaction handle, or false on error. */ function fbird_trans($trans_args = null, $link_identifier = null) {} /** * This is an alias of ibase_commit * Commit a transaction * @link https://php.net/manual/en/function.fbird-commit.php * @param resource $link_or_trans_identifier [optional]

    * If called without an argument, this function commits the default * transaction of the default link. If the argument is a connection * identifier, the default transaction of the corresponding connection * will be committed. If the argument is a transaction identifier, the * corresponding transaction will be committed. *

    * @return bool true on success or false on failure. */ function fbird_commit($link_or_trans_identifier = null) {} /** * This is an alias of ibase_rollback * Roll back a transaction * @link https://php.net/manual/en/function.fbird-rollback.php * @param resource $link_or_trans_identifier [optional]

    * If called without an argument, this function rolls back the default * transaction of the default link. If the argument is a connection * identifier, the default transaction of the corresponding connection * will be rolled back. If the argument is a transaction identifier, the * corresponding transaction will be rolled back. *

    * @return bool true on success or false on failure. */ function fbird_rollback($link_or_trans_identifier = null) {} /** * This is an alias of ibase_commit_ret * Commit a transaction without closing it * @link https://php.net/manual/en/function.fbird-commit-ret.php * @param resource $link_or_trans_identifier [optional]

    * If called without an argument, this function commits the default * transaction of the default link. If the argument is a connection * identifier, the default transaction of the corresponding connection * will be committed. If the argument is a transaction identifier, the * corresponding transaction will be committed. The transaction context * will be retained, so statements executed from within this transaction * will not be invalidated. *

    * @return bool true on success or false on failure. */ function fbird_commit_ret($link_or_trans_identifier = null) {} /** * This is an alias of ibase_rollback_ret * Roll back a transaction without closing it * @link https://php.net/manual/en/function.fbird-rollback-ret.php * @param resource $link_or_trans_identifier [optional]

    * If called without an argument, this function rolls back the default * transaction of the default link. If the argument is a connection * identifier, the default transaction of the corresponding connection * will be rolled back. If the argument is a transaction identifier, the * corresponding transaction will be rolled back. The transaction context * will be retained, so statements executed from within this transaction * will not be invalidated. *

    * @return bool true on success or false on failure. */ function fbird_rollback_ret($link_or_trans_identifier = null) {} /** * This is an alias of ibase_blob_info * Return blob length and other useful info * @link https://php.net/manual/en/function.fbird-blob-info.php * @param resource $link_identifier

    * An InterBase link identifier. If omitted, the last opened link is * assumed. *

    * @param string $blob_id

    * A BLOB id. *

    * @return array an array containing information about a BLOB. The information returned * consists of the length of the BLOB, the number of segments it contains, the size * of the largest segment, and whether it is a stream BLOB or a segmented BLOB. */ function fbird_blob_info($link_identifier, $blob_id) {} /** * This is an alias of ibase_blob_create * Create a new blob for adding data * @link https://php.net/manual/en/function.fbird-blob-create.php * @param resource $link_identifier [optional]

    * An InterBase link identifier. If omitted, the last opened link is * assumed. *

    * @return resource|false a BLOB handle for later use with * fbird_blob_add or false on failure. */ function fbird_blob_create($link_identifier = null) {} /** * This is an alias of ibase_blob_add * Add data into a newly created blob * @link https://php.net/manual/en/function.fbird-blob-add.php * @param resource $blob_handle

    * A blob handle opened with fbird_blob_create. *

    * @param string $data

    * The data to be added. *

    * @return void */ function fbird_blob_add($blob_handle, $data) {} /** * This is an alias of ibase_blob_cancel * Cancel creating blob * @link https://php.net/manual/en/function.fbird-blob-cancel.php * @param resource $blob_handle

    * A BLOB handle opened with fbird_blob_create. *

    * @return bool true on success or false on failure. */ function fbird_blob_cancel($blob_handle) {} /** * This is an alias of ibase_blob_close * Close blob * @link https://php.net/manual/en/function.fbird-blob-close.php * @param resource $blob_handle

    * A BLOB handle opened with fbird_blob_create or * fbird_blob_open. *

    * @return mixed If the BLOB was being read, this function returns true on success, if * the BLOB was being written to, this function returns a string containing * the BLOB id that has been assigned to it by the database. On failure, this * function returns false. */ function fbird_blob_close($blob_handle) {} /** * This is an alias of ibase_blob_open * Open blob for retrieving data parts * @link https://php.net/manual/en/function.fbird-blob-open.php * @param resource $link_identifier

    * An InterBase link identifier. If omitted, the last opened link is * assumed. *

    * @param string $blob_id

    * A BLOB id. *

    * @return resource|false a BLOB handle for later use with * fbird_blob_get or false on failure. */ function fbird_blob_open($link_identifier, $blob_id) {} /** * This is an alias of ibase_blob_get * Get len bytes data from open blob * @link https://php.net/manual/en/function.fbird-blob-get.php * @param resource $blob_handle

    * A BLOB handle opened with fbird_blob_open. *

    * @param int $len

    * Size of returned data. *

    * @return string|false at most len bytes from the BLOB, or false * on failure. */ function fbird_blob_get($blob_handle, $len) {} /** * This is an alias of ibase_blob_echo * Output blob contents to browser * @link https://php.net/manual/en/function.fbird-blob-echo.php * @param string $blob_id

    *

    * @return bool true on success or false on failure. */ function fbird_blob_echo($blob_id) {} /** * This is an alias of ibase_blob_import * Create blob, copy file in it, and close it * @link https://php.net/manual/en/function.fbird-blob-import.php * @param resource $link_identifier

    * An InterBase link identifier. If omitted, the last opened link is * assumed. *

    * @param resource $file_handle

    * The file handle is a handle returned by fopen. *

    * @return string|false the BLOB id on success, or false on error. */ function fbird_blob_import($link_identifier, $file_handle) {} /** * This is an alias of ibase_errmsg * Return error messages * @link https://php.net/manual/en/function.fbird-errmsg.php * @return string|false the error message as a string, or false if no error occurred. */ function fbird_errmsg() {} /** * This is an alias of ibase_errcode * Return an error code * @link https://php.net/manual/en/function.fbird-errcode.php * @return int|false the error code as an integer, or false if no error occurred. */ function fbird_errcode() {} /** * This is an alias of ibase_add_user * Add a user to a security database (only for IB6 or later) * @link https://php.net/manual/en/function.fbird-add-user.php * @param resource $service_handle * @param string $user_name * @param string $password * @param string $first_name [optional] * @param string $middle_name [optional] * @param string $last_name [optional] * @return bool true on success or false on failure. */ function fbird_add_user($service_handle, $user_name, $password, $first_name = null, $middle_name = null, $last_name = null) {} /** * This is an alias of ibase_modify_user * Modify a user to a security database (only for IB6 or later) * @link https://php.net/manual/en/function.fbird-modify-user.php * @param resource $service_handle * @param string $user_name * @param string $password * @param string $first_name [optional] * @param string $middle_name [optional] * @param string $last_name [optional] * @return bool true on success or false on failure. */ function fbird_modify_user($service_handle, $user_name, $password, $first_name = null, $middle_name = null, $last_name = null) {} /** * This is an alias of ibase_delete_user * Delete a user from a security database (only for IB6 or later) * @link https://php.net/manual/en/function.fbird-delete-user.php * @param resource $service_handle * @param string $user_name * @return bool true on success or false on failure. */ function fbird_delete_user($service_handle, $user_name) {} /** * This is an alias of ibase_service_attach * Connect to the service manager * @link https://php.net/manual/en/function.fbird-service-attach.php * @param string $host * @param string $dba_username * @param string $dba_password * @return resource|false */ function fbird_service_attach($host, $dba_username, $dba_password) {} /** * This is an alias of ibase_service_detach * Disconnect from the service manager * @link https://php.net/manual/en/function.fbird-service-detach.php * @param resource $service_handle * @return bool true on success or false on failure. */ function fbird_service_detach($service_handle) {} /** * This is an alias of ibase_backup * Initiates a backup task in the service manager and returns immediately * @link https://php.net/manual/en/function.fbird-backup.php * @param resource $service_handle * @param string $source_db * @param string $dest_file * @param int $options [optional] * @param bool $verbose [optional] * @return mixed */ function fbird_backup($service_handle, $source_db, $dest_file, $options = null, $verbose = null) {} /** * This is an alias of ibase_restore * Initiates a restore task in the service manager and returns immediately * @link https://php.net/manual/en/function.fbird-restore.php * @param resource $service_handle * @param string $source_file * @param string $dest_db * @param int $options [optional] * @param bool $verbose [optional] * @return mixed */ function fbird_restore($service_handle, $source_file, $dest_db, $options = null, $verbose = null) {} /** * This is an alias of ibase_maintain_db * Execute a maintenance command on the database server * @link https://php.net/manual/en/function.fbird-maintain-db.php * @param resource $service_handle * @param string $db * @param int $action * @param int $argument [optional] * @return bool true on success or false on failure. */ function fbird_maintain_db($service_handle, $db, $action, $argument = null) {} /** * This is an alias of ibase_db_info * Request statistics about a database * @link https://php.net/manual/en/function.fbird-db-info.php * @param resource $service_handle * @param string $db * @param int $action * @param int $argument [optional] * @return string */ function fbird_db_info($service_handle, $db, $action, $argument = null) {} /** * This is an alias of ibase_server_info * Request information about a database server * @link https://php.net/manual/en/function.fbird-server-info.php * @param resource $service_handle * @param int $action * @return string */ function fbird_server_info($service_handle, $action) {} /** * This is an alias of ibase_wait_event * Wait for an event to be posted by the database * @link https://php.net/manual/en/function.fbird-wait-event.php * @param string $event_name1

    * The event name. *

    * @param string $event_name2 [optional]

    *

    * @param string ...$_ [optional] * @return string the name of the event that was posted. */ function fbird_wait_event($event_name1, $event_name2 = null, ...$_) {} /** * This is an alias of ibase_set_event_handler * Register a callback function to be called when events are posted * @link https://php.net/manual/en/function.fbird-set-event-handler.php * @param callable $event_handler

    * The callback is called with the event name and the link resource as * arguments whenever one of the specified events is posted by the * database. *

    *

    * The callback must return false if the event handler should be * canceled. Any other return value is ignored. This function accepts up * to 15 event arguments. *

    * @param string $event_name1

    * An event name. *

    * @param string $event_name2 [optional]

    * At most 15 events allowed. *

    * @param string ...$_ [optional] * @return resource The return value is an event resource. This resource can be used to free * the event handler using fbird_free_event_handler. */ function fbird_set_event_handler($event_handler, $event_name1, $event_name2 = null, ...$_) {} /** * This is an alias of ibase_free_event_handler * Cancels a registered event handler * @link https://php.net/manual/en/function.fbird-free-event-handler.php * @param resource $event

    * An event resource, created by * fbird_set_event_handler. *

    * @return bool true on success or false on failure. */ function fbird_free_event_handler($event) {} /** * The default transaction settings are to be used. * This default is determined by the client library, which defines it as IBASE_WRITE|IBASE_CONCURRENCY|IBASE_WAIT in most cases. * @link https://www.php.net/manual/en/ibase.constants.php */ define('IBASE_DEFAULT', 0); /** * @link https://www.php.net/manual/en/ibase.constants.php */ define('IBASE_CREATE', 0); /** * Causes BLOB contents to be fetched inline, instead of being fetched as BLOB identifiers. * @link https://www.php.net/manual/en/ibase.constants.php */ define('IBASE_TEXT', 1); /** * Also available as IBASE_TEXT for backward compatibility. * Causes BLOB contents to be fetched inline, instead of being fetched as BLOB identifiers. * @link https://www.php.net/manual/en/ibase.constants.php */ define('IBASE_FETCH_BLOBS', 1); /** * Causes arrays to be fetched inline. Otherwise, array identifiers are returned. * Array identifiers can only be used as arguments to INSERT operations, as no functions to handle array identifiers are currently available. * @link https://www.php.net/manual/en/ibase.constants.php */ define('IBASE_FETCH_ARRAYS', 2); /** * Causes date and time fields not to be returned as strings, but as UNIX timestamps (the number of seconds since the epoch, which is 1-Jan-1970 0:00 UTC). * Might be problematic if used with dates before 1970 on some systems. * @link https://www.php.net/manual/en/ibase.constants.php */ define('IBASE_UNIXTIME', 4); /** * Starts a read-write transaction. * @link https://www.php.net/manual/en/ibase.constants.php */ define('IBASE_WRITE', 1); /** * Starts a read-only transaction. * @link https://www.php.net/manual/en/ibase.constants.php */ define('IBASE_READ', 2); /** * Starts a transaction with the isolation level set to 'read committed'. * This flag should be combined with either IBASE_REC_VERSION or IBASE_REC_NO_VERSION. * This isolation level allows access to changes that were committed after the transaction was started. * If IBASE_REC_NO_VERSION was specified, only the latest version of a row can be read. * If IBASE_REC_VERSION was specified, a row can even be read when a modification to it is pending in a concurrent transaction. * @link https://www.php.net/manual/en/ibase.constants.php */ define('IBASE_COMMITTED', 8); /** * Starts a transaction with the isolation level set to 'consistency', * which means the transaction cannot read from tables that are being modified by other concurrent transactions. * @link https://www.php.net/manual/en/ibase.constants.php */ define('IBASE_CONSISTENCY', 16); /** * Starts a transaction with the isolation level set to 'concurrency' (or 'snapshot'), * which means the transaction has access to all tables, * but cannot see changes that were committed by other transactions after the transaction was started. * @link https://www.php.net/manual/en/ibase.constants.php */ define('IBASE_CONCURRENCY', 4); /** * Row can even be read when a modification to it is pending in a concurrent transaction. * @link https://www.php.net/manual/en/ibase.constants.php */ define('IBASE_REC_VERSION', 64); /** * Only the latest version of a row can be read * @link https://www.php.net/manual/en/ibase.constants.php */ define('IBASE_REC_NO_VERSION', 32); /** * Indicated that a transaction should fail immediately when a conflict occurs. * @link https://www.php.net/manual/en/ibase.constants.php */ define('IBASE_NOWAIT', 256); /** * Indicated that a transaction should wait and retry when a conflict occurs. * @link https://www.php.net/manual/en/ibase.constants.php */ define('IBASE_WAIT', 128); define('IBASE_BKP_IGNORE_CHECKSUMS', 1); define('IBASE_BKP_IGNORE_LIMBO', 2); define('IBASE_BKP_METADATA_ONLY', 4); define('IBASE_BKP_NO_GARBAGE_COLLECT', 8); define('IBASE_BKP_OLD_DESCRIPTIONS', 16); define('IBASE_BKP_NON_TRANSPORTABLE', 32); /** * Options to ibase_backup * @link https://php.net/manual/en/ibase.constants.php */ define('IBASE_BKP_CONVERT', 64); define('IBASE_RES_DEACTIVATE_IDX', 256); define('IBASE_RES_NO_SHADOW', 512); define('IBASE_RES_NO_VALIDITY', 1024); define('IBASE_RES_ONE_AT_A_TIME', 2048); define('IBASE_RES_REPLACE', 4096); define('IBASE_RES_CREATE', 8192); /** * Options to ibase_restore * @link https://php.net/manual/en/ibase.constants.php */ define('IBASE_RES_USE_ALL_SPACE', 16384); define('IBASE_PRP_PAGE_BUFFERS', 5); define('IBASE_PRP_SWEEP_INTERVAL', 6); define('IBASE_PRP_SHUTDOWN_DB', 7); define('IBASE_PRP_DENY_NEW_TRANSACTIONS', 10); define('IBASE_PRP_DENY_NEW_ATTACHMENTS', 9); define('IBASE_PRP_RESERVE_SPACE', 11); define('IBASE_PRP_RES_USE_FULL', 35); define('IBASE_PRP_RES', 36); define('IBASE_PRP_WRITE_MODE', 12); define('IBASE_PRP_WM_ASYNC', 37); define('IBASE_PRP_WM_SYNC', 38); define('IBASE_PRP_ACCESS_MODE', 13); define('IBASE_PRP_AM_READONLY', 39); define('IBASE_PRP_AM_READWRITE', 40); define('IBASE_PRP_SET_SQL_DIALECT', 14); define('IBASE_PRP_ACTIVATE', 256); define('IBASE_PRP_DB_ONLINE', 512); define('IBASE_RPR_CHECK_DB', 16); define('IBASE_RPR_IGNORE_CHECKSUM', 32); define('IBASE_RPR_KILL_SHADOWS', 64); define('IBASE_RPR_MEND_DB', 4); define('IBASE_RPR_VALIDATE_DB', 1); define('IBASE_RPR_FULL', 128); /** * Options to ibase_maintain_db * @link https://php.net/manual/en/ibase.constants.php */ define('IBASE_RPR_SWEEP_DB', 2); define('IBASE_STS_DATA_PAGES', 1); define('IBASE_STS_DB_LOG', 2); define('IBASE_STS_HDR_PAGES', 4); define('IBASE_STS_IDX_PAGES', 8); /** * Options to ibase_db_info * @link https://php.net/manual/en/ibase.constants.php */ define('IBASE_STS_SYS_RELATIONS', 16); define('IBASE_SVC_SERVER_VERSION', 55); define('IBASE_SVC_IMPLEMENTATION', 56); define('IBASE_SVC_GET_ENV', 59); define('IBASE_SVC_GET_ENV_LOCK', 60); define('IBASE_SVC_GET_ENV_MSG', 61); define('IBASE_SVC_USER_DBPATH', 58); define('IBASE_SVC_SVR_DB_INFO', 50); /** * Options to ibase_server_info * @link https://php.net/manual/en/ibase.constants.php */ define('IBASE_SVC_GET_USERS', 68); // End of interbase v. IntlChar provides access to a number of utility methods that can be used to access information about Unicode characters.

    *

    The methods and constants adhere closely to the names and behavior used by the underlying ICU library.

    * @since 7.0 */ class IntlChar { public const UNICODE_VERSION = 13.0; public const CODEPOINT_MIN = 0; public const CODEPOINT_MAX = 1114111; public const FOLD_CASE_DEFAULT = 0; public const FOLD_CASE_EXCLUDE_SPECIAL_I = 1; public const PROPERTY_ALPHABETIC = 0; public const PROPERTY_BINARY_START = 0; public const PROPERTY_ASCII_HEX_DIGIT = 1; public const PROPERTY_BIDI_CONTROL = 2; public const PROPERTY_BIDI_MIRRORED = 3; public const PROPERTY_DASH = 4; public const PROPERTY_DEFAULT_IGNORABLE_CODE_POINT = 5; public const PROPERTY_DEPRECATED = 6; public const PROPERTY_DIACRITIC = 7; public const PROPERTY_EXTENDER = 8; public const PROPERTY_FULL_COMPOSITION_EXCLUSION = 9; public const PROPERTY_GRAPHEME_BASE = 10; public const PROPERTY_GRAPHEME_EXTEND = 11; public const PROPERTY_GRAPHEME_LINK = 12; public const PROPERTY_HEX_DIGIT = 13; public const PROPERTY_HYPHEN = 14; public const PROPERTY_ID_CONTINUE = 15; public const PROPERTY_ID_START = 16; public const PROPERTY_IDEOGRAPHIC = 17; public const PROPERTY_IDS_BINARY_OPERATOR = 18; public const PROPERTY_IDS_TRINARY_OPERATOR = 19; public const PROPERTY_JOIN_CONTROL = 20; public const PROPERTY_LOGICAL_ORDER_EXCEPTION = 21; public const PROPERTY_LOWERCASE = 22; public const PROPERTY_MATH = 23; public const PROPERTY_NONCHARACTER_CODE_POINT = 24; public const PROPERTY_QUOTATION_MARK = 25; public const PROPERTY_RADICAL = 26; public const PROPERTY_SOFT_DOTTED = 27; public const PROPERTY_TERMINAL_PUNCTUATION = 28; public const PROPERTY_UNIFIED_IDEOGRAPH = 29; public const PROPERTY_UPPERCASE = 30; public const PROPERTY_WHITE_SPACE = 31; public const PROPERTY_XID_CONTINUE = 32; public const PROPERTY_XID_START = 33; public const PROPERTY_CASE_SENSITIVE = 34; public const PROPERTY_S_TERM = 35; public const PROPERTY_VARIATION_SELECTOR = 36; public const PROPERTY_NFD_INERT = 37; public const PROPERTY_NFKD_INERT = 38; public const PROPERTY_NFC_INERT = 39; public const PROPERTY_NFKC_INERT = 40; public const PROPERTY_SEGMENT_STARTER = 41; public const PROPERTY_PATTERN_SYNTAX = 42; public const PROPERTY_PATTERN_WHITE_SPACE = 43; public const PROPERTY_POSIX_ALNUM = 44; public const PROPERTY_POSIX_BLANK = 45; public const PROPERTY_POSIX_GRAPH = 46; public const PROPERTY_POSIX_PRINT = 47; public const PROPERTY_POSIX_XDIGIT = 48; public const PROPERTY_CASED = 49; public const PROPERTY_CASE_IGNORABLE = 50; public const PROPERTY_CHANGES_WHEN_LOWERCASED = 51; public const PROPERTY_CHANGES_WHEN_UPPERCASED = 52; public const PROPERTY_CHANGES_WHEN_TITLECASED = 53; public const PROPERTY_CHANGES_WHEN_CASEFOLDED = 54; public const PROPERTY_CHANGES_WHEN_CASEMAPPED = 55; public const PROPERTY_CHANGES_WHEN_NFKC_CASEFOLDED = 56; public const PROPERTY_BINARY_LIMIT = 65; public const PROPERTY_BIDI_CLASS = 4096; public const PROPERTY_INT_START = 4096; public const PROPERTY_BLOCK = 4097; public const PROPERTY_CANONICAL_COMBINING_CLASS = 4098; public const PROPERTY_DECOMPOSITION_TYPE = 4099; public const PROPERTY_EAST_ASIAN_WIDTH = 4100; public const PROPERTY_GENERAL_CATEGORY = 4101; public const PROPERTY_JOINING_GROUP = 4102; public const PROPERTY_JOINING_TYPE = 4103; public const PROPERTY_LINE_BREAK = 4104; public const PROPERTY_NUMERIC_TYPE = 4105; public const PROPERTY_SCRIPT = 4106; public const PROPERTY_HANGUL_SYLLABLE_TYPE = 4107; public const PROPERTY_NFD_QUICK_CHECK = 4108; public const PROPERTY_NFKD_QUICK_CHECK = 4109; public const PROPERTY_NFC_QUICK_CHECK = 4110; public const PROPERTY_NFKC_QUICK_CHECK = 4111; public const PROPERTY_LEAD_CANONICAL_COMBINING_CLASS = 4112; public const PROPERTY_TRAIL_CANONICAL_COMBINING_CLASS = 4113; public const PROPERTY_GRAPHEME_CLUSTER_BREAK = 4114; public const PROPERTY_SENTENCE_BREAK = 4115; public const PROPERTY_WORD_BREAK = 4116; public const PROPERTY_BIDI_PAIRED_BRACKET_TYPE = 4117; public const PROPERTY_INT_LIMIT = 4121; public const PROPERTY_GENERAL_CATEGORY_MASK = 8192; public const PROPERTY_MASK_START = 8192; public const PROPERTY_MASK_LIMIT = 8193; public const PROPERTY_NUMERIC_VALUE = 12288; public const PROPERTY_DOUBLE_START = 12288; public const PROPERTY_DOUBLE_LIMIT = 12289; public const PROPERTY_AGE = 16384; public const PROPERTY_STRING_START = 16384; public const PROPERTY_BIDI_MIRRORING_GLYPH = 16385; public const PROPERTY_CASE_FOLDING = 16386; public const PROPERTY_ISO_COMMENT = 16387; public const PROPERTY_LOWERCASE_MAPPING = 16388; public const PROPERTY_NAME = 16389; public const PROPERTY_SIMPLE_CASE_FOLDING = 16390; public const PROPERTY_SIMPLE_LOWERCASE_MAPPING = 16391; public const PROPERTY_SIMPLE_TITLECASE_MAPPING = 16392; public const PROPERTY_SIMPLE_UPPERCASE_MAPPING = 16393; public const PROPERTY_TITLECASE_MAPPING = 16394; public const PROPERTY_UNICODE_1_NAME = 16395; public const PROPERTY_UPPERCASE_MAPPING = 16396; public const PROPERTY_BIDI_PAIRED_BRACKET = 16397; public const PROPERTY_STRING_LIMIT = 16398; public const PROPERTY_SCRIPT_EXTENSIONS = 28672; public const PROPERTY_OTHER_PROPERTY_START = 28672; public const PROPERTY_OTHER_PROPERTY_LIMIT = 28673; public const PROPERTY_INVALID_CODE = -1; public const CHAR_CATEGORY_UNASSIGNED = 0; public const CHAR_CATEGORY_GENERAL_OTHER_TYPES = 0; public const CHAR_CATEGORY_UPPERCASE_LETTER = 1; public const CHAR_CATEGORY_LOWERCASE_LETTER = 2; public const CHAR_CATEGORY_TITLECASE_LETTER = 3; public const CHAR_CATEGORY_MODIFIER_LETTER = 4; public const CHAR_CATEGORY_OTHER_LETTER = 5; public const CHAR_CATEGORY_NON_SPACING_MARK = 6; public const CHAR_CATEGORY_ENCLOSING_MARK = 7; public const CHAR_CATEGORY_COMBINING_SPACING_MARK = 8; public const CHAR_CATEGORY_DECIMAL_DIGIT_NUMBER = 9; public const CHAR_CATEGORY_LETTER_NUMBER = 10; public const CHAR_CATEGORY_OTHER_NUMBER = 11; public const CHAR_CATEGORY_SPACE_SEPARATOR = 12; public const CHAR_CATEGORY_LINE_SEPARATOR = 13; public const CHAR_CATEGORY_PARAGRAPH_SEPARATOR = 14; public const CHAR_CATEGORY_CONTROL_CHAR = 15; public const CHAR_CATEGORY_FORMAT_CHAR = 16; public const CHAR_CATEGORY_PRIVATE_USE_CHAR = 17; public const CHAR_CATEGORY_SURROGATE = 18; public const CHAR_CATEGORY_DASH_PUNCTUATION = 19; public const CHAR_CATEGORY_START_PUNCTUATION = 20; public const CHAR_CATEGORY_END_PUNCTUATION = 21; public const CHAR_CATEGORY_CONNECTOR_PUNCTUATION = 22; public const CHAR_CATEGORY_OTHER_PUNCTUATION = 23; public const CHAR_CATEGORY_MATH_SYMBOL = 24; public const CHAR_CATEGORY_CURRENCY_SYMBOL = 25; public const CHAR_CATEGORY_MODIFIER_SYMBOL = 26; public const CHAR_CATEGORY_OTHER_SYMBOL = 27; public const CHAR_CATEGORY_INITIAL_PUNCTUATION = 28; public const CHAR_CATEGORY_FINAL_PUNCTUATION = 29; public const CHAR_CATEGORY_CHAR_CATEGORY_COUNT = 30; public const CHAR_DIRECTION_LEFT_TO_RIGHT = 0; public const CHAR_DIRECTION_RIGHT_TO_LEFT = 1; public const CHAR_DIRECTION_EUROPEAN_NUMBER = 2; public const CHAR_DIRECTION_EUROPEAN_NUMBER_SEPARATOR = 3; public const CHAR_DIRECTION_EUROPEAN_NUMBER_TERMINATOR = 4; public const CHAR_DIRECTION_ARABIC_NUMBER = 5; public const CHAR_DIRECTION_COMMON_NUMBER_SEPARATOR = 6; public const CHAR_DIRECTION_BLOCK_SEPARATOR = 7; public const CHAR_DIRECTION_SEGMENT_SEPARATOR = 8; public const CHAR_DIRECTION_WHITE_SPACE_NEUTRAL = 9; public const CHAR_DIRECTION_OTHER_NEUTRAL = 10; public const CHAR_DIRECTION_LEFT_TO_RIGHT_EMBEDDING = 11; public const CHAR_DIRECTION_LEFT_TO_RIGHT_OVERRIDE = 12; public const CHAR_DIRECTION_RIGHT_TO_LEFT_ARABIC = 13; public const CHAR_DIRECTION_RIGHT_TO_LEFT_EMBEDDING = 14; public const CHAR_DIRECTION_RIGHT_TO_LEFT_OVERRIDE = 15; public const CHAR_DIRECTION_POP_DIRECTIONAL_FORMAT = 16; public const CHAR_DIRECTION_DIR_NON_SPACING_MARK = 17; public const CHAR_DIRECTION_BOUNDARY_NEUTRAL = 18; public const CHAR_DIRECTION_FIRST_STRONG_ISOLATE = 19; public const CHAR_DIRECTION_LEFT_TO_RIGHT_ISOLATE = 20; public const CHAR_DIRECTION_RIGHT_TO_LEFT_ISOLATE = 21; public const CHAR_DIRECTION_POP_DIRECTIONAL_ISOLATE = 22; public const CHAR_DIRECTION_CHAR_DIRECTION_COUNT = 23; public const BLOCK_CODE_NO_BLOCK = 0; public const BLOCK_CODE_BASIC_LATIN = 1; public const BLOCK_CODE_LATIN_1_SUPPLEMENT = 2; public const BLOCK_CODE_LATIN_EXTENDED_A = 3; public const BLOCK_CODE_LATIN_EXTENDED_B = 4; public const BLOCK_CODE_IPA_EXTENSIONS = 5; public const BLOCK_CODE_SPACING_MODIFIER_LETTERS = 6; public const BLOCK_CODE_COMBINING_DIACRITICAL_MARKS = 7; public const BLOCK_CODE_GREEK = 8; public const BLOCK_CODE_CYRILLIC = 9; public const BLOCK_CODE_ARMENIAN = 10; public const BLOCK_CODE_HEBREW = 11; public const BLOCK_CODE_ARABIC = 12; public const BLOCK_CODE_SYRIAC = 13; public const BLOCK_CODE_THAANA = 14; public const BLOCK_CODE_DEVANAGARI = 15; public const BLOCK_CODE_BENGALI = 16; public const BLOCK_CODE_GURMUKHI = 17; public const BLOCK_CODE_GUJARATI = 18; public const BLOCK_CODE_ORIYA = 19; public const BLOCK_CODE_TAMIL = 20; public const BLOCK_CODE_TELUGU = 21; public const BLOCK_CODE_KANNADA = 22; public const BLOCK_CODE_MALAYALAM = 23; public const BLOCK_CODE_SINHALA = 24; public const BLOCK_CODE_THAI = 25; public const BLOCK_CODE_LAO = 26; public const BLOCK_CODE_TIBETAN = 27; public const BLOCK_CODE_MYANMAR = 28; public const BLOCK_CODE_GEORGIAN = 29; public const BLOCK_CODE_HANGUL_JAMO = 30; public const BLOCK_CODE_ETHIOPIC = 31; public const BLOCK_CODE_CHEROKEE = 32; public const BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS = 33; public const BLOCK_CODE_OGHAM = 34; public const BLOCK_CODE_RUNIC = 35; public const BLOCK_CODE_KHMER = 36; public const BLOCK_CODE_MONGOLIAN = 37; public const BLOCK_CODE_LATIN_EXTENDED_ADDITIONAL = 38; public const BLOCK_CODE_GREEK_EXTENDED = 39; public const BLOCK_CODE_GENERAL_PUNCTUATION = 40; public const BLOCK_CODE_SUPERSCRIPTS_AND_SUBSCRIPTS = 41; public const BLOCK_CODE_CURRENCY_SYMBOLS = 42; public const BLOCK_CODE_COMBINING_MARKS_FOR_SYMBOLS = 43; public const BLOCK_CODE_LETTERLIKE_SYMBOLS = 44; public const BLOCK_CODE_NUMBER_FORMS = 45; public const BLOCK_CODE_ARROWS = 46; public const BLOCK_CODE_MATHEMATICAL_OPERATORS = 47; public const BLOCK_CODE_MISCELLANEOUS_TECHNICAL = 48; public const BLOCK_CODE_CONTROL_PICTURES = 49; public const BLOCK_CODE_OPTICAL_CHARACTER_RECOGNITION = 50; public const BLOCK_CODE_ENCLOSED_ALPHANUMERICS = 51; public const BLOCK_CODE_BOX_DRAWING = 52; public const BLOCK_CODE_BLOCK_ELEMENTS = 53; public const BLOCK_CODE_GEOMETRIC_SHAPES = 54; public const BLOCK_CODE_MISCELLANEOUS_SYMBOLS = 55; public const BLOCK_CODE_DINGBATS = 56; public const BLOCK_CODE_BRAILLE_PATTERNS = 57; public const BLOCK_CODE_CJK_RADICALS_SUPPLEMENT = 58; public const BLOCK_CODE_KANGXI_RADICALS = 59; public const BLOCK_CODE_IDEOGRAPHIC_DESCRIPTION_CHARACTERS = 60; public const BLOCK_CODE_CJK_SYMBOLS_AND_PUNCTUATION = 61; public const BLOCK_CODE_HIRAGANA = 62; public const BLOCK_CODE_KATAKANA = 63; public const BLOCK_CODE_BOPOMOFO = 64; public const BLOCK_CODE_HANGUL_COMPATIBILITY_JAMO = 65; public const BLOCK_CODE_KANBUN = 66; public const BLOCK_CODE_BOPOMOFO_EXTENDED = 67; public const BLOCK_CODE_ENCLOSED_CJK_LETTERS_AND_MONTHS = 68; public const BLOCK_CODE_CJK_COMPATIBILITY = 69; public const BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A = 70; public const BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS = 71; public const BLOCK_CODE_YI_SYLLABLES = 72; public const BLOCK_CODE_YI_RADICALS = 73; public const BLOCK_CODE_HANGUL_SYLLABLES = 74; public const BLOCK_CODE_HIGH_SURROGATES = 75; public const BLOCK_CODE_HIGH_PRIVATE_USE_SURROGATES = 76; public const BLOCK_CODE_LOW_SURROGATES = 77; public const BLOCK_CODE_PRIVATE_USE_AREA = 78; public const BLOCK_CODE_PRIVATE_USE = 78; public const BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS = 79; public const BLOCK_CODE_ALPHABETIC_PRESENTATION_FORMS = 80; public const BLOCK_CODE_ARABIC_PRESENTATION_FORMS_A = 81; public const BLOCK_CODE_COMBINING_HALF_MARKS = 82; public const BLOCK_CODE_CJK_COMPATIBILITY_FORMS = 83; public const BLOCK_CODE_SMALL_FORM_VARIANTS = 84; public const BLOCK_CODE_ARABIC_PRESENTATION_FORMS_B = 85; public const BLOCK_CODE_SPECIALS = 86; public const BLOCK_CODE_HALFWIDTH_AND_FULLWIDTH_FORMS = 87; public const BLOCK_CODE_OLD_ITALIC = 88; public const BLOCK_CODE_GOTHIC = 89; public const BLOCK_CODE_DESERET = 90; public const BLOCK_CODE_BYZANTINE_MUSICAL_SYMBOLS = 91; public const BLOCK_CODE_MUSICAL_SYMBOLS = 92; public const BLOCK_CODE_MATHEMATICAL_ALPHANUMERIC_SYMBOLS = 93; public const BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B = 94; public const BLOCK_CODE_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT = 95; public const BLOCK_CODE_TAGS = 96; public const BLOCK_CODE_CYRILLIC_SUPPLEMENT = 97; public const BLOCK_CODE_CYRILLIC_SUPPLEMENTARY = 97; public const BLOCK_CODE_TAGALOG = 98; public const BLOCK_CODE_HANUNOO = 99; public const BLOCK_CODE_BUHID = 100; public const BLOCK_CODE_TAGBANWA = 101; public const BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A = 102; public const BLOCK_CODE_SUPPLEMENTAL_ARROWS_A = 103; public const BLOCK_CODE_SUPPLEMENTAL_ARROWS_B = 104; public const BLOCK_CODE_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B = 105; public const BLOCK_CODE_SUPPLEMENTAL_MATHEMATICAL_OPERATORS = 106; public const BLOCK_CODE_KATAKANA_PHONETIC_EXTENSIONS = 107; public const BLOCK_CODE_VARIATION_SELECTORS = 108; public const BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_A = 109; public const BLOCK_CODE_SUPPLEMENTARY_PRIVATE_USE_AREA_B = 110; public const BLOCK_CODE_LIMBU = 111; public const BLOCK_CODE_TAI_LE = 112; public const BLOCK_CODE_KHMER_SYMBOLS = 113; public const BLOCK_CODE_PHONETIC_EXTENSIONS = 114; public const BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_ARROWS = 115; public const BLOCK_CODE_YIJING_HEXAGRAM_SYMBOLS = 116; public const BLOCK_CODE_LINEAR_B_SYLLABARY = 117; public const BLOCK_CODE_LINEAR_B_IDEOGRAMS = 118; public const BLOCK_CODE_AEGEAN_NUMBERS = 119; public const BLOCK_CODE_UGARITIC = 120; public const BLOCK_CODE_SHAVIAN = 121; public const BLOCK_CODE_OSMANYA = 122; public const BLOCK_CODE_CYPRIOT_SYLLABARY = 123; public const BLOCK_CODE_TAI_XUAN_JING_SYMBOLS = 124; public const BLOCK_CODE_VARIATION_SELECTORS_SUPPLEMENT = 125; public const BLOCK_CODE_ANCIENT_GREEK_MUSICAL_NOTATION = 126; public const BLOCK_CODE_ANCIENT_GREEK_NUMBERS = 127; public const BLOCK_CODE_ARABIC_SUPPLEMENT = 128; public const BLOCK_CODE_BUGINESE = 129; public const BLOCK_CODE_CJK_STROKES = 130; public const BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT = 131; public const BLOCK_CODE_COPTIC = 132; public const BLOCK_CODE_ETHIOPIC_EXTENDED = 133; public const BLOCK_CODE_ETHIOPIC_SUPPLEMENT = 134; public const BLOCK_CODE_GEORGIAN_SUPPLEMENT = 135; public const BLOCK_CODE_GLAGOLITIC = 136; public const BLOCK_CODE_KHAROSHTHI = 137; public const BLOCK_CODE_MODIFIER_TONE_LETTERS = 138; public const BLOCK_CODE_NEW_TAI_LUE = 139; public const BLOCK_CODE_OLD_PERSIAN = 140; public const BLOCK_CODE_PHONETIC_EXTENSIONS_SUPPLEMENT = 141; public const BLOCK_CODE_SUPPLEMENTAL_PUNCTUATION = 142; public const BLOCK_CODE_SYLOTI_NAGRI = 143; public const BLOCK_CODE_TIFINAGH = 144; public const BLOCK_CODE_VERTICAL_FORMS = 145; public const BLOCK_CODE_NKO = 146; public const BLOCK_CODE_BALINESE = 147; public const BLOCK_CODE_LATIN_EXTENDED_C = 148; public const BLOCK_CODE_LATIN_EXTENDED_D = 149; public const BLOCK_CODE_PHAGS_PA = 150; public const BLOCK_CODE_PHOENICIAN = 151; public const BLOCK_CODE_CUNEIFORM = 152; public const BLOCK_CODE_CUNEIFORM_NUMBERS_AND_PUNCTUATION = 153; public const BLOCK_CODE_COUNTING_ROD_NUMERALS = 154; public const BLOCK_CODE_SUNDANESE = 155; public const BLOCK_CODE_LEPCHA = 156; public const BLOCK_CODE_OL_CHIKI = 157; public const BLOCK_CODE_CYRILLIC_EXTENDED_A = 158; public const BLOCK_CODE_VAI = 159; public const BLOCK_CODE_CYRILLIC_EXTENDED_B = 160; public const BLOCK_CODE_SAURASHTRA = 161; public const BLOCK_CODE_KAYAH_LI = 162; public const BLOCK_CODE_REJANG = 163; public const BLOCK_CODE_CHAM = 164; public const BLOCK_CODE_ANCIENT_SYMBOLS = 165; public const BLOCK_CODE_PHAISTOS_DISC = 166; public const BLOCK_CODE_LYCIAN = 167; public const BLOCK_CODE_CARIAN = 168; public const BLOCK_CODE_LYDIAN = 169; public const BLOCK_CODE_MAHJONG_TILES = 170; public const BLOCK_CODE_DOMINO_TILES = 171; public const BLOCK_CODE_SAMARITAN = 172; public const BLOCK_CODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED = 173; public const BLOCK_CODE_TAI_THAM = 174; public const BLOCK_CODE_VEDIC_EXTENSIONS = 175; public const BLOCK_CODE_LISU = 176; public const BLOCK_CODE_BAMUM = 177; public const BLOCK_CODE_COMMON_INDIC_NUMBER_FORMS = 178; public const BLOCK_CODE_DEVANAGARI_EXTENDED = 179; public const BLOCK_CODE_HANGUL_JAMO_EXTENDED_A = 180; public const BLOCK_CODE_JAVANESE = 181; public const BLOCK_CODE_MYANMAR_EXTENDED_A = 182; public const BLOCK_CODE_TAI_VIET = 183; public const BLOCK_CODE_MEETEI_MAYEK = 184; public const BLOCK_CODE_HANGUL_JAMO_EXTENDED_B = 185; public const BLOCK_CODE_IMPERIAL_ARAMAIC = 186; public const BLOCK_CODE_OLD_SOUTH_ARABIAN = 187; public const BLOCK_CODE_AVESTAN = 188; public const BLOCK_CODE_INSCRIPTIONAL_PARTHIAN = 189; public const BLOCK_CODE_INSCRIPTIONAL_PAHLAVI = 190; public const BLOCK_CODE_OLD_TURKIC = 191; public const BLOCK_CODE_RUMI_NUMERAL_SYMBOLS = 192; public const BLOCK_CODE_KAITHI = 193; public const BLOCK_CODE_EGYPTIAN_HIEROGLYPHS = 194; public const BLOCK_CODE_ENCLOSED_ALPHANUMERIC_SUPPLEMENT = 195; public const BLOCK_CODE_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT = 196; public const BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C = 197; public const BLOCK_CODE_MANDAIC = 198; public const BLOCK_CODE_BATAK = 199; public const BLOCK_CODE_ETHIOPIC_EXTENDED_A = 200; public const BLOCK_CODE_BRAHMI = 201; public const BLOCK_CODE_BAMUM_SUPPLEMENT = 202; public const BLOCK_CODE_KANA_SUPPLEMENT = 203; public const BLOCK_CODE_PLAYING_CARDS = 204; public const BLOCK_CODE_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS = 205; public const BLOCK_CODE_EMOTICONS = 206; public const BLOCK_CODE_TRANSPORT_AND_MAP_SYMBOLS = 207; public const BLOCK_CODE_ALCHEMICAL_SYMBOLS = 208; public const BLOCK_CODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D = 209; public const BLOCK_CODE_ARABIC_EXTENDED_A = 210; public const BLOCK_CODE_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS = 211; public const BLOCK_CODE_CHAKMA = 212; public const BLOCK_CODE_MEETEI_MAYEK_EXTENSIONS = 213; public const BLOCK_CODE_MEROITIC_CURSIVE = 214; public const BLOCK_CODE_MEROITIC_HIEROGLYPHS = 215; public const BLOCK_CODE_MIAO = 216; public const BLOCK_CODE_SHARADA = 217; public const BLOCK_CODE_SORA_SOMPENG = 218; public const BLOCK_CODE_SUNDANESE_SUPPLEMENT = 219; public const BLOCK_CODE_TAKRI = 220; public const BLOCK_CODE_BASSA_VAH = 221; public const BLOCK_CODE_CAUCASIAN_ALBANIAN = 222; public const BLOCK_CODE_COPTIC_EPACT_NUMBERS = 223; public const BLOCK_CODE_COMBINING_DIACRITICAL_MARKS_EXTENDED = 224; public const BLOCK_CODE_DUPLOYAN = 225; public const BLOCK_CODE_ELBASAN = 226; public const BLOCK_CODE_GEOMETRIC_SHAPES_EXTENDED = 227; public const BLOCK_CODE_GRANTHA = 228; public const BLOCK_CODE_KHOJKI = 229; public const BLOCK_CODE_KHUDAWADI = 230; public const BLOCK_CODE_LATIN_EXTENDED_E = 231; public const BLOCK_CODE_LINEAR_A = 232; public const BLOCK_CODE_MAHAJANI = 233; public const BLOCK_CODE_MANICHAEAN = 234; public const BLOCK_CODE_MENDE_KIKAKUI = 235; public const BLOCK_CODE_MODI = 236; public const BLOCK_CODE_MRO = 237; public const BLOCK_CODE_MYANMAR_EXTENDED_B = 238; public const BLOCK_CODE_NABATAEAN = 239; public const BLOCK_CODE_OLD_NORTH_ARABIAN = 240; public const BLOCK_CODE_OLD_PERMIC = 241; public const BLOCK_CODE_ORNAMENTAL_DINGBATS = 242; public const BLOCK_CODE_PAHAWH_HMONG = 243; public const BLOCK_CODE_PALMYRENE = 244; public const BLOCK_CODE_PAU_CIN_HAU = 245; public const BLOCK_CODE_PSALTER_PAHLAVI = 246; public const BLOCK_CODE_SHORTHAND_FORMAT_CONTROLS = 247; public const BLOCK_CODE_SIDDHAM = 248; public const BLOCK_CODE_SINHALA_ARCHAIC_NUMBERS = 249; public const BLOCK_CODE_SUPPLEMENTAL_ARROWS_C = 250; public const BLOCK_CODE_TIRHUTA = 251; public const BLOCK_CODE_WARANG_CITI = 252; public const BLOCK_CODE_COUNT = 309; public const BLOCK_CODE_INVALID_CODE = -1; public const BPT_NONE = 0; public const BPT_OPEN = 1; public const BPT_CLOSE = 2; public const BPT_COUNT = 3; public const EA_NEUTRAL = 0; public const EA_AMBIGUOUS = 1; public const EA_HALFWIDTH = 2; public const EA_FULLWIDTH = 3; public const EA_NARROW = 4; public const EA_WIDE = 5; public const EA_COUNT = 6; public const UNICODE_CHAR_NAME = 0; public const UNICODE_10_CHAR_NAME = 1; public const EXTENDED_CHAR_NAME = 2; public const CHAR_NAME_ALIAS = 3; public const CHAR_NAME_CHOICE_COUNT = 4; public const SHORT_PROPERTY_NAME = 0; public const LONG_PROPERTY_NAME = 1; public const PROPERTY_NAME_CHOICE_COUNT = 2; public const DT_NONE = 0; public const DT_CANONICAL = 1; public const DT_COMPAT = 2; public const DT_CIRCLE = 3; public const DT_FINAL = 4; public const DT_FONT = 5; public const DT_FRACTION = 6; public const DT_INITIAL = 7; public const DT_ISOLATED = 8; public const DT_MEDIAL = 9; public const DT_NARROW = 10; public const DT_NOBREAK = 11; public const DT_SMALL = 12; public const DT_SQUARE = 13; public const DT_SUB = 14; public const DT_SUPER = 15; public const DT_VERTICAL = 16; public const DT_WIDE = 17; public const DT_COUNT = 18; public const JT_NON_JOINING = 0; public const JT_JOIN_CAUSING = 1; public const JT_DUAL_JOINING = 2; public const JT_LEFT_JOINING = 3; public const JT_RIGHT_JOINING = 4; public const JT_TRANSPARENT = 5; public const JT_COUNT = 6; public const JG_NO_JOINING_GROUP = 0; public const JG_AIN = 1; public const JG_ALAPH = 2; public const JG_ALEF = 3; public const JG_BEH = 4; public const JG_BETH = 5; public const JG_DAL = 6; public const JG_DALATH_RISH = 7; public const JG_E = 8; public const JG_FEH = 9; public const JG_FINAL_SEMKATH = 10; public const JG_GAF = 11; public const JG_GAMAL = 12; public const JG_HAH = 13; public const JG_TEH_MARBUTA_GOAL = 14; public const JG_HAMZA_ON_HEH_GOAL = 14; public const JG_HE = 15; public const JG_HEH = 16; public const JG_HEH_GOAL = 17; public const JG_HETH = 18; public const JG_KAF = 19; public const JG_KAPH = 20; public const JG_KNOTTED_HEH = 21; public const JG_LAM = 22; public const JG_LAMADH = 23; public const JG_MEEM = 24; public const JG_MIM = 25; public const JG_NOON = 26; public const JG_NUN = 27; public const JG_PE = 28; public const JG_QAF = 29; public const JG_QAPH = 30; public const JG_REH = 31; public const JG_REVERSED_PE = 32; public const JG_SAD = 33; public const JG_SADHE = 34; public const JG_SEEN = 35; public const JG_SEMKATH = 36; public const JG_SHIN = 37; public const JG_SWASH_KAF = 38; public const JG_SYRIAC_WAW = 39; public const JG_TAH = 40; public const JG_TAW = 41; public const JG_TEH_MARBUTA = 42; public const JG_TETH = 43; public const JG_WAW = 44; public const JG_YEH = 45; public const JG_YEH_BARREE = 46; public const JG_YEH_WITH_TAIL = 47; public const JG_YUDH = 48; public const JG_YUDH_HE = 49; public const JG_ZAIN = 50; public const JG_FE = 51; public const JG_KHAPH = 52; public const JG_ZHAIN = 53; public const JG_BURUSHASKI_YEH_BARREE = 54; public const JG_FARSI_YEH = 55; public const JG_NYA = 56; public const JG_ROHINGYA_YEH = 57; public const JG_MANICHAEAN_ALEPH = 58; public const JG_MANICHAEAN_AYIN = 59; public const JG_MANICHAEAN_BETH = 60; public const JG_MANICHAEAN_DALETH = 61; public const JG_MANICHAEAN_DHAMEDH = 62; public const JG_MANICHAEAN_FIVE = 63; public const JG_MANICHAEAN_GIMEL = 64; public const JG_MANICHAEAN_HETH = 65; public const JG_MANICHAEAN_HUNDRED = 66; public const JG_MANICHAEAN_KAPH = 67; public const JG_MANICHAEAN_LAMEDH = 68; public const JG_MANICHAEAN_MEM = 69; public const JG_MANICHAEAN_NUN = 70; public const JG_MANICHAEAN_ONE = 71; public const JG_MANICHAEAN_PE = 72; public const JG_MANICHAEAN_QOPH = 73; public const JG_MANICHAEAN_RESH = 74; public const JG_MANICHAEAN_SADHE = 75; public const JG_MANICHAEAN_SAMEKH = 76; public const JG_MANICHAEAN_TAW = 77; public const JG_MANICHAEAN_TEN = 78; public const JG_MANICHAEAN_TETH = 79; public const JG_MANICHAEAN_THAMEDH = 80; public const JG_MANICHAEAN_TWENTY = 81; public const JG_MANICHAEAN_WAW = 82; public const JG_MANICHAEAN_YODH = 83; public const JG_MANICHAEAN_ZAYIN = 84; public const JG_STRAIGHT_WAW = 85; public const JG_COUNT = 102; public const GCB_OTHER = 0; public const GCB_CONTROL = 1; public const GCB_CR = 2; public const GCB_EXTEND = 3; public const GCB_L = 4; public const GCB_LF = 5; public const GCB_LV = 6; public const GCB_LVT = 7; public const GCB_T = 8; public const GCB_V = 9; public const GCB_SPACING_MARK = 10; public const GCB_PREPEND = 11; public const GCB_REGIONAL_INDICATOR = 12; public const GCB_COUNT = 18; public const WB_OTHER = 0; public const WB_ALETTER = 1; public const WB_FORMAT = 2; public const WB_KATAKANA = 3; public const WB_MIDLETTER = 4; public const WB_MIDNUM = 5; public const WB_NUMERIC = 6; public const WB_EXTENDNUMLET = 7; public const WB_CR = 8; public const WB_EXTEND = 9; public const WB_LF = 10; public const WB_MIDNUMLET = 11; public const WB_NEWLINE = 12; public const WB_REGIONAL_INDICATOR = 13; public const WB_HEBREW_LETTER = 14; public const WB_SINGLE_QUOTE = 15; public const WB_DOUBLE_QUOTE = 16; public const WB_COUNT = 23; public const SB_OTHER = 0; public const SB_ATERM = 1; public const SB_CLOSE = 2; public const SB_FORMAT = 3; public const SB_LOWER = 4; public const SB_NUMERIC = 5; public const SB_OLETTER = 6; public const SB_SEP = 7; public const SB_SP = 8; public const SB_STERM = 9; public const SB_UPPER = 10; public const SB_CR = 11; public const SB_EXTEND = 12; public const SB_LF = 13; public const SB_SCONTINUE = 14; public const SB_COUNT = 15; public const LB_UNKNOWN = 0; public const LB_AMBIGUOUS = 1; public const LB_ALPHABETIC = 2; public const LB_BREAK_BOTH = 3; public const LB_BREAK_AFTER = 4; public const LB_BREAK_BEFORE = 5; public const LB_MANDATORY_BREAK = 6; public const LB_CONTINGENT_BREAK = 7; public const LB_CLOSE_PUNCTUATION = 8; public const LB_COMBINING_MARK = 9; public const LB_CARRIAGE_RETURN = 10; public const LB_EXCLAMATION = 11; public const LB_GLUE = 12; public const LB_HYPHEN = 13; public const LB_IDEOGRAPHIC = 14; public const LB_INSEPARABLE = 15; public const LB_INSEPERABLE = 15; public const LB_INFIX_NUMERIC = 16; public const LB_LINE_FEED = 17; public const LB_NONSTARTER = 18; public const LB_NUMERIC = 19; public const LB_OPEN_PUNCTUATION = 20; public const LB_POSTFIX_NUMERIC = 21; public const LB_PREFIX_NUMERIC = 22; public const LB_QUOTATION = 23; public const LB_COMPLEX_CONTEXT = 24; public const LB_SURROGATE = 25; public const LB_SPACE = 26; public const LB_BREAK_SYMBOLS = 27; public const LB_ZWSPACE = 28; public const LB_NEXT_LINE = 29; public const LB_WORD_JOINER = 30; public const LB_H2 = 31; public const LB_H3 = 32; public const LB_JL = 33; public const LB_JT = 34; public const LB_JV = 35; public const LB_CLOSE_PARENTHESIS = 36; public const LB_CONDITIONAL_JAPANESE_STARTER = 37; public const LB_HEBREW_LETTER = 38; public const LB_REGIONAL_INDICATOR = 39; public const LB_COUNT = 43; public const NT_NONE = 0; public const NT_DECIMAL = 1; public const NT_DIGIT = 2; public const NT_NUMERIC = 3; public const NT_COUNT = 4; public const HST_NOT_APPLICABLE = 0; public const HST_LEADING_JAMO = 1; public const HST_VOWEL_JAMO = 2; public const HST_TRAILING_JAMO = 3; public const HST_LV_SYLLABLE = 4; public const HST_LVT_SYLLABLE = 5; public const HST_COUNT = 6; public const NO_NUMERIC_VALUE = -123456789; /** * @since 8.4 */ public const PROPERTY_IDS_UNARY_OPERATOR = 72; /** * @since 8.4 */ public const PROPERTY_ID_COMPAT_MATH_START = 73; /** * @since 8.4 */ public const PROPERTY_ID_COMPAT_MATH_CONTINUE = 74; /** * Check a binary Unicode property for a code point * @link https://php.net/manual/en/intlchar.hasbinaryproperty.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @param int $property The Unicode property to lookup (see the IntlChar::PROPERTY_* constants). * @return bool|null Returns TRUE or FALSE according to the binary Unicode property value for codepoint. * Also FALSE if property is out of bounds or if the Unicode version does not have data for the property at all, or not for this code point. * Or NULL if codepoint is out of bounds. * @since 7.0 */ #[Pure] #[TentativeType] public static function hasBinaryProperty( #[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $property ): ?bool {} /** * @link https://php.net/manual/en/intlchar.charage.php * Get the "age" of the code point * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return array|null The Unicode version number, as an array. For example, version 1.3.31.2 would be represented as [1, 3, 31, 2]. * Or NULL if codepoint is out of bounds. * @since 7.0 */ #[TentativeType] public static function charAge(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?array {} /** * @link https://php.net/manual/en/intlchar.chardigitvalue.php * Get the decimal digit value of a decimal digit character * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return int|null The decimal digit value of codepoint, or -1 if it is not a decimal digit character. * Or NULL if codepoint is out of bounds. * @since 7.0 */ #[TentativeType] public static function charDigitValue(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?int {} /** * Get bidirectional category value for a code point * @link https://php.net/manual/en/intlchar.chardirection.php * @param int|string $codepoint

    The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}")

    * @return int|null

    The bidirectional category value; one of the following constants: *

    *
      *
    • IntlChar::CHAR_DIRECTION_LEFT_TO_RIGHT
    • *
    • IntlChar::CHAR_DIRECTION_RIGHT_TO_LEFT
    • *
    • IntlChar::CHAR_DIRECTION_EUROPEAN_NUMBER
    • *
    • IntlChar::CHAR_DIRECTION_EUROPEAN_NUMBER_SEPARATOR
    • *
    • IntlChar::CHAR_DIRECTION_EUROPEAN_NUMBER_TERMINATOR
    • *
    • IntlChar::CHAR_DIRECTION_ARABIC_NUMBER
    • *
    • IntlChar::CHAR_DIRECTION_COMMON_NUMBER_SEPARATOR
    • *
    • IntlChar::CHAR_DIRECTION_BLOCK_SEPARATOR
    • *
    • IntlChar::CHAR_DIRECTION_SEGMENT_SEPARATOR
    • *
    • IntlChar::CHAR_DIRECTION_WHITE_SPACE_NEUTRAL
    • *
    • IntlChar::CHAR_DIRECTION_OTHER_NEUTRAL
    • *
    • IntlChar::CHAR_DIRECTION_LEFT_TO_RIGHT_EMBEDDING
    • *
    • IntlChar::CHAR_DIRECTION_LEFT_TO_RIGHT_OVERRIDE
    • *
    • IntlChar::CHAR_DIRECTION_RIGHT_TO_LEFT_ARABIC
    • *
    • IntlChar::CHAR_DIRECTION_RIGHT_TO_LEFT_EMBEDDING
    • *
    • IntlChar::CHAR_DIRECTION_RIGHT_TO_LEFT_OVERRIDE
    • *
    • IntlChar::CHAR_DIRECTION_POP_DIRECTIONAL_FORMAT
    • *
    • IntlChar::CHAR_DIRECTION_DIR_NON_SPACING_MARK
    • *
    • IntlChar::CHAR_DIRECTION_BOUNDARY_NEUTRAL
    • *
    • IntlChar::CHAR_DIRECTION_FIRST_STRONG_ISOLATE
    • *
    • IntlChar::CHAR_DIRECTION_LEFT_TO_RIGHT_ISOLATE
    • *
    • IntlChar::CHAR_DIRECTION_RIGHT_TO_LEFT_ISOLATE
    • *
    • IntlChar::CHAR_DIRECTION_POP_DIRECTIONAL_ISOLATE
    • *
    • IntlChar::CHAR_DIRECTION_CHAR_DIRECTION_COUNT
    • *
    * Or NULL if codepoint is out of bounds. * @since 7.0 */ #[TentativeType] public static function charDirection(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?int {} /** * @link https://php.net/manual/en/intlchar.charfromname.php * Find Unicode character by name and return its code point value * @param string $name

    Full name of the Unicode character.

    * @param int $type [optional]

    * Which set of names to use for the lookup. Can be any of these constants: *

      *
    • IntlChar::UNICODE_CHAR_NAME (default)
    • *
    • IntlChar::UNICODE_10_CHAR_NAME
    • *
    • IntlChar::EXTENDED_CHAR_NAME
    • *
    • IntlChar::CHAR_NAME_ALIAS
    • *
    • IntlChar::CHAR_NAME_CHOICE_COUNT
    • *
    * @return int|null The Unicode value of the code point with the given name (as an integer), or NULL if there is no such code point. * @since 7.0 */ #[TentativeType] public static function charFromName( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $type = IntlChar::UNICODE_CHAR_NAME ): ?int {} /** * @link https://php.net/manual/en/intlchar.charmirror.php * Get the "mirror-image" character for a code point * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return int|string|null Returns another Unicode code point that may serve as a mirror-image substitute, or codepoint itself if there is no such mapping or codepoint does not have the Bidi_Mirrored property. * The return type will be integer unless the code point was passed as a UTF-8 string, in which case a string will be returned. * Or NULL if codepoint will be out of bound. */ #[TentativeType] public static function charMirror(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): string|int|null {} /** * Retrieve the name of a Unicode character * @link https://php.net/manual/en/intlchar.charname.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @param int $type [optional] Which set of names to use for the lookup. Can be any of these constants: *
      *
    • IntlChar::UNICODE_CHAR_NAME (default)
    • *
    • IntlChar::UNICODE_10_CHAR_NAME
    • *
    • IntlChar::EXTENDED_CHAR_NAME
    • *
    • IntlChar::CHAR_NAME_ALIAS
    • *
    • IntlChar::CHAR_NAME_CHOICE_COUNT
    • *
    * @return string|null The corresponding name, or an empty string if there is no name for this character, or NULL if codepoint is out of bounds. * @since 7.0 */ #[TentativeType] public static function charName( #[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $type = IntlChar::UNICODE_CHAR_NAME ): ?string {} /** * Get the general category value for a code point * @link https://php.net/manual/en/intlchar.chartype.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return int|null Returns the general category type, which may be one of the following constants: *

      *
    • IntlChar::CHAR_CATEGORY_UNASSIGNED
    • *
    • IntlChar::CHAR_CATEGORY_GENERAL_OTHER_TYPES
    • *
    • IntlChar::CHAR_CATEGORY_UPPERCASE_LETTER
    • *
    • IntlChar::CHAR_CATEGORY_LOWERCASE_LETTER
    • *
    • IntlChar::CHAR_CATEGORY_TITLECASE_LETTER
    • *
    • IntlChar::CHAR_CATEGORY_MODIFIER_LETTER
    • *
    • IntlChar::CHAR_CATEGORY_OTHER_LETTER
    • *
    • IntlChar::CHAR_CATEGORY_NON_SPACING_MARK
    • *
    • IntlChar::CHAR_CATEGORY_ENCLOSING_MARK
    • *
    • IntlChar::CHAR_CATEGORY_COMBINING_SPACING_MARK
    • *
    • IntlChar::CHAR_CATEGORY_DECIMAL_DIGIT_NUMBER
    • *
    • IntlChar::CHAR_CATEGORY_LETTER_NUMBER
    • *
    • IntlChar::CHAR_CATEGORY_OTHER_NUMBER
    • *
    • IntlChar::CHAR_CATEGORY_SPACE_SEPARATOR
    • *
    • IntlChar::CHAR_CATEGORY_LINE_SEPARATOR
    • *
    • IntlChar::CHAR_CATEGORY_PARAGRAPH_SEPARATOR
    • *
    • IntlChar::CHAR_CATEGORY_CONTROL_CHAR
    • *
    • IntlChar::CHAR_CATEGORY_FORMAT_CHAR
    • *
    • IntlChar::CHAR_CATEGORY_PRIVATE_USE_CHAR
    • *
    • IntlChar::CHAR_CATEGORY_SURROGATE
    • *
    • IntlChar::CHAR_CATEGORY_DASH_PUNCTUATION
    • *
    • IntlChar::CHAR_CATEGORY_START_PUNCTUATION
    • *
    • IntlChar::CHAR_CATEGORY_END_PUNCTUATION
    • *
    • IntlChar::CHAR_CATEGORY_CONNECTOR_PUNCTUATION
    • *
    • IntlChar::CHAR_CATEGORY_OTHER_PUNCTUATION
    • *
    • IntlChar::CHAR_CATEGORY_MATH_SYMBOL
    • *
    • IntlChar::CHAR_CATEGORY_CURRENCY_SYMBOL
    • *
    • IntlChar::CHAR_CATEGORY_MODIFIER_SYMBOL
    • *
    • IntlChar::CHAR_CATEGORY_OTHER_SYMBOL
    • *
    • IntlChar::CHAR_CATEGORY_INITIAL_PUNCTUATION
    • *
    • IntlChar::CHAR_CATEGORY_FINAL_PUNCTUATION
    • *
    • IntlChar::CHAR_CATEGORY_CHAR_CATEGORY_COUNT
    *

    Or NULL if codepoint is out of bound.

    'int|string'], default: '')] $codepoint): ?int {} /** * Return Unicode character by code point value * @link https://php.net/manual/en/intlchar.chr.php * @param mixed $codepoint

    The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}")

    * @return string|null A string containing the single character specified by the Unicode code point value. * Or NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function chr(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?string {} /** * Get the decimal digit value of a code point for a given radix * @link https://php.net/manual/en/intlchar.digit.php * @param int|string $codepoint

    The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}")

    * @param int $base

    The radix (defaults to 10).

    * @return int|false|null Returns the numeric value represented by the character in the specified radix, * or FALSE if there is no value or if the value exceeds the radix, * or NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function digit( #[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $base = 10 ): int|false|null {} /** * Enumerate all assigned Unicode characters within a range * @link https://php.net/manual/en/intlchar.enumcharnames.php * @param int|string $start The first code point in the enumeration range. * @param int|string $end One more than the last code point in the enumeration range (the first one after the range). * @param callable $callback

    * The function that is to be called for each character name. The following three arguments will be passed into it: *

      *
    • integer $codepoint - The numeric code point value
    • *
    • integer $nameChoice - The same value as the nameChoice parameter below
    • *
    • string $name - The name of the character
    • *
    * @param int $type [optional]

    * Selector for which kind of names to enumerate. Can be any of these constants: *

      *
    • IntlChar::UNICODE_CHAR_NAME (default)
    • *
    • IntlChar::UNICODE_10_CHAR_NAME
    • *
    • IntlChar::EXTENDED_CHAR_NAME
    • *
    • IntlChar::CHAR_NAME_ALIAS
    • *
    • IntlChar::CHAR_NAME_CHOICE_COUNT
    • *
    * @since 7.0 */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'bool'], default: 'bool|null')] public static function enumCharNames( #[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $start, #[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $end, #[LanguageLevelTypeAware(['8.0' => 'callable'], default: '')] $callback, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $type = IntlChar::UNICODE_CHAR_NAME ) {} /** * Enumerate all code points with their Unicode general categories * @link https://php.net/manual/en/intlchar.enumchartypes.php * @param callable $callback

    * The function that is to be called for each contiguous range of code points with the same general category. * The following three arguments will be passed into it: *

      *
    • integer $start - The starting code point of the range
    • *
    • integer $end - The ending code point of the range
    • *
    • integer $name - The category type (one of the IntlChar::CHAR_CATEGORY_* constants)
    • *
    * @since 7.0 */ #[TentativeType] public static function enumCharTypes( #[PhpStormStubsElementAvailable(from: '7.0', to: '7.4')] $callback = null, #[PhpStormStubsElementAvailable(from: '8.0')] callable $callback ): void {} /** * Perform case folding on a code point * @link https://php.net/manual/en/intlchar.foldcase.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @param int $options [optional] Either IntlChar::FOLD_CASE_DEFAULT (default) or IntlChar::FOLD_CASE_EXCLUDE_SPECIAL_I. * @return int|string|null Returns the Simple_Case_Folding of the code point, if any; otherwise the code point itself. * Returns NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function foldCase( #[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $options = IntlChar::FOLD_CASE_DEFAULT ): string|int|null {} /** * Get character representation for a given digit and radix * @link https://php.net/manual/en/intlchar.fordigit.php * @param int $digit

    The number to convert to a character.

    * @param int $base [optional]

    The radix (defaults to 10).

    * @return int The character representation (as a string) of the specified digit in the specified radix. * @since 7.0 */ #[TentativeType] public static function forDigit( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $digit, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $base = 10 ): int {} /** * Get the paired bracket character for a code point * @link https://php.net/manual/en/intlchar.getbidipairedbracket.php * @param int|string $codepoint

    The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}")

    * @return int|string|null Returns the paired bracket code point, or codepoint itself if there is no such mapping. * The return type will be integer unless the code point was passed as a UTF-8 string, in which case a string will be returned. * Or NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function getBidiPairedBracket(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): string|int|null {} /** * Get the Unicode allocation block containing a code point * @link https://php.net/manual/en/intlchar.getblockcode.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return int|null Returns the block value for codepoint, or NULL if codepoint is out of bound. * See the IntlChar::BLOCK_CODE_* constants for possible return values. * @since 7.0 */ #[TentativeType] public static function getBlockCode(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?int {} /** * Get the combining class of a code point * @link https://php.net/manual/en/intlchar.getcombiningclass.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return int|null Returns the combining class of the character. * Or NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function getCombiningClass(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?int {} /** * Get the FC_NFKC_Closure property for a code point * @link https://php.net/manual/en/intlchar.getfc-nfkc-closure.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return string|false|null Returns the FC_NFKC_Closure property string for the codepoint, or an empty string if there is none, * or NULL if codepoint is out of bound, * or FALSE if there was an error. * @since 7.0 */ #[TentativeType] public static function getFC_NFKC_Closure(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): string|false|null {} /** * Get the max value for a Unicode property * @link https://php.net/manual/en/intlchar.getintpropertymaxvalue.php * @param int $property The Unicode property to lookup (see the IntlChar::PROPERTY_* constants). * @return int The maximum value returned by {@see IntlChar::getIntPropertyValue()} for a Unicode property. <=0 if the property selector is out of range. * @since 7.0 */ #[TentativeType] public static function getIntPropertyMaxValue(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $property): int {} /** * Get the min value for a Unicode property * @link https://php.net/manual/en/intlchar.getintpropertyminvalue.php * @param int $property The Unicode property to lookup (see the IntlChar::PROPERTY_* constants). * @return int The minimum value returned by {@see IntlChar::getIntPropertyValue()} for a Unicode property. 0 if the property selector is out of range. * @since 7.0 */ #[TentativeType] public static function getIntPropertyMinValue(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $property): int {} /** * Get the value for a Unicode property for a code point * @link https://php.net/manual/en/intlchar.getintpropertyvalue.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @param int $property The Unicode property to lookup (see the IntlChar::PROPERTY_* constants). * @return int|null

    * Returns the numeric value that is directly the property value or, for enumerated properties, corresponds to the * numeric value of the enumerated constant of the respective property value enumeration type. *

    *

    * Returns 0 or 1 (for FALSE/TRUE) for binary Unicode properties. *

    *

    * Returns a bit-mask for mask properties. *

    *

    * Returns 0 if property is out of bounds or if the Unicode version does not * have data for the property at all, or not for this code point. *

    *

    * Returns NULL if codepoint is out of bound. *

    * @since 7.0 */ #[TentativeType] public static function getIntPropertyValue( #[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $property ): ?int {} /** * Get the numeric value for a Unicode code point * @link https://php.net/manual/en/intlchar.getnumericvalue.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return float|null Numeric value of codepoint, or float(-123456789) if none is defined, or NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function getNumericValue(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?float {} /** * Get the property constant value for a given property name * @link https://php.net/manual/en/intlchar.getpropertyenum.php * @param string $alias The property name to be matched. The name is compared using "loose matching" as described in PropertyAliases.txt. * @return int Returns an IntlChar::PROPERTY_ constant value, or IntlChar::PROPERTY_INVALID_CODE if the given name does not match any property. * @since 7.0 */ #[TentativeType] public static function getPropertyEnum(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $alias): int {} /** * Get the Unicode name for a property * @link https://php.net/manual/en/intlchar.getpropertyname.php * @param int $property

    The Unicode property to lookup (see the IntlChar::PROPERTY_* constants).

    *

    IntlChar::PROPERTY_INVALID_CODE should not be used. Also, if property is out of range, FALSE is returned.

    * @param int $type

    Selector for which name to get. If out of range, FALSE is returned.

    *

    All properties have a long name. Most have a short name, but some do not. Unicode allows for additional names; if present these will be returned by adding 1, 2, etc. to IntlChar::LONG_PROPERTY_NAME.

    * @return string|false

    * Returns the name, or FALSE if either the property or the nameChoice * is out of range. *

    *

    * If a given nameChoice returns FALSE, then all larger values of * nameChoice will return FALSE, with one exception: if FALSE is returned for * IntlChar::SHORT_PROPERTY_NAME, then IntlChar::LONG_PROPERTY_NAME * (and higher) may still return a non-FALSE value. *

    * @since 7.0 */ #[TentativeType] public static function getPropertyName( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $property, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $type = IntlChar::LONG_PROPERTY_NAME ): string|false {} /** * Get the property value for a given value name * @link https://php.net/manual/en/intlchar.getpropertyvalueenum.php * @param int $property

    The Unicode property to lookup (see the IntlChar::PROPERTY_* constants). * If out of range, or this method doesn't work with the given value, IntlChar::PROPERTY_INVALID_CODE is returned

    * @param string $name

    The value name to be matched. The name is compared using "loose matching" as described in PropertyValueAliases.txt.

    * @return int Returns the corresponding value integer, or IntlChar::PROPERTY_INVALID_CODE if the given name does not match any value of the given property, or if the property is invalid. * @since 7.0 */ #[TentativeType] public static function getPropertyValueEnum( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $property, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name ): int {} /** * Get the Unicode name for a property value * @link https://php.net/manual/en/intlchar.getpropertyvaluename.php * @param int $property

    * The Unicode property to lookup (see the IntlChar::PROPERTY_* constants). * If out of range, or this method doesn't work with the given value, FALSE is returned. *

    * @param int $value

    * Selector for a value for the given property. If out of range, FALSE is returned. *

    *

    * In general, valid values range from 0 up to some maximum. There are a couple exceptions: *

      *
    • * IntlChar::PROPERTY_BLOCK values begin at the non-zero value IntlChar::BLOCK_CODE_BASIC_LATIN *
    • *
    • * IntlChar::PROPERTY_CANONICAL_COMBINING_CLASS values are not contiguous and range from 0..240. *
    • *
    * @param int $type [optional]

    * Selector for which name to get. If out of range, FALSE is returned. * All values have a long name. Most have a short name, but some do not. Unicode allows for additional names; if present these will be returned by adding 1, 2, etc. to IntlChar::LONG_PROPERTY_NAME. *

    * @return string|false Returns the name, or FALSE if either the property or the nameChoice is out of range. * If a given nameChoice returns FALSE, then all larger values of nameChoice will return FALSE, with one exception: if FALSE is returned for IntlChar::SHORT_PROPERTY_NAME, then IntlChar::LONG_PROPERTY_NAME (and higher) may still return a non-FALSE value. * @since 7.0 */ #[TentativeType] public static function getPropertyValueName( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $property, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $value, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $type = IntlChar::LONG_PROPERTY_NAME ): string|false {} /** * Get the Unicode version * @link https://php.net/manual/en/intlchar.getunicodeversion.php * @return array An array containing the Unicode version number. * @since 7.0 */ #[TentativeType] public static function getUnicodeVersion(): array {} /** * Check if code point is an alphanumeric character * @link https://php.net/manual/en/intlchar.isalnum.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint is an alphanumeric character, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isalnum(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is a letter character * @link https://php.net/manual/en/intlchar.isalpha.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint is a letter character, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isalpha(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is a base character * @link https://php.net/manual/en/intlchar.isbase.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint is a base character, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isbase(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is a "blank" or "horizontal space" character * @link https://php.net/manual/en/intlchar.isblank.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint is either a "blank" or "horizontal space" character, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isblank(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is a control character * @link https://php.net/manual/en/intlchar.iscntrl.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint is a control character, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function iscntrl(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check whether the code point is defined * @link https://php.net/manual/en/intlchar.isdefined.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint is a defined character, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isdefined(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is a digit character * @link https://php.net/manual/en/intlchar.isdigit.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint is a digit character, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isdigit(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is a graphic character * @link https://php.net/manual/en/intlchar.isgraph.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint is a "graphic" character, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isgraph(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is an ignorable character * @link https://php.net/manual/en/intlchar.isidignorable.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint is ignorable in identifiers, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isIDIgnorable(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is permissible in an identifier * @link https://php.net/manual/en/intlchar.isidpart.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint is the code point may occur in an identifier, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isIDPart(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is permissible as the first character in an identifier * @link https://php.net/manual/en/intlchar.isidstart.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint may start an identifier, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isIDStart(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is an ISO control code * @link https://php.net/manual/en/intlchar.isisocontrol.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint is an ISO control code, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isISOControl(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is permissible in a Java identifier * @link https://php.net/manual/en/intlchar.isjavaidpart.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint may occur in a Java identifier, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isJavaIDPart(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is permissible as the first character in a Java identifier * @link https://php.net/manual/en/intlchar.isjavaidstart.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint may start a Java identifier, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isJavaIDStart(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is a space character according to Java * @link https://php.net/manual/en/intlchar.isjavaspacechar.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint is a space character according to Java, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isJavaSpaceChar(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is a lowercase letter * @link https://php.net/manual/en/intlchar.islower.php * @param int|string $codepoint

    The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), * or the character encoded as a UTF-8 string (e.g. "\u{2603}")

    * @return bool|null Returns TRUE if codepoint is an Ll lowercase letter, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function islower(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point has the Bidi_Mirrored property * @link https://php.net/manual/en/intlchar.ismirrored.php * @param int|string $codepoint

    The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}")

    * @return bool|null Returns TRUE if codepoint has the Bidi_Mirrored property, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isMirrored(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is a printable character * @link https://php.net/manual/en/intlchar.isprint.php * @param int|string $codepoint

    The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}")

    * @return bool|null Returns TRUE if codepoint is a printable character, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isprint(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is punctuation character * @link https://php.net/manual/en/intlchar.ispunct.php * @param int|string $codepoint

    The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), * or the character encoded as a UTF-8 string (e.g. "\u{2603}")

    * @return bool|null Returns TRUE if codepoint is a punctuation character, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function ispunct(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is a space character * @link https://php.net/manual/en/intlchar.isspace.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint is a space character, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isspace(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is a titlecase letter * @link https://php.net/manual/en/intlchar.istitle.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint is a titlecase letter, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function istitle(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point has the Alphabetic Unicode property * @link https://php.net/manual/en/intlchar.isualphabetic.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint has the Alphabetic Unicode property, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isUAlphabetic(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point has the Lowercase Unicode property * @link https://php.net/manual/en/intlchar.isulowercase.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint has the Lowercase Unicode property, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isULowercase(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point has the general category "Lu" (uppercase letter) * @link https://php.net/manual/en/intlchar.isupper.php * @param int|string $codepoint

    The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), * or the character encoded as a UTF-8 string (e.g. "\u{2603}")

    * @return bool|null Returns TRUE if codepoint is an Lu uppercase letter, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isupper(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point has the Uppercase Unicode property * @link https://php.net/manual/en/intlchar.isuuppercase.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint has the Uppercase Unicode property, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isUUppercase(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point has the White_Space Unicode property * @link https://php.net/manual/en/intlchar.isuwhitespace.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint has the White_Space Unicode property, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isUWhiteSpace(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is a whitespace character according to ICU * @link https://php.net/manual/en/intlchar.iswhitespace.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint is a whitespace character according to ICU, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isWhitespace(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Check if code point is a hexadecimal digit * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return bool|null Returns TRUE if codepoint is a hexadecimal character, FALSE if not, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function isxdigit(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): ?bool {} /** * Return Unicode code point value of character * @link https://php.net/manual/en/intlchar.ord.php * @param int|string $character

    A Unicode character.

    * @return int|null Returns the Unicode code point value as an integer, NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function ord(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $character): ?int {} /** * Make Unicode character lowercase * @link https://php.net/manual/en/intlchar.tolower.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return int|string|null Returns the Simple_Lowercase_Mapping of the code point, if any; otherwise the code point itself. * The return type will be integer unless the code point was passed as a UTF-8 string, in which case a string will be returned. * Or NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function tolower(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): string|int|null {} /** * Make Unicode character titlecase * @link https://php.net/manual/en/intlchar.totitle.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return int|string|null Returns the Simple_Titlecase_Mapping of the code point, if any; otherwise the code point itself. * The return type will be integer unless the code point was passed as a UTF-8 string, in which case a string will be returned. * Or NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function totitle(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): string|int|null {} /** * Make Unicode character uppercase * @link https://php.net/manual/en/intlchar.toupper.php * @param int|string $codepoint The integer codepoint value (e.g. 0x2603 for U+2603 SNOWMAN), or the character encoded as a UTF-8 string (e.g. "\u{2603}") * @return int|string|null Returns the Simple_Uppercase_Mapping of the code point, if any; otherwise the code point itself. * The return type will be integer unless the code point was passed as a UTF-8 string, in which case a string will be returned. * Or NULL if codepoint is out of bound. * @since 7.0 */ #[TentativeType] public static function toupper(#[LanguageLevelTypeAware(['8.0' => 'int|string'], default: '')] $codepoint): string|int|null {} } * Sort strings with different accents from the back of the string. This * attribute is automatically set to * On * for the French locales and a few others. Users normally would not need * to explicitly set this attribute. There is a string comparison * performance cost when it is set On, * but sort key length is unaffected. Possible values are: * Collator::ON * Collator::OFF(default) * Collator::DEFAULT_VALUE *

    *

    * FRENCH_COLLATION rules *

    * F=OFF cote < coté < côte < côté * F=ON cote < côte < coté < côté *

    *

    * @link https://php.net/manual/en/class.collator.php#intl.collator-constants */ public const FRENCH_COLLATION = 0; /** *

    * The Alternate attribute is used to control the handling of the so called * variable characters in the UCA: whitespace, punctuation and symbols. If * Alternate is set to NonIgnorable * (N), then differences among these characters are of the same importance * as differences among letters. If Alternate is set to * Shifted * (S), then these characters are of only minor importance. The * Shifted value is often used in combination with * Strength * set to Quaternary. In such a case, whitespace, punctuation, and symbols * are considered when comparing strings, but only if all other aspects of * the strings (base letters, accents, and case) are identical. If * Alternate is not set to Shifted, then there is no difference between a * Strength of 3 and a Strength of 4. For more information and examples, * see Variable_Weighting in the * UCA. * The reason the Alternate values are not simply * On and Off * is that additional Alternate values may be added in the future. The UCA * option Blanked is expressed with Strength set to 3, and Alternate set to * Shifted. The default for most locales is NonIgnorable. If Shifted is * selected, it may be slower if there are many strings that are the same * except for punctuation; sort key length will not be affected unless the * strength level is also increased. *

    *

    * Possible values are: * Collator::NON_IGNORABLE(default) * Collator::SHIFTED * Collator::DEFAULT_VALUE *

    *

    * ALTERNATE_HANDLING rules *

    * S=3, A=N di Silva < Di Silva < diSilva < U.S.A. < USA * S=3, A=S di Silva = diSilva < Di Silva < U.S.A. = USA * S=4, A=S di Silva < diSilva < Di Silva < U.S.A. < USA *

    *

    * @link https://php.net/manual/en/class.collator.php#intl.collator-constants */ public const ALTERNATE_HANDLING = 1; /** *

    * The Case_First attribute is used to control whether uppercase letters * come before lowercase letters or vice versa, in the absence of other * differences in the strings. The possible values are * Uppercase_First * (U) and Lowercase_First * (L), plus the standard Default * and Off. * There is almost no difference between the Off and Lowercase_First * options in terms of results, so typically users will not use * Lowercase_First: only Off or Uppercase_First. (People interested in the * detailed differences between X and L should consult the Collation * Customization). Specifying either L or U won't affect string comparison * performance, but will affect the sort key length. *

    *

    * Possible values are: * Collator::OFF(default) * Collator::LOWER_FIRST * Collator::UPPER_FIRST * Collator:DEFAULT *

    *

    * CASE_FIRST rules *

    * C=X or C=L "china" < "China" < "denmark" < "Denmark" * C=U "China" < "china" < "Denmark" < "denmark" *

    *

    * @link https://php.net/manual/en/class.collator.php#intl.collator-constants */ public const CASE_FIRST = 2; /** *

    * The Case_Level attribute is used when ignoring accents but not case. In * such a situation, set Strength to be Primary, * and Case_Level to be On. * In most locales, this setting is Off by default. There is a small * string comparison performance and sort key impact if this attribute is * set to be On. *

    *

    * Possible values are: * Collator::OFF(default) * Collator::ON * Collator::DEFAULT_VALUE *

    *

    * CASE_LEVEL rules *

    * S=1, E=X role = Role = rôle * S=1, E=O role = rôle < Role *

    *

    * @link https://php.net/manual/en/class.collator.php#intl.collator-constants */ public const CASE_LEVEL = 3; /** *

    * The Normalization setting determines whether text is thoroughly * normalized or not in comparison. Even if the setting is off (which is * the default for many locales), text as represented in common usage will * compare correctly (for details, see UTN #5). Only if the accent marks * are in noncanonical order will there be a problem. If the setting is * On, * then the best results are guaranteed for all possible text input. * There is a medium string comparison performance cost if this attribute * is On, * depending on the frequency of sequences that require normalization. * There is no significant effect on sort key length. If the input text is * known to be in NFD or NFKD normalization forms, there is no need to * enable this Normalization option. *

    *

    * Possible values are: * Collator::OFF(default) * Collator::ON * Collator::DEFAULT_VALUE *

    * @link https://php.net/manual/en/class.collator.php#intl.collator-constants */ public const NORMALIZATION_MODE = 4; /** *

    * The ICU Collation Service supports many levels of comparison (named * "Levels", but also known as "Strengths"). Having these categories * enables ICU to sort strings precisely according to local conventions. * However, by allowing the levels to be selectively employed, searching * for a string in text can be performed with various matching conditions. * For more detailed information, see * collator_set_strength chapter. *

    *

    * Possible values are: * Collator::PRIMARY * Collator::SECONDARY * Collator::TERTIARY(default) * Collator::QUATERNARY * Collator::IDENTICAL * Collator::DEFAULT_VALUE *

    * @link https://php.net/manual/en/class.collator.php#intl.collator-constants */ public const STRENGTH = 5; /** *

    * Compatibility with JIS x 4061 requires the introduction of an additional * level to distinguish Hiragana and Katakana characters. If compatibility * with that standard is required, then this attribute should be set * On, * and the strength set to Quaternary. This will affect sort key length * and string comparison string comparison performance. *

    *

    * Possible values are: * Collator::OFF(default) * Collator::ON * Collator::DEFAULT_VALUE *

    * @link https://php.net/manual/en/class.collator.php#intl.collator-constants */ public const HIRAGANA_QUATERNARY_MODE = 6; /** *

    * When turned on, this attribute generates a collation key for the numeric * value of substrings of digits. This is a way to get '100' to sort AFTER * '2'. *

    *

    * Possible values are: * Collator::OFF(default) * Collator::ON * Collator::DEFAULT_VALUE *

    * @link https://php.net/manual/en/class.collator.php#intl.collator-constants */ public const NUMERIC_COLLATION = 7; public const SORT_REGULAR = 0; public const SORT_STRING = 1; public const SORT_NUMERIC = 2; /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Create a collator * @link https://php.net/manual/en/collator.construct.php * @param string $locale */ #[Pure] public function __construct(#[LanguageAware(['8.0' => 'string'], default: '')] $locale) {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Create a collator * @link https://php.net/manual/en/collator.create.php * @param string $locale

    * The locale containing the required collation rules. Special values for * locales can be passed in - if null is passed for the locale, the * default locale collation rules will be used. If empty string ("") or * "root" are passed, UCA rules will be used. *

    * @return Collator|null Return new instance of Collator object, or NULL * on error. */ #[TentativeType] public static function create(#[LanguageAware(['8.0' => 'string'], default: '')] $locale): ?Collator {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Compare two Unicode strings * @link https://php.net/manual/en/collator.compare.php * @param string $string1

    * The first string to compare. *

    * @param string $string2

    * The second string to compare. *

    * @return int|false Return comparison result:

    *

    *

    * 1 if str1 is greater than * str2 ; *

    *

    * 0 if str1 is equal to * str2; *

    *

    * -1 if str1 is less than * str2 . *

    * On error * boolean * FALSE * is returned. */ #[Pure] #[TentativeType] public function compare( #[LanguageAware(['8.0' => 'string'], default: '')] $string1, #[LanguageAware(['8.0' => 'string'], default: '')] $string2 ): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Sort array using specified collator * @link https://php.net/manual/en/collator.sort.php * @param string[] &$array

    * Array of strings to sort. *

    * @param int $flags [optional]

    * Optional sorting type, one of the following: *

    *

    * Collator::SORT_REGULAR * - compare items normally (don't change types) *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function sort( array &$array, #[LanguageAware(['8.0' => 'int'], default: '')] #[EV([Collator::SORT_REGULAR])] $flags = 0 ): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Sort array using specified collator and sort keys * @link https://php.net/manual/en/collator.sortwithsortkeys.php * @param string[] &$array

    Array of strings to sort

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function sortWithSortKeys( array &$array, #[ElementAvailable(from: '5.3', to: '5.6')] $flags = [] ): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Sort array maintaining index association * @link https://php.net/manual/en/collator.asort.php * @param string[] &$array

    Array of strings to sort.

    * @param int $flags [optional]

    * Optional sorting type, one of the following: * Collator::SORT_REGULAR * - compare items normally (don't change types) *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function asort( array &$array, #[LanguageAware(['8.0' => 'int'], default: '')] #[EV([Collator::SORT_REGULAR])] $flags = 0 ): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get collation attribute value * @link https://php.net/manual/en/collator.getattribute.php * @param int $attribute

    * Attribute to get value for. *

    * @return int|false Attribute value, or boolean FALSE on error. */ #[Pure] #[TentativeType] public function getAttribute(#[LanguageAware(['8.0' => 'int'], default: '')] $attribute): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set collation attribute * @link https://php.net/manual/en/collator.setattribute.php * @param int $attribute

    Attribute.

    * @param int $value

    * Attribute value. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function setAttribute( #[LanguageAware(['8.0' => 'int'], default: '')] $attribute, #[LanguageAware(['8.0' => 'int'], default: '')] $value ): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get current collation strength * @link https://php.net/manual/en/collator.getstrength.php * @return int current collation strength, or boolean FALSE on error. */ #[Pure] #[TentativeType] public function getStrength(): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set collation strength * @link https://php.net/manual/en/collator.setstrength.php * @param int $strength

    Strength to set.

    *

    * Possible values are: * Collator::PRIMARY *

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function setStrength(#[LanguageAware(['8.0' => 'int'], default: '')] #[EV([Collator::PRIMARY])] $strength) {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get collator's last error code * @link https://php.net/manual/en/collator.geterrorcode.php * @return int|false Error code returned by the last Collator API function call. */ #[Pure] #[TentativeType] public function getErrorCode(): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the locale name of the collator * @link https://php.net/manual/en/collator.getlocale.php * @param int $type

    * You can choose between valid and actual locale ( * Locale::VALID_LOCALE and * Locale::ACTUAL_LOCALE, * respectively). *

    * @return string|false Real locale name from which the collation data comes. If the collator was * instantiated from rules or an error occurred, returns * boolean FALSE. */ #[Pure] #[TentativeType] public function getLocale( #[LanguageAware(['8.0' => 'int'], default: '')] #[EV([Locale::VALID_LOCALE, Locale::ACTUAL_LOCALE])] $type ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get text for collator's last error code * @link https://php.net/manual/en/collator.geterrormessage.php * @return string|false Description of an error occurred in the last Collator API function call. */ #[Pure] #[TentativeType] public function getErrorMessage(): string|false {} /** * (PHP 5 >= 5.3.2, PECL intl >= 1.0.3)
    * Get sorting key for a string * @link https://php.net/manual/en/collator.getsortkey.php * @param string $string

    * The string to produce the key from. *

    * @return string|false the collation key for the string. Collation keys can be compared directly instead of strings. */ #[Pure] #[TentativeType] public function getSortKey( #[LanguageAware(['8.0' => 'string'], default: '')] $string, #[ElementAvailable(from: '5.3', to: '5.6')] $arg2 ): string|false {} } class NumberFormatter { public const CURRENCY_ACCOUNTING = 12; /** * Decimal format defined by pattern * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const PATTERN_DECIMAL = 0; /** * Decimal format * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const DECIMAL = 1; /** * Currency format * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const CURRENCY = 2; /** * Percent format * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const PERCENT = 3; /** * Scientific format * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const SCIENTIFIC = 4; /** * Spellout rule-based format * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const SPELLOUT = 5; /** * Ordinal rule-based format * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const ORDINAL = 6; /** * Duration rule-based format * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const DURATION = 7; /** * Rule-based format defined by pattern * @link https://php.net/manual/en/class.locale.php#intl.locale-constants */ public const PATTERN_RULEBASED = 9; /** * Alias for PATTERN_DECIMAL * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const IGNORE = 0; /** * Default format for the locale * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const DEFAULT_STYLE = 1; /** * Rounding mode to round towards positive infinity. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const ROUND_CEILING = 0; /** * Rounding mode to round towards negative infinity. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const ROUND_FLOOR = 1; /** * Rounding mode to round towards zero. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const ROUND_DOWN = 2; /** * Rounding mode to round away from zero. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const ROUND_UP = 3; /** * Rounding mode to round towards the "nearest neighbor" unless both * neighbors are equidistant, in which case, round towards the even * neighbor. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const ROUND_HALFEVEN = 4; /** * Rounding mode to round towards "nearest neighbor" unless both neighbors * are equidistant, in which case round down. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const ROUND_HALFDOWN = 5; /** * Rounding mode to round towards "nearest neighbor" unless both neighbors * are equidistant, in which case round up. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const ROUND_HALFUP = 6; /** * Pad characters inserted before the prefix. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const PAD_BEFORE_PREFIX = 0; /** * Pad characters inserted after the prefix. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const PAD_AFTER_PREFIX = 1; /** * Pad characters inserted before the suffix. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const PAD_BEFORE_SUFFIX = 2; /** * Pad characters inserted after the suffix. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const PAD_AFTER_SUFFIX = 3; /** * Parse integers only. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const PARSE_INT_ONLY = 0; /** * Use grouping separator. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const GROUPING_USED = 1; /** * Always show decimal point. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const DECIMAL_ALWAYS_SHOWN = 2; /** * Maximum integer digits. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const MAX_INTEGER_DIGITS = 3; /** * Minimum integer digits. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const MIN_INTEGER_DIGITS = 4; /** * Integer digits. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const INTEGER_DIGITS = 5; /** * Maximum fraction digits. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const MAX_FRACTION_DIGITS = 6; /** * Minimum fraction digits. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const MIN_FRACTION_DIGITS = 7; /** * Fraction digits. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const FRACTION_DIGITS = 8; /** * Multiplier. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const MULTIPLIER = 9; /** * Grouping size. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const GROUPING_SIZE = 10; /** * Rounding Mode. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const ROUNDING_MODE = 11; /** * Rounding increment. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const ROUNDING_INCREMENT = 12; /** * The width to which the output of format() is padded. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const FORMAT_WIDTH = 13; /** * The position at which padding will take place. See pad position * constants for possible argument values. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const PADDING_POSITION = 14; /** * Secondary grouping size. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const SECONDARY_GROUPING_SIZE = 15; /** * Use significant digits. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const SIGNIFICANT_DIGITS_USED = 16; /** * Minimum significant digits. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const MIN_SIGNIFICANT_DIGITS = 17; /** * Maximum significant digits. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const MAX_SIGNIFICANT_DIGITS = 18; /** * Lenient parse mode used by rule-based formats. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const LENIENT_PARSE = 19; /** * Positive prefix. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const POSITIVE_PREFIX = 0; /** * Positive suffix. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const POSITIVE_SUFFIX = 1; /** * Negative prefix. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const NEGATIVE_PREFIX = 2; /** * Negative suffix. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const NEGATIVE_SUFFIX = 3; /** * The character used to pad to the format width. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const PADDING_CHARACTER = 4; /** * The ISO currency code. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const CURRENCY_CODE = 5; /** * The default rule set. This is only available with rule-based * formatters. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const DEFAULT_RULESET = 6; /** * The public rule sets. This is only available with rule-based * formatters. This is a read-only attribute. The public rulesets are * returned as a single string, with each ruleset name delimited by ';' * (semicolon). * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const PUBLIC_RULESETS = 7; /** * The decimal separator. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const DECIMAL_SEPARATOR_SYMBOL = 0; /** * The grouping separator. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const GROUPING_SEPARATOR_SYMBOL = 1; /** * The pattern separator. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const PATTERN_SEPARATOR_SYMBOL = 2; /** * The percent sign. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const PERCENT_SYMBOL = 3; /** * Zero. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const ZERO_DIGIT_SYMBOL = 4; /** * Character representing a digit in the pattern. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const DIGIT_SYMBOL = 5; /** * The minus sign. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const MINUS_SIGN_SYMBOL = 6; /** * The plus sign. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const PLUS_SIGN_SYMBOL = 7; /** * The currency symbol. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const CURRENCY_SYMBOL = 8; /** * The international currency symbol. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const INTL_CURRENCY_SYMBOL = 9; /** * The monetary separator. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const MONETARY_SEPARATOR_SYMBOL = 10; /** * The exponential symbol. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const EXPONENTIAL_SYMBOL = 11; /** * Per mill symbol. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const PERMILL_SYMBOL = 12; /** * Escape padding character. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const PAD_ESCAPE_SYMBOL = 13; /** * Infinity symbol. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const INFINITY_SYMBOL = 14; /** * Not-a-number symbol. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const NAN_SYMBOL = 15; /** * Significant digit symbol. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const SIGNIFICANT_DIGIT_SYMBOL = 16; /** * The monetary grouping separator. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const MONETARY_GROUPING_SEPARATOR_SYMBOL = 17; /** * Derive the type from variable type * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const TYPE_DEFAULT = 0; /** * Format/parse as 32-bit integer * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const TYPE_INT32 = 1; /** * Format/parse as 64-bit integer * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const TYPE_INT64 = 2; /** * Format/parse as floating point value * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const TYPE_DOUBLE = 3; /** * Format/parse as currency value * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants * @deprecated 8.3 */ public const TYPE_CURRENCY = 4; /** * @since 8.4 */ public const ROUND_TOWARD_ZERO = 2; /** * @since 8.4 */ public const ROUND_AWAY_FROM_ZERO = 3; /** * @since 8.4 */ public const ROUND_HALFODD = 8; public const DECIMAL_COMPACT_SHORT = 14; public const DECIMAL_COMPACT_LONG = 15; public const CURRENCY_ISO = 10; public const CURRENCY_PLURAL = 11; public const CASH_CURRENCY = 13; public const CURRENCY_STANDARD = 16; /** * @link https://www.php.net/manual/en/class.numberformatter.php * @param string $locale * @param int $style * @param string $pattern [optional] */ #[Pure] public function __construct( #[LanguageAware(['8.0' => 'string'], default: '')] $locale, #[LanguageAware(['8.0' => 'int'], default: '')] #[EV([NumberFormatter::DECIMAL, NumberFormatter::PATTERN_DECIMAL, NumberFormatter::DECIMAL, NumberFormatter::CURRENCY, NumberFormatter::PERCENT, NumberFormatter::SCIENTIFIC, NumberFormatter::SPELLOUT, NumberFormatter::ORDINAL, NumberFormatter::DURATION, NumberFormatter::PATTERN_RULEBASED, NumberFormatter::CURRENCY_ACCOUNTING, NumberFormatter::DEFAULT_STYLE, NumberFormatter::IGNORE])] $style, #[LanguageAware(['8.0' => 'string|null'], default: '')] $pattern = null ) {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Create a number formatter * @link https://php.net/manual/en/numberformatter.create.php * @param string $locale

    * Locale in which the number would be formatted (locale name, e.g. en_CA). *

    * @param int $style

    * Style of the formatting, one of the * format style constants. If * NumberFormatter::PATTERN_DECIMAL * or NumberFormatter::PATTERN_RULEBASED * is passed then the number format is opened using the given pattern, * which must conform to the syntax described in * ICU DecimalFormat * documentation or * ICU RuleBasedNumberFormat * documentation, respectively. *

    * @param string $pattern [optional]

    * Pattern string if the chosen style requires a pattern. *

    * @return NumberFormatter|false NumberFormatter object or FALSE on error. */ #[TentativeType] public static function create( #[LanguageAware(['8.0' => 'string'], default: '')] $locale, #[LanguageAware(['8.0' => 'int'], default: '')] #[EV([NumberFormatter::DECIMAL, NumberFormatter::PATTERN_DECIMAL, NumberFormatter::DECIMAL, NumberFormatter::CURRENCY, NumberFormatter::PERCENT, NumberFormatter::SCIENTIFIC, NumberFormatter::SPELLOUT, NumberFormatter::ORDINAL, NumberFormatter::DURATION, NumberFormatter::PATTERN_RULEBASED, NumberFormatter::CURRENCY_ACCOUNTING, NumberFormatter::DEFAULT_STYLE, NumberFormatter::IGNORE])] $style, #[LanguageAware(['8.0' => 'string|null'], default: '')] $pattern = null ): ?NumberFormatter {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Format a number * @link https://php.net/manual/en/numberformatter.format.php * @param int|float $num

    * The value to format. Can be integer or float, * other values will be converted to a numeric value. *

    * @param int $type [optional]

    * The * formatting type to use. *

    * @return string|false the string containing formatted value, or FALSE on error. */ #[Pure] #[TentativeType] public function format( #[LanguageAware(['8.0' => 'int|float'], default: '')] $num, #[LanguageAware(['8.0' => 'int'], default: '')] $type = 0 ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Parse a number * @link https://php.net/manual/en/numberformatter.parse.php * @param string $string * @param int $type [optional]

    * The * formatting type to use. By default, * NumberFormatter::TYPE_DOUBLE is used. *

    * @param int &$offset [optional]

    * Offset in the string at which to begin parsing. On return, this value * will hold the offset at which parsing ended. *

    * @return mixed The value of the parsed number or FALSE on error. */ #[TentativeType] public function parse( #[LanguageAware(['8.0' => 'string'], default: '')] $string, #[LanguageAware(['8.0' => 'int'], default: '')] $type = NumberFormatter::TYPE_DOUBLE, &$offset = null ): int|float|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Format a currency value * @link https://php.net/manual/en/numberformatter.formatcurrency.php * @param float $amount

    * The numeric currency value. *

    * @param string $currency

    * The 3-letter ISO 4217 currency code indicating the currency to use. *

    * @return string|false String representing the formatted currency value. */ #[Pure] #[TentativeType] public function formatCurrency( #[LanguageAware(['8.0' => 'float'], default: '')] $amount, #[LanguageAware(['8.0' => 'string'], default: '')] $currency ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Parse a currency number * @link https://php.net/manual/en/numberformatter.parsecurrency.php * @param string $string * @param string &$currency

    * Parameter to receive the currency name (3-letter ISO 4217 currency * code). *

    * @param int &$offset [optional]

    * Offset in the string at which to begin parsing. On return, this value * will hold the offset at which parsing ended. *

    * @return float|false The parsed numeric value or FALSE on error. */ #[TentativeType] public function parseCurrency(#[LanguageAware(['8.0' => 'string'], default: '')] $string, &$currency, &$offset = null): float|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set an attribute * @link https://php.net/manual/en/numberformatter.setattribute.php * @param int $attribute

    * Attribute specifier - one of the * numeric attribute constants. *

    * @param int $value

    * The attribute value. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function setAttribute( #[LanguageAware(['8.0' => 'int'], default: '')] $attribute, #[LanguageAware(['8.0' => 'int|float'], default: '')] $value ): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get an attribute * @link https://php.net/manual/en/numberformatter.getattribute.php * @param int $attribute

    * Attribute specifier - one of the * numeric attribute constants. *

    * @return int|float|false Return attribute value on success, or FALSE on error. */ #[Pure] #[TentativeType] public function getAttribute(#[LanguageAware(['8.0' => 'int'], default: '')] $attribute): int|float|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set a text attribute * @link https://php.net/manual/en/numberformatter.settextattribute.php * @param int $attribute

    * Attribute specifier - one of the * text attribute * constants. *

    * @param string $value

    * Text for the attribute value. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function setTextAttribute( #[LanguageAware(['8.0' => 'int'], default: '')] $attribute, #[LanguageAware(['8.0' => 'string'], default: '')] $value ): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get a text attribute * @link https://php.net/manual/en/numberformatter.gettextattribute.php * @param int $attribute

    * Attribute specifier - one of the * text attribute constants. *

    * @return string|false Return attribute value on success, or FALSE on error. */ #[Pure] #[TentativeType] public function getTextAttribute(#[LanguageAware(['8.0' => 'int'], default: '')] $attribute): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set a symbol value * @link https://php.net/manual/en/numberformatter.setsymbol.php * @param int $symbol

    * Symbol specifier, one of the * format symbol constants. *

    * @param string $value

    * Text for the symbol. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function setSymbol( #[LanguageAware(['8.0' => 'int'], default: '')] $symbol, #[LanguageAware(['8.0' => 'string'], default: '')] $value ): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get a symbol value * @link https://php.net/manual/en/numberformatter.getsymbol.php * @param int $symbol

    * Symbol specifier, one of the * format symbol constants. *

    * @return string|false The symbol string or FALSE on error. */ #[Pure] #[TentativeType] public function getSymbol(#[LanguageAware(['8.0' => 'int'], default: '')] $symbol): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set formatter pattern * @link https://php.net/manual/en/numberformatter.setpattern.php * @param string $pattern

    * Pattern in syntax described in * ICU DecimalFormat * documentation. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function setPattern(#[LanguageAware(['8.0' => 'string'], default: '')] $pattern): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get formatter pattern * @link https://php.net/manual/en/numberformatter.getpattern.php * @return string|false Pattern string that is used by the formatter, or FALSE if an error happens. */ #[Pure] #[TentativeType] public function getPattern(): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get formatter locale * @link https://php.net/manual/en/numberformatter.getlocale.php * @param int $type [optional]

    * You can choose between valid and actual locale ( * Locale::VALID_LOCALE, * Locale::ACTUAL_LOCALE, * respectively). The default is the actual locale. *

    * @return string|false The locale name used to create the formatter. */ #[Pure] #[TentativeType] public function getLocale( #[LanguageAware(['8.0' => 'int'], default: '')] #[EV([Locale::VALID_LOCALE, Locale::ACTUAL_LOCALE])] $type = 0 ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get formatter's last error code. * @link https://php.net/manual/en/numberformatter.geterrorcode.php * @return int error code from last formatter call. */ #[Pure] #[TentativeType] public function getErrorCode(): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get formatter's last error message. * @link https://php.net/manual/en/numberformatter.geterrormessage.php * @return string error message from last formatter call. */ #[Pure] #[TentativeType] public function getErrorMessage(): string {} } class Normalizer { public const NFKC_CF = 48; public const FORM_KC_CF = 48; /** * Default normalization options * @link https://secure.php.net/manual/en/class.normalizer.php */ public const OPTION_DEFAULT = ""; /** * No decomposition/composition * @link https://secure.php.net/manual/en/class.normalizer.php * @removed 8.0 */ public const NONE = "1"; /** * Normalization Form D (NFD) - Canonical Decomposition * @link https://secure.php.net/manual/en/class.normalizer.php */ public const FORM_D = 4; public const NFD = 4; /** * Normalization Form KD (NFKD) - Compatibility Decomposition * @link https://secure.php.net/manual/en/class.normalizer.php */ public const FORM_KD = 8; public const NFKD = 8; /** * Normalization Form C (NFC) - Canonical Decomposition followed by * Canonical Composition * @link https://secure.php.net/manual/en/class.normalizer.php */ public const FORM_C = 16; public const NFC = 16; /** * Normalization Form KC (NFKC) - Compatibility Decomposition, followed by * Canonical Composition * @link https://secure.php.net/manual/en/class.normalizer.php */ public const FORM_KC = 32; public const NFKC = 32; /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Normalizes the input provided and returns the normalized string * @link https://php.net/manual/en/normalizer.normalize.php * @param string $string

    The input string to normalize

    * @param int $form

    One of the normalization forms.

    * @return string|false The normalized string or FALSE if an error occurred. */ #[TentativeType] public static function normalize( #[LanguageAware(['8.0' => 'string'], default: '')] $string, #[ElementAvailable(from: '5.3', to: '5.6')] $form, #[ElementAvailable(from: '7.0')] #[LanguageAware(['8.0' => 'int'], default: '')] $form = Normalizer::FORM_C, #[ElementAvailable(from: '5.3', to: '5.6')] $arg3 ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Checks if the provided string is already in the specified normalization form. * @link https://php.net/manual/en/normalizer.isnormalized.php * @param string $string

    The input string to normalize

    * @param int $form

    * One of the normalization forms. *

    * @return bool TRUE if normalized, FALSE otherwise or if there an error */ #[TentativeType] public static function isNormalized( #[LanguageAware(['8.0' => 'string'], default: '')] $string, #[ElementAvailable(from: '5.3', to: '5.6')] $form, #[ElementAvailable(from: '7.0')] #[LanguageAware(['8.0' => 'int'], default: '')] $form = Normalizer::FORM_C, #[ElementAvailable(from: '5.3', to: '5.6')] $arg3 ): bool {} /** * @param string $string

    The input string to normalize

    * @param int $form * @return string|null

    Returns a string containing the Decomposition_Mapping property, if present in the UCD. * Returns null if there is no Decomposition_Mapping property for the character.

    * @link https://www.php.net/manual/en/normalizer.getrawdecomposition.php * @since 7.3 */ #[TentativeType] public static function getRawDecomposition( string $string, #[ElementAvailable(from: '8.0')] int $form = 16 ): ?string {} } class Locale { /** * This is locale the data actually comes from. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const ACTUAL_LOCALE = 0; /** * This is the most specific locale supported by ICU. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const VALID_LOCALE = 1; /** * Used as locale parameter with the methods of the various locale affected classes, * such as NumberFormatter. This constant would make the methods to use default * locale. * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const DEFAULT_LOCALE = null; /** * Language subtag * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const LANG_TAG = "language"; /** * Extended language subtag * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const EXTLANG_TAG = "extlang"; /** * Script subtag * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const SCRIPT_TAG = "script"; /** * Region subtag * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const REGION_TAG = "region"; /** * Variant subtag * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const VARIANT_TAG = "variant"; /** * Grandfathered Language subtag * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const GRANDFATHERED_LANG_TAG = "grandfathered"; /** * Private subtag * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ public const PRIVATE_TAG = "private"; /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Gets the default locale value from the INTL global 'default_locale' * @link https://php.net/manual/en/locale.getdefault.php * @return string The current runtime locale */ #[TentativeType] public static function getDefault(): string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * sets the default runtime locale * @link https://php.net/manual/en/locale.setdefault.php * @param string $locale

    * Is a BCP 47 compliant language tag containing the *

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public static function setDefault(#[LanguageAware(['8.0' => 'string'], default: '')] $locale) {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Gets the primary language for the input locale * @link https://php.net/manual/en/locale.getprimarylanguage.php * @param string $locale

    * The locale to extract the primary language code from *

    * @return string|null The language code associated with the language or NULL in case of error. */ #[TentativeType] public static function getPrimaryLanguage(#[LanguageAware(['8.0' => 'string'], default: '')] $locale): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Gets the script for the input locale * @link https://php.net/manual/en/locale.getscript.php * @param string $locale

    * The locale to extract the script code from *

    * @return string|null The script subtag for the locale or NULL if not present */ #[TentativeType] public static function getScript(#[LanguageAware(['8.0' => 'string'], default: '')] $locale): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Gets the region for the input locale * @link https://php.net/manual/en/locale.getregion.php * @param string $locale

    * The locale to extract the region code from *

    * @return string|null The region subtag for the locale or NULL if not present */ #[TentativeType] public static function getRegion(#[LanguageAware(['8.0' => 'string'], default: '')] $locale): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Gets the keywords for the input locale * @link https://php.net/manual/en/locale.getkeywords.php * @param string $locale

    * The locale to extract the keywords from *

    * @return array|false|null Associative array containing the keyword-value pairs for this locale */ #[TentativeType] public static function getKeywords(#[LanguageAware(['8.0' => 'string'], default: '')] $locale): array|false|null {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Returns an appropriately localized display name for script of the input locale * @link https://php.net/manual/en/locale.getdisplayscript.php * @param string $locale

    * The locale to return a display script for *

    * @param string $displayLocale

    * Optional format locale to use to display the script name *

    * @return string|false Display name of the script for the $locale in the format appropriate for * $in_locale. */ #[TentativeType] public static function getDisplayScript( #[LanguageAware(['8.0' => 'string'], default: '')] $locale, #[ElementAvailable(from: '5.3', to: '5.6')] $displayLocale, #[ElementAvailable(from: '7.0')] #[LanguageAware(['8.0' => 'string|null'], default: '')] $displayLocale = null ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Returns an appropriately localized display name for region of the input locale * @link https://php.net/manual/en/locale.getdisplayregion.php * @param string $locale

    * The locale to return a display region for. *

    * @param string $displayLocale

    * Optional format locale to use to display the region name *

    * @return string|false display name of the region for the $locale in the format appropriate for * $in_locale. */ #[TentativeType] public static function getDisplayRegion( #[LanguageAware(['8.0' => 'string'], default: '')] $locale, #[ElementAvailable(from: '5.3', to: '5.6')] $displayLocale, #[ElementAvailable(from: '7.0')] #[LanguageAware(['8.0' => 'string|null'], default: '')] $displayLocale = null ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Returns an appropriately localized display name for the input locale * @link https://php.net/manual/en/locale.getdisplayname.php * @param string $locale

    * The locale to return a display name for. *

    * @param string $displayLocale

    optional format locale

    * @return string|false Display name of the locale in the format appropriate for $in_locale. */ #[TentativeType] public static function getDisplayName( #[LanguageAware(['8.0' => 'string'], default: '')] $locale, #[ElementAvailable(from: '5.3', to: '5.6')] $displayLocale, #[ElementAvailable(from: '7.0')] #[LanguageAware(['8.0' => 'string|null'], default: '')] $displayLocale = null ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Returns an appropriately localized display name for language of the inputlocale * @link https://php.net/manual/en/locale.getdisplaylanguage.php * @param string $locale

    * The locale to return a display language for *

    * @param string $displayLocale

    * Optional format locale to use to display the language name *

    * @return string|false display name of the language for the $locale in the format appropriate for * $in_locale. */ #[TentativeType] public static function getDisplayLanguage( #[LanguageAware(['8.0' => 'string'], default: '')] $locale, #[ElementAvailable(from: '5.3', to: '5.6')] $displayLocale, #[ElementAvailable(from: '7.0')] #[LanguageAware(['8.0' => 'string|null'], default: '')] $displayLocale = null ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Returns an appropriately localized display name for variants of the input locale * @link https://php.net/manual/en/locale.getdisplayvariant.php * @param string $locale

    * The locale to return a display variant for *

    * @param string $displayLocale

    * Optional format locale to use to display the variant name *

    * @return string|false Display name of the variant for the $locale in the format appropriate for * $in_locale. */ #[TentativeType] public static function getDisplayVariant( #[LanguageAware(['8.0' => 'string'], default: '')] $locale, #[ElementAvailable(from: '5.3', to: '5.6')] $displayLocale, #[ElementAvailable(from: '7.0')] #[LanguageAware(['8.0' => 'string|null'], default: '')] $displayLocale = null ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Returns a correctly ordered and delimited locale ID * @link https://php.net/manual/en/locale.composelocale.php * @param array $subtags

    * an array containing a list of key-value pairs, where the keys identify * the particular locale ID subtags, and the values are the associated * subtag values. *

    * The 'variant' and 'private' subtags can take maximum 15 values * whereas 'extlang' can take maximum 3 values.e.g. Variants are allowed * with the suffix ranging from 0-14. Hence the keys for the input array * can be variant0, variant1, ...,variant14. In the returned locale id, * the subtag is ordered by suffix resulting in variant0 followed by * variant1 followed by variant2 and so on. *

    *

    * The 'variant', 'private' and 'extlang' multiple values can be specified both * as array under specific key (e.g. 'variant') and as multiple numbered keys * (e.g. 'variant0', 'variant1', etc.). *

    *

    * @return string|false The corresponding locale identifier. */ #[TentativeType] public static function composeLocale(array $subtags): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Returns a key-value array of locale ID subtag elements. * @link https://php.net/manual/en/locale.parselocale.php * @param string $locale

    * The locale to extract the subtag array from. Note: The 'variant' and * 'private' subtags can take maximum 15 values whereas 'extlang' can take * maximum 3 values. *

    * @return array|null an array containing a list of key-value pairs, where the keys * identify the particular locale ID subtags, and the values are the * associated subtag values. The array will be ordered as the locale id * subtags e.g. in the locale id if variants are '-varX-varY-varZ' then the * returned array will have variant0=>varX , variant1=>varY , * variant2=>varZ */ #[TentativeType] public static function parseLocale(#[LanguageAware(['8.0' => 'string'], default: '')] $locale): ?array {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Gets the variants for the input locale * @link https://php.net/manual/en/locale.getallvariants.php * @param string $locale

    * The locale to extract the variants from *

    * @return array|null The array containing the list of all variants subtag for the locale * or NULL if not present */ #[TentativeType] public static function getAllVariants(#[LanguageAware(['8.0' => 'string'], default: '')] $locale): ?array {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Checks if a language tag filter matches with locale * @link https://php.net/manual/en/locale.filtermatches.php * @param string $languageTag

    * The language tag to check *

    * @param string $locale

    * The language range to check against *

    * @param bool $canonicalize

    * If true, the arguments will be converted to canonical form before * matching. *

    * @return bool|null TRUE if $locale matches $langtag FALSE otherwise. */ #[TentativeType] public static function filterMatches( #[LanguageAware(['8.0' => 'string'], default: '')] $languageTag, #[LanguageAware(['8.0' => 'string'], default: '')] $locale, #[ElementAvailable(from: '5.3', to: '5.6')] $canonicalize, #[ElementAvailable(from: '7.0')] #[LanguageAware(['8.0' => 'bool'], default: '')] $canonicalize = false ): ?bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Searches the language tag list for the best match to the language * @link https://php.net/manual/en/locale.lookup.php * @param array $languageTag

    * An array containing a list of language tags to compare to * locale. Maximum 100 items allowed. *

    * @param string $locale

    * The locale to use as the language range when matching. *

    * @param bool $canonicalize

    * If true, the arguments will be converted to canonical form before * matching. *

    * @param string $defaultLocale

    * The locale to use if no match is found. *

    * @return string|null The closest matching language tag or default value. */ #[TentativeType] public static function lookup( array $languageTag, #[LanguageAware(['8.0' => 'string'], default: '')] $locale, #[ElementAvailable(from: '5.3', to: '5.6')] $canonicalize, #[ElementAvailable(from: '5.3', to: '5.6')] $defaultLocale, #[ElementAvailable(from: '7.0')] #[LanguageAware(['8.0' => 'bool'], default: '')] $canonicalize = false, #[ElementAvailable(from: '7.0')] #[LanguageAware(['8.0' => 'string|null'], default: '')] $defaultLocale = null ): ?string {} /** * @link https://php.net/manual/en/locale.canonicalize.php * @param string $locale * @return string|null */ #[TentativeType] public static function canonicalize(#[LanguageAware(['8.0' => 'string'], default: '')] $locale): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Tries to find out best available locale based on HTTP "Accept-Language" header * @link https://php.net/manual/en/locale.acceptfromhttp.php * @param string $header

    * The string containing the "Accept-Language" header according to format in RFC 2616. *

    * @return string|false The corresponding locale identifier. */ #[TentativeType] public static function acceptFromHttp(#[LanguageAware(['8.0' => 'string'], default: '')] $header): string|false {} /** * @since 8.5 */ public static function isRightToLeft(string $locale): bool {} /** * @since 8.5 */ public static function addLikelySubtags(string $locale): string|false {} /** * @since 8.5 */ public static function minimizeSubtags(string $locale): string|false {} } class MessageFormatter { /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Constructs a new Message Formatter * @link https://php.net/manual/en/messageformatter.create.php * @param string $locale

    * The locale to use when formatting arguments *

    * @param string $pattern

    * The pattern string to stick arguments into. * The pattern uses an 'apostrophe-friendly' syntax; it is run through * umsg_autoQuoteApostrophe * before being interpreted. *

    * @throws IntlException on failure. */ #[Pure] public function __construct( #[LanguageAware(['8.0' => 'string'], default: '')] $locale, #[LanguageAware(['8.0' => 'string'], default: '')] $pattern ) {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Constructs a new Message Formatter * @link https://php.net/manual/en/messageformatter.create.php * @param string $locale

    * The locale to use when formatting arguments *

    * @param string $pattern

    * The pattern string to stick arguments into. * The pattern uses an 'apostrophe-friendly' syntax; it is run through * umsg_autoQuoteApostrophe * before being interpreted. *

    * @return MessageFormatter|null The formatter object */ #[TentativeType] public static function create( #[LanguageAware(['8.0' => 'string'], default: '')] $locale, #[LanguageAware(['8.0' => 'string'], default: '')] $pattern ): ?MessageFormatter {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Format the message * @link https://php.net/manual/en/messageformatter.format.php * @param array $values

    * Arguments to insert into the format string *

    * @return string|false The formatted string, or FALSE if an error occurred */ #[Pure] #[TentativeType] public function format(array $values): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Quick format message * @link https://php.net/manual/en/messageformatter.formatmessage.php * @param string $locale

    * The locale to use for formatting locale-dependent parts *

    * @param string $pattern

    * The pattern string to insert things into. * The pattern uses an 'apostrophe-friendly' syntax; it is run through * umsg_autoQuoteApostrophe * before being interpreted. *

    * @param array $values

    * The array of values to insert into the format string *

    * @return string|false The formatted pattern string or FALSE if an error occurred */ #[TentativeType] public static function formatMessage( #[LanguageAware(['8.0' => 'string'], default: '')] $locale, #[LanguageAware(['8.0' => 'string'], default: '')] $pattern, array $values ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Parse input string according to pattern * @link https://php.net/manual/en/messageformatter.parse.php * @param string $string

    * The string to parse *

    * @return array|false An array containing the items extracted, or FALSE on error */ #[Pure] #[TentativeType] public function parse(#[LanguageAware(['8.0' => 'string'], default: '')] $string): array|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Quick parse input string * @link https://php.net/manual/en/messageformatter.parsemessage.php * @param string $locale

    * The locale to use for parsing locale-dependent parts *

    * @param string $pattern

    * The pattern with which to parse the value. *

    * @param string $message

    * The string to parse, conforming to the pattern. *

    * @return array|false An array containing items extracted, or FALSE on error */ #[TentativeType] public static function parseMessage( #[LanguageAware(['8.0' => 'string'], default: '')] $locale, #[LanguageAware(['8.0' => 'string'], default: '')] $pattern, #[LanguageAware(['8.0' => 'string'], default: '')] $message ): array|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set the pattern used by the formatter * @link https://php.net/manual/en/messageformatter.setpattern.php * @param string $pattern

    * The pattern string to use in this message formatter. * The pattern uses an 'apostrophe-friendly' syntax; it is run through * umsg_autoQuoteApostrophe * before being interpreted. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function setPattern(#[LanguageAware(['8.0' => 'string'], default: '')] $pattern): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the pattern used by the formatter * @link https://php.net/manual/en/messageformatter.getpattern.php * @return string|false The pattern string for this message formatter */ #[Pure] #[TentativeType] public function getPattern(): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the locale for which the formatter was created. * @link https://php.net/manual/en/messageformatter.getlocale.php * @return string The locale name */ #[Pure] #[TentativeType] public function getLocale(): string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the error code from last operation * @link https://php.net/manual/en/messageformatter.geterrorcode.php * @return int The error code, one of UErrorCode values. Initial value is U_ZERO_ERROR. */ #[Pure] #[TentativeType] public function getErrorCode(): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the error text from the last operation * @link https://php.net/manual/en/messageformatter.geterrormessage.php * @return string Description of the last error. */ #[Pure] #[TentativeType] public function getErrorMessage(): string {} } class IntlDateFormatter { /** * Completely specified style (Tuesday, April 12, 1952 AD or 3:30:42pm PST) * @link https://php.net/manual/en/class.intldateformatter.php#intl.intldateformatter-constants */ public const FULL = 0; /** * Long style (January 12, 1952 or 3:30:32pm) * @link https://php.net/manual/en/class.intldateformatter.php#intl.intldateformatter-constants */ public const LONG = 1; /** * Medium style (Jan 12, 1952) * @link https://php.net/manual/en/class.intldateformatter.php#intl.intldateformatter-constants */ public const MEDIUM = 2; /** * Most abbreviated style, only essential data (12/13/52 or 3:30pm) * @link https://php.net/manual/en/class.intldateformatter.php#intl.intldateformatter-constants */ public const SHORT = 3; /** * Do not include this element * @link https://php.net/manual/en/class.intldateformatter.php#intl.intldateformatter-constants */ public const NONE = -1; /** * Gregorian Calendar * @link https://php.net/manual/en/class.intldateformatter.php#intl.intldateformatter-constants */ public const GREGORIAN = 1; /** * Non-Gregorian Calendar * @link https://php.net/manual/en/class.intldateformatter.php#intl.intldateformatter-constants */ public const TRADITIONAL = 0; public const RELATIVE_FULL = 128; public const RELATIVE_LONG = 129; public const RELATIVE_MEDIUM = 130; public const RELATIVE_SHORT = 131; public const PATTERN = -2; /** * @param string|null $locale * @param int $dateType * @param int $timeType * @param mixed|null $timezone [optional] * @param mixed|null $calendar [optional] * @param string $pattern [optional] */ #[Pure] public function __construct( #[LanguageAware(['8.0' => 'string|null'], default: '')] $locale, #[ElementAvailable(from: '5.3', to: '8.0')] #[LanguageAware(['8.0' => 'int'], default: '')] $dateType, #[ElementAvailable(from: '5.3', to: '8.0')] #[LanguageAware(['8.0' => 'int'], default: '')] $timeType, #[ElementAvailable(from: '8.1')] int $dateType = 0, #[ElementAvailable(from: '8.1')] int $timeType = 0, #[LanguageAware(['8.5' => 'IntlTimeZone|DateTimeZone|string|null'], default: '')] $timezone = null, $calendar = null, #[LanguageAware(['8.0' => 'string|null'], default: '')] $pattern = null ) {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Create a date formatter * @link https://php.net/manual/en/intldateformatter.create.php * @param string $locale

    * Locale to use when formatting or parsing; default is specified in the ini setting intl.default_locale. *

    * @param int $dateType

    * Date type to use (none, * short, medium, * long, full). * This is one of the * IntlDateFormatter constants. *

    * @param int $timeType

    * Time type to use (none, * short, medium, * long, full). * This is one of the * IntlDateFormatter constants. *

    * @param string $timezone [optional]

    * Time zone ID, default is system default. *

    * @param int $calendar [optional]

    * Calendar to use for formatting or parsing; default is Gregorian. * This is one of the * IntlDateFormatter calendar constants. *

    * @param string $pattern [optional]

    * Optional pattern to use when formatting or parsing. * Possible patterns are documented at http://userguide.icu-project.org/formatparse/datetime. *

    * @return IntlDateFormatter|null */ #[TentativeType] public static function create( #[LanguageAware(['8.0' => 'string|null'], default: '')] $locale, #[ElementAvailable(from: '5.3', to: '8.0')] #[LanguageAware(['8.0' => 'int'], default: '')] $dateType, #[ElementAvailable(from: '5.3', to: '8.0')] #[LanguageAware(['8.0' => 'int'], default: '')] $timeType, #[ElementAvailable(from: '8.1')] int $dateType = 0, #[ElementAvailable(from: '8.1')] int $timeType = 0, #[LanguageAware(['8.5' => 'IntlTimeZone|DateTimeZone|string|null'], default: '')] $timezone = null, #[LanguageAware(['8.0' => 'IntlCalendar|int|null'], default: '')] $calendar = null, #[LanguageAware(['8.0' => 'string|null'], default: '')] $pattern = null ): ?IntlDateFormatter {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the datetype used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.getdatetype.php * @return int|false The current date type value of the formatter. */ #[Pure] #[TentativeType] public function getDateType(): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the timetype used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.gettimetype.php * @return int|false The current date type value of the formatter. */ #[Pure] #[TentativeType] public function getTimeType(): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the calendar used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.getcalendar.php * @return int|false The calendar being used by the formatter. */ #[Pure] #[TentativeType] public function getCalendar(): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * sets the calendar used to the appropriate calendar, which must be * @link https://php.net/manual/en/intldateformatter.setcalendar.php * @param int $calendar

    * The calendar to use. * Default is IntlDateFormatter::GREGORIAN. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function setCalendar(#[LanguageAware(['8.0' => 'IntlCalendar|int|null'], default: '')] $calendar): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the timezone-id used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.gettimezoneid.php * @return string|false ID string for the time zone used by this formatter. */ #[Pure] #[TentativeType] public function getTimeZoneId(): string|false {} /** * (PHP 5 >= 5.5.0, PECL intl >= 3.0.0)
    * Get copy of formatter's calendar object * @link https://secure.php.net/manual/en/intldateformatter.getcalendarobject.php * @return IntlCalendar|false|null A copy of the internal calendar object used by this formatter. */ #[Pure] #[TentativeType] public function getCalendarObject(): IntlCalendar|false|null {} /** * (PHP 5 >= 5.5.0, PECL intl >= 3.0.0)
    * Get formatter's timezone * @link https://secure.php.net/manual/en/intldateformatter.gettimezone.php * @return IntlTimeZone|false The associated IntlTimeZone object or FALSE on failure. */ #[Pure] #[TentativeType] public function getTimeZone(): IntlTimeZone|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Sets the time zone to use * @link https://php.net/manual/en/intldateformatter.settimezoneid.php * @param string $zone

    * The time zone ID string of the time zone to use. * If NULL or the empty string, the default time zone for the runtime is used. *

    * @return bool TRUE on success or FALSE on failure. * @removed 7.0 * @see IntlDateFormatter::setTimeZone() */ #[Deprecated(replacement: "%class%->setTimeZone(%parametersList%)", since: "5.5")] public function setTimeZoneId($zone) {} /** * (PHP 5 >= 5.5.0, PECL intl >= 3.0.0)
    * Sets formatter's timezone * @link https://php.net/manual/en/intldateformatter.settimezone.php * @param mixed $timezone

    * The timezone to use for this formatter. This can be specified in the * following forms: *

      *
    • *

      * NULL, in which case the default timezone will be used, as specified in * the ini setting {@link "https://secure.php.net/manual/en/datetime.configuration.php#ini.date.timezone" date.timezone} or * through the function {@link "https://secure.php.net/manual/en/function.date-default-timezone-set.php" date_default_timezone_set()} and as * returned by {@link "https://secure.php.net/manual/en/function.date-default-timezone-get.php" date_default_timezone_get()}. *

      *
    • *
    • *

      * An {@link "https://secure.php.net/manual/en/class.intltimezone.php" IntlTimeZone}, which will be used directly. *

      *
    • *
    • *

      * A {@link "https://secure.php.net/manual/en/class.datetimezone.php" DateTimeZone}. Its identifier will be extracted * and an ICU timezone object will be created; the timezone will be backed * by ICU's database, not PHP's. *

      *
    • *
    • *

      * A {@link "https://secure.php.net/manual/en/language.types.string.php" string}, which should be a valid ICU timezone identifier. * See IntlTimeZone::createTimeZoneIDEnumeration(). Raw offsets such as "GMT+08:30" are also accepted. *

      *
    • *
    *

    * @return bool|null TRUE on success or FALSE on failure. */ #[TentativeType] #[LanguageAware(['8.3' => 'bool'], default: 'bool|null')] public function setTimeZone(#[LanguageAware(['8.5' => 'IntlTimeZone|DateTimeZone|string|null'], default: '')] $timezone) {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set the pattern used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.setpattern.php * @param string $pattern

    * New pattern string to use. * Possible patterns are documented at http://userguide.icu-project.org/formatparse/datetime. *

    * @return bool TRUE on success or FALSE on failure. * Bad formatstrings are usually the cause of the failure. */ #[TentativeType] public function setPattern(#[LanguageAware(['8.0' => 'string'], default: '')] $pattern): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the pattern used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.getpattern.php * @return string|false The pattern string being used to format/parse. */ #[Pure] #[TentativeType] public function getPattern(): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the locale used by formatter * @link https://php.net/manual/en/intldateformatter.getlocale.php * @param int $type [optional] * @return string|false the locale of this formatter or 'false' if error */ #[Pure] #[TentativeType] public function getLocale( #[ElementAvailable(from: '8.0')] #[LanguageAware(['8.0' => 'int'], default: '')] $type = 0 ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set the leniency of the parser * @link https://php.net/manual/en/intldateformatter.setlenient.php * @param bool $lenient

    * Sets whether the parser is lenient or not, default is TRUE (lenient). *

    * @return void */ #[TentativeType] public function setLenient(#[LanguageAware(['8.0' => 'bool'], default: '')] $lenient): void {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the lenient used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.islenient.php * @return bool TRUE if parser is lenient, FALSE if parser is strict. By default the parser is lenient. */ #[Pure] #[TentativeType] public function isLenient(): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Format the date/time value as a string * @link https://php.net/manual/en/intldateformatter.format.php * @param mixed $datetime

    * Value to format. This may be a DateTime object, * an integer representing a Unix timestamp value (seconds * since epoch, UTC) or an array in the format output by * localtime. *

    * @return string|false The formatted string or, if an error occurred, FALSE. */ #[TentativeType] public function format( #[ElementAvailable(from: '5.3', to: '7.4')] $datetime = null, #[ElementAvailable(from: '8.0')] $datetime, #[ElementAvailable(from: '5.3', to: '7.4')] $array = null ): string|false {} /** * (PHP 5 >= 5.5.0, PECL intl >= 3.0.0)
    * Formats an object * @link https://secure.php.net/manual/en/intldateformatter.formatobject.php * @param object $datetime

    * An object of type {@link "https://secure.php.net/manual/en/class.intlcalendar.php" IntlCalendar} or {@link "https://secure.php.net/manual/en/class.datetime.php" DateTime}. The timezone information in the object will be used. *

    * @param mixed $format [optional]

    * How to format the date/time. This can either be an {@link "https://secure.php.net/manual/en/language.types.array.php" array} with * two elements (first the date style, then the time style, these being one * of the constants IntlDateFormatter::NONE, * IntlDateFormatter::SHORT, * IntlDateFormatter::MEDIUM, * IntlDateFormatter::LONG, * IntlDateFormatter::FULL), a long with * the value of one of these constants (in which case it will be used both * for the time and the date) or a {@link "https://secure.php.net/manual/en/language.types.string.php" string} with the format * described in {@link "http://www.icu-project.org/apiref/icu4c/classSimpleDateFormat.html#details" the ICU documentation}. * If NULL, the default style will be used. *

    * @param string|null $locale [optional]

    * The locale to use, or NULL to use the {@link "https://secure.php.net/manual/en/intl.configuration.php#ini.intl.default-locale" default one}.

    * @return string|false A string with result or FALSE on failure. */ #[TentativeType] public static function formatObject($datetime, $format = null, #[LanguageAware(['8.0' => 'string|null'], default: '')] $locale = null): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Parse string to a timestamp value * @link https://php.net/manual/en/intldateformatter.parse.php * @param string $string

    * string to convert to a time *

    * @param int &$offset [optional]

    * Position at which to start the parsing in $value (zero-based). * If no error occurs before $value is consumed, $parse_pos will contain -1 * otherwise it will contain the position at which parsing ended (and the error occurred). * This variable will contain the end position if the parse fails. * If $parse_pos > strlen($value), the parse fails immediately. *

    * @return int|float|false timestamp parsed value */ #[TentativeType] public function parse(#[LanguageAware(['8.0' => 'string'], default: '')] $string, &$offset = null): int|float|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Parse string to a field-based time value * @link https://php.net/manual/en/intldateformatter.localtime.php * @param string $string

    * string to convert to a time *

    * @param int &$offset [optional]

    * Position at which to start the parsing in $value (zero-based). * If no error occurs before $value is consumed, $parse_pos will contain -1 * otherwise it will contain the position at which parsing ended . * If $parse_pos > strlen($value), the parse fails immediately. *

    * @return array|false Localtime compatible array of integers : contains 24 hour clock value in tm_hour field */ #[TentativeType] public function localtime(#[LanguageAware(['8.0' => 'string'], default: '')] $string, &$offset = null): array|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the error code from last operation * @link https://php.net/manual/en/intldateformatter.geterrorcode.php * @return int The error code, one of UErrorCode values. Initial value is U_ZERO_ERROR. */ #[Pure] #[TentativeType] public function getErrorCode(): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the error text from the last operation. * @link https://php.net/manual/en/intldateformatter.geterrormessage.php * @return string Description of the last error. */ #[Pure] #[TentativeType] public function getErrorMessage(): string {} /** * @since 8.4 */ public function parseToCalendar(string $string, &$offset = null): int|float|false {} } class ResourceBundle implements IteratorAggregate, Countable { /** * @link https://www.php.net/manual/en/resourcebundle.create.php * @param string $locale

    Locale for which the resources should be loaded (locale name, e.g. en_CA).

    * @param string $bundle

    The directory where the data is stored or the name of the .dat file.

    * @param bool $fallback [optional]

    Whether locale should match exactly or fallback to parent locale is allowed.

    */ #[Pure] public function __construct( #[LanguageAware(['8.0' => 'string|null'], default: '')] $locale, #[LanguageAware(['8.0' => 'string|null'], default: '')] $bundle, #[LanguageAware(['8.0' => 'bool'], default: '')] $fallback = true ) {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)
    * Create a resource bundle * @link https://php.net/manual/en/resourcebundle.create.php * @param string $locale

    * Locale for which the resources should be loaded (locale name, e.g. en_CA). *

    * @param string $bundle

    * The directory where the data is stored or the name of the .dat file. *

    * @param bool $fallback [optional]

    * Whether locale should match exactly or fallback to parent locale is allowed. *

    * @return ResourceBundle|null ResourceBundle object or null on error. */ #[TentativeType] public static function create( #[LanguageAware(['8.0' => 'string|null'], default: '')] $locale, #[LanguageAware(['8.0' => 'string|null'], default: '')] $bundle, #[LanguageAware(['8.0' => 'bool'], default: '')] $fallback = true ): ?ResourceBundle {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)
    * Get data from the bundle * @link https://php.net/manual/en/resourcebundle.get.php * @param string|int $index

    * Data index, must be string or integer. *

    * @param bool $fallback * @return mixed the data located at the index or NULL on error. Strings, integers and binary data strings * are returned as corresponding PHP types, integer array is returned as PHP array. Complex types are * returned as ResourceBundle object. */ #[Pure] #[TentativeType] #[LanguageAware(['8.4' => 'ResourceBundle|array|string|int|null'], default: 'mixed')] public function get(#[LanguageAware(['8.4' => 'string|int'], default: '')] $index, #[LanguageAware(['8.0' => 'bool'], default: '')] $fallback = true) {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)
    * Get number of elements in the bundle * @link https://php.net/manual/en/resourcebundle.count.php * @return int<0,max> number of elements in the bundle. */ #[Pure] #[TentativeType] public function count(): int {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)
    * Get supported locales * @link https://php.net/manual/en/resourcebundle.locales.php * @param string $bundle

    * Path of ResourceBundle for which to get available locales, or * empty string for default locales list. *

    * @return array|false the list of locales supported by the bundle. */ #[TentativeType] public static function getLocales(#[LanguageAware(['8.0' => 'string'], default: '')] $bundle): array|false {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)
    * Get bundle's last error code. * @link https://php.net/manual/en/resourcebundle.geterrorcode.php * @return int error code from last bundle object call. */ #[Pure] #[TentativeType] public function getErrorCode(): int {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)
    * Get bundle's last error message. * @link https://php.net/manual/en/resourcebundle.geterrormessage.php * @return string error message from last bundle object's call. */ #[Pure] #[TentativeType] public function getErrorMessage(): string {} /** * @return Iterator * @since 8.0 */ #[Pure] public function getIterator(): Iterator {} } /** * @since 5.4 */ class Transliterator { public const FORWARD = 0; public const REVERSE = 1; /** * Starting 8.2 $id is readonly to unlock subclassing it */ #[LanguageAware(['8.1' => 'string'], default: '')] public readonly string $id; /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Private constructor to deny instantiation * @link https://php.net/manual/en/transliterator.construct.php */ final private function __construct() {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Create a transliterator * @link https://php.net/manual/en/transliterator.create.php * @param string $id

    * The id. *

    * @param int $direction [optional]

    * The direction, defaults to * Transliterator::FORWARD. * May also be set to * Transliterator::REVERSE. *

    * @return Transliterator|null a Transliterator object on success, * or NULL on failure. */ #[TentativeType] public static function create( #[LanguageAware(['8.0' => 'string'], default: '')] $id, #[LanguageAware(['8.0' => 'int'], default: '')] #[EV([Transliterator::FORWARD, Transliterator::REVERSE])] $direction = 0 ): ?Transliterator {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Create transliterator from rules * @link https://php.net/manual/en/transliterator.createfromrules.php * @param string $rules

    * The rules. *

    * @param int $direction [optional]

    * The direction, defaults to * {@see Transliterator::FORWARD}. * May also be set to * {@see Transliterator::REVERSE}. *

    * @return Transliterator|null a Transliterator object on success, * or NULL on failure. */ #[TentativeType] public static function createFromRules( #[LanguageAware(['8.0' => 'string'], default: '')] $rules, #[LanguageAware(['8.0' => 'int'], default: '')] #[EV([Transliterator::FORWARD, Transliterator::REVERSE])] $direction = 0 ): ?Transliterator {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Create an inverse transliterator * @link https://php.net/manual/en/transliterator.createinverse.php * @return Transliterator|null a Transliterator object on success, * or NULL on failure */ #[Pure] #[TentativeType] public function createInverse(): ?Transliterator {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Get transliterator IDs * @link https://php.net/manual/en/transliterator.listids.php * @return array|false An array of registered transliterator IDs on success, * or FALSE on failure. */ #[TentativeType] public static function listIDs(): array|false {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Transliterate a string * @link https://php.net/manual/en/transliterator.transliterate.php * @param string $string

    * The string to be transformed. *

    * @param int $start [optional]

    * The start index (in UTF-16 code units) from which the string will start * to be transformed, inclusive. Indexing starts at 0. The text before will * be left as is. *

    * @param int $end [optional]

    * The end index (in UTF-16 code units) until which the string will be * transformed, exclusive. Indexing starts at 0. The text after will be * left as is. *

    * @return string|false The transfomed string on success, or FALSE on failure. */ #[Pure] #[TentativeType] public function transliterate( #[LanguageAware(['8.0' => 'string'], default: '')] $string, #[LanguageAware(['8.0' => 'int'], default: '')] $start = 0, #[LanguageAware(['8.0' => 'int'], default: '')] $end = -1 ): string|false {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Get last error code * @link https://php.net/manual/en/transliterator.geterrorcode.php * @return int|false The error code on success, * or FALSE if none exists, or on failure. */ #[Pure] #[TentativeType] #[LanguageAware(['8.5' => 'int'], default: 'int|false')] public function getErrorCode() {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Get last error message * @link https://php.net/manual/en/transliterator.geterrormessage.php * @return string|false The error code on success, * or FALSE if none exists, or on failure. */ #[Pure] #[TentativeType] #[LanguageAware(['8.5' => 'string'], default: 'string|false')] public function getErrorMessage() {} } /** * @link https://php.net/manual/en/class.spoofchecker.php */ class Spoofchecker { public const SINGLE_SCRIPT_CONFUSABLE = 1; public const MIXED_SCRIPT_CONFUSABLE = 2; public const WHOLE_SCRIPT_CONFUSABLE = 4; public const ANY_CASE = 8; public const SINGLE_SCRIPT = 16; public const INVISIBLE = 32; public const CHAR_LIMIT = 64; public const ASCII = 268435456; public const HIGHLY_RESTRICTIVE = 805306368; public const MODERATELY_RESTRICTIVE = 1073741824; public const MINIMALLY_RESTRICTIVE = 1342177280; public const UNRESTRICTIVE = 1610612736; public const SINGLE_SCRIPT_RESTRICTIVE = 536870912; public const MIXED_NUMBERS = 1; public const HIDDEN_OVERLAY = 2; /** * @since 8.4 */ public const IGNORE_SPACE = 1; /** * @since 8.4 */ public const CASE_INSENSITIVE = 2; /** * @since 8.4 */ public const ADD_CASE_MAPPINGS = 4; /** * @since 8.4 */ public const SIMPLE_CASE_INSENSITIVE = 6; /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Constructor * @link https://php.net/manual/en/spoofchecker.construct.php */ #[Pure] public function __construct() {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Checks if a given text contains any suspicious characters * @link https://php.net/manual/en/spoofchecker.issuspicious.php * @param string $string

    *

    * @param string &$errorCode [optional]

    *

    * @return bool */ #[TentativeType] public function isSuspicious(#[LanguageAware(['8.0' => 'string'], default: '')] $string, &$errorCode = null): bool {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Checks if a given text contains any confusable characters * @link https://php.net/manual/en/spoofchecker.areconfusable.php * @param string $string1

    *

    * @param string $string2

    *

    * @param int &$errorCode [optional]

    *

    * @return bool */ #[TentativeType] public function areConfusable( #[LanguageAware(['8.0' => 'string'], default: '')] $string1, #[LanguageAware(['8.0' => 'string'], default: '')] $string2, &$errorCode = null ): bool {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Locales to use when running checks * @link https://php.net/manual/en/spoofchecker.setallowedlocales.php * @param string $locales

    *

    * @return void */ #[TentativeType] public function setAllowedLocales(#[LanguageAware(['8.0' => 'string'], default: '')] $locales): void {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Set the checks to run * @link https://php.net/manual/en/spoofchecker.setchecks.php * @param int $checks

    *

    * @return void */ #[TentativeType] public function setChecks(#[LanguageAware(['8.0' => 'int'], default: '')] $checks): void {} /** * @param int $level */ #[TentativeType] public function setRestrictionLevel(#[LanguageAware(['8.0' => 'int'], default: '')] $level): void {} /** * @since 8.4 */ public function setAllowedChars(string $pattern, int $patternOptions = 0): void {} } /** * @since 5.5 */ class IntlGregorianCalendar extends IntlCalendar { /** * @link https://www.php.net/manual/en/intlgregoriancalendar.construct * @param int $timezoneOrYear [optional] * @param int $localeOrMonth [optional] * @param int $day [optional] * @param int $hour [optional] * @param int $minute [optional] * @param int $second [optional] */ public function __construct($timezoneOrYear, $localeOrMonth, $day, $hour, $minute, $second) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * @param mixed $timeZone * @param string $locale * @return IntlGregorianCalendar */ public static function createInstance($timeZone = null, $locale = null) {} /** * @param float $timestamp */ #[TentativeType] public function setGregorianChange(#[LanguageAware(['8.0' => 'float'], default: '')] $timestamp): bool {} /** * @return float */ #[Pure] #[TentativeType] public function getGregorianChange(): float {} /** * @param int $year * @return bool */ #[Pure] #[TentativeType] public function isLeapYear(#[LanguageAware(['8.0' => 'int'], default: '')] $year): bool {} /** * @since 8.3 */ public static function createFromDate(int $year, int $month, int $dayOfMonth): static {} /** * @since 8.3 */ public static function createFromDateTime(int $year, int $month, int $dayOfMonth, int $hour, int $minute, ?int $second = null): static {} } /** * @since 5.5 */ class IntlCalendar { /* Constants */ public const FIELD_ERA = 0; public const FIELD_YEAR = 1; public const FIELD_MONTH = 2; public const FIELD_WEEK_OF_YEAR = 3; public const FIELD_WEEK_OF_MONTH = 4; public const FIELD_DATE = 5; public const FIELD_DAY_OF_YEAR = 6; public const FIELD_DAY_OF_WEEK = 7; public const FIELD_DAY_OF_WEEK_IN_MONTH = 8; public const FIELD_AM_PM = 9; public const FIELD_HOUR = 10; public const FIELD_HOUR_OF_DAY = 11; public const FIELD_MINUTE = 12; public const FIELD_SECOND = 13; public const FIELD_MILLISECOND = 14; public const FIELD_ZONE_OFFSET = 15; public const FIELD_DST_OFFSET = 16; public const FIELD_YEAR_WOY = 17; public const FIELD_DOW_LOCAL = 18; public const FIELD_EXTENDED_YEAR = 19; public const FIELD_JULIAN_DAY = 20; public const FIELD_MILLISECONDS_IN_DAY = 21; public const FIELD_IS_LEAP_MONTH = 22; public const FIELD_FIELD_COUNT = 23; public const FIELD_DAY_OF_MONTH = 5; public const DOW_SUNDAY = 1; public const DOW_MONDAY = 2; public const DOW_TUESDAY = 3; public const DOW_WEDNESDAY = 4; public const DOW_THURSDAY = 5; public const DOW_FRIDAY = 6; public const DOW_SATURDAY = 7; public const DOW_TYPE_WEEKDAY = 0; public const DOW_TYPE_WEEKEND = 1; public const DOW_TYPE_WEEKEND_OFFSET = 2; public const DOW_TYPE_WEEKEND_CEASE = 3; public const WALLTIME_FIRST = 1; public const WALLTIME_LAST = 0; public const WALLTIME_NEXT_VALID = 2; /* Methods */ /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Add a (signed) amount of time to a field * @link https://secure.php.net/manual/en/intlcalendar.add.php * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. * These are integer values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @param int $value

    The signed amount to add to the current field. If the amount is positive, the instant will be moved forward; if it is negative, the instant wil be moved into the past. The unit is implicit to the field type. * For instance, hours for IntlCalendar::FIELD_HOUR_OF_DAY.

    * @return bool Returns TRUE on success or FALSE on failure. */ #[TentativeType] public function add( #[LanguageAware(['8.0' => 'int'], default: '')] $field, #[LanguageAware(['8.0' => 'int'], default: '')] $value ): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Whether this object's time is after that of the passed object * https://secure.php.net/manual/en/intlcalendar.after.php * @param IntlCalendar $other

    The calendar whose time will be checked against this object's time.

    * @return bool * Returns TRUE if this object's current time is after that of the * calendar argument's time. Returns FALSE otherwise. * Also returns FALSE on failure. You can use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or * {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to detect error conditions. */ #[Pure] #[TentativeType] public function after(IntlCalendar $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Whether this object's time is before that of the passed object * @link https://secure.php.net/manual/en/intlcalendar.before.php * @param IntlCalendar $other

    The calendar whose time will be checked against this object's time.

    * @return bool * Returns TRUE if this object's current time is before that of the * calendar argument's time. Returns FALSE otherwise. * Also returns FALSE on failure. You can use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or * {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to detect error conditions. */ #[Pure] #[TentativeType] public function before(IntlCalendar $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Clear a field or all fields * @link https://secure.php.net/manual/en/intlcalendar.clear.php * @param int $field [optional]

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return bool Returns TRUE on success or FALSE on failure. Failure can only occur is invalid arguments are provided. */ #[LanguageAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function clear(#[LanguageAware(['8.0' => 'int|null'], default: '')] $field = null) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Private constructor for disallowing instantiation * @link https://secure.php.net/manual/en/intlcalendar.construct.php */ private function __construct() {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Create a new IntlCalendar * @link https://secure.php.net/manual/en/intlcalendar.createinstance.php * @param mixed $timezone [optional]

    * The timezone to use. *

    * *
      *
    • *

      * NULL, in which case the default timezone will be used, as specified in * the ini setting {@link https://secure.php.net/manual/en/datetime.configuration.php#ini.date.timezone date.timezone} or * through the function {@link https://secure.php.net/manual/en/function.date-default-timezone-set.php date_default_timezone_set()} and as * returned by {@link https://secure.php.net/manual/en/function.date-default-timezone-get.php date_default_timezone_get()}. *

      *
    • *
    • *

      * An {@link https://secure.php.net/manual/en/class.intltimezone.php IntlTimeZone}, which will be used directly. *

      *
    • *
    • *

      * A {@link https://secure.php.net/manual/en/class.datetimezone.php DateTimeZone}. Its identifier will be extracted * and an ICU timezone object will be created; the timezone will be backed * by ICU's database, not PHP's. *

      *
    • *
    • *

      * A {@link https://secure.php.net/manual/en/language.types.string.php string}, which should be a valid ICU timezone identifier. * See IntlTimeZone::createTimeZoneIDEnumeration(). Raw * offsets such as "GMT+08:30" are also accepted. *

      *
    • *
    *

    * @param string|null $locale [optional]

    * A locale to use or NULL to use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.default-locale the default locale}. *

    * @return IntlCalendar|null * The created {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} instance or NULL on * failure. */ #[TentativeType] public static function createInstance( #[LanguageAware(['8.5' => 'IntlTimeZone|DateTimeZone|string|null'], default: '')] $timezone = null, #[LanguageAware(['8.0' => 'string|null'], default: '')] $locale = null ): ?IntlCalendar {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Compare time of two IntlCalendar objects for equality * @link https://secure.php.net/manual/en/intlcalendar.equals.php * @param IntlCalendar $other * @return bool

    * Returns TRUE if the current time of both this and the passed in * {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} object are the same, or FALSE * otherwise. The value FALSE can also be returned on failure. This can only * happen if bad arguments are passed in. In any case, the two cases can be * distinguished by calling {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()}. *

    */ #[Pure] #[TentativeType] public function equals(#[LanguageAware(['8.0' => 'IntlCalendar'], default: '')] $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Calculate difference between given time and this object's time * @link https://secure.php.net/manual/en/intlcalendar.fielddifference.php * @param float $timestamp

    * The time against which to compare the quantity represented by the * field. For the result to be positive, the time * given for this parameter must be ahead of the time of the object the * method is being invoked on. *

    * @param int $field

    * The field that represents the quantity being compared. *

    * *

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return int|false Returns a (signed) difference of time in the unit associated with the * specified field or FALSE on failure. */ #[Pure] #[TentativeType] public function fieldDifference( #[LanguageAware(['8.0' => 'float'], default: '')] $timestamp, #[LanguageAware(['8.0' => 'int'], default: '')] $field ): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a2)
    * Create an IntlCalendar from a DateTime object or string * @link https://secure.php.net/manual/en/intlcalendar.fromdatetime.php * @param mixed $datetime

    * A {@link https://secure.php.net/manual/en/class.datetime.php DateTime} object or a {@link https://secure.php.net/manual/en/language.types.string.php string} that * can be passed to {@link https://secure.php.net/manual/en/datetime.construct.php DateTime::__construct()}. *

    * @param $locale [optional] * @return IntlCalendar|null * The created {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} object or NULL in case of * failure. If a {@link https://secure.php.net/manual/en/language.types.string.php string} is passed, any exception that occurs * inside the {@link https://secure.php.net/manual/en/class.datetime.php DateTime} constructor is propagated. */ #[TentativeType] public static function fromDateTime( #[LanguageAware(['8.0' => 'DateTime|string'], default: '')] $datetime, #[LanguageAware(['8.0' => 'string|null'], default: '')] #[ElementAvailable(from: '8.0')] $locale ): ?IntlCalendar {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the value for a field * @link https://secure.php.net/manual/en/intlcalendar.get.php * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return int|false An integer with the value of the time field. */ #[Pure] #[TentativeType] public function get(#[LanguageAware(['8.0' => 'int'], default: '')] $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * The maximum value for a field, considering the object's current time * @link https://secure.php.net/manual/en/intlcalendar.getactualmaximum.php * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return int|false * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing the maximum value in the units associated * with the given field or FALSE on failure. */ #[Pure] #[TentativeType] public function getActualMaximum(#[LanguageAware(['8.0' => 'int'], default: '')] $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * The minimum value for a field, considering the object's current time * @link https://secure.php.net/manual/en/intlcalendar.getactualminimum.php * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. * These are integer values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return int|false * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing the minimum value in the field's * unit or FALSE on failure. */ #[Pure] #[TentativeType] public function getActualMinimum(#[LanguageAware(['8.0' => 'int'], default: '')] $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get array of locales for which there is data * @link https://secure.php.net/manual/en/intlcalendar.getavailablelocales.php * @return string[] An array of strings, one for which locale. */ #[TentativeType] public static function getAvailableLocales(): array {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Tell whether a day is a weekday, weekend or a day that has a transition between the two * @param int $dayOfWeek

    * One of the constants IntlCalendar::DOW_SUNDAY, * IntlCalendar::DOW_MONDAY, ..., * IntlCalendar::DOW_SATURDAY. *

    * @return int|false * Returns one of the constants * IntlCalendar::DOW_TYPE_WEEKDAY, * IntlCalendar::DOW_TYPE_WEEKEND, * IntlCalendar::DOW_TYPE_WEEKEND_OFFSET or * IntlCalendar::DOW_TYPE_WEEKEND_CEASE or FALSE on failure. */ #[Pure] #[TentativeType] public function getDayOfWeekType(#[LanguageAware(['8.0' => 'int'], default: '')] $dayOfWeek): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get last error code on the object * @link https://secure.php.net/manual/en/intlcalendar.geterrorcode.php * @return int|false An ICU error code indicating either success, failure or a warning. */ #[Pure] #[TentativeType] public function getErrorCode(): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get last error message on the object * @link https://secure.php.net/manual/en/intlcalendar.geterrormessage.php * @return string|false The error message associated with last error that occurred in a function call on this object, or a string indicating the non-existance of an error. */ #[Pure] #[TentativeType] public function getErrorMessage(): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the first day of the week for the calendar's locale * @link https://secure.php.net/manual/en/intlcalendar.getfirstdayofweek.php * @return int|false * One of the constants IntlCalendar::DOW_SUNDAY, * IntlCalendar::DOW_MONDAY, ..., * IntlCalendar::DOW_SATURDAY or FALSE on failure. */ #[Pure] #[TentativeType] public function getFirstDayOfWeek(): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the largest local minimum value for a field * @link https://secure.php.net/manual/en/intlcalendar.getgreatestminimum.php * @param int $field * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. * @return int|false * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing a field value, in the field's * unit, or FALSE on failure. */ #[Pure] #[TentativeType] public function getGreatestMinimum(#[LanguageAware(['8.0' => 'int'], default: '')] $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get set of locale keyword values * @param string $keyword

    * The locale keyword for which relevant values are to be queried. Only * 'calendar' is supported. *

    * @param string $locale

    * The locale onto which the keyword/value pair are to be appended. *

    * @param bool $onlyCommon *

    * Whether to show only the values commonly used for the specified locale. *

    * @return Iterator|false An iterator that yields strings with the locale keyword values or FALSE on failure. */ #[TentativeType] public static function getKeywordValuesForLocale( #[LanguageAware(['8.0' => 'string'], default: '')] $keyword, #[LanguageAware(['8.0' => 'string'], default: '')] $locale, #[LanguageAware(['8.0' => 'bool'], default: '')] $onlyCommon ): IntlIterator|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the smallest local maximum for a field * @link https://secure.php.net/manual/en/intlcalendar.getleastmaximum.php * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return int|false * An {@link https://secure.php.net/manual/en/language.types.integer.ph int} representing a field value in the field's * unit or FALSE on failure. */ #[Pure] #[TentativeType] public function getLeastMaximum(#[LanguageAware(['8.0' => 'int'], default: '')] $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the locale associated with the object * @link https://secure.php.net/manual/en/intlcalendar.getlocale.php * @param int $type

    * Whether to fetch the actual locale (the locale from which the calendar * data originates, with Locale::ACTUAL_LOCALE) or the * valid locale, i.e., the most specific locale supported by ICU relatively * to the requested locale – see Locale::VALID_LOCALE. * From the most general to the most specific, the locales are ordered in * this fashion – actual locale, valid locale, requested locale. *

    * @return string|false */ #[Pure] #[TentativeType] public function getLocale(#[LanguageAware(['8.0' => 'int'], default: '')] $type): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the global maximum value for a field * @link https://secure.php.net/manual/en/intlcalendar.getmaximum.php * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return int|false */ #[Pure] #[TentativeType] public function getMaximum(#[LanguageAware(['8.0' => 'int'], default: '')] $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get minimal number of days the first week in a year or month can have * @link https://secure.php.net/manual/en/intlcalendar.getminimaldaysinfirstweek.php * @return int|false * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing a number of days or FALSE on failure. */ #[Pure] #[TentativeType] public function getMinimalDaysInFirstWeek(): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the global minimum value for a field * @link https://secure.php.net/manual/en/intlcalendar.getminimum.php * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return int|false * An int representing a value for the given field in the field's unit or FALSE on failure. */ #[Pure] #[TentativeType] public function getMinimum(#[LanguageAware(['8.0' => 'int'], default: '')] $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get number representing the current time * @return float A float representing a number of milliseconds since the epoch, not counting leap seconds. */ #[TentativeType] public static function getNow(): float {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get behavior for handling repeating wall time * @link https://secure.php.net/manual/en/intlcalendar.getrepeatedwalltimeoption.php * @return int * One of the constants IntlCalendar::WALLTIME_FIRST or * IntlCalendar::WALLTIME_LAST. */ #[Pure] #[TentativeType] public function getRepeatedWallTimeOption(): int {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get behavior for handling skipped wall time * @link https://secure.php.net/manual/en/intlcalendar.getskippedwalltimeoption.php * @return int * One of the constants IntlCalendar::WALLTIME_FIRST, * IntlCalendar::WALLTIME_LAST or * IntlCalendar::WALLTIME_NEXT_VALID. */ #[Pure] #[TentativeType] public function getSkippedWallTimeOption(): int {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get time currently represented by the object * @return float|false * A {@link https://secure.php.net/manual/en/language.types.float.php float} representing the number of milliseconds elapsed since the * reference time (1 Jan 1970 00:00:00 UTC). */ #[Pure] #[TentativeType] public function getTime(): float|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the object's timezone * @link https://secure.php.net/manual/en/intlcalendar.gettimezone.php * @return IntlTimeZone|false * An {@link https://secure.php.net/manual/en/class.intltimezone.php IntlTimeZone} object corresponding to the one used * internally in this object. */ #[Pure] #[TentativeType] public function getTimeZone(): IntlTimeZone|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the calendar type * @link https://secure.php.net/manual/en/intlcalendar.gettype.php * @return string * A {@link https://secure.php.net/manual/en/language.types.string.php string} representing the calendar type, such as * 'gregorian', 'islamic', etc. */ #[Pure] #[TentativeType] public function getType(): string {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get time of the day at which weekend begins or ends * @link https://secure.php.net/manual/en/intlcalendar.getweekendtransition.php * @param string $dayOfWeek

    * One of the constants IntlCalendar::DOW_SUNDAY, * IntlCalendar::DOW_MONDAY, ..., * IntlCalendar::DOW_SATURDAY. *

    * @return int|false * The number of milliseconds into the day at which the the weekend begins or * ends or FALSE on failure. */ #[Pure] #[TentativeType] public function getWeekendTransition(#[LanguageAware(['8.0' => 'int'], default: '')] $dayOfWeek): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Whether the object's time is in Daylight Savings Time * @link https://secure.php.net/manual/en/intlcalendar.indaylighttime.php * @return bool * Returns TRUE if the date is in Daylight Savings Time, FALSE otherwise. * The value FALSE may also be returned on failure, for instance after * specifying invalid field values on non-lenient mode; use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or query * {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to disambiguate. */ #[Pure] #[TentativeType] public function inDaylightTime(): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Whether another calendar is equal but for a different time * @link https://secure.php.net/manual/en/intlcalendar.isequivalentto.php * @param IntlCalendar $other The other calendar against which the comparison is to be made. * @return bool * Assuming there are no argument errors, returns TRUE iif the calendars are equivalent except possibly for their set time. */ #[Pure] #[TentativeType] public function isEquivalentTo(IntlCalendar $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Whether date/time interpretation is in lenient mode * @link https://secure.php.net/manual/en/intlcalendar.islenient.php * @return bool * A {@link https://secure.php.net/manual/en/language.types.boolean.php bool} representing whether the calendar is set to lenient mode. */ #[Pure] #[TentativeType] public function isLenient(): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Whether a certain date/time is in the weekend * @link https://secure.php.net/manual/en/intlcalendar.isweekend.php * @param float|null $timestamp [optional]

    * An optional timestamp representing the number of milliseconds since the * epoch, excluding leap seconds. If NULL, this object's current time is * used instead. *

    * @return bool *

    A {@link https://secure.php.net/manual/en/language.types.boolean.php bool} indicating whether the given or this object's time occurs * in a weekend. *

    *

    * The value FALSE may also be returned on failure, for instance after giving * a date out of bounds on non-lenient mode; use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or query * {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to disambiguate.

    */ #[Pure] #[TentativeType] public function isWeekend(#[LanguageAware(['8.0' => 'float|null'], default: '')] $timestamp = null): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Add value to field without carrying into more significant fields * @link https://secure.php.net/manual/en/intlcalendar.roll.php * @param int $field *

    One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time * {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @param mixed $value

    * The (signed) amount to add to the field, TRUE for rolling up (adding * 1), or FALSE for rolling down (subtracting * 1). *

    * @return bool Returns TRUE on success or FALSE on failure. */ #[TentativeType] public function roll(#[LanguageAware(['8.0' => 'int'], default: '')] $field, $value): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Whether a field is set * @link https://secure.php.net/manual/en/intlcalendar.isset.php * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time * {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. * These are integer values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return bool Assuming there are no argument errors, returns TRUE iif the field is set. */ #[TentativeType] public function PS_UNRESERVE_PREFIX_isSet(#[LanguageAware(['8.0' => 'int'], default: '')] $field): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Set a time field or several common fields at once * @link https://secure.php.net/manual/en/intlcalendar.set.php * @param int $year

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @param int $month

    * The new value for IntlCalendar::FIELD_MONTH. *

    * @param int $dayOfMonth [optional]

    * The new value for IntlCalendar::FIELD_DAY_OF_MONTH. * The month sequence is zero-based, i.e., January is represented by 0, * February by 1, ..., December is 11 and Undecember (if the calendar has * it) is 12. *

    * @param int $hour [optional] *

    * The new value for IntlCalendar::FIELD_HOUR_OF_DAY. *

    * @param int $minute [optional] *

    * The new value for IntlCalendar::FIELD_MINUTE. *

    * @param int $second [optional]

    * The new value for IntlCalendar::FIELD_SECOND. *

    * @return bool Returns TRUE on success and FALSE on failure. */ public function set($year, $month, $dayOfMonth = null, $hour = null, $minute = null, $second = null) {} /** * (PHP 5 >= 5.5.0 PECL intl >= 3.0.0a1)
    * Set a time field or several common fields at once * @link https://secure.php.net/manual/en/intlcalendar.set.php * @param int $field One of the IntlCalendar date/time field constants. These are integer values between 0 and IntlCalendar::FIELD_COUNT. * @param int $value The new value of the given field. * @return bool Returns TRUE on success and FALSE on failure. * @since 5.5 */ public function set($field, $value) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Set the day on which the week is deemed to start * @link https://secure.php.net/manual/en/intlcalendar.setfirstdayofweek.php * @param int $dayOfWeek

    * One of the constants IntlCalendar::DOW_SUNDAY, * IntlCalendar::DOW_MONDAY, ..., * IntlCalendar::DOW_SATURDAY. *

    * @return bool Returns TRUE on success. Failure can only happen due to invalid parameters. */ #[LanguageAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function setFirstDayOfWeek(#[LanguageAware(['8.0' => 'int'], default: '')] $dayOfWeek) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Set whether date/time interpretation is to be lenient * @link https://secure.php.net/manual/en/intlcalendar.setlenient.php * @param bool $lenient

    * Use TRUE to activate the lenient mode; FALSE otherwise. *

    * @return bool Returns TRUE on success. Failure can only happen due to invalid parameters. */ #[LanguageAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function setLenient(#[LanguageAware(['8.0' => 'bool'], default: '')] $lenient) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Set behavior for handling repeating wall times at negative timezone offset transitions * @link https://secure.php.net/manual/en/intlcalendar.setrepeatedwalltimeoption.php * @param int $option

    * One of the constants IntlCalendar::WALLTIME_FIRST or * IntlCalendar::WALLTIME_LAST. *

    * @return bool * Returns TRUE on success. Failure can only happen due to invalid parameters. */ #[LanguageAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function setRepeatedWallTimeOption(#[LanguageAware(['8.0' => 'int'], default: '')] $option) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Set behavior for handling skipped wall times at positive timezone offset transitions * @link https://secure.php.net/manual/en/intlcalendar.setskippedwalltimeoption.php * @param int $option

    * One of the constants IntlCalendar::WALLTIME_FIRST, * IntlCalendar::WALLTIME_LAST or * IntlCalendar::WALLTIME_NEXT_VALID. *

    * @return bool *

    * Returns TRUE on success. Failure can only happen due to invalid parameters. *

    */ #[LanguageAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function setSkippedWallTimeOption(#[LanguageAware(['8.0' => 'int'], default: '')] $option) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Set the calendar time in milliseconds since the epoch * @link https://secure.php.net/manual/en/intlcalendar.settime.php * @param float $timestamp

    * An instant represented by the number of number of milliseconds between * such instant and the epoch, ignoring leap seconds. *

    * @return bool * Returns TRUE on success and FALSE on failure. */ #[TentativeType] public function setTime(#[LanguageAware(['8.0' => 'float'], default: '')] $timestamp): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Set the timezone used by this calendar * @link https://secure.php.net/manual/en/intlcalendar.settimezone.php * @param mixed $timezone

    * The new timezone to be used by this calendar. It can be specified in the * following ways: * *

      *
    • *

      * NULL, in which case the default timezone will be used, as specified in * the ini setting {@link https://secure.php.net/manual/en/datetime.configuration.php#ini.date.timezone date.timezone} or * through the function {@link https://secure.php.net/manual/en/function.date-default-timezone-set.php date_default_timezone_set()} and as * returned by {@link https://secure.php.net/manual/en/function.date-default-timezone-get.php date_default_timezone_get()}. *

      *
    • *
    • *

      * An {@link https://secure.php.net/manual/en/class.intltimezone.php IntlTimeZone}, which will be used directly. *

      *
    • *
    • *

      * A {@link https://secure.php.net/manual/en/class.datetimezone.php DateTimeZone}. Its identifier will be extracted * and an ICU timezone object will be created; the timezone will be backed * by ICU's database, not PHP's. *

      *
    • *
    • *

      * A {@link https://secure.php.net/manual/en/language.types.string.php string}, which should be a valid ICU timezone identifier. * See b>IntlTimeZone::createTimeZoneIDEnumeration(). Raw * offsets such as "GMT+08:30" are also accepted. *

      *
    • *
    * @return bool Returns TRUE on success and FALSE on failure. */ #[TentativeType] public function setTimeZone(#[LanguageAware(['8.5' => 'IntlTimeZone|DateTimeZone|string|null'], default: '')] $timezone): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a2)
    * Convert an IntlCalendar into a DateTime object * @link https://secure.php.net/manual/en/intlcalendar.todatetime.php * @return DateTime|false * A {@link https://secure.php.net/manual/en/class.datetime.php DateTime} object with the same timezone as this * object (though using PHP's database instead of ICU's) and the same time, * except for the smaller precision (second precision instead of millisecond). * Returns FALSE on failure. */ #[Pure] #[TentativeType] public function toDateTime(): DateTime|false {} /** * @link https://www.php.net/manual/en/intlcalendar.setminimaldaysinfirstweek.php * @param int $days * @return bool */ #[LanguageAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function setMinimalDaysInFirstWeek(#[LanguageAware(['8.0' => 'int'], default: '')] $days) {} /** * @since 8.3 */ public function setDate(int $year, int $month, int $dayOfMonth): void {} /** * @since 8.3 */ public function setDateTime(int $year, int $month, int $dayOfMonth, int $hour, int $minute, ?int $second = null): void {} } /** * @since 5.5 */ class IntlIterator implements Iterator { #[TentativeType] public function current(): mixed {} #[TentativeType] public function key(): mixed {} #[TentativeType] public function next(): void {} #[TentativeType] public function rewind(): void {} #[TentativeType] public function valid(): bool {} } /** * @since 5.5 */ class IntlException extends Exception {} /** * @since 5.5 */ class IntlTimeZone { /* Constants */ public const DISPLAY_SHORT = 1; public const DISPLAY_LONG = 2; public const DISPLAY_SHORT_GENERIC = 3; public const DISPLAY_LONG_GENERIC = 4; public const DISPLAY_SHORT_GMT = 5; public const DISPLAY_LONG_GMT = 6; public const DISPLAY_SHORT_COMMONLY_USED = 7; public const DISPLAY_GENERIC_LOCATION = 8; public const TYPE_ANY = 0; public const TYPE_CANONICAL = 1; public const TYPE_CANONICAL_LOCATION = 2; /* Methods */ private function __construct() {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the number of IDs in the equivalency group that includes the given ID * @link https://secure.php.net/manual/en/intltimezone.countequivalentids.php * @param string $timezoneId * @return int|false number of IDs or FALSE on failure */ #[TentativeType] public static function countEquivalentIDs(#[LanguageAware(['8.0' => 'string'], default: '')] $timezoneId): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Create a new copy of the default timezone for this host * @link https://secure.php.net/manual/en/intltimezone.createdefault.php * @return IntlTimeZone */ #[TentativeType] public static function createDefault(): IntlTimeZone {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get an enumeration over time zone IDs associated with the given country or offset * @link https://secure.php.net/manual/en/intltimezone.createenumeration.php * @param mixed $countryOrRawOffset [optional] * @return IntlIterator|false an iterator or FALSE on failure */ #[TentativeType] public static function createEnumeration(#[LanguageAware(['8.5' => 'string|int|null'], default: '')] $countryOrRawOffset): IntlIterator|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Create a timezone object for the given ID * @link https://secure.php.net/manual/en/intltimezone.createtimezone.php * @param string $timezoneId * @return IntlTimeZone|null a timezone object or NULL on failure */ #[TentativeType] public static function createTimeZone(#[LanguageAware(['8.0' => 'string'], default: '')] $timezoneId): ?IntlTimeZone {} /** * (PHP 5 >=5.5.0)
    * Get an enumeration over system time zone IDs with the given filter conditions * @link https://secure.php.net/manual/en/intltimezone.createtimezoneidenumeration.php * @param int $type * @param string|null $region [optional] * @param int $rawOffset [optional] * @return IntlIterator|false an iterator or FALSE on failure */ #[TentativeType] public static function createTimeZoneIDEnumeration( #[LanguageAware(['8.0' => 'int'], default: '')] $type, #[LanguageAware(['8.0' => 'string|null'], default: '')] $region = null, #[LanguageAware(['8.0' => 'int|null'], default: '')] $rawOffset = null ): IntlIterator|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Create a timezone object from DateTimeZone * @link https://secure.php.net/manual/en/intltimezone.fromdatetimezone.php * @param DateTimeZone $timezone * @return IntlTimeZone|null a timezone object or NULL on failure */ #[TentativeType] public static function fromDateTimeZone(#[LanguageAware(['8.0' => 'DateTimeZone'], default: '')] $timezone): ?IntlTimeZone {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the canonical system timezone ID or the normalized custom time zone ID for the given time zone ID * @link https://secure.php.net/manual/en/intltimezone.getcanonicalid.php * @param string $timezoneId * @param bool &$isSystemId [optional] * @return string|false the timezone ID or FALSE on failure */ #[TentativeType] public static function getCanonicalID(#[LanguageAware(['8.0' => 'string'], default: '')] $timezoneId, &$isSystemId): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get a name of this time zone suitable for presentation to the user * @param bool $dst [optional] * @param int $style [optional] * @param string $locale [optional] * @return string|false the timezone name or FALSE on failure */ #[Pure] #[TentativeType] public function getDisplayName( #[LanguageAware(['8.0' => 'bool'], default: '')] $dst = false, #[LanguageAware(['8.0' => 'int'], default: '')] $style = 2, #[LanguageAware(['8.0' => 'string|null'], default: '')] $locale ): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the amount of time to be added to local standard time to get local wall clock time * @link https://secure.php.net/manual/en/intltimezone.getequivalentid.php * @return int */ #[Pure] #[TentativeType] public function getDSTSavings(): int {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get an ID in the equivalency group that includes the given ID * @link https://secure.php.net/manual/en/intltimezone.getequivalentid.php * @param string $timezoneId * @param int $offset * @return string|false the time zone ID or FALSE on failure */ #[TentativeType] public static function getEquivalentID( #[LanguageAware(['8.0' => 'string'], default: '')] $timezoneId, #[LanguageAware(['8.0' => 'int'], default: '')] $offset ): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get last error code on the object * @link https://secure.php.net/manual/en/intltimezone.geterrorcode.php * @return int|false */ #[Pure] #[TentativeType] public function getErrorCode(): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get last error message on the object * @link https://secure.php.net/manual/en/intltimezone.geterrormessage.php * @return string|false */ #[Pure] #[TentativeType] public function getErrorMessage(): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Create GMT (UTC) timezone * @link https://secure.php.net/manual/en/intltimezone.getgmt.php * @return IntlTimeZone */ #[TentativeType] public static function getGMT(): IntlTimeZone {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get timezone ID * @return string|false */ #[Pure] #[TentativeType] public function getID(): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the time zone raw and GMT offset for the given moment in time * @link https://secure.php.net/manual/en/intltimezone.getoffset.php * @param float $timestamp * moment in time for which to return offsets, in units of milliseconds from * January 1, 1970 0:00 GMT, either GMT time or local wall time, depending on * `local'. * @param bool $local * if true, `date' is local wall time; otherwise it is in GMT time. * @param int &$rawOffset * output parameter to receive the raw offset, that is, the offset not * including DST adjustments * @param int &$dstOffset * output parameter to receive the DST offset, that is, the offset to be added * to `rawOffset' to obtain the total offset between local and GMT time. If * DST is not in effect, this value is zero; otherwise it is a positive value, * typically one hour. * @return bool boolean indication of success */ #[TentativeType] public function getOffset( #[LanguageAware(['8.0' => 'float'], default: '')] $timestamp, #[LanguageAware(['8.0' => 'bool'], default: '')] $local, &$rawOffset, &$dstOffset ): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the raw GMT offset (before taking daylight savings time into account * @link https://secure.php.net/manual/en/intltimezone.getrawoffset.php * @return int */ #[Pure] #[TentativeType] public function getRawOffset(): int {} /** * (PHP 5 >=5.5.0)
    * Get the region code associated with the given system time zone ID * @link https://secure.php.net/manual/en/intltimezone.getregion.php * @param string $timezoneId * @return string|false region or FALSE on failure */ #[TentativeType] public static function getRegion(#[LanguageAware(['8.0' => 'string'], default: '')] $timezoneId): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the timezone data version currently used by ICU * @link https://secure.php.net/manual/en/intltimezone.gettzdataversion.php * @return string|false */ #[TentativeType] public static function getTZDataVersion(): string|false {} /** * (PHP 5 >=5.5.0)
    * Get the "unknown" time zone * @link https://secure.php.net/manual/en/intltimezone.getunknown.php * @return IntlTimeZone */ #[TentativeType] public static function getUnknown(): IntlTimeZone {} /** * (PHP 7 >=7.1.0)
    * Translates a system timezone (e.g. "America/Los_Angeles") into a Windows * timezone (e.g. "Pacific Standard Time"). * @link https://secure.php.net/manual/en/intltimezone.getwindowsid.php * @param string $timezoneId * @return string|false the Windows timezone or FALSE on failure * @since 7.1 */ #[TentativeType] public static function getWindowsID(string $timezoneId): string|false {} /** * @link https://www.php.net/manual/en/intltimezone.getidforwindowsid.php * @param string $timezoneId * @param string|null $region * @return string|false the Windows timezone or FALSE on failure * @since 7.1 */ #[TentativeType] public static function getIDForWindowsID(string $timezoneId, ?string $region = null): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Check if this zone has the same rules and offset as another zone * @link https://secure.php.net/manual/en/intltimezone.hassamerules.php * @param IntlTimeZone $other * @return bool */ #[Pure] #[TentativeType] public function hasSameRules(IntlTimeZone $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Convert to DateTimeZone object * @link https://secure.php.net/manual/en/intltimezone.todatetimezone.php * @return DateTimeZone|false the DateTimeZone object or FALSE on failure */ #[Pure] #[TentativeType] public function toDateTimeZone(): DateTimeZone|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Check if this time zone uses daylight savings time * @link https://secure.php.net/manual/en/intltimezone.usedaylighttime.php * @return bool */ #[TentativeType] public function useDaylightTime(): bool {} /** * @since 8.4 */ public static function getIanaID(string $timezoneId): string|false {} } /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Create a collator * @link https://php.net/manual/en/collator.create.php * @param string $locale

    * The locale containing the required collation rules. Special values for * locales can be passed in - if null is passed for the locale, the * default locale collation rules will be used. If empty string ("") or * "root" are passed, UCA rules will be used. *

    * @return Collator|null Return new instance of Collator object, or NULL * on error. */ #[Pure] function collator_create(string $locale): ?Collator {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Compare two Unicode strings * @link https://php.net/manual/en/collator.compare.php * @param Collator $object * @param string $string1

    * The first string to compare. *

    * @param string $string2

    * The second string to compare. *

    * @return int|false Return comparison result:

    *

    *

    * 1 if string1 is greater than * string2 ; *

    *

    * 0 if string1 is equal to * string2; *

    *

    * -1 if string1 is less than * string2 . *

    * On error * boolean * FALSE * is returned. */ #[Pure] function collator_compare(Collator $object, string $string1, string $string2): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get collation attribute value * @link https://php.net/manual/en/collator.getattribute.php * @param Collator $object * @param int $attribute

    * Attribute to get value for. *

    * @return int|false Attribute value, or boolean FALSE on error. */ #[Pure] function collator_get_attribute(Collator $object, int $attribute): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set collation attribute * @link https://php.net/manual/en/collator.setattribute.php * @param Collator $object * @param int $attribute

    Attribute.

    * @param int $value

    * Attribute value. *

    * @return bool TRUE on success or FALSE on failure. */ function collator_set_attribute(Collator $object, int $attribute, int $value): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get current collation strength * @link https://php.net/manual/en/collator.getstrength.php * @param Collator $object * @return int current collation strength */ #[Pure] function collator_get_strength(Collator $object): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set collation strength * @link https://php.net/manual/en/collator.setstrength.php * @param Collator $object * @param int $strength

    Strength to set.

    *

    * Possible values are: * Collator::PRIMARY *

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageAware(['8.4' => 'true'], default: 'bool')] function collator_set_strength(Collator $object, int $strength) {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Sort array using specified collator * @link https://php.net/manual/en/collator.sort.php * @param Collator $object * @param string[] &$array

    * Array of strings to sort. *

    * @param int $flags

    * Optional sorting type, one of the following: *

    *

    * Collator::SORT_REGULAR * - compare items normally (don't change types) *

    * @return bool TRUE on success or FALSE on failure. */ function collator_sort(Collator $object, array &$array, int $flags = 0): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Sort array using specified collator and sort keys * @link https://php.net/manual/en/collator.sortwithsortkeys.php * @param Collator $object * @param string[] &$array

    Array of strings to sort

    * @return bool TRUE on success or FALSE on failure. */ function collator_sort_with_sort_keys( Collator $object, array &$array, #[ElementAvailable(from: '5.3', to: '5.6')] $sort_flags = [] ): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Sort array maintaining index association * @link https://php.net/manual/en/collator.asort.php * @param Collator $object * @param string[] &$array

    Array of strings to sort.

    * @param int $flags

    * Optional sorting type, one of the following: * Collator::SORT_REGULAR * - compare items normally (don't change types) *

    * @return bool TRUE on success or FALSE on failure. */ function collator_asort(Collator $object, array &$array, int $flags = 0): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the locale name of the collator * @link https://php.net/manual/en/collator.getlocale.php * @param Collator $object * @param int $type

    * You can choose between valid and actual locale ( * Locale::VALID_LOCALE and * Locale::ACTUAL_LOCALE, * respectively). The default is the actual locale. *

    * @return string|false Real locale name from which the collation data comes. If the collator was * instantiated from rules or an error occurred, returns * boolean FALSE. */ #[Pure] function collator_get_locale(Collator $object, int $type): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get collator's last error code * @link https://php.net/manual/en/collator.geterrorcode.php * @param Collator $object * @return int|false Error code returned by the last Collator API function call. */ #[Pure(true)] function collator_get_error_code(Collator $object): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get text for collator's last error code * @link https://php.net/manual/en/collator.geterrormessage.php * @param Collator $object * @return string|false Description of an error occurred in the last Collator API function call. */ #[Pure] function collator_get_error_message(Collator $object): string|false {} /** * (PHP 5 >= 5.3.2, PHP 7, PECL intl >= 1.0.3)
    * Get sorting key for a string * @link https://php.net/manual/en/collator.getsortkey.php * @param Collator $object * @param string $string

    * The string to produce the key from. *

    * @return string|false the collation key for the string. Collation keys can be compared directly instead of strings. */ #[Pure] function collator_get_sort_key( Collator $object, string $string, #[ElementAvailable(from: '5.3', to: '5.6')] $arg3 ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Create a number formatter * @link https://php.net/manual/en/numberformatter.create.php * @param string $locale

    * Locale in which the number would be formatted (locale name, e.g. en_CA). *

    * @param int $style

    * Style of the formatting, one of the * format style constants. If * NumberFormatter::PATTERN_DECIMAL * or NumberFormatter::PATTERN_RULEBASED * is passed then the number format is opened using the given pattern, * which must conform to the syntax described in * ICU DecimalFormat * documentation or * ICU RuleBasedNumberFormat * documentation, respectively. *

    * @param string|null $pattern [optional]

    * Pattern string if the chosen style requires a pattern. *

    * @return NumberFormatter|null NumberFormatter object or NULL on error. */ #[Pure] function numfmt_create(string $locale, int $style, #[LanguageAware(['8.0' => 'string|null'], default: 'string')] $pattern = null): ?NumberFormatter {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Format a number * @link https://php.net/manual/en/numberformatter.format.php * @param NumberFormatter $formatter * @param int|float $num

    * The value to format. Can be integer or float, * other values will be converted to a numeric value. *

    * @param int $type

    * The * formatting type to use. *

    * @return string|false the string containing formatted value, or FALSE on error. */ #[Pure] function numfmt_format(NumberFormatter $formatter, int|float $num, int $type = 0): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Parse a number * @link https://php.net/manual/en/numberformatter.parse.php * @param NumberFormatter $formatter * @param string $string * @param int $type [optional]

    * The * formatting type to use. By default, * NumberFormatter::TYPE_DOUBLE is used. *

    * @param int &$offset [optional]

    * Offset in the string at which to begin parsing. On return, this value * will hold the offset at which parsing ended. *

    * @return int|float|false The value of the parsed number or FALSE on error. */ #[Pure] function numfmt_parse(NumberFormatter $formatter, string $string, int $type = NumberFormatter::TYPE_DOUBLE, &$offset = null): int|float|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Format a currency value * @link https://php.net/manual/en/numberformatter.formatcurrency.php * @param NumberFormatter $formatter * @param float $amount

    * The numeric currency value. *

    * @param string $currency

    * The 3-letter ISO 4217 currency code indicating the currency to use. *

    * @return string|false String representing the formatted currency value. */ #[Pure] function numfmt_format_currency(NumberFormatter $formatter, float $amount, string $currency): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Parse a currency number * @link https://php.net/manual/en/numberformatter.parsecurrency.php * @param NumberFormatter $formatter * @param string $string * @param string &$currency

    * Parameter to receive the currency name (3-letter ISO 4217 currency * code). *

    * @param int &$offset [optional]

    * Offset in the string at which to begin parsing. On return, this value * will hold the offset at which parsing ended. *

    * @return float|false The parsed numeric value or FALSE on error. */ function numfmt_parse_currency(NumberFormatter $formatter, string $string, &$currency, &$offset = null): float|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set an attribute * @link https://php.net/manual/en/numberformatter.setattribute.php * @param NumberFormatter $formatter * @param int $attribute

    * Attribute specifier - one of the * numeric attribute constants. *

    * @param int|float $value

    * The attribute value. *

    * @return bool TRUE on success or FALSE on failure. */ function numfmt_set_attribute(NumberFormatter $formatter, int $attribute, int|float $value): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get an attribute * @link https://php.net/manual/en/numberformatter.getattribute.php * @param NumberFormatter $formatter * @param int $attribute

    * Attribute specifier - one of the * numeric attribute constants. *

    * @return int|float|false Return attribute value on success, or FALSE on error. */ #[Pure] function numfmt_get_attribute(NumberFormatter $formatter, int $attribute): int|float|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set a text attribute * @link https://php.net/manual/en/numberformatter.settextattribute.php * @param NumberFormatter $formatter * @param int $attribute

    * Attribute specifier - one of the * text attribute * constants. *

    * @param string $value

    * Text for the attribute value. *

    * @return bool TRUE on success or FALSE on failure. */ function numfmt_set_text_attribute(NumberFormatter $formatter, int $attribute, string $value): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get a text attribute * @link https://php.net/manual/en/numberformatter.gettextattribute.php * @param NumberFormatter $formatter * @param int $attribute

    * Attribute specifier - one of the * text attribute constants. *

    * @return string|false Return attribute value on success, or FALSE on error. */ #[Pure] function numfmt_get_text_attribute(NumberFormatter $formatter, int $attribute): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set a symbol value * @link https://php.net/manual/en/numberformatter.setsymbol.php * @param NumberFormatter $formatter * @param int $symbol

    * Symbol specifier, one of the * format symbol constants. *

    * @param string $value

    * Text for the symbol. *

    * @return bool TRUE on success or FALSE on failure. */ function numfmt_set_symbol(NumberFormatter $formatter, int $symbol, string $value): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get a symbol value * @link https://php.net/manual/en/numberformatter.getsymbol.php * @param NumberFormatter $formatter * @param int $symbol

    * Symbol specifier, one of the * format symbol constants. *

    * @return string|false The symbol string or FALSE on error. */ #[Pure] function numfmt_get_symbol(NumberFormatter $formatter, int $symbol): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set formatter pattern * @link https://php.net/manual/en/numberformatter.setpattern.php * @param NumberFormatter $formatter * @param string $pattern

    * Pattern in syntax described in * ICU DecimalFormat * documentation. *

    * @return bool TRUE on success or FALSE on failure. */ function numfmt_set_pattern(NumberFormatter $formatter, string $pattern): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get formatter pattern * @link https://php.net/manual/en/numberformatter.getpattern.php * @param NumberFormatter $formatter * @return string|false Pattern string that is used by the formatter, or FALSE if an error happens. */ #[Pure] function numfmt_get_pattern(NumberFormatter $formatter): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get formatter locale * @link https://php.net/manual/en/numberformatter.getlocale.php * @param NumberFormatter $formatter * @param int $type

    * You can choose between valid and actual locale ( * Locale::VALID_LOCALE, * Locale::ACTUAL_LOCALE, * respectively). The default is the actual locale. *

    * @return string|false The locale name used to create the formatter. */ #[Pure] function numfmt_get_locale(NumberFormatter $formatter, int $type = 0): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get formatter's last error code. * @link https://php.net/manual/en/numberformatter.geterrorcode.php * @param NumberFormatter $formatter * @return int error code from last formatter call. */ #[Pure(true)] function numfmt_get_error_code(NumberFormatter $formatter): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get formatter's last error message. * @link https://php.net/manual/en/numberformatter.geterrormessage.php * @param NumberFormatter $formatter * @return string error message from last formatter call. */ #[Pure(true)] function numfmt_get_error_message(NumberFormatter $formatter): string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Normalizes the input provided and returns the normalized string * @link https://php.net/manual/en/normalizer.normalize.php * @param string $string

    The input string to normalize

    * @param int $form [optional]

    One of the normalization forms.

    * @return string|false The normalized string or FALSE if an error occurred. */ #[Pure] function normalizer_normalize(string $string, int $form = Normalizer::FORM_C): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Checks if the provided string is already in the specified normalization * form. * @link https://php.net/manual/en/normalizer.isnormalized.php * @param string $string

    The input string to normalize

    * @param int $form [optional]

    * One of the normalization forms. *

    * @return bool TRUE if normalized, FALSE otherwise or if there an error */ #[Pure] function normalizer_is_normalized(string $string, int $form = Normalizer::FORM_C): bool {} /** * Gets the default locale value from the intl global 'default_locale' * @link https://php.net/manual/en/function.locale-get-default.php * @return string a string with the current Locale. */ #[Pure] function locale_get_default(): string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set the default runtime Locale * @link https://php.net/manual/en/function.locale-set-default.php * @param string $locale

    * The new Locale name. A comprehensive list of the supported locales is * available at . *

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageAware(['8.4' => 'true'], default: 'bool')] function locale_set_default(string $locale) {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Gets the primary language for the input locale * @link https://php.net/manual/en/locale.getprimarylanguage.php * @param string $locale

    * The locale to extract the primary language code from *

    * @return string|null The language code associated with the language or NULL in case of error. */ #[Pure] function locale_get_primary_language(string $locale): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Gets the script for the input locale * @link https://php.net/manual/en/locale.getscript.php * @param string $locale

    * The locale to extract the script code from *

    * @return string|null The script subtag for the locale or NULL if not present */ #[Pure] function locale_get_script(string $locale): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Gets the region for the input locale * @link https://php.net/manual/en/locale.getregion.php * @param string $locale

    * The locale to extract the region code from *

    * @return string|null The region subtag for the locale or NULL if not present */ #[Pure] function locale_get_region(string $locale): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Gets the keywords for the input locale * @link https://php.net/manual/en/locale.getkeywords.php * @param string $locale

    * The locale to extract the keywords from *

    * @return array|false|null Associative array containing the keyword-value pairs for this locale */ #[Pure] function locale_get_keywords(string $locale): array|false|null {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Returns an appropriately localized display name for script of the input locale * @link https://php.net/manual/en/locale.getdisplayscript.php * @param string $locale

    * The locale to return a display script for *

    * @param string|null $displayLocale

    * Optional format locale to use to display the script name *

    * @return string|false Display name of the script for the $locale in the format appropriate for * $in_locale. */ #[Pure] function locale_get_display_script( string $locale, #[ElementAvailable(from: '5.3', to: '5.6')] ?string $displayLocale, #[ElementAvailable(from: '7.0')] ?string $displayLocale = null ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Returns an appropriately localized display name for region of the input locale * @link https://php.net/manual/en/locale.getdisplayregion.php * @param string $locale

    * The locale to return a display region for. *

    * @param string|null $displayLocale

    * Optional format locale to use to display the region name *

    * @return string|false display name of the region for the $locale in the format appropriate for * $in_locale. */ #[Pure] function locale_get_display_region( string $locale, #[ElementAvailable(from: '5.3', to: '5.6')] ?string $displayLocale, #[ElementAvailable(from: '7.0')] ?string $displayLocale = null ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Returns an appropriately localized display name for the input locale * @link https://php.net/manual/en/locale.getdisplayname.php * @param string $locale

    * The locale to return a display name for. *

    * @param string|null $displayLocale

    optional format locale

    * @return string|false Display name of the locale in the format appropriate for $in_locale. */ #[Pure] function locale_get_display_name( string $locale, #[ElementAvailable(from: '5.3', to: '5.6')] ?string $displayLocale, #[ElementAvailable(from: '7.0')] ?string $displayLocale = null ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Returns an appropriately localized display name for language of the inputlocale * @link https://php.net/manual/en/locale.getdisplaylanguage.php * @param string $locale

    * The locale to return a display language for *

    * @param string|null $displayLocale

    * Optional format locale to use to display the language name *

    * @return string|false display name of the language for the $locale in the format appropriate for * $in_locale. */ #[Pure] function locale_get_display_language( string $locale, #[ElementAvailable(from: '5.3', to: '5.6')] ?string $displayLocale, #[ElementAvailable(from: '7.0')] ?string $displayLocale = null ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Returns an appropriately localized display name for variants of the input locale * @link https://php.net/manual/en/locale.getdisplayvariant.php * @param string $locale

    * The locale to return a display variant for *

    * @param string|null $displayLocale

    * Optional format locale to use to display the variant name *

    * @return string|false Display name of the variant for the $locale in the format appropriate for * $in_locale. */ #[Pure] function locale_get_display_variant( string $locale, #[ElementAvailable(from: '5.3', to: '5.6')] ?string $displayLocale, #[ElementAvailable(from: '7.0')] ?string $displayLocale = null ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Returns a correctly ordered and delimited locale ID * @link https://php.net/manual/en/locale.composelocale.php * @param string[] $subtags

    * an array containing a list of key-value pairs, where the keys identify * the particular locale ID subtags, and the values are the associated * subtag values. *

    * The 'variant' and 'private' subtags can take maximum 15 values * whereas 'extlang' can take maximum 3 values.e.g. Variants are allowed * with the suffix ranging from 0-14. Hence the keys for the input array * can be variant0, variant1, ...,variant14. In the returned locale id, * the subtag is ordered by suffix resulting in variant0 followed by * variant1 followed by variant2 and so on. *

    *

    * The 'variant', 'private' and 'extlang' multiple values can be specified both * as array under specific key (e.g. 'variant') and as multiple numbered keys * (e.g. 'variant0', 'variant1', etc.). *

    *

    * @return string|false The corresponding locale identifier. */ #[Pure] function locale_compose(array $subtags): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Returns a key-value array of locale ID subtag elements. * @link https://php.net/manual/en/locale.parselocale.php * @param string $locale

    * The locale to extract the subtag array from. Note: The 'variant' and * 'private' subtags can take maximum 15 values whereas 'extlang' can take * maximum 3 values. *

    * @return string[]|null an array containing a list of key-value pairs, where the keys * identify the particular locale ID subtags, and the values are the * associated subtag values. The array will be ordered as the locale id * subtags e.g. in the locale id if variants are '-varX-varY-varZ' then the * returned array will have variant0=>varX , variant1=>varY , * variant2=>varZ */ #[Pure] function locale_parse(string $locale): ?array {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Gets the variants for the input locale * @link https://php.net/manual/en/locale.getallvariants.php * @param string $locale

    * The locale to extract the variants from *

    * @return array|null The array containing the list of all variants subtag for the locale * or NULL if not present */ #[Pure] function locale_get_all_variants(string $locale): ?array {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Checks if a language tag filter matches with locale * @link https://php.net/manual/en/locale.filtermatches.php * @param string $languageTag

    * The language tag to check *

    * @param string $locale

    * The language range to check against *

    * @param bool $canonicalize

    * If true, the arguments will be converted to canonical form before * matching. *

    * @return bool|null TRUE if $locale matches $langtag FALSE otherwise. */ #[Pure] function locale_filter_matches( string $languageTag, string $locale, #[ElementAvailable(from: '5.3', to: '5.6')] bool $canonicalize, #[ElementAvailable(from: '7.0')] bool $canonicalize = false ): ?bool {} /** * Canonicalize the locale string * @param string $locale * * @return null|string */ #[Pure] function locale_canonicalize(string $locale): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Searches the language tag list for the best match to the language * @link https://php.net/manual/en/locale.lookup.php * @param string[] $languageTag

    * An array containing a list of language tags to compare to * locale. Maximum 100 items allowed. *

    * @param string $locale

    * The locale to use as the language range when matching. *

    * @param bool $canonicalize

    * If true, the arguments will be converted to canonical form before * matching. *

    * @param string|null $defaultLocale

    * The locale to use if no match is found. *

    * @return string|null The closest matching language tag or default value. */ #[Pure] function locale_lookup( array $languageTag, string $locale, #[ElementAvailable(from: '5.3', to: '5.6')] bool $canonicalize, #[ElementAvailable(from: '5.3', to: '5.6')] ?string $defaultLocale, #[ElementAvailable(from: '7.0')] bool $canonicalize = false, #[ElementAvailable(from: '7.0')] ?string $defaultLocale = null, ): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Tries to find out best available locale based on HTTP "Accept-Language" header * @link https://php.net/manual/en/locale.acceptfromhttp.php * @param string $header

    * The string containing the "Accept-Language" header according to format in RFC 2616. *

    * @return string|false The corresponding locale identifier. */ #[Pure] function locale_accept_from_http(string $header): string|false {} /** * Constructs a new message formatter * @param string $locale * @param string $pattern * @return MessageFormatter|null */ #[Pure] function msgfmt_create(string $locale, string $pattern): ?MessageFormatter {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Format the message * @link https://php.net/manual/en/messageformatter.format.php * @param MessageFormatter $formatter * @param array $values

    * Arguments to insert into the format string *

    * @return string|false The formatted string, or FALSE if an error occurred */ #[Pure] function msgfmt_format(MessageFormatter $formatter, array $values): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Quick format message * @link https://php.net/manual/en/messageformatter.formatmessage.php * @param string $locale

    * The locale to use for formatting locale-dependent parts *

    * @param string $pattern

    * The pattern string to insert things into. * The pattern uses an 'apostrophe-friendly' syntax; it is run through * umsg_autoQuoteApostrophe * before being interpreted. *

    * @param array $values

    * The array of values to insert into the format string *

    * @return string|false The formatted pattern string or FALSE if an error occurred */ #[Pure] function msgfmt_format_message(string $locale, string $pattern, array $values): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Parse input string according to pattern * @link https://php.net/manual/en/messageformatter.parse.php * @param MessageFormatter $formatter * @param string $string

    * The string to parse *

    * @return array|false An array containing the items extracted, or FALSE on error */ #[Pure] function msgfmt_parse(MessageFormatter $formatter, string $string): array|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Quick parse input string * @link https://php.net/manual/en/messageformatter.parsemessage.php * @param string $locale

    * The locale to use for parsing locale-dependent parts *

    * @param string $pattern

    * The pattern with which to parse the value. *

    * @param string $message

    * The string to parse, conforming to the pattern. *

    * @return array|false An array containing items extracted, or FALSE on error */ #[Pure] function msgfmt_parse_message(string $locale, string $pattern, string $message): array|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set the pattern used by the formatter * @link https://php.net/manual/en/messageformatter.setpattern.php * @param MessageFormatter $formatter * @param string $pattern

    * The pattern string to use in this message formatter. * The pattern uses an 'apostrophe-friendly' syntax; it is run through * umsg_autoQuoteApostrophe * before being interpreted. *

    * @return bool TRUE on success or FALSE on failure. */ function msgfmt_set_pattern(MessageFormatter $formatter, string $pattern): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the pattern used by the formatter * @link https://php.net/manual/en/messageformatter.getpattern.php * @param MessageFormatter $formatter * @return string|false The pattern string for this message formatter */ #[Pure] function msgfmt_get_pattern(MessageFormatter $formatter): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the locale for which the formatter was created. * @link https://php.net/manual/en/messageformatter.getlocale.php * @param MessageFormatter $formatter * @return string The locale name */ #[Pure] function msgfmt_get_locale(MessageFormatter $formatter): string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the error code from last operation * @link https://php.net/manual/en/messageformatter.geterrorcode.php * @param MessageFormatter $formatter * @return int The error code, one of UErrorCode values. Initial value is U_ZERO_ERROR. */ #[Pure(true)] function msgfmt_get_error_code(MessageFormatter $formatter): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the error text from the last operation * @link https://php.net/manual/en/messageformatter.geterrormessage.php * @param MessageFormatter $formatter * @return string Description of the last error. */ #[Pure(true)] function msgfmt_get_error_message(MessageFormatter $formatter): string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Create a date formatter * @link https://php.net/manual/en/intldateformatter.create.php * @param string|null $locale

    * Locale to use when formatting or parsing. *

    * @param int $dateType

    * Date type to use (none, * short, medium, * long, full). * This is one of the * IntlDateFormatter constants. *

    * @param int $timeType

    * Time type to use (none, * short, medium, * long, full). * This is one of the * IntlDateFormatter constants. *

    * @param string|null $timezone [optional]

    * Time zone ID, default is system default. *

    * @param IntlCalendar|int|null $calendar [optional]

    * Calendar to use for formatting or parsing; default is Gregorian. * This is one of the * IntlDateFormatter calendar constants. *

    * @param string|null $pattern [optional]

    * Optional pattern to use when formatting or parsing. * Possible patterns are documented at http://userguide.icu-project.org/formatparse/datetime. *

    * @return IntlDateFormatter|null */ #[Pure] function datefmt_create( ?string $locale, #[ElementAvailable(from: '5.3', to: '8.0')] int $dateType, #[ElementAvailable(from: '8.1')] int $dateType = 0, #[ElementAvailable(from: '5.3', to: '8.0')] int $timeType, #[ElementAvailable(from: '8.1')] int $timeType = 0, #[LanguageAware(['8.5' => 'IntlTimeZone|DateTimeZone|string|null'], default: '')] $timezone = null, IntlCalendar|int|null $calendar = null, #[LanguageAware(['8.0' => 'string|null'], default: 'string')] $pattern = null ): ?IntlDateFormatter {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the datetype used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.getdatetype.php * @param IntlDateFormatter $formatter * @return int|false The current date type value of the formatter. */ #[Pure] function datefmt_get_datetype(IntlDateFormatter $formatter): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the timetype used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.gettimetype.php * @param IntlDateFormatter $formatter * @return int|false The current date type value of the formatter. */ #[Pure] function datefmt_get_timetype(IntlDateFormatter $formatter): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the calendar type used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.getcalendar.php * @param IntlDateFormatter $formatter * @return int|false The calendar being used by the formatter. */ #[Pure] function datefmt_get_calendar(IntlDateFormatter $formatter): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * sets the calendar used to the appropriate calendar, which must be * @link https://php.net/manual/en/intldateformatter.setcalendar.php * @param IntlDateFormatter $formatter $mf * @param IntlCalendar|int|null $calendar

    * The calendar to use. * Default is IntlDateFormatter::GREGORIAN. *

    * @return bool TRUE on success or FALSE on failure. */ function datefmt_set_calendar(IntlDateFormatter $formatter, IntlCalendar|int|null $calendar): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the locale used by formatter * @link https://php.net/manual/en/intldateformatter.getlocale.php * @param IntlDateFormatter $formatter * @param int $type [optional] * @return string|false the locale of this formatter or 'false' if error */ #[Pure] function datefmt_get_locale( IntlDateFormatter $formatter, #[ElementAvailable(from: '8.0')] int $type = ULOC_ACTUAL_LOCALE ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the timezone-id used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.gettimezoneid.php * @param IntlDateFormatter $formatter * @return string|false ID string for the time zone used by this formatter. */ #[Pure] function datefmt_get_timezone_id(IntlDateFormatter $formatter): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 3.0.0)
    * Get copy of formatter's calendar object * @link https://secure.php.net/manual/en/intldateformatter.getcalendarobject.php * @param IntlDateFormatter $formatter * @return IntlCalendar|false|null A copy of the internal calendar object used by this formatter. */ #[Pure] function datefmt_get_calendar_object(IntlDateFormatter $formatter): IntlCalendar|false|null {} /** * (PHP 5 >= 5.5.0, PECL intl >= 3.0.0)
    * Get formatter's timezone * @link https://secure.php.net/manual/en/intldateformatter.gettimezone.php * @param IntlDateFormatter $formatter * @return IntlTimeZone|false The associated IntlTimeZone object or FALSE on failure. */ #[Pure] function datefmt_get_timezone(IntlDateFormatter $formatter): IntlTimeZone|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Sets the time zone to use * @link https://php.net/manual/en/intldateformatter.settimezoneid.php * @param MessageFormatter $mf * @param string $zone

    * The time zone ID string of the time zone to use. * If NULL or the empty string, the default time zone for the runtime is used. *

    * @return bool TRUE on success or FALSE on failure. * @removed 7.0 * @see datefmt_set_timezone() */ #[Deprecated(replacement: "datefmt_set_timezone(%parametersList%)", since: "5.5")] function datefmt_set_timezone_id(MessageFormatter $mf, $zone) {} /** * (PHP 5 >= 5.5.0, PECL intl >= 3.0.0)
    * Sets formatter's timezone * @link https://php.net/manual/en/intldateformatter.settimezone.php * @param IntlDateFormatter $formatter * @param IntlTimeZone|DateTimeZone|string|null $timezone

    * The timezone to use for this formatter. This can be specified in the * following forms: *

      *
    • *

      * NULL, in which case the default timezone will be used, as specified in * the ini setting {@link "https://secure.php.net/manual/en/datetime.configuration.php#ini.date.timezone" date.timezone} or * through the function {@link "https://secure.php.net/manual/en/function.date-default-timezone-set.php" date_default_timezone_set()} and as * returned by {@link "https://secure.php.net/manual/en/function.date-default-timezone-get.php" date_default_timezone_get()}. *

      *
    • *
    • *

      * An {@link "https://secure.php.net/manual/en/class.intltimezone.php" IntlTimeZone}, which will be used directly. *

      *
    • *
    • *

      * A {@link "https://secure.php.net/manual/en/class.datetimezone.php" DateTimeZone}. Its identifier will be extracted * and an ICU timezone object will be created; the timezone will be backed * by ICU's database, not PHP's. *

      *
    • *
    • *

      * A {@link "https://secure.php.net/manual/en/language.types.string.php" string}, which should be a valid ICU timezone identifier. * See IntlTimeZone::createTimeZoneIDEnumeration(). Raw offsets such as "GMT+08:30" are also accepted. *

      *
    • *
    *

    * @return bool|null TRUE on success or FALSE on failure. */ #[LanguageAware(['8.3' => 'bool'], default: 'bool|null')] function datefmt_set_timezone(IntlDateFormatter $formatter, #[LanguageAware(['8.5' => 'IntlTimeZone|DateTimeZone|string|null'], default: '')] $timezone) {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the pattern used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.getpattern.php * @param IntlDateFormatter $formatter * @return string|false The pattern string being used to format/parse. */ #[Pure] function datefmt_get_pattern(IntlDateFormatter $formatter): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set the pattern used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.setpattern.php * @param IntlDateFormatter $formatter * @param string $pattern

    * New pattern string to use. * Possible patterns are documented at http://userguide.icu-project.org/formatparse/datetime. *

    * @return bool TRUE on success or FALSE on failure. * Bad formatstrings are usually the cause of the failure. */ function datefmt_set_pattern(IntlDateFormatter $formatter, string $pattern): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the lenient used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.islenient.php * @param IntlDateFormatter $formatter * @return bool TRUE if parser is lenient, FALSE if parser is strict. By default the parser is lenient. */ #[Pure] function datefmt_is_lenient(IntlDateFormatter $formatter): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Set the leniency of the parser * @link https://php.net/manual/en/intldateformatter.setlenient.php * @param IntlDateFormatter $formatter * @param bool $lenient

    * Sets whether the parser is lenient or not, default is TRUE (lenient). *

    * @return void */ function datefmt_set_lenient( IntlDateFormatter $formatter, #[ElementAvailable(from: '8.0')] bool $lenient ): void {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Format the date/time value as a string * @link https://php.net/manual/en/intldateformatter.format.php * @param IntlDateFormatter $formatter * @param object|array|string|int|float $datetime

    * Value to format. This may be a DateTime object, * an integer representing a Unix timestamp value (seconds * since epoch, UTC) or an array in the format output by * localtime. *

    * @return string|false The formatted string or, if an error occurred, FALSE. */ #[Pure] function datefmt_format( #[LanguageAware(['8.0' => 'IntlDateFormatter'], default: '')] #[ElementAvailable(from: '5.3', to: '7.4')] $formatter = null, #[LanguageAware(['8.0' => 'IntlDateFormatter'], default: '')] #[ElementAvailable(from: '8.0')] $formatter, #[ElementAvailable(from: '5.3', to: '7.4')] $datetime = null, #[ElementAvailable(from: '8.0')] $datetime ): string|false {} /** * (PHP 5 >= 5.5.0, PECL intl >= 3.0.0)
    * Formats an object * @link https://secure.php.net/manual/en/intldateformatter.formatobject.php * @param IntlCalendar|DateTimeInterface $datetime

    * An object of type IntlCalendar or DateTime. The timezone information in the object will be used. *

    * @param array|int|string|null $format [optional]

    * How to format the date/time. This can either be an {https://secure.php.net/manual/en/language.types.array.php array} with * two elements (first the date style, then the time style, these being one * of the constants IntlDateFormatter::NONE, * IntlDateFormatter::SHORT, * IntlDateFormatter::MEDIUM, * IntlDateFormatter::LONG, * IntlDateFormatter::FULL), a long with * the value of one of these constants (in which case it will be used both * for the time and the date) or a {@link https://secure.php.net/manual/en/language.types.string.php} with the format * described in {@link http://www.icu-project.org/apiref/icu4c/classSimpleDateFormat.html#details the ICU documentation} * documentation. If NULL, the default style will be used. *

    * @param string|null $locale [optional]

    * The locale to use, or NULL to use the default one.

    * @return string|false The formatted string or, if an error occurred, FALSE. */ #[Pure] function datefmt_format_object($datetime, $format = null, ?string $locale = null): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Parse string to a timestamp value * @link https://php.net/manual/en/intldateformatter.parse.php * @param IntlDateFormatter $formatter * @param string $string

    * string to convert to a time *

    * @param int &$offset [optional]

    * Position at which to start the parsing in $value (zero-based). * If no error occurs before $value is consumed, $parse_pos will contain -1 * otherwise it will contain the position at which parsing ended (and the error occurred). * This variable will contain the end position if the parse fails. * If $parse_pos > strlen($value), the parse fails immediately. *

    * @return int|float|false timestamp parsed value */ function datefmt_parse(IntlDateFormatter $formatter, string $string, &$offset = null): int|float|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Parse string to a field-based time value * @link https://php.net/manual/en/intldateformatter.localtime.php * @param IntlDateFormatter $formatter * @param string $string

    * string to convert to a time *

    * @param int &$offset [optional]

    * Position at which to start the parsing in $value (zero-based). * If no error occurs before $value is consumed, $parse_pos will contain -1 * otherwise it will contain the position at which parsing ended . * If $parse_pos > strlen($value), the parse fails immediately. *

    * @return array|false Localtime compatible array of integers : contains 24 hour clock value in tm_hour field */ function datefmt_localtime(IntlDateFormatter $formatter, string $string, &$offset = null): array|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the error code from last operation * @link https://php.net/manual/en/intldateformatter.geterrorcode.php * @param IntlDateFormatter $formatter * @return int The error code, one of UErrorCode values. Initial value is U_ZERO_ERROR. */ #[Pure(true)] function datefmt_get_error_code(IntlDateFormatter $formatter): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the error text from the last operation. * @link https://php.net/manual/en/intldateformatter.geterrormessage.php * @param IntlDateFormatter $formatter * @return string Description of the last error. */ #[Pure(true)] function datefmt_get_error_message(IntlDateFormatter $formatter): string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get string length in grapheme units * @link https://php.net/manual/en/function.grapheme-strlen.php * @param string $string

    * The string being measured for length. It must be a valid UTF-8 string. *

    * @return int|false|null The length of the string on success, and 0 if the string is empty. */ #[Pure] function grapheme_strlen(string $string): int|false|null {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Find position (in grapheme units) of first occurrence of a string * @link https://php.net/manual/en/function.grapheme-strpos.php * @param string $haystack

    * The string to look in. Must be valid UTF-8. *

    * @param string $needle

    * The string to look for. Must be valid UTF-8. *

    * @param int $offset [optional]

    * The optional $offset parameter allows you to specify where in $haystack to * start searching as an offset in grapheme units (not bytes or characters). * The position returned is still relative to the beginning of haystack * regardless of the value of $offset. *

    * @return int|false the position as an integer. If needle is not found, strpos() will return boolean FALSE. */ #[Pure] function grapheme_strpos(string $haystack, string $needle, int $offset = 0, #[ElementAvailable(from: '8.5')] string $locale = ""): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Find position (in grapheme units) of first occurrence of a case-insensitive string * @link https://php.net/manual/en/function.grapheme-stripos.php * @param string $haystack

    * The string to look in. Must be valid UTF-8. *

    * @param string $needle

    * The string to look for. Must be valid UTF-8. *

    * @param int $offset [optional]

    * The optional $offset parameter allows you to specify where in haystack to * start searching as an offset in grapheme units (not bytes or characters). * The position returned is still relative to the beginning of haystack * regardless of the value of $offset. *

    * @return int|false the position as an integer. If needle is not found, grapheme_stripos() will return boolean FALSE. */ #[Pure] function grapheme_stripos(string $haystack, string $needle, int $offset = 0, #[ElementAvailable(from: '8.5')] string $locale = ""): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Find position (in grapheme units) of last occurrence of a string * @link https://php.net/manual/en/function.grapheme-strrpos.php * @param string $haystack

    * The string to look in. Must be valid UTF-8. *

    * @param string $needle

    * The string to look for. Must be valid UTF-8. *

    * @param int $offset [optional]

    * The optional $offset parameter allows you to specify where in $haystack to * start searching as an offset in grapheme units (not bytes or characters). * The position returned is still relative to the beginning of haystack * regardless of the value of $offset. *

    * @return int|false the position as an integer. If needle is not found, grapheme_strrpos() will return boolean FALSE. */ #[Pure] function grapheme_strrpos(string $haystack, string $needle, int $offset = 0, #[ElementAvailable(from: '8.5')] string $locale = ""): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Find position (in grapheme units) of last occurrence of a case-insensitive string * @link https://php.net/manual/en/function.grapheme-strripos.php * @param string $haystack

    * The string to look in. Must be valid UTF-8. *

    * @param string $needle

    * The string to look for. Must be valid UTF-8. *

    * @param int $offset [optional]

    * The optional $offset parameter allows you to specify where in $haystack to * start searching as an offset in grapheme units (not bytes or characters). * The position returned is still relative to the beginning of haystack * regardless of the value of $offset. *

    * @return int|false the position as an integer. If needle is not found, grapheme_strripos() will return boolean FALSE. */ #[Pure] function grapheme_strripos(string $haystack, string $needle, int $offset = 0, #[ElementAvailable(from: '8.5')] string $locale = ""): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Return part of a string * @link https://php.net/manual/en/function.grapheme-substr.php * @param string $string

    * The input string. Must be valid UTF-8. *

    * @param int $offset

    * Start position in default grapheme units. * If $start is non-negative, the returned string will start at the * $start'th position in $string, counting from zero. If $start is negative, * the returned string will start at the $start'th grapheme unit from the * end of string. *

    * @param int|null $length [optional]

    * Length in grapheme units. * If $length is given and is positive, the string returned will contain * at most $length grapheme units beginning from $start (depending on the * length of string). If $length is given and is negative, then * that many grapheme units 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, FALSE will be returned. *

    * @return string|false

    the extracted part of $string,
    * or FALSE if $length is negative and $start denotes a position beyond truncation $length,
    * or also FALSE if $start denotes a position beyond $string length

    */ #[Pure] function grapheme_substr(string $string, int $offset, ?int $length = null, #[ElementAvailable(from: '8.5')] string $locale = ""): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Returns part of haystack string from the first occurrence of needle to the end of haystack. * @link https://php.net/manual/en/function.grapheme-strstr.php * @param string $haystack

    * The input string. Must be valid UTF-8. *

    * @param string $needle

    * The string to look for. Must be valid UTF-8. *

    * @param bool $beforeNeedle [optional]

    * If TRUE, grapheme_strstr() returns the part of the * haystack before the first occurrence of the needle (excluding the needle). *

    * @return string|false the portion of string, or FALSE if needle is not found. */ #[Pure] function grapheme_strstr(string $haystack, string $needle, bool $beforeNeedle = false, #[ElementAvailable(from: '8.5')] string $locale = ""): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Returns part of haystack string from the first occurrence of case-insensitive needle to the end of haystack. * @link https://php.net/manual/en/function.grapheme-stristr.php * @param string $haystack

    * The input string. Must be valid UTF-8. *

    * @param string $needle

    * The string to look for. Must be valid UTF-8. *

    * @param bool $beforeNeedle [optional]

    * If TRUE, grapheme_strstr() returns the part of the * haystack before the first occurrence of the needle (excluding needle). *

    * @return string|false the portion of $haystack, or FALSE if $needle is not found. */ #[Pure] function grapheme_stristr(string $haystack, string $needle, bool $beforeNeedle = false, #[ElementAvailable(from: '8.5')] string $locale = ""): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Function to extract a sequence of default grapheme clusters from a text buffer, which must be encoded in UTF-8. * @link https://php.net/manual/en/function.grapheme-extract.php * @param string $haystack

    * String to search. *

    * @param int $size

    * Maximum number items - based on the $extract_type - to return. *

    * @param int $type

    * Defines the type of units referred to by the $size parameter: *

    *

    * GRAPHEME_EXTR_COUNT (default) - $size is the number of default * grapheme clusters to extract. * GRAPHEME_EXTR_MAXBYTES - $size is the maximum number of bytes * returned. * GRAPHEME_EXTR_MAXCHARS - $size is the maximum number of UTF-8 * characters returned. *

    * @param int $offset [optional]

    * Starting position in $haystack in bytes - if given, it must be zero or a * positive value that is less than or equal to the length of $haystack in * bytes. If $start does not point to the first byte of a UTF-8 * character, the start position is moved to the next character boundary. *

    * @param int &$next [optional]

    * Reference to a value that will be set to the next starting position. * When the call returns, this may point to the first byte position past the end of the string. *

    * @return string|false A string starting at offset $start and ending on a default grapheme cluster * boundary that conforms to the $size and $extract_type specified. */ function grapheme_extract(string $haystack, int $size, int $type = 0, int $offset = 0, &$next = null): string|false {} /** * (PHP 5 >= 5.3.0, PHP 7, PECL intl >= 1.0.2, PHP 7, PECL idn >= 0.1)
    * Convert domain name to IDNA ASCII form. * @link https://php.net/manual/en/function.idn-to-ascii.php * @param string $domain

    * Domain to convert. In PHP 5 must be UTF-8 encoded. * If e.g. an ISO-8859-1 (aka Western Europe latin1) encoded string is * passed it will be converted into an ACE encoded "xn--" string. * It will not be the one you expected though! *

    * @param int $flags [optional]

    * Conversion options - combination of IDNA_* constants (except IDNA_ERROR_* constants). *

    * @param int $variant [optional]

    * Either INTL_IDNA_VARIANT_2003 for IDNA 2003 or INTL_IDNA_VARIANT_UTS46 for UTS #46. *

    * @param array &$idna_info [optional]

    * This parameter can be used only if INTL_IDNA_VARIANT_UTS46 was used for variant. * In that case, it will be filled with an array with the keys 'result', * the possibly illegal result of the transformation, 'isTransitionalDifferent', * a boolean indicating whether the usage of the transitional mechanisms of UTS #46 * either has or would have changed the result and 'errors', * which is an int representing a bitset of the error constants IDNA_ERROR_*. *

    * @return string|false The ACE encoded version of the domain name or FALSE on failure. */ function idn_to_ascii(string $domain, int $flags = IDNA_DEFAULT, int $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info): string|false {} /** * (PHP 5 >= 5.3.0, PHP 7, PECL intl >= 1.0.2, PHP 7, PECL idn >= 0.1)
    * Convert domain name from IDNA ASCII to Unicode. * @link https://php.net/manual/en/function.idn-to-utf8.php * @param string $domain

    * Domain to convert in IDNA ASCII-compatible format. * The ASCII encoded domain name. Looks like "xn--..." if the it originally contained non-ASCII characters. *

    * @param int $flags [optional]

    * Conversion options - combination of IDNA_* constants (except IDNA_ERROR_* constants). *

    * @param int $variant [optional]

    * Either INTL_IDNA_VARIANT_2003 for IDNA 2003 or INTL_IDNA_VARIANT_UTS46 for UTS #46. *

    * @param array &$idna_info [optional]

    * This parameter can be used only if INTL_IDNA_VARIANT_UTS46 was used for variant. * In that case, it will be filled with an array with the keys 'result', * the possibly illegal result of the transformation, 'isTransitionalDifferent', * a boolean indicating whether the usage of the transitional mechanisms of UTS #46 * either has or would have changed the result and 'errors', * which is an int representing a bitset of the error constants IDNA_ERROR_*. *

    * @return string|false The UTF-8 encoded version of the domain name or FALSE on failure. * RFC 3490 4.2 states though "ToUnicode never fails. If any step fails, then the original input * sequence is returned immediately in that step." */ function idn_to_utf8(string $domain, int $flags = IDNA_DEFAULT, int $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Create a new IntlCalendar * @link https://secure.php.net/manual/en/intlcalendar.createinstance.php * @param IntlTimeZone|DateTimeZone|string|null $timezone [optional]

    * The timezone to use. *

    * *
      *
    • *

      * NULL, in which case the default timezone will be used, as specified in * the ini setting {@link https://secure.php.net/manual/en/datetime.configuration.php#ini.date.timezone date.timezone} or * through the function {@link https://secure.php.net/manual/en/function.date-default-timezone-set.php date_default_timezone_set()} and as * returned by {@link https://secure.php.net/manual/en/function.date-default-timezone-get.php date_default_timezone_get()}. *

      *
    • *
    • *

      * An {@link https://secure.php.net/manual/en/class.intltimezone.php IntlTimeZone}, which will be used directly. *

      *
    • *
    • *

      * A {@link https://secure.php.net/manual/en/class.datetimezone.php DateTimeZone}. Its identifier will be extracted * and an ICU timezone object will be created; the timezone will be backed * by ICU's database, not PHP's. *

      *
    • *
    • *

      * A {@link https://secure.php.net/manual/en/language.types.string.php string}, which should be a valid ICU timezone identifier. * See IntlTimeZone::createTimeZoneIDEnumeration(). Raw * offsets such as "GMT+08:30" are also accepted. *

      *
    • *
    *

    * @param string|null $locale [optional]

    * A locale to use or NULL to use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.default-locale the default locale}. *

    * @return IntlCalendar|null * The created {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} instance or NULL on * failure. * @since 5.5 */ #[Pure] function intlcal_create_instance(#[LanguageAware(['8.5' => 'IntlTimeZone|DateTimeZone|string|null'], default: '')] $timezone = null, ?string $locale = null): ?IntlCalendar {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get set of locale keyword values * @param string $keyword

    * The locale keyword for which relevant values are to be queried. Only * 'calendar' is supported. *

    * @param string $locale

    * The locale onto which the keyword/value pair are to be appended. *

    * @param bool $onlyCommon *

    * Whether to show only the values commonly used for the specified locale. *

    * @return IntlIterator|false An iterator that yields strings with the locale keyword values or FALSE on failure. * @since 5.5 */ #[Pure] function intlcal_get_keyword_values_for_locale(string $keyword, string $locale, bool $onlyCommon): IntlIterator|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get number representing the current time * @link https://secure.php.net/manual/en/intlcalendar.getnow.php * @return float A float representing a number of milliseconds since the epoch, not counting leap seconds. * @since 5.5 */ #[Pure(true)] function intlcal_get_now(): float {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get array of locales for which there is data * @link https://secure.php.net/manual/en/intlcalendar.getavailablelocales.php * @return string[] An array of strings, one for which locale. * @since 5.5 */ #[Pure] function intlcal_get_available_locales(): array {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the value for a field * @link https://secure.php.net/manual/en/intlcalendar.get.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return int An integer with the value of the time field. * @since 5.5 */ #[Pure] function intl_get($calendar, $field) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get time currently represented by the object * @param IntlCalendar $calendar

    The calendar whose time will be checked against this object's time.

    * @return float * A {@link https://secure.php.net/manual/en/language.types.float.php float} representing the number of milliseconds elapsed since the * reference time (1 Jan 1970 00:00:00 UTC). * @since 5.5 */ #[Pure] #[LanguageAware(['8.0' => 'float|false'], default: 'float')] function intlcal_get_time(IntlCalendar $calendar) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Set the calendar time in milliseconds since the epoch * @link https://secure.php.net/manual/en/intlcalendar.settime.php * @param IntlCalendar $calendar

    * The IntlCalendar resource. *

    * @param float $timestamp

    * An instant represented by the number of number of milliseconds between * such instant and the epoch, ignoring leap seconds. *

    * @return bool * Returns TRUE on success and FALSE on failure. * @since 5.5 */ function intlcal_set_time(IntlCalendar $calendar, float $timestamp): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Add a (signed) amount of time to a field * @link https://secure.php.net/manual/en/intlcalendar.add.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. * These are integer values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @param int $value

    The signed amount to add to the current field. If the amount is positive, the instant will be moved forward; if it is negative, the instant wil be moved into the past. The unit is implicit to the field type. * For instance, hours for IntlCalendar::FIELD_HOUR_OF_DAY.

    * @return bool Returns TRUE on success or FALSE on failure. * @since 5.5 */ function intlcal_add(IntlCalendar $calendar, int $field, int $value): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Set the timezone used by this calendar * @link https://secure.php.net/manual/en/intlcalendar.settimezone.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param IntlTimeZone|DateTimeZone|string|null $timezone

    * The new timezone to be used by this calendar. It can be specified in the * following ways: * *

      *
    • *

      * NULL, in which case the default timezone will be used, as specified in * the ini setting {@link https://secure.php.net/manual/en/datetime.configuration.php#ini.date.timezone date.timezone} or * through the function {@link https://secure.php.net/manual/en/function.date-default-timezone-set.php date_default_timezone_set()} and as * returned by {@link https://secure.php.net/manual/en/function.date-default-timezone-get.php date_default_timezone_get()}. *

      *
    • *
    • *

      * An {@link https://secure.php.net/manual/en/class.intltimezone.php IntlTimeZone}, which will be used directly. *

      *
    • *
    • *

      * A {@link https://secure.php.net/manual/en/class.datetimezone.php DateTimeZone}. Its identifier will be extracted * and an ICU timezone object will be created; the timezone will be backed * by ICU's database, not PHP's. *

      *
    • *
    • *

      * A {@link https://secure.php.net/manual/en/language.types.string.php string}, which should be a valid ICU timezone identifier. * See IntlTimeZone::createTimeZoneIDEnumeration(). Raw * offsets such as "GMT+08:30" are also accepted. *

      *
    • *
    * @return bool Returns TRUE on success and FALSE on failure. * @since 5.5 */ function intlcal_set_time_zone(IntlCalendar $calendar, #[LanguageAware(['8.5' => 'IntlTimeZone|DateTimeZone|string|null'], default: '')] $timezone): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Whether this object's time is after that of the passed object * https://secure.php.net/manual/en/intlcalendar.after.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param IntlCalendar $other

    The calendar whose time will be checked against this object's time.

    * @return bool * Returns TRUE if this object's current time is after that of the * calendar argument's time. Returns FALSE otherwise. * Also returns FALSE on failure. You can use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or * {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to detect error conditions. * @since 5.5 */ #[Pure] function intlcal_after(IntlCalendar $calendar, IntlCalendar $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Whether this object's time is before that of the passed object * @link https://secure.php.net/manual/en/intlcalendar.before.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param IntlCalendar $other

    The calendar whose time will be checked against this object's time.

    * @return bool *

    * Returns TRUE if this object's current time is before that of the * calendar argument's time. Returns FALSE otherwise. * Also returns FALSE on failure. You can use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or * {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to detect error conditions. *

    * @since 5.5 */ #[Pure] function intlcal_before(IntlCalendar $calendar, IntlCalendar $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Set a time field or several common fields at once * @link https://secure.php.net/manual/en/intlcalendar.set.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $year

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @param int $month

    * The new value for IntlCalendar::FIELD_MONTH. *

    * @param int $dayOfMonth [optional]

    * The new value for IntlCalendar::FIELD_DAY_OF_MONTH. * The month sequence is zero-based, i.e., January is represented by 0, * February by 1, ..., December is 11 and Undecember (if the calendar has * it) is 12. *

    * @param int $hour [optional] *

    * The new value for IntlCalendar::FIELD_HOUR_OF_DAY. *

    * @param int $minute [optional] *

    * The new value for IntlCalendar::FIELD_MINUTE. *

    * @param int $second [optional]

    * The new value for IntlCalendar::FIELD_SECOND. *

    * @return bool Returns TRUE on success and FALSE on failure. * @since 5.5 */ #[LanguageAware(['8.3' => 'true'], default: 'bool')] #[Deprecated( reason: 'use IntlCalendar::set(), IntlCalendar::setDate(), or IntlCalendar::setDateTime() instead', since: '8.4' )] function intlcal_set(IntlCalendar $calendar, int $year, int $month, int $dayOfMonth, int $hour, int $minute, int $second) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Add value to field without carrying into more significant fields * @link https://secure.php.net/manual/en/intlcalendar.roll.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $field

    One of the * {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time * {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. * These are integer values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @param int|bool $value

    * The (signed) amount to add to the field, TRUE for rolling up (adding * 1), or FALSE for rolling down (subtracting * 1). *

    * @return bool Returns TRUE on success or FALSE on failure. * @since 5.5 */ function intlcal_roll( IntlCalendar $calendar, int $field, #[ElementAvailable(from: '5.3', to: '7.4')] $value = null, #[ElementAvailable(from: '8.0')] $value ): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Clear a field or all fields * @link https://secure.php.net/manual/en/intlcalendar.clear.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int|null $field [optional]

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return bool Returns TRUE on success or FALSE on failure. Failure can only occur is invalid arguments are provided. * @since 5.5 */ #[LanguageAware(['8.3' => 'true'], default: 'bool')] function intlcal_clear(IntlCalendar $calendar, ?int $field = null): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Calculate difference between given time and this object's time * @link https://secure.php.net/manual/en/intlcalendar.fielddifference.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param float $timestamp

    * The time against which to compare the quantity represented by the * field. For the result to be positive, the time * given for this parameter must be ahead of the time of the object the * method is being invoked on. *

    * @param int $field

    * The field that represents the quantity being compared. *

    * *

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return int Returns a (signed) difference of time in the unit associated with the * specified field or FALSE on failure. * @since 5.5 */ #[Pure] #[LanguageAware(['8.0' => 'int|false'], default: 'int')] function intlcal_field_difference(IntlCalendar $calendar, float $timestamp, int $field) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * The maximum value for a field, considering the object's current time * @link https://secure.php.net/manual/en/intlcalendar.getactualmaximum.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return int * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing the maximum value in the units associated * with the given field or FALSE on failure. * @since 5.5 */ #[Pure] #[LanguageAware(['8.0' => 'int|false'], default: 'int')] function intlcal_get_actual_maximum(IntlCalendar $calendar, int $field) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * The minimum value for a field, considering the object's current time * @link https://secure.php.net/manual/en/intlcalendar.getactualminimum.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. * These are integer values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return int * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing the minimum value in the field's * unit or FALSE on failure. * @since 5.5 */ #[Pure] #[LanguageAware(['8.0' => 'int|false'], default: 'int')] function intlcal_get_actual_minimum(IntlCalendar $calendar, int $field) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * @link https://secure.php.net/manual/en/intlcalendar.getdayofweektype.php * Tell whether a day is a weekday, weekend or a day that has a transition between the two * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $dayOfWeek

    * One of the constants IntlCalendar::DOW_SUNDAY, * IntlCalendar::DOW_MONDAY, ..., * IntlCalendar::DOW_SATURDAY. *

    * @return int * Returns one of the constants * IntlCalendar::DOW_TYPE_WEEKDAY, * IntlCalendar::DOW_TYPE_WEEKEND, * IntlCalendar::DOW_TYPE_WEEKEND_OFFSET or * IntlCalendar::DOW_TYPE_WEEKEND_CEASE or FALSE on failure. * @since 5.5 */ #[Pure] #[LanguageAware(['8.0' => 'int|false'], default: 'int')] function intlcal_get_day_of_week_type(IntlCalendar $calendar, int $dayOfWeek) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the first day of the week for the calendar's locale * @link https://secure.php.net/manual/en/intlcalendar.getfirstdayofweek.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @return int * One of the constants IntlCalendar::DOW_SUNDAY, * IntlCalendar::DOW_MONDAY, ..., * IntlCalendar::DOW_SATURDAY or FALSE on failure. * @since 5.5 */ #[Pure] #[LanguageAware(['8.0' => 'int|false'], default: 'int')] function intlcal_get_first_day_of_week(IntlCalendar $calendar) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the largest local minimum value for a field * @link https://secure.php.net/manual/en/intlcalendar.getgreatestminimum.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT.

    * @return int * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing a field value, in the field's * unit, or FALSE on failure. * @since 5.5 */ #[Pure] function intlcal_greates_minimum($calendar, $field) {} /** * (PHP >= 5.5.0, PECL intl >= 3.0.0a1)
    * Gets the value for a specific field. * @link https://www.php.net/manual/en/intlcalendar.get.php * @param IntlCalendar $calendar

    * The IntlCalendar resource. *

    * @param int $field

    * One of the IntlCalendar date/time field constants. These are integer values between 0 and IntlCalendar::FIELD_COUNT. *

    * @return int An integer with the value of the time field. */ #[Pure] #[LanguageAware(['8.0' => 'int|false'], default: 'int')] function intlcal_get(IntlCalendar $calendar, int $field) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the smallest local maximum for a field * @link https://secure.php.net/manual/en/intlcalendar.getleastmaximum.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return int *

    An {@link https://secure.php.net/manual/en/language.types.integer.ph int} representing a field value in the field's * unit or FALSE on failure. *

    * @since 5.5 */ #[Pure] #[LanguageAware(['8.0' => 'int|false'], default: 'int')] function intlcal_get_least_maximum(IntlCalendar $calendar, int $field) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the largest local minimum value for a field * @link https://secure.php.net/manual/en/intlcalendar.getgreatestminimum.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT.

    * @return int * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing a field value, in the field's * unit, or FALSE on failure. * @since 5.5 */ #[Pure] #[LanguageAware(['8.0' => 'int|false'], default: 'int')] function intlcal_get_greatest_minimum(IntlCalendar $calendar, int $field) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the locale associated with the object * @link https://secure.php.net/manual/en/intlcalendar.getlocale.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $type

    * Whether to fetch the actual locale (the locale from which the calendar * data originates, with Locale::ACTUAL_LOCALE) or the * valid locale, i.e., the most specific locale supported by ICU relatively * to the requested locale – see Locale::VALID_LOCALE. * From the most general to the most specific, the locales are ordered in * this fashion – actual locale, valid locale, requested locale. *

    * @return string * A locale string or FALSE on failure. * @since 5.5 */ #[Pure] #[LanguageAware(['8.0' => 'string|false'], default: 'string')] function intlcal_get_locale(IntlCalendar $calendar, int $type) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the global maximum value for a field * @link https://secure.php.net/manual/en/intlcalendar.getmaximum.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return int|false * @since 5.5 */ #[Pure] function intcal_get_maximum($calendar, $field) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * @link https://secure.php.net/manual/en/intlcalendar.getminimaldaysinfirstweek.php * Get minimal number of days the first week in a year or month can have * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @return int * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing a number of days or FALSE on failure. * @since 5.5 */ #[Pure] #[LanguageAware(['8.0' => 'int|false'], default: 'int')] function intlcal_get_minimal_days_in_first_week(IntlCalendar $calendar) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the global minimum value for a field * @link https://secure.php.net/manual/en/intlcalendar.getminimum.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return int * An int representing a value for the given field in the field's unit or FALSE on failure. * @since 5.5 */ #[Pure] #[LanguageAware(['8.0' => 'int|false'], default: 'int')] function intlcal_get_minimum(IntlCalendar $calendar, int $field) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the object's timezone * @link https://secure.php.net/manual/en/intlcalendar.gettimezone.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @return IntlTimeZone|false * An {@link https://secure.php.net/manual/en/class.intltimezone.php IntlTimeZone} object corresponding to the one used * internally in this object. * @since 5.5 */ #[Pure] function intlcal_get_time_zone(IntlCalendar $calendar): IntlTimeZone|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the calendar type * @link https://secure.php.net/manual/en/intlcalendar.gettype.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @return string * A {@link https://secure.php.net/manual/en/language.types.string.php string} representing the calendar type, such as * 'gregorian', 'islamic', etc. * @since 5.5 */ #[Pure] function intlcal_get_type(IntlCalendar $calendar): string {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get time of the day at which weekend begins or ends * @link https://secure.php.net/manual/en/intlcalendar.getweekendtransition.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $dayOfWeek

    * One of the constants IntlCalendar::DOW_SUNDAY, * IntlCalendar::DOW_MONDAY, ..., * IntlCalendar::DOW_SATURDAY. *

    * @return int * The number of milliseconds into the day at which the the weekend begins or * ends or FALSE on failure. * @since 5.5 */ #[Pure] #[LanguageAware(['8.0' => 'int|false'], default: 'int')] function intlcal_get_weekend_transition(IntlCalendar $calendar, int $dayOfWeek) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Whether the object's time is in Daylight Savings Time * @link https://secure.php.net/manual/en/intlcalendar.indaylighttime.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @return bool * Returns TRUE if the date is in Daylight Savings Time, FALSE otherwise. * The value FALSE may also be returned on failure, for instance after * specifying invalid field values on non-lenient mode; use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or query * {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to disambiguate. * @since 5.5 */ #[Pure] function intlcal_in_daylight_time(IntlCalendar $calendar): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Whether date/time interpretation is in lenient mode * @link https://secure.php.net/manual/en/intlcalendar.islenient.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @return bool * A {@link https://secure.php.net/manual/en/language.types.boolean.php bool} representing whether the calendar is set to lenient mode. * @since 5.5 */ #[Pure] function intlcal_is_lenient(IntlCalendar $calendar): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Whether a field is set * @link https://secure.php.net/manual/en/intlcalendar.isset.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return bool Assuming there are no argument errors, returns TRUE iif the field is set. * @since 5.5 */ #[Pure] function intlcal_is_set(IntlCalendar $calendar, int $field): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the global maximum value for a field * @link https://secure.php.net/manual/en/intlcalendar.getmaximum.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $field

    * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between 0 and * IntlCalendar::FIELD_COUNT. *

    * @return int|false * @since 5.5 */ #[Pure] #[LanguageAware(['8.0' => 'int|false'], default: 'int')] function intlcal_get_maximum(IntlCalendar $calendar, int $field) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Whether another calendar is equal but for a different time * @link https://secure.php.net/manual/en/intlcalendar.isequivalentto.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param IntlCalendar $other The other calendar against which the comparison is to be made. * @return bool * Assuming there are no argument errors, returns TRUE iif the calendars are equivalent except possibly for their set time. * @since 5.5 */ #[Pure] function intlcal_is_equivalent_to(IntlCalendar $calendar, IntlCalendar $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Whether a certain date/time is in the weekend * @link https://secure.php.net/manual/en/intlcalendar.isweekend.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param float|null $timestamp [optional]

    * An optional timestamp representing the number of milliseconds since the * epoch, excluding leap seconds. If NULL, this object's current time is * used instead. *

    * @return bool *

    A {@link https://secure.php.net/manual/en/language.types.boolean.php bool} indicating whether the given or this object's time occurs * in a weekend. *

    *

    * The value FALSE may also be returned on failure, for instance after giving * a date out of bounds on non-lenient mode; use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or query * {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to disambiguate.

    * @since 5.5 */ #[Pure] function intlcal_is_weekend(IntlCalendar $calendar, ?float $timestamp = null): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Set the day on which the week is deemed to start * @link https://secure.php.net/manual/en/intlcalendar.setfirstdayofweek.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $dayOfWeek

    * One of the constants IntlCalendar::DOW_SUNDAY, * IntlCalendar::DOW_MONDAY, ..., * IntlCalendar::DOW_SATURDAY. *

    * @return bool Returns TRUE on success. Failure can only happen due to invalid parameters. * @since 5.5 */ #[LanguageAware(['8.3' => 'true'], default: 'bool')] function intlcal_set_first_day_of_week(IntlCalendar $calendar, int $dayOfWeek) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Set whether date/time interpretation is to be lenient * @link https://secure.php.net/manual/en/intlcalendar.setlenient.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param bool $lenient

    * Use TRUE to activate the lenient mode; FALSE otherwise. *

    * @return bool Returns TRUE on success. Failure can only happen due to invalid parameters. * @since 5.5 */ #[LanguageAware(['8.3' => 'true'], default: 'bool')] function intlcal_set_lenient(IntlCalendar $calendar, bool $lenient) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get behavior for handling repeating wall time * @link https://secure.php.net/manual/en/intlcalendar.getrepeatedwalltimeoption.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @return int * One of the constants IntlCalendar::WALLTIME_FIRST or * IntlCalendar::WALLTIME_LAST. * @since 5.5 */ #[Pure] function intlcal_get_repeated_wall_time_option(IntlCalendar $calendar): int {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Compare time of two IntlCalendar objects for equality * @link https://secure.php.net/manual/en/intlcalendar.equals.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param IntlCalendar $other * @return bool

    * Returns TRUE if the current time of both this and the passed in * {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} object are the same, or FALSE * otherwise. The value FALSE can also be returned on failure. This can only * happen if bad arguments are passed in. In any case, the two cases can be * distinguished by calling {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()}. *

    * @since 5.5 */ #[Pure] function intlcal_equals(IntlCalendar $calendar, IntlCalendar $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get behavior for handling skipped wall time * @link https://secure.php.net/manual/en/intlcalendar.getskippedwalltimeoption.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @return int * One of the constants IntlCalendar::WALLTIME_FIRST, * IntlCalendar::WALLTIME_LAST or * IntlCalendar::WALLTIME_NEXT_VALID. * @since 5.5 */ #[Pure] function intlcal_get_skipped_wall_time_option(IntlCalendar $calendar): int {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Set behavior for handling repeating wall times at negative timezone offset transitions * @link https://secure.php.net/manual/en/intlcalendar.setrepeatedwalltimeoption.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $option

    * One of the constants IntlCalendar::WALLTIME_FIRST or * IntlCalendar::WALLTIME_LAST. *

    * @return bool * Returns TRUE on success. Failure can only happen due to invalid parameters. * @since 5.5 */ #[LanguageAware(['8.3' => 'true'], default: 'bool')] function intlcal_set_repeated_wall_time_option(IntlCalendar $calendar, int $option) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Set behavior for handling skipped wall times at positive timezone offset transitions * @link https://secure.php.net/manual/en/intlcalendar.setskippedwalltimeoption.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @param int $option

    * One of the constants IntlCalendar::WALLTIME_FIRST, * IntlCalendar::WALLTIME_LAST or * IntlCalendar::WALLTIME_NEXT_VALID. *

    * @return bool *

    * Returns TRUE on success. Failure can only happen due to invalid parameters. *

    * @since 5.5 */ #[LanguageAware(['8.3' => 'true'], default: 'bool')] function intlcal_set_skipped_wall_time_option(IntlCalendar $calendar, int $option) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a2)
    * Create an IntlCalendar from a DateTime object or string * @link https://secure.php.net/manual/en/intlcalendar.fromdatetime.php * @param DateTime|string $datetime

    * A {@link https://secure.php.net/manual/en/class.datetime.php DateTime} object or a {@link https://secure.php.net/manual/en/language.types.string.php string} that * can be passed to {@link https://secure.php.net/manual/en/datetime.construct.php DateTime::__construct()}. *

    * @param null|string $locale * @return IntlCalendar|null * The created {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} object or NULL in case of * failure. If a {@link https://secure.php.net/manual/en/language.types.string.php string} is passed, any exception that occurs * inside the {@link https://secure.php.net/manual/en/class.datetime.php DateTime} constructor is propagated. * @since 5.5 */ #[Pure] function intlcal_from_date_time( DateTime|string $datetime, #[ElementAvailable(from: '8.0')] ?string $locale = null ): ?IntlCalendar {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a2)
    * Convert an IntlCalendar into a DateTime object * @link https://secure.php.net/manual/en/intlcalendar.todatetime.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @return DateTime|false * A {@link https://secure.php.net/manual/en/class.datetime.php DateTime} object with the same timezone as this * object (though using PHP's database instead of ICU's) and the same time, * except for the smaller precision (second precision instead of millisecond). * Returns FALSE on failure. * @since 5.5 */ #[Pure] function intlcal_to_date_time(IntlCalendar $calendar): DateTime|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get last error code on the object * @link https://secure.php.net/manual/en/intlcalendar.geterrorcode.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @return int|false An ICU error code indicating either success, failure or a warning. * @since 5.5 */ #[Pure(true)] function intlcal_get_error_code(IntlCalendar $calendar): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get last error message on the object * @link https://secure.php.net/manual/en/intlcalendar.geterrormessage.php * @param IntlCalendar $calendar

    * The calendar object, on the procedural style interface. *

    * @return string|false The error message associated with last error that occurred in a function call on this object, or a string indicating the non-existance of an error. * @since 5.5 */ #[Pure(true)] function intlcal_get_error_message(IntlCalendar $calendar): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the number of IDs in the equivalency group that includes the given ID * @link https://secure.php.net/manual/en/intltimezone.countequivalentids.php * @param string $timezoneId * @return int|false * @since 5.5 */ #[Pure] function intltz_count_equivalent_ids(string $timezoneId): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Create a new copy of the default timezone for this host * @link https://secure.php.net/manual/en/intltimezone.createdefault.php * @return IntlTimeZone * @since 5.5 */ #[Pure] function intlz_create_default() {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * @link https://secure.php.net/manual/en/intltimezone.createenumeration.php * @param IntlTimeZone|string|int|float|null $countryOrRawOffset [optional] * @return IntlIterator|false * @since 5.5 */ #[Pure] function intltz_create_enumeration(#[LanguageAware(['8.5' => 'string|int|null'], default: '')] $countryOrRawOffset): IntlIterator|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * @link https://secure.php.net/manual/en/intltimezone.createtimezone.php * @param string $timezoneId * @return IntlTimeZone|null * @since 5.5 */ #[Pure] function intltz_create_time_zone(string $timezoneId): ?IntlTimeZone {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * @link https://secure.php.net/manual/en/intltimezone.fromdatetimezone.php * @param DateTimeZone $timezone * @return IntlTimeZone|null * @since 5.5 */ #[Pure] function intltz_from_date_time_zone(DateTimeZone $timezone): ?IntlTimeZone {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the canonical system timezone ID or the normalized custom time zone ID for the given time zone ID * @link https://secure.php.net/manual/en/intltimezone.getcanonicalid.php * @param string $timezoneId * @param bool &$isSystemId [optional] * @return string|false * @since 5.5 */ #[Pure] function intltz_get_canonical_id(string $timezoneId, &$isSystemId): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get a name of this time zone suitable for presentation to the user * @param IntlTimeZone $timezone -

    * The time zone object, on the procedural style interface. *

    * @param bool $dst [optional] * @param int $style [optional] * @param string|null $locale [optional] * @return string|false * @since 5.5 */ #[Pure] function intltz_get_display_name(IntlTimeZone $timezone, bool $dst = false, int $style = 2, ?string $locale): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the amount of time to be added to local standard time to get local wall clock time * @param IntlTimeZone $timezone -

    * The time zone object, on the procedural style interface. *

    * @return int * @link https://secure.php.net/manual/en/intltimezone.getequivalentid.php * @since 5.5 */ #[Pure] function intltz_get_dst_savings(IntlTimeZone $timezone): int {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get an ID in the equivalency group that includes the given ID * @link https://secure.php.net/manual/en/intltimezone.getequivalentid.php * @param string $timezoneId * @param int $offset * @return string|false * @since 5.5 */ #[Pure] function intltz_get_equivalent_id(string $timezoneId, int $offset): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get last error code on the object * @link https://secure.php.net/manual/en/intltimezone.geterrorcode.php * @param IntlTimeZone $timezone -

    * The time zone object, on the procedural style interface. *

    * @return int|false * @since 5.5 */ #[Pure(true)] function intltz_get_error_code(IntlTimeZone $timezone): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get last error message on the object * @link https://secure.php.net/manual/en/intltimezone.geterrormessage.php * @param IntlTimeZone $timezone -

    * The time zone object, on the procedural style interface. *

    * @return string|false * @since 5.5 */ #[Pure(true)] function intltz_get_error_message(IntlTimeZone $timezone): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Create GMT (UTC) timezone * @link https://secure.php.net/manual/en/intltimezone.getgmt.php * @return IntlTimeZone * @since 5.5 */ #[Pure] function intltz_getGMT(): IntlTimeZone {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get timezone ID * @link https://secure.php.net/manual/en/intltimezone.getid.php * @param IntlTimeZone $timezone * @return string|false * @since 5.5 */ #[Pure] function intltz_get_id(IntlTimeZone $timezone): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the time zone raw and GMT offset for the given moment in time * @link https://secure.php.net/manual/en/intltimezone.getoffset.php * @param IntlTimeZone $timezone * @param float $timestamp * @param bool $local * @param int &$rawOffset * @param int &$dstOffset * @return bool * @since 5.5 */ #[Pure] function intltz_get_offset(IntlTimeZone $timezone, float $timestamp, bool $local, &$rawOffset, &$dstOffset): bool {} /** * Get the raw GMT offset (before taking daylight savings time into account * @link https://secure.php.net/manual/en/intltimezone.getrawoffset.php * @param IntlTimeZone $timezone * @return int */ #[Pure] function intltz_get_raw_offset(IntlTimeZone $timezone): int {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Get the timezone data version currently used by ICU * @link https://secure.php.net/manual/en/intltimezone.gettzdataversion.php * @return string|false * @since 5.5 */ #[Pure] function intltz_get_tz_data_version(): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Check if this zone has the same rules and offset as another zone * @link https://secure.php.net/manual/en/intltimezone.hassamerules.php * @param IntlTimeZone $timezone * @param IntlTimeZone $other * @return bool * @since 5.5 */ #[Pure] function intltz_has_same_rules( IntlTimeZone $timezone, #[ElementAvailable(from: '5.5', to: '7.4')] IntlTimeZone $other = null, #[ElementAvailable(from: '8.0')] IntlTimeZone $other ): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Convert to DateTimeZone object * @link https://secure.php.net/manual/en/intltimezone.todatetimezone.php * @param IntlTimeZone $timezone * @return DateTimeZone|false * @since 5.5 */ #[Pure] function intltz_to_date_time_zone(IntlTimeZone $timezone): DateTimeZone|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * Check if this time zone uses daylight savings time * @link https://secure.php.net/manual/en/intltimezone.usedaylighttime.php * @param IntlTimeZone $timezone * @return bool * @since 5.5 */ #[Pure] function intltz_use_daylight_time(IntlTimeZone $timezone): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)
    * @param DateTimeZone|IntlTimeZone|string|int|null $timezoneOrYear [optional] * @param string|null $localeOrMonth [optional] * @param int $day [optional] * @param int $hour [optional] * @param int $minute [optional] * @param int $second [optional] * @return IntlGregorianCalendar|null * @since 5.5 */ #[Pure] #[Deprecated( reason: 'use IntlGregorianCalendar::__construct(), IntlGregorianCalendar::createFromDate(), or IntlGregorianCalendar::createFromDateTime() instead', since: '8.4' )] function intlgregcal_create_instance($timezoneOrYear, $localeOrMonth, $day, $hour, $minute, $second): ?IntlGregorianCalendar {} /** * @param IntlGregorianCalendar $calendar * @param float $timestamp * @return bool */ function intlgregcal_set_gregorian_change(IntlGregorianCalendar $calendar, float $timestamp): bool {} /** * @param IntlGregorianCalendar $calendar * @return float */ #[Pure] function intlgregcal_get_gregorian_change(IntlGregorianCalendar $calendar): float {} /** * @param IntlGregorianCalendar $calendar * @param int $year * @return bool */ #[Pure] function intlgregcal_is_leap_year(IntlGregorianCalendar $calendar, int $year): bool {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)
    * Create a resource bundle * @link https://php.net/manual/en/resourcebundle.create.php * @param string|null $locale

    * Locale for which the resources should be loaded (locale name, e.g. en_CA). *

    * @param string|null $bundle

    * The directory where the data is stored or the name of the .dat file. *

    * @param bool $fallback [optional]

    * Whether locale should match exactly or fallback to parent locale is allowed. *

    * @return ResourceBundle|null ResourceBundle object or NULL on error. */ #[Pure] function resourcebundle_create(?string $locale, ?string $bundle, bool $fallback = true): ?ResourceBundle {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)
    * Get data from the bundle * @link https://php.net/manual/en/resourcebundle.get.php * @param ResourceBundle $bundle * @param string|int $index

    * Data index, must be string or integer. *

    * @param bool $fallback * @return mixed the data located at the index or NULL on error. Strings, integers and binary data strings * are returned as corresponding PHP types, integer array is returned as PHP array. Complex types are * returned as ResourceBundle object. */ #[Pure] #[LanguageAware(['8.4' => 'ResourceBundle|array|string|int|null'], default: 'mixed')] function resourcebundle_get(ResourceBundle $bundle, string|int $index, bool $fallback = true) {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)
    * Get number of elements in the bundle * @link https://php.net/manual/en/resourcebundle.count.php * @param ResourceBundle $bundle * @return int number of elements in the bundle. */ #[Pure] function resourcebundle_count(ResourceBundle $bundle): int {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)
    * Get supported locales * @link https://php.net/manual/en/resourcebundle.locales.php * @param string $bundle

    * Path of ResourceBundle for which to get available locales, or * empty string for default locales list. *

    * @return array|false the list of locales supported by the bundle. */ #[Pure] function resourcebundle_locales(string $bundle): array|false {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)
    * Get bundle's last error code. * @link https://php.net/manual/en/resourcebundle.geterrorcode.php * @param ResourceBundle $bundle * @return int error code from last bundle object call. */ #[Pure(true)] function resourcebundle_get_error_code(ResourceBundle $bundle): int {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)
    * Get bundle's last error message. * @link https://php.net/manual/en/resourcebundle.geterrormessage.php * @param ResourceBundle $bundle * @return string error message from last bundle object's call. */ #[Pure(true)] function resourcebundle_get_error_message(ResourceBundle $bundle): string {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Create a transliterator * @link https://php.net/manual/en/transliterator.create.php * @param string $id

    * The id. *

    * @param int $direction

    * The direction, defaults to * Transliterator::FORWARD. * May also be set to * Transliterator::REVERSE. *

    * @return Transliterator|null a Transliterator object on success, * or NULL on failure. * @since 5.4 */ #[Pure] function transliterator_create(string $id, int $direction = 0): ?Transliterator {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Create transliterator from rules * @link https://php.net/manual/en/transliterator.createfromrules.php * @param string $rules

    * The rules. *

    * @param int $direction

    * The direction, defaults to * Transliterator::FORWARD. * May also be set to * Transliterator::REVERSE. *

    * @return Transliterator|null a Transliterator object on success, * or NULL on failure. * @since 5.4 */ #[Pure] function transliterator_create_from_rules(string $rules, int $direction = 0): ?Transliterator {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Get transliterator IDs * @link https://php.net/manual/en/transliterator.listids.php * @return string[]|false An array of registered transliterator IDs on success, * or FALSE on failure. * @since 5.4 */ #[Pure] function transliterator_list_ids(): array|false {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Create an inverse transliterator * @link https://php.net/manual/en/transliterator.createinverse.php * @param Transliterator $transliterator * @return Transliterator|null a Transliterator object on success, * or NULL on failure * @since 5.4 */ #[Pure] function transliterator_create_inverse(Transliterator $transliterator): ?Transliterator {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Transliterate a string * @link https://php.net/manual/en/transliterator.transliterate.php * @param Transliterator|string $transliterator * @param string $string

    * The string to be transformed. *

    * @param int $start

    * The start index (in UTF-16 code units) from which the string will start * to be transformed, inclusive. Indexing starts at 0. The text before will * be left as is. *

    * @param int $end

    * The end index (in UTF-16 code units) until which the string will be * transformed, exclusive. Indexing starts at 0. The text after will be * left as is. *

    * @return string|false The transfomed string on success, or FALSE on failure. * @since 5.4 */ #[Pure] function transliterator_transliterate(Transliterator|string $transliterator, string $string, int $start = 0, int $end = -1): string|false {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Get last error code * @link https://php.net/manual/en/transliterator.geterrorcode.php * @param Transliterator $transliterator * @return int|false The error code on success, * or FALSE if none exists, or on failure. * @since 5.4 */ #[Pure(true)] #[LanguageAware(['8.5' => 'int'], default: 'int|false')] function transliterator_get_error_code(Transliterator $transliterator) {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)
    * Get last error message * @link https://php.net/manual/en/transliterator.geterrormessage.php * @param Transliterator $transliterator * @return string|false The error code on success, * or FALSE if none exists, or on failure. * @since 5.4 */ #[Pure(true)] #[LanguageAware(['8.5' => 'string'], default: 'string|false')] function transliterator_get_error_message(Transliterator $transliterator) {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get the last error code * @link https://php.net/manual/en/function.intl-get-error-code.php * @return int Error code returned by the last API function call. */ #[Pure(true)] function intl_get_error_code(): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get description of the last error * @link https://php.net/manual/en/function.intl-get-error-message.php * @return string Description of an error occurred in the last API function call. */ #[Pure(true)] function intl_get_error_message(): string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Check whether the given error code indicates failure * @link https://php.net/manual/en/function.intl-is-failure.php * @param int $errorCode

    * is a value that returned by functions: * intl_get_error_code, * collator_get_error_code . *

    * @return bool TRUE if it the code indicates some failure, and FALSE * in case of success or a warning. */ #[Pure] function intl_is_failure(int $errorCode): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
    * Get symbolic name for a given error code * @link https://php.net/manual/en/function.intl-error-name.php * @param int $errorCode

    * ICU error code. *

    * @return string The returned string will be the same as the name of the error code * constant. */ #[Pure] function intl_error_name(int $errorCode): string {} /** * Gets the Decomposition_Mapping property for the given UTF-8 encoded code point * * @link https://www.php.net/manual/en/normalizer.getrawdecomposition.php * * @param string $string * @param int $form * @return string|null * * @since 7.3 */ #[Pure] function normalizer_get_raw_decomposition(string $string, #[ElementAvailable(from: '8.0')] int $form = Normalizer::FORM_C): ?string {} /** * @return IntlTimeZone * @since 5.5 */ #[Pure] function intltz_create_default(): IntlTimeZone {} /** * @return IntlTimeZone * @since 5.5 */ #[Pure] function intltz_get_gmt(): IntlTimeZone {} /** * @return IntlTimeZone * @since 5.5 */ #[Pure] function intltz_get_unknown(): IntlTimeZone {} /** * @param int $type * @param null|string $region * @param null|int $rawOffset * @return IntlIterator|false * @since 5.5 */ #[Pure] function intltz_create_time_zone_id_enumeration(int $type, ?string $region = null, ?int $rawOffset = null): IntlIterator|false {} /** * @param string $timezoneId * @return string|false * @since 5.5 */ #[Pure] function intltz_get_region(string $timezoneId): string|false {} /** * Set minimal number of days the first week in a year or month can have * * @link https://www.php.net/manual/en/intlcalendar.setminimaldaysinfirstweek.php * * @param IntlCalendar $calendar * @param int $days * @return bool * * @since 5.5.1 */ #[LanguageAware(['8.3' => 'true'], default: 'bool')] function intlcal_set_minimal_days_in_first_week(IntlCalendar $calendar, int $days) {} function intltz_get_windows_id(string $timezoneId): string|false {} function intltz_get_id_for_windows_id(string $timezoneId, ?string $region = null): string|false {} /** * @since 8.4 */ function grapheme_str_split(string $string, int $length = 1): array|false {} /** * @since 8.4 */ function intltz_get_iana_id(string $timezoneId): string|false {} /** * @since 8.5 */ function grapheme_levenshtein(string $string1, string $string2, int $insertion_cost = 1, int $replacement_cost = 1, int $deletion_cost = 1, string $locale = ""): int|false {} /** * @since 8.5 */ function locale_is_right_to_left(string $locale): bool {} /** * @since 8.5 */ function locale_add_likely_subtags(string $locale): string|false {} /** * @since 8.5 */ function locale_minimize_subtags(string $locale): string|false {} /** * Limit on locale length, set to 80 in PHP code. Locale names longer * than this limit will not be accepted. * @link https://php.net/manual/en/intl.constants.php */ define('INTL_MAX_LOCALE_LEN', 156); define('INTL_ICU_VERSION', "74.1"); define('INTL_ICU_DATA_VERSION', "74.1"); define('ULOC_ACTUAL_LOCALE', 0); define('ULOC_VALID_LOCALE', 1); define('GRAPHEME_EXTR_COUNT', 0); define('GRAPHEME_EXTR_MAXBYTES', 1); define('GRAPHEME_EXTR_MAXCHARS', 2); define('U_USING_FALLBACK_WARNING', -128); define('U_ERROR_WARNING_START', -128); define('U_USING_DEFAULT_WARNING', -127); define('U_SAFECLONE_ALLOCATED_WARNING', -126); define('U_STATE_OLD_WARNING', -125); define('U_STRING_NOT_TERMINATED_WARNING', -124); define('U_SORT_KEY_TOO_SHORT_WARNING', -123); define('U_AMBIGUOUS_ALIAS_WARNING', -122); define('U_DIFFERENT_UCA_VERSION', -121); define('U_ERROR_WARNING_LIMIT', -119); define('U_ZERO_ERROR', 0); define('U_ILLEGAL_ARGUMENT_ERROR', 1); define('U_MISSING_RESOURCE_ERROR', 2); define('U_INVALID_FORMAT_ERROR', 3); define('U_FILE_ACCESS_ERROR', 4); define('U_INTERNAL_PROGRAM_ERROR', 5); define('U_MESSAGE_PARSE_ERROR', 6); define('U_MEMORY_ALLOCATION_ERROR', 7); define('U_INDEX_OUTOFBOUNDS_ERROR', 8); define('U_PARSE_ERROR', 9); define('U_INVALID_CHAR_FOUND', 10); define('U_TRUNCATED_CHAR_FOUND', 11); define('U_ILLEGAL_CHAR_FOUND', 12); define('U_INVALID_TABLE_FORMAT', 13); define('U_INVALID_TABLE_FILE', 14); define('U_BUFFER_OVERFLOW_ERROR', 15); define('U_UNSUPPORTED_ERROR', 16); define('U_RESOURCE_TYPE_MISMATCH', 17); define('U_ILLEGAL_ESCAPE_SEQUENCE', 18); define('U_UNSUPPORTED_ESCAPE_SEQUENCE', 19); define('U_NO_SPACE_AVAILABLE', 20); define('U_CE_NOT_FOUND_ERROR', 21); define('U_PRIMARY_TOO_LONG_ERROR', 22); define('U_STATE_TOO_OLD_ERROR', 23); define('U_TOO_MANY_ALIASES_ERROR', 24); define('U_ENUM_OUT_OF_SYNC_ERROR', 25); define('U_INVARIANT_CONVERSION_ERROR', 26); define('U_INVALID_STATE_ERROR', 27); define('U_COLLATOR_VERSION_MISMATCH', 28); define('U_USELESS_COLLATOR_ERROR', 29); define('U_NO_WRITE_PERMISSION', 30); define('U_STANDARD_ERROR_LIMIT', 32); define('U_BAD_VARIABLE_DEFINITION', 65536); define('U_PARSE_ERROR_START', 65536); define('U_MALFORMED_RULE', 65537); define('U_MALFORMED_SET', 65538); define('U_MALFORMED_SYMBOL_REFERENCE', 65539); define('U_MALFORMED_UNICODE_ESCAPE', 65540); define('U_MALFORMED_VARIABLE_DEFINITION', 65541); define('U_MALFORMED_VARIABLE_REFERENCE', 65542); define('U_MISMATCHED_SEGMENT_DELIMITERS', 65543); define('U_MISPLACED_ANCHOR_START', 65544); define('U_MISPLACED_CURSOR_OFFSET', 65545); define('U_MISPLACED_QUANTIFIER', 65546); define('U_MISSING_OPERATOR', 65547); define('U_MISSING_SEGMENT_CLOSE', 65548); define('U_MULTIPLE_ANTE_CONTEXTS', 65549); define('U_MULTIPLE_CURSORS', 65550); define('U_MULTIPLE_POST_CONTEXTS', 65551); define('U_TRAILING_BACKSLASH', 65552); define('U_UNDEFINED_SEGMENT_REFERENCE', 65553); define('U_UNDEFINED_VARIABLE', 65554); define('U_UNQUOTED_SPECIAL', 65555); define('U_UNTERMINATED_QUOTE', 65556); define('U_RULE_MASK_ERROR', 65557); define('U_MISPLACED_COMPOUND_FILTER', 65558); define('U_MULTIPLE_COMPOUND_FILTERS', 65559); define('U_INVALID_RBT_SYNTAX', 65560); define('U_INVALID_PROPERTY_PATTERN', 65561); define('U_MALFORMED_PRAGMA', 65562); define('U_UNCLOSED_SEGMENT', 65563); define('U_ILLEGAL_CHAR_IN_SEGMENT', 65564); define('U_VARIABLE_RANGE_EXHAUSTED', 65565); define('U_VARIABLE_RANGE_OVERLAP', 65566); define('U_ILLEGAL_CHARACTER', 65567); define('U_INTERNAL_TRANSLITERATOR_ERROR', 65568); define('U_INVALID_ID', 65569); define('U_INVALID_FUNCTION', 65570); define('U_PARSE_ERROR_LIMIT', 65571); define('U_UNEXPECTED_TOKEN', 65792); define('U_FMT_PARSE_ERROR_START', 65792); define('U_MULTIPLE_DECIMAL_SEPARATORS', 65793); define('U_MULTIPLE_DECIMAL_SEPERATORS', 65793); define('U_MULTIPLE_EXPONENTIAL_SYMBOLS', 65794); define('U_MALFORMED_EXPONENTIAL_PATTERN', 65795); define('U_MULTIPLE_PERCENT_SYMBOLS', 65796); define('U_MULTIPLE_PERMILL_SYMBOLS', 65797); define('U_MULTIPLE_PAD_SPECIFIERS', 65798); define('U_PATTERN_SYNTAX_ERROR', 65799); define('U_ILLEGAL_PAD_POSITION', 65800); define('U_UNMATCHED_BRACES', 65801); define('U_UNSUPPORTED_PROPERTY', 65802); define('U_UNSUPPORTED_ATTRIBUTE', 65803); define('U_FMT_PARSE_ERROR_LIMIT', 65812); define('U_BRK_INTERNAL_ERROR', 66048); define('U_BRK_ERROR_START', 66048); define('U_BRK_HEX_DIGITS_EXPECTED', 66049); define('U_BRK_SEMICOLON_EXPECTED', 66050); define('U_BRK_RULE_SYNTAX', 66051); define('U_BRK_UNCLOSED_SET', 66052); define('U_BRK_ASSIGN_ERROR', 66053); define('U_BRK_VARIABLE_REDFINITION', 66054); define('U_BRK_MISMATCHED_PAREN', 66055); define('U_BRK_NEW_LINE_IN_QUOTED_STRING', 66056); define('U_BRK_UNDEFINED_VARIABLE', 66057); define('U_BRK_INIT_ERROR', 66058); define('U_BRK_RULE_EMPTY_SET', 66059); define('U_BRK_UNRECOGNIZED_OPTION', 66060); define('U_BRK_MALFORMED_RULE_TAG', 66061); define('U_BRK_ERROR_LIMIT', 66062); define('U_REGEX_INTERNAL_ERROR', 66304); define('U_REGEX_ERROR_START', 66304); define('U_REGEX_RULE_SYNTAX', 66305); define('U_REGEX_INVALID_STATE', 66306); define('U_REGEX_BAD_ESCAPE_SEQUENCE', 66307); define('U_REGEX_PROPERTY_SYNTAX', 66308); define('U_REGEX_UNIMPLEMENTED', 66309); define('U_REGEX_MISMATCHED_PAREN', 66310); define('U_REGEX_NUMBER_TOO_BIG', 66311); define('U_REGEX_BAD_INTERVAL', 66312); define('U_REGEX_MAX_LT_MIN', 66313); define('U_REGEX_INVALID_BACK_REF', 66314); define('U_REGEX_INVALID_FLAG', 66315); define('U_REGEX_LOOK_BEHIND_LIMIT', 66316); define('U_REGEX_SET_CONTAINS_STRING', 66317); define('U_REGEX_ERROR_LIMIT', 66326); define('U_IDNA_PROHIBITED_ERROR', 66560); define('U_IDNA_ERROR_START', 66560); define('U_IDNA_UNASSIGNED_ERROR', 66561); define('U_IDNA_CHECK_BIDI_ERROR', 66562); define('U_IDNA_STD3_ASCII_RULES_ERROR', 66563); define('U_IDNA_ACE_PREFIX_ERROR', 66564); define('U_IDNA_VERIFICATION_ERROR', 66565); define('U_IDNA_LABEL_TOO_LONG_ERROR', 66566); define('U_IDNA_ZERO_LENGTH_LABEL_ERROR', 66567); define('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR', 66568); define('U_IDNA_ERROR_LIMIT', 66569); define('U_STRINGPREP_PROHIBITED_ERROR', 66560); define('U_STRINGPREP_UNASSIGNED_ERROR', 66561); define('U_STRINGPREP_CHECK_BIDI_ERROR', 66562); define('U_ERROR_LIMIT', 66818); /** * Prohibit processing of unassigned codepoints in the input for IDN * functions and do not check if the input conforms to domain name ASCII rules. * @link https://php.net/manual/en/intl.constants.php */ define('IDNA_DEFAULT', 48); /** * Allow processing of unassigned codepoints in the input for IDN functions. * @link https://php.net/manual/en/intl.constants.php */ define('IDNA_ALLOW_UNASSIGNED', 1); /** * Check if the input for IDN functions conforms to domain name ASCII rules. * @link https://php.net/manual/en/intl.constants.php */ define('IDNA_USE_STD3_RULES', 2); /** * Check whether the input conforms to the BiDi rules. * Ignored by the IDNA2003 implementation, which always performs this check. * @link https://php.net/manual/en/intl.constants.php */ define('IDNA_CHECK_BIDI', 4); /** * Check whether the input conforms to the CONTEXTJ rules. * Ignored by the IDNA2003 implementation, as this check is new in IDNA2008. * @link https://php.net/manual/en/intl.constants.php */ define('IDNA_CHECK_CONTEXTJ', 8); /** * Option for nontransitional processing in * idn_to_ascii. Transitional processing is activated * by default. This option is ignored by the IDNA2003 implementation. * @link https://php.net/manual/en/intl.constants.php */ define('IDNA_NONTRANSITIONAL_TO_ASCII', 16); /** * Option for nontransitional processing in * idn_to_utf8. Transitional processing is activated * by default. This option is ignored by the IDNA2003 implementation. * @link https://php.net/manual/en/intl.constants.php */ define('IDNA_NONTRANSITIONAL_TO_UNICODE', 32); /** * Use IDNA 2003 algorithm in {@see idn_to_utf8} and * {@see idn_to_ascii}. This is the default. * @link https://php.net/manual/en/intl.constants.php * @deprecated 7.2 Use {@see INTL_IDNA_VARIANT_UTS46} instead. */ define('INTL_IDNA_VARIANT_2003', 0); /** * Use UTS #46 algorithm in idn_to_utf8 and * idn_to_ascii. * @link https://php.net/manual/en/intl.constants.php */ define('INTL_IDNA_VARIANT_UTS46', 1); /** * Errors reported in a bitset returned by the UTS #46 algorithm in * idn_to_utf8 and * idn_to_ascii. * @link https://php.net/manual/en/intl.constants.php */ define('IDNA_ERROR_EMPTY_LABEL', 1); /** * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ define('IDNA_ERROR_LABEL_TOO_LONG', 2); /** * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ define('IDNA_ERROR_DOMAIN_NAME_TOO_LONG', 4); /** * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ define('IDNA_ERROR_LEADING_HYPHEN', 8); /** * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ define('IDNA_ERROR_TRAILING_HYPHEN', 16); /** * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ define('IDNA_ERROR_HYPHEN_3_4', 32); /** * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ define('IDNA_ERROR_LEADING_COMBINING_MARK', 64); /** * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ define('IDNA_ERROR_DISALLOWED', 128); /** * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ define('IDNA_ERROR_PUNYCODE', 256); /** * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ define('IDNA_ERROR_LABEL_HAS_DOT', 512); /** * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ define('IDNA_ERROR_INVALID_ACE_LABEL', 1024); /** * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ define('IDNA_ERROR_BIDI', 2048); /** * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ define('IDNA_ERROR_CONTEXTJ', 4096); /** * @since 5.5 */ class IntlBreakIterator implements IteratorAggregate { /* Constants */ public const DONE = -1; public const WORD_NONE = 0; public const WORD_NONE_LIMIT = 100; public const WORD_NUMBER = 100; public const WORD_NUMBER_LIMIT = 200; public const WORD_LETTER = 200; public const WORD_LETTER_LIMIT = 300; public const WORD_KANA = 300; public const WORD_KANA_LIMIT = 400; public const WORD_IDEO = 400; public const WORD_IDEO_LIMIT = 500; public const LINE_SOFT = 0; public const LINE_SOFT_LIMIT = 100; public const LINE_HARD = 100; public const LINE_HARD_LIMIT = 200; public const SENTENCE_TERM = 0; public const SENTENCE_TERM_LIMIT = 100; public const SENTENCE_SEP = 100; public const SENTENCE_SEP_LIMIT = 200; /* Methods */ /** * (PHP 5 >=5.5.0)
    * Private constructor for disallowing instantiation */ private function __construct() {} /** * (PHP 5 >=5.5.0)
    * Create break iterator for boundaries of combining character sequences * @link https://secure.php.net/manual/en/intlbreakiterator.createcharacterinstance.php * @param string $locale * @return IntlBreakIterator|null */ #[TentativeType] public static function createCharacterInstance(#[LanguageAware(['8.0' => 'string|null'], default: '')] $locale = null): ?IntlBreakIterator {} /** * (PHP 5 >=5.5.0)
    * Create break iterator for boundaries of code points * @link https://secure.php.net/manual/en/intlbreakiterator.createcodepointinstance.php * @return IntlCodePointBreakIterator */ #[TentativeType] public static function createCodePointInstance(): IntlCodePointBreakIterator {} /** * (PHP 5 >=5.5.0)
    * Create break iterator for logically possible line breaks * @link https://secure.php.net/manual/en/intlbreakiterator.createlineinstance.php * @param string $locale [optional] * @return IntlBreakIterator|null */ #[TentativeType] public static function createLineInstance(#[LanguageAware(['8.0' => 'string|null'], default: '')] $locale): ?IntlBreakIterator {} /** * (PHP 5 >=5.5.0)
    * Create break iterator for sentence breaks * @link https://secure.php.net/manual/en/intlbreakiterator.createsentenceinstance.php * @param string $locale [optional] * @return IntlBreakIterator|null */ #[TentativeType] public static function createSentenceInstance(#[LanguageAware(['8.0' => 'string|null'], default: '')] $locale): ?IntlBreakIterator {} /** * (PHP 5 >=5.5.0)
    * Create break iterator for title-casing breaks * @link https://secure.php.net/manual/en/intlbreakiterator.createtitleinstance.php * @param string $locale [optional] * @return IntlBreakIterator|null */ #[TentativeType] public static function createTitleInstance(#[LanguageAware(['8.0' => 'string|null'], default: '')] $locale): ?IntlBreakIterator {} /** * (PHP 5 >=5.5.0)
    * Create break iterator for word breaks * @link https://secure.php.net/manual/en/intlbreakiterator.createwordinstance.php * @param string $locale [optional] * @return IntlBreakIterator|null */ #[TentativeType] public static function createWordInstance(#[LanguageAware(['8.0' => 'string|null'], default: '')] $locale): ?IntlBreakIterator {} /** * (PHP 5 >=5.5.0)
    * Get index of current position * @link https://secure.php.net/manual/en/intlbreakiterator.current.php * @return int */ #[Pure] #[TentativeType] public function current(): int {} /** * (PHP 5 >=5.5.0)
    * Set position to the first character in the text * @link https://secure.php.net/manual/en/intlbreakiterator.first.php */ #[TentativeType] public function first(): int {} /** * (PHP 5 >=5.5.0)
    * Advance the iterator to the first boundary following specified offset * @link https://secure.php.net/manual/en/intlbreakiterator.following.php * @param int $offset */ #[TentativeType] public function following(#[LanguageAware(['8.0' => 'int'], default: '')] $offset): int {} /** * (PHP 5 >=5.5.0)
    * Get last error code on the object * @link https://secure.php.net/manual/en/intlbreakiterator.geterrorcode.php * @return int */ #[Pure] #[TentativeType] public function getErrorCode(): int {} /** * (PHP 5 >=5.5.0)
    * Get last error message on the object * @link https://secure.php.net/manual/en/intlbreakiterator.geterrormessage.php * @return string */ #[Pure] #[TentativeType] public function getErrorMessage(): string {} /** * (PHP 5 >=5.5.0)
    * Get the locale associated with the object * @link https://secure.php.net/manual/en/intlbreakiterator.getlocale.php * @param string $type */ #[Pure] #[TentativeType] public function getLocale(#[LanguageAware(['8.0' => 'int'], default: '')] $type): string|false {} /** * (PHP 5 >=5.5.0)
    * Create iterator for navigating fragments between boundaries * @link https://secure.php.net/manual/en/intlbreakiterator.getpartsiterator.php * @param int $type [optional] *

    * Optional key type. Possible values are: *

      *
    • * {@see IntlPartsIterator::KEY_SEQUENTIAL} * - The default. Sequentially increasing integers used as key. *
    • *
    • * {@see IntlPartsIterator::KEY_LEFT} * - Byte offset left of current part used as key. *
    • *
    • * {@see IntlPartsIterator::KEY_RIGHT} * - Byte offset right of current part used as key. *
    • *
    */ #[Pure] #[TentativeType] public function getPartsIterator( #[LanguageAware(['8.0' => 'int', '8.3' => 'string'], default: '')] #[EV([IntlPartsIterator::KEY_SEQUENTIAL, IntlPartsIterator::KEY_LEFT, IntlPartsIterator::KEY_RIGHT])] $type = IntlPartsIterator::KEY_SEQUENTIAL ): IntlPartsIterator {} /** * (PHP 5 >=5.5.0)
    * Get the text being scanned * @link https://secure.php.net/manual/en/intlbreakiterator.gettext.php */ #[Pure] #[TentativeType] public function getText(): ?string {} /** * (PHP 5 >=5.5.0)
    * Tell whether an offset is a boundary's offset * @link https://secure.php.net/manual/en/intlbreakiterator.isboundary.php * @param int $offset */ #[Pure] #[TentativeType] public function isBoundary(#[LanguageAware(['8.0' => 'int'], default: '')] $offset): bool {} /** * (PHP 5 >=5.5.0)
    * Set the iterator position to index beyond the last character * @link https://secure.php.net/manual/en/intlbreakiterator.last.php * @return int */ #[TentativeType] public function last(): int {} /** * (PHP 5 >=5.5.0)
    * @link https://secure.php.net/manual/en/intlbreakiterator.next.php * @param int $offset [optional] * @return int */ #[TentativeType] public function next(#[LanguageAware(['8.0' => 'int|null'], default: '')] $offset = null): int {} /** * (PHP 5 >=5.5.0)
    * @link https://secure.php.net/manual/en/intlbreakiterator.preceding.php * @param int $offset */ #[TentativeType] public function preceding(#[LanguageAware(['8.0' => 'int'], default: '')] $offset): int {} /** * (PHP 5 >=5.5.0)
    * Set the iterator position to the boundary immediately before the current * @link https://secure.php.net/manual/en/intlbreakiterator.previous.php * @return int */ #[TentativeType] public function previous(): int {} /** * (PHP 5 >=5.5.0)
    * Set the text being scanned * @link https://secure.php.net/manual/en/intlbreakiterator.settext.php * @param string $text */ #[TentativeType] #[LanguageAware(['8.3' => 'bool'], default: 'bool|null')] public function setText(#[LanguageAware(['8.0' => 'string'], default: '')] $text) {} /** * @since 8.0 * @return Iterator */ #[Pure] public function getIterator(): Iterator {} } class IntlRuleBasedBreakIterator extends IntlBreakIterator implements Traversable { /* Methods */ /** * (PHP 5 >=5.5.0)
    * @link https://secure.php.net/manual/en/intlbreakiterator.construct.php * @param string $rules * @param string $compiled [optional] */ #[Pure] public function __construct( #[LanguageAware(['8.0' => 'string'], default: '')] $rules, #[LanguageAware(['8.0' => 'bool'], default: '')] $compiled = false ) {} /** * (PHP 5 >=5.5.0)
    * Create break iterator for boundaries of combining character sequences * @link https://secure.php.net/manual/en/intlbreakiterator.createcharacterinstance.php * @param string $locale * @return IntlRuleBasedBreakIterator */ public static function createCharacterInstance($locale) {} /** * (PHP 5 >=5.5.0)
    * Create break iterator for boundaries of code points * @link https://secure.php.net/manual/en/intlbreakiterator.createcodepointinstance.php * @return IntlRuleBasedBreakIterator */ public static function createCodePointInstance() {} /** * (PHP 5 >=5.5.0)
    * Create break iterator for logically possible line breaks * @link https://secure.php.net/manual/en/intlbreakiterator.createlineinstance.php * @param string $locale [optional] * @return IntlRuleBasedBreakIterator */ public static function createLineInstance($locale) {} /** * (PHP 5 >=5.5.0)
    * Create break iterator for sentence breaks * @link https://secure.php.net/manual/en/intlbreakiterator.createsentenceinstance.php * @param string $locale [optional] * @return IntlRuleBasedBreakIterator */ public static function createSentenceInstance($locale) {} /** * (PHP 5 >=5.5.0)
    * Create break iterator for title-casing breaks * @link https://secure.php.net/manual/en/intlbreakiterator.createtitleinstance.php * @param string $locale [optional] * @return IntlRuleBasedBreakIterator */ public static function createTitleInstance($locale) {} /** * (PHP 5 >=5.5.0)
    * Create break iterator for word breaks * @link https://secure.php.net/manual/en/intlbreakiterator.createwordinstance.php * @param string $locale [optional] * @return IntlRuleBasedBreakIterator */ public static function createWordInstance($locale) {} /** * (PHP 5 >=5.5.0)
    * @link https://secure.php.net/manual/en/intlrulebasedbreakiterator.getbinaryrules.php * Get the binary form of compiled rules * @return string|false */ #[Pure] #[TentativeType] public function getBinaryRules(): string|false {} /** * (PHP 5 >=5.5.0)
    * @link https://secure.php.net/manual/en/intlrulebasedbreakiterator.getrules.php * Get the rule set used to create this object * @return string|false */ #[Pure] #[TentativeType] public function getRules(): string|false {} /** * (PHP 5 >=5.5.0)
    * @link https://secure.php.net/manual/en/intlrulebasedbreakiterator.getrulesstatus.php * Get the largest status value from the break rules that determined the current break position * @return int */ #[Pure] #[TentativeType] public function getRuleStatus(): int {} /** * (PHP 5 >=5.5.0)
    * @link https://secure.php.net/manual/en/intlrulebasedbreakiterator.getrulestatusvec.php * Get the status values from the break rules that determined the current break position * @return array|false */ #[Pure] #[TentativeType] public function getRuleStatusVec(): array|false {} } /** * @link https://www.php.net/manual/en/class.intlpartsiterator.php * @since 5.5 */ class IntlPartsIterator extends IntlIterator implements Iterator { public const KEY_SEQUENTIAL = 0; public const KEY_LEFT = 1; public const KEY_RIGHT = 2; /** * @return IntlBreakIterator */ #[Pure] #[TentativeType] public function getBreakIterator(): IntlBreakIterator {} /** * @since 8.1 */ #[TentativeType] public function getRuleStatus(): int {} } class IntlCodePointBreakIterator extends IntlBreakIterator implements Traversable { /** * (PHP 5 >=5.5.0)
    * Get last code point passed over after advancing or receding the iterator * @link https://secure.php.net/manual/en/intlcodepointbreakiterator.getlastcodepoint.php * @return int */ #[Pure] #[TentativeType] public function getLastCodePoint(): int {} } class UConverter { /* Constants */ public const REASON_UNASSIGNED = 0; public const REASON_ILLEGAL = 1; public const REASON_IRREGULAR = 2; public const REASON_RESET = 3; public const REASON_CLOSE = 4; public const REASON_CLONE = 5; public const UNSUPPORTED_CONVERTER = -1; public const SBCS = 0; public const DBCS = 1; public const MBCS = 2; public const LATIN_1 = 3; public const UTF8 = 4; public const UTF16_BigEndian = 5; public const UTF16_LittleEndian = 6; public const UTF32_BigEndian = 7; public const UTF32_LittleEndian = 8; public const EBCDIC_STATEFUL = 9; public const ISO_2022 = 10; public const LMBCS_1 = 11; public const LMBCS_2 = 12; public const LMBCS_3 = 13; public const LMBCS_4 = 14; public const LMBCS_5 = 15; public const LMBCS_6 = 16; public const LMBCS_8 = 17; public const LMBCS_11 = 18; public const LMBCS_16 = 19; public const LMBCS_17 = 20; public const LMBCS_18 = 21; public const LMBCS_19 = 22; public const LMBCS_LAST = 22; public const HZ = 23; public const SCSU = 24; public const ISCII = 25; public const US_ASCII = 26; public const UTF7 = 27; public const BOCU1 = 28; public const UTF16 = 29; public const UTF32 = 30; public const CESU8 = 31; public const IMAP_MAILBOX = 32; /* Methods */ /** * (PHP 5 >=5.5.0)
    * Create UConverter object * @link https://php.net/manual/en/uconverter.construct.php * @param string $destination_encoding * @param string $source_encoding */ #[Pure] public function __construct( #[LanguageAware(['8.0' => 'string|null'], default: '')] $destination_encoding = null, #[LanguageAware(['8.0' => 'string|null'], default: '')] $source_encoding = null ) {} /** * (PHP 5 >=5.5.0)
    * Convert string from one charset to anothe * @link https://php.net/manual/en/uconverter.convert.php * @param string $str * @param bool $reverse [optional] * @return string|false */ #[Pure] #[TentativeType] public function convert( #[LanguageAware(['8.0' => 'string'], default: '')] $str, #[LanguageAware(['8.0' => 'bool'], default: '')] $reverse = false ): string|false {} /** * (PHP 5 >=5.5.0)
    * Default "from" callback function * @link https://php.net/manual/en/uconverter.fromucallback.php * @param int $reason * @param string $source * @param string $codePoint * @param int &$error * @return array|string|int|null */ #[TentativeType] public function fromUCallback( #[LanguageAware(['8.0' => 'int'], default: '')] $reason, #[LanguageAware(['8.0' => 'array'], default: '')] $source, #[LanguageAware(['8.0' => 'int'], default: '')] $codePoint, &$error ): array|string|int|null {} /** * (PHP 5 >=5.5.0)
    * Get the aliases of the given name * @link https://php.net/manual/en/uconverter.getaliases.php * @param string $name * @return array|false|null */ #[TentativeType] public static function getAliases( #[ElementAvailable(from: '5.5', to: '5.6')] $name = '', #[ElementAvailable(from: '7.0')] #[LanguageAware(['8.0' => 'string'], default: '')] $name ): array|false|null {} /** * (PHP 5 >=5.5.0)
    * Get the available canonical converter names * @link https://php.net/manual/en/uconverter.getavailable.php * @return array */ #[TentativeType] public static function getAvailable(): array {} /** * (PHP 5 >=5.5.0)
    * Get the destination encoding * @link https://php.net/manual/en/uconverter.getdestinationencoding.php * @return string|false|null */ #[Pure] #[TentativeType] public function getDestinationEncoding(): string|false|null {} /** * (PHP 5 >=5.5.0)
    * Get the destination converter type * @link https://php.net/manual/en/uconverter.getdestinationtype.php * @return int|false|null */ #[Pure] #[TentativeType] public function getDestinationType(): int|false|null {} /** * (PHP 5 >=5.5.0)
    * Get last error code on the object * @link https://php.net/manual/en/uconverter.geterrorcode.php * @return int */ #[Pure] #[TentativeType] public function getErrorCode(): int {} /** * (PHP 5 >=5.5.0)
    * Get last error message on the object * @link https://php.net/manual/en/uconverter.geterrormessage.php * @return string|null */ #[Pure] #[TentativeType] public function getErrorMessage(): ?string {} /** * (PHP 5 >=5.5.0)
    * Get the source encoding * @link https://php.net/manual/en/uconverter.getsourceencoding.php * @return string|false|null */ #[Pure] #[TentativeType] public function getSourceEncoding(): string|false|null {} /** * (PHP 5 >=5.5.0)
    * Get the source convertor type * @link https://php.net/manual/en/uconverter.getsourcetype.php * @return int|false|null */ #[Pure] #[TentativeType] public function getSourceType(): int|false|null {} /** * (PHP 5 >=5.5.0)
    * Get standards associated to converter names * @link https://php.net/manual/en/uconverter.getstandards.php * @return array|null */ #[Pure] #[TentativeType] public static function getStandards(): ?array {} /** * (PHP 5 >=5.5.0)
    * Get substitution chars * @link https://php.net/manual/en/uconverter.getsubstchars.php * @return string|false|null */ #[Pure] #[TentativeType] public function getSubstChars(): string|false|null {} /** * (PHP 5 >=5.5.0)
    * Get string representation of the callback reason * @link https://php.net/manual/en/uconverter.reasontext.php * @param int $reason * @return string */ #[Pure] #[TentativeType] public static function reasonText( #[ElementAvailable(from: '5.3', to: '7.4')] $reason = 0, #[ElementAvailable(from: '8.0')] int $reason ): string {} /** * (PHP 5 >=5.5.0)
    * Set the destination encoding * @link https://php.net/manual/en/uconverter.setdestinationencoding.php * @param string $encoding * @return bool */ #[TentativeType] public function setDestinationEncoding(#[LanguageAware(['8.0' => 'string'], default: '')] $encoding): bool {} /** * (PHP 5 >=5.5.0)
    * Set the source encoding * @link https://php.net/manual/en/uconverter.setsourceencoding.php * @param string $encoding * @return bool */ #[TentativeType] public function setSourceEncoding(#[LanguageAware(['8.0' => 'string'], default: '')] $encoding): bool {} /** * (PHP 5 >=5.5.0)
    * Set the substitution chars * @link https://php.net/manual/en/uconverter.setsubstchars.php * @param string $chars * @return bool */ #[TentativeType] public function setSubstChars(#[LanguageAware(['8.0' => 'string'], default: '')] $chars): bool {} /** * (PHP 5 >=5.5.0)
    * Default "to" callback function * @link https://php.net/manual/en/uconverter.toucallback.php * @param int $reason * @param string $source * @param string $codeUnits * @param int &$error * @return array|string|int|null */ #[TentativeType] public function toUCallback( #[LanguageAware(['8.0' => 'int'], default: '')] $reason, #[LanguageAware(['8.0' => 'string'], default: '')] $source, #[LanguageAware(['8.0' => 'string'], default: '')] $codeUnits, &$error ): array|string|int|null {} /** * (PHP 5 >=5.5.0)
    * Convert string from one charset to another * @link https://php.net/manual/en/uconverter.transcode.php * @param string $str * @param string $toEncoding * @param string $fromEncoding * @param array|null $options * @return string|false */ #[TentativeType] public static function transcode( #[LanguageAware(['8.0' => 'string'], default: '')] $str, #[LanguageAware(['8.0' => 'string'], default: '')] $toEncoding, #[LanguageAware(['8.0' => 'string'], default: '')] $fromEncoding, #[LanguageAware(['8.0' => 'array|null'], default: '')] $options = null ): string|false {} } // End of intl v.1.1.0 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)
    * Takes a JSON encoded string and converts it into a PHP value. * @link https://www.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 as specified by RFC 7159. *

    * @param bool|null $associative

    * When TRUE, JSON objects will be returned as associative arrays; when FALSE, JSON objects will be returned as objects. * When NULL, JSON objects will be returned as associative arrays or objects depending on whether JSON_OBJECT_AS_ARRAY is set in the flags. *

    * @param int $depth [optional]

    * Maximum nesting depth of the structure being decoded. The value must be greater than 0, and less than or equal to 2147483647. *

    * @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, Available as of PHP 7.2.0. * {@see JSON_OBJECT_AS_ARRAY} Decodes JSON objects as PHP array. This option can be added automatically by calling json_decode() with the second parameter equal to true. * {@see JSON_THROW_ON_ERROR} 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(). JSON_PARTIAL_OUTPUT_ON_ERROR takes precedence over JSON_THROW_ON_ERROR. Available as of PHP 7.3.0.
    *

    * @return mixed Returns the value encoded in json as an appropriate PHP type. Unquoted values true, FALSE * and NULL 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 nesting limit. */ function json_decode(#[Language("JSON")] 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(true)] function json_last_error_msg(): string {} /** * @since 8.3 */ function json_validate(#[Language("JSON")] 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 FALSE on failure (not found). * @throws JsonPathException * @since 7.4 */ public function find(array $data, string $expression): array|false {} } /** * @since 7.4 */ class JsonPathException extends \RuntimeException {} * 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. 'LDAP\Connection'], default: 'resource')] $ldap, #[Available(from: '7.1', to: '7.1')] string $user = "", #[Available(from: '7.2', to: '7.2')] string $user = "", #[Available(from: '7.3')] string $user = "", #[Available(from: '7.1', to: '7.1')] string $old_password = "", #[Available(from: '7.2', to: '7.2')] string $old_password = "", #[Available(from: '7.3')] string $old_password = "", #[Available(from: '7.1', to: '7.1')] string $new_password = "", #[Available(from: '7.2', to: '7.2')] string $new_password = "", #[Available(from: '7.3')] string $new_password = "", #[Available(from: '7.3')] &$controls = null ): string|bool {} /** * Refresh extended operation helper * @link https://www.php.net/manual/en/function.ldap-exop-refresh.php * @param resource $ldap An LDAP link identifier, returned by ldap_connect(). * @param string $dn dn of the entry to refresh. * @param int $ttl $ttl Time in seconds (between 1 and 31557600) that the client requests that the entry exists in the directory before being automatically removed. * @return int|false From RFC: The responseTtl field is the time in seconds which the server chooses to have as the time-to-live field for that entry. It must not be any smaller than that which the client requested, and it may be larger. However, to allow servers to maintain a relatively accurate directory, and to prevent clients from abusing the dynamic extensions, servers are permitted to shorten a client-requested time-to-live value, down to a minimum of 86400 seconds (one day). FALSE will be returned on error. * @since 7.3 */ function ldap_exop_refresh(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $dn, int $ttl): int|false {} /** * WHOAMI extended operation helper * @link https://www.php.net/manual/en/function.ldap-exop-whoami.php * @param resource $ldap An LDAP link identifier, returned by ldap_connect(). * @return string|false The data returned by the server, or FALSE on error. * @since 7.2 */ function ldap_exop_whoami(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap): string|false {} /** * Performs an extended operation on the specified link with reqoid the OID of the operation and reqdata the data. * @link https://www.php.net/manual/en/function.ldap-exop.php * @param resource $ldap An LDAP link identifier, returned by ldap_connect(). * @param string $request_oid The extended operation request OID. You may use one of LDAP_EXOP_START_TLS, LDAP_EXOP_MODIFY_PASSWD, LDAP_EXOP_REFRESH, LDAP_EXOP_WHO_AM_I, LDAP_EXOP_TURN, or a string with the OID of the operation you want to send. * @param string|null $request_data [optional] The extended operation request data. May be NULL for some operations like LDAP_EXOP_WHO_AM_I, may also need to be BER encoded. * @param array|null $controls If provided, a password policy request control is send with the request and this is filled with an array of LDAP Controls returned with the request. * @param string &$response_data [optional] Will be filled with the extended operation response data if provided. If not provided you may use ldap_parse_exop on the result object later to get this data. * @param string &$response_oid [optional] Will be filled with the response OID if provided, usually equal to the request OID. * @return resource|bool When used with retdata, returns TRUE on success or FALSE on error. When used without retdata, returns a result identifier or FALSE on error. * @since 7.2 */ #[PhpVersionAware(['8.1' => 'LDAP\Result|bool'], default: 'resource|bool')] function ldap_exop(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $request_oid, ?string $request_data = null, #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null, &$response_data, &$response_oid) {} /** * Parse LDAP extended operation data from result object result * @link https://www.php.net/manual/en/function.ldap-parse-exop.php * @param resource $ldap An LDAP link identifier, returned by ldap_connect(). * @param resource $result An LDAP result resource, returned by ldap_exop(). * @param string &$response_data Will be filled by the response data. * @param string &$response_oid Will be filled by the response OID. * @return bool Returns TRUE on success or FALSE on failure. * @since 7.2 */ function ldap_parse_exop( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, #[PhpVersionAware(['8.1' => 'LDAP\Result'], default: 'resource')] $result, #[Available(from: '7.2', to: '7.4')] &$response_data = null, #[Available(from: '8.0')] &$response_data = null, #[Available(from: '7.2', to: '7.4')] &$response_oid = null, #[Available(from: '8.0')] &$response_oid = null ): bool {} /** * Translate 8859 characters to t61 characters * @link https://www.php.net/manual/en/function.ldap-8859-to-t61.php * @param string $value * @return string */ function ldap_8859_to_t61(string $value): string {} /** * Translate t61 characters to 8859 characters * @link https://www.php.net/manual/en/function.ldap-t61-to-8859.php * @param string $value * @return string */ function ldap_t61_to_8859(string $value): string {} /** * Connect to an LDAP server * @link https://php.net/manual/en/function.ldap-connect.php * @param string|null $uri [optional]

    * If you are using OpenLDAP 2.x.x you can specify a URL instead of the * hostname. To use LDAP with SSL, compile OpenLDAP 2.x.x with SSL * support, configure PHP with SSL, and set this parameter as * ldaps://hostname/. *

    * @param int $port [optional]

    * The port to connect to. Not used when using URLs. *

    * @return resource|false a positive LDAP link identifier on success, or FALSE on error. * When OpenLDAP 2.x.x is used, ldap_connect will always * return a resource as it does not actually connect but just * initializes the connecting parameters. The actual connect happens with * the next calls to ldap_* funcs, usually with * ldap_bind. *

    *

    * If no arguments are specified then the link identifier of the already * opened link will be returned. */ #[PhpVersionAware(['8.1' => 'LDAP\Connection|false'], default: 'resource|false')] function ldap_connect(?string $uri = null, int $port = 389) {} /** * Alias of ldap_unbind * @link https://php.net/manual/en/function.ldap-close.php * @param resource $ldap * @return bool */ function ldap_close(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap): bool {} /** * Bind to LDAP directory * @link https://php.net/manual/en/function.ldap-bind.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param string|null $dn [optional] * @param string|null $password [optional] * @return bool TRUE on success or FALSE on failure. */ function ldap_bind(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, ?string $dn = null, ?string $password = null): bool {} /** * Bind to LDAP directory * Does the same thing as ldap_bind() but returns the LDAP result resource to be parsed with ldap_parse_result(). * @link https://php.net/manual/en/function.ldap-bind.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param string|null $dn [optional] * @param string|null $password [optional] * @param array|null $controls Array of LDAP Controls to send with the request. * @return resource|false * @since 7.3 */ #[PhpVersionAware(['8.1' => 'LDAP\Result|false'], default: 'resource|false')] function ldap_bind_ext( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, ?string $dn = null, ?string $password = null, #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null ) {} /** * Bind to LDAP directory using SASL * @link https://php.net/manual/en/function.ldap-sasl-bind.php * @param resource $ldap * @param string $binddn [optional] * @param string $password [optional] * @param string $sasl_mech [optional] * @param string $sasl_realm [optional] * @param string $sasl_authc_id [optional] * @param string $sasl_authz_id [optional] * @param string $props [optional] * @return bool TRUE on success or FALSE on failure. */ function ldap_sasl_bind(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, $binddn = null, $password = null, $sasl_mech = null, $sasl_realm = null, $sasl_authc_id = null, $sasl_authz_id = null, $props = null): bool {} /** * Unbind from LDAP directory * @link https://php.net/manual/en/function.ldap-unbind.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @return bool TRUE on success or FALSE on failure. */ function ldap_unbind(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap): bool {} /** * Read an entry * @link https://php.net/manual/en/function.ldap-read.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param array|array|string $base

    * The base DN for the directory. *

    * @param array|string $filter

    * An empty filter is not allowed. If you want to retrieve absolutely all * information for this entry, use a filter of * objectClass=*. If you know which entry types are * used on the directory server, you might use an appropriate filter such * as objectClass=inetOrgPerson. *

    * @param array $attributes

    * An array of the required attributes, e.g. array("mail", "sn", "cn"). * Note that the "dn" is always returned irrespective of which attributes * types are requested. *

    *

    * Using this parameter is much more efficient than the default action * (which is to return all attributes and their associated values). * The use of this parameter should therefore be considered good * practice. *

    * @param int $attributes_only

    * Should be set to 1 if only attribute types are wanted. If set to 0 * both attributes types and attribute values are fetched which is the * default behaviour. *

    * @param int $sizelimit [optional]

    * Enables you to limit the count of entries fetched. Setting this to 0 * means no limit. *

    *

    * This parameter can NOT override server-side preset sizelimit. You can * set it lower though. *

    *

    * Some directory server hosts will be configured to return no more than * a preset number of entries. If this occurs, the server will indicate * that it has only returned a partial results set. This also occurs if * you use this parameter to limit the count of fetched entries. *

    * @param int $timelimit [optional]

    * Sets the number of seconds how long is spend on the search. Setting * this to 0 means no limit. *

    *

    * This parameter can NOT override server-side preset timelimit. You can * set it lower though. *

    * @param int $deref

    * Specifies how aliases should be handled during the search. It can be * one of the following: * LDAP_DEREF_NEVER - (default) aliases are never * dereferenced.

    * @param array|null $controls Array of LDAP Controls to send with the request. * @return resource|false a search result identifier or FALSE on error. */ #[PhpVersionAware(['8.1' => 'LDAP\Result|array|false'], default: 'resource|false')] function ldap_read( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, array|string $base, array|string $filter, array $attributes = [], int $attributes_only = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = 0, #[Available(from: '7.3')] #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null ) {} /** * Single-level search * @link https://php.net/manual/en/function.ldap-list.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param array|array|string $base

    * The base DN for the directory. *

    * @param array|string $filter * @param array $attributes

    * An array of the required attributes, e.g. array("mail", "sn", "cn"). * Note that the "dn" is always returned irrespective of which attributes * types are requested. *

    *

    * Using this parameter is much more efficient than the default action * (which is to return all attributes and their associated values). * The use of this parameter should therefore be considered good * practice. *

    * @param int $attributes_only

    * Should be set to 1 if only attribute types are wanted. If set to 0 * both attributes types and attribute values are fetched which is the * default behaviour. *

    * @param int $sizelimit [optional]

    * Enables you to limit the count of entries fetched. Setting this to 0 * means no limit. *

    *

    * This parameter can NOT override server-side preset sizelimit. You can * set it lower though. *

    *

    * Some directory server hosts will be configured to return no more than * a preset number of entries. If this occurs, the server will indicate * that it has only returned a partial results set. This also occurs if * you use this parameter to limit the count of fetched entries. *

    * @param int $timelimit [optional]

    * Sets the number of seconds how long is spend on the search. Setting * this to 0 means no limit. *

    *

    * This parameter can NOT override server-side preset timelimit. You can * set it lower though. *

    * @param int $deref

    * Specifies how aliases should be handled during the search. It can be * one of the following: * LDAP_DEREF_NEVER - (default) aliases are never * dereferenced.

    * @param array|null $controls Array of LDAP Controls to send with the request. * @return resource|false a search result identifier or FALSE on error. */ #[PhpVersionAware(['8.1' => 'LDAP\Result|array|false'], default: 'resource|false')] function ldap_list( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, array|string $base, array|string $filter, array $attributes = [], int $attributes_only = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = 0, #[Available(from: '7.3')] #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null ) {} /** * Search LDAP tree * @link https://php.net/manual/en/function.ldap-search.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param array|string $base

    * The base DN for the directory. *

    * @param array|string $filter

    * The search filter can be simple or advanced, using boolean operators in * the format described in the LDAP documentation (see the Netscape Directory SDK for full * information on filters). *

    * @param array $attributes

    * An array of the required attributes, e.g. array("mail", "sn", "cn"). * Note that the "dn" is always returned irrespective of which attributes * types are requested. *

    *

    * Using this parameter is much more efficient than the default action * (which is to return all attributes and their associated values). * The use of this parameter should therefore be considered good * practice. *

    * @param int $attributes_only

    * Should be set to 1 if only attribute types are wanted. If set to 0 * both attributes types and attribute values are fetched which is the * default behaviour. *

    * @param int $sizelimit [optional]

    * Enables you to limit the count of entries fetched. Setting this to 0 * means no limit. *

    *

    * This parameter can NOT override server-side preset sizelimit. You can * set it lower though. *

    *

    * Some directory server hosts will be configured to return no more than * a preset number of entries. If this occurs, the server will indicate * that it has only returned a partial results set. This also occurs if * you use this parameter to limit the count of fetched entries. *

    * @param int $timelimit [optional]

    * Sets the number of seconds how long is spend on the search. Setting * this to 0 means no limit. *

    *

    * This parameter can NOT override server-side preset timelimit. You can * set it lower though. *

    * @param int $deref

    * Specifies how aliases should be handled during the search. It can be * one of the following: * LDAP_DEREF_NEVER - (default) aliases are never * dereferenced.

    * @param array|null $controls Array of LDAP Controls to send with the request. * @return resource|false a search result identifier or FALSE on error. */ #[PhpVersionAware(['8.1' => 'LDAP\Result|array|false'], default: 'resource|false')] function ldap_search( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, array|string $base, array|string $filter, array $attributes = [], int $attributes_only = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = 0, #[Available(from: '7.3')] #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null ) {} /** * Free result memory * @link https://php.net/manual/en/function.ldap-free-result.php * @param resource|Result $result * @return bool TRUE on success or FALSE on failure. */ function ldap_free_result( #[Available(from: '5.3', to: '8.0')] $ldap, #[Available(from: '8.1')] Result $result ): bool {} /** * Count the number of entries in a search * @link https://php.net/manual/en/function.ldap-count-entries.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param resource $result

    * The internal LDAP result. *

    * @return int|false number of entries in the result or FALSE on error. */ #[PhpVersionAware(["8.0" => "int"], default: "int|false")] function ldap_count_entries( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, #[PhpVersionAware(['8.1' => 'LDAP\Result'], default: 'resource')] $result ) {} /** * Return first result id * @link https://php.net/manual/en/function.ldap-first-entry.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param resource $result * @return resource|false the result entry identifier for the first entry on success and * FALSE on error. */ #[PhpVersionAware(['8.1' => 'LDAP\ResultEntry|false'], default: 'resource|false')] function ldap_first_entry( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, #[PhpVersionAware(['8.1' => 'LDAP\Result'], default: 'resource')] $result ) {} /** * Get next result entry * @link https://php.net/manual/en/function.ldap-next-entry.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param resource $entry * @return resource|false entry identifier for the next entry in the result whose entries * are being read starting with ldap_first_entry. If * there are no more entries in the result then it returns FALSE. */ #[PhpVersionAware(['8.1' => 'LDAP\ResultEntry|false'], default: 'resource|false')] function ldap_next_entry( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, #[PhpVersionAware(['8.1' => 'LDAP\ResultEntry'], default: 'resource')] $entry ) {} /** * Get all result entries * @link https://php.net/manual/en/function.ldap-get-entries.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param resource $result * @return array|false a complete result information in a multi-dimensional array on * success and FALSE on error. *

    *

    * The structure of the array is as follows. * The attribute index is converted to lowercase. (Attributes are * case-insensitive for directory servers, but not when used as * array indices.) *

     * return_value["count"] = number of entries in the result
     * return_value[0] : refers to the details of first entry
     * return_value[i]["dn"] = DN of the ith entry in the result
     * return_value[i]["count"] = number of attributes in ith entry
     * return_value[i][j] = NAME of the jth attribute in the ith entry in the result
     * return_value[i]["attribute"]["count"] = number of values for
     * attribute in ith entry
     * return_value[i]["attribute"][j] = jth value of attribute in ith entry
     * 
    */ function ldap_get_entries( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, #[PhpVersionAware(['8.1' => 'LDAP\Result'], default: 'resource')] $result ): array|false {} /** * Return first attribute * @link https://php.net/manual/en/function.ldap-first-attribute.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param resource $entry * @return string|false the first attribute in the entry on success and FALSE on * error. */ function ldap_first_attribute( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, #[PhpVersionAware(['8.1' => 'LDAP\ResultEntry'], default: 'resource')] $entry ): string|false {} /** * Get the next attribute in result * @link https://php.net/manual/en/function.ldap-next-attribute.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param resource $entry * @return string|false the next attribute in an entry on success and FALSE on * error. */ function ldap_next_attribute( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, #[PhpVersionAware(['8.1' => 'LDAP\ResultEntry'], default: 'resource')] $entry ): string|false {} /** * Get attributes from a search result entry * @link https://php.net/manual/en/function.ldap-get-attributes.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param resource $entry * @return array a complete entry information in a multi-dimensional array * on success and FALSE on error. */ function ldap_get_attributes( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, #[PhpVersionAware(['8.1' => 'LDAP\ResultEntry'], default: 'resource')] $entry ): array {} /** * Get all values from a result entry * @link https://php.net/manual/en/function.ldap-get-values.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param resource $entry * @param string $attribute * @return array|false an array of values for the attribute on success and FALSE on * error. The number of values can be found by indexing "count" in the * resultant array. Individual values are accessed by integer index in the * array. The first index is 0. *

    *

    * LDAP allows more than one entry for an attribute, so it can, for example, * store a number of email addresses for one person's directory entry all * labeled with the attribute "mail" * return_value["count"] = number of values for attribute * return_value[0] = first value of attribute * return_value[i] = ith value of attribute */ function ldap_get_values( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, #[PhpVersionAware(['8.1' => 'LDAP\ResultEntry'], default: 'resource')] $entry, string $attribute ): array|false {} /** * Get all binary values from a result entry * @link https://php.net/manual/en/function.ldap-get-values-len.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param resource $entry * @param string $attribute * @return array|false an array of values for the attribute on success and FALSE on * error. Individual values are accessed by integer index in the array. The * first index is 0. The number of values can be found by indexing "count" * in the resultant array. */ function ldap_get_values_len( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, #[PhpVersionAware(['8.1' => 'LDAP\ResultEntry'], default: 'resource')] $entry, string $attribute ): array|false {} /** * Get the DN of a result entry * @link https://php.net/manual/en/function.ldap-get-dn.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param resource $entry * @return string|false the DN of the result entry and FALSE on error. */ function ldap_get_dn( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, #[PhpVersionAware(['8.1' => 'LDAP\ResultEntry'], default: 'resource')] $entry ): string|false {} /** * Splits DN into its component parts * @link https://php.net/manual/en/function.ldap-explode-dn.php * @param string $dn

    * The distinguished name of an LDAP entity. *

    * @param int $with_attrib

    * Used to request if the RDNs are returned with only values or their * attributes as well. To get RDNs with the attributes (i.e. in * attribute=value format) set with_attrib to 0 * and to get only values set it to 1. *

    * @return array|false an array of all DN components. * The first element in this array has count key and * represents the number of returned values, next elements are numerically * indexed DN components. */ #[ArrayShape(["count" => "int"])] function ldap_explode_dn(string $dn, int $with_attrib): array|false {} /** * Convert DN to User Friendly Naming format * @link https://php.net/manual/en/function.ldap-dn2ufn.php * @param string $dn

    * The distinguished name of an LDAP entity. *

    * @return string|false the user friendly name. */ function ldap_dn2ufn(string $dn): string|false {} /** * Add entries to LDAP directory * @link https://php.net/manual/en/function.ldap-add.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param string $dn

    * The distinguished name of an LDAP entity. *

    * @param array $entry

    * An array that specifies the information about the entry. The values in * the entries are indexed by individual attributes. * In case of multiple values for an attribute, they are indexed using * integers starting with 0. * * $entree["attribut1"] = "value"; * $entree["attribut2"][0] = "value1"; * $entree["attribut2"][1] = "value2"; * *

    * @param array|null $controls Array of LDAP Controls to send with the request. * @return bool TRUE on success or FALSE on failure. */ function ldap_add( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $dn, array $entry, #[Available(from: '7.3')] #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null ): bool {} /** * Add entries to LDAP directory * Does the same thing as ldap_add() but returns the LDAP result resource to be parsed with ldap_parse_result(). * @link https://www.php.net/manual/en/function.ldap-add-ext.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param string $dn

    * The distinguished name of an LDAP entity. *

    * @param array $entry

    * An array that specifies the information about the entry. The values in * the entries are indexed by individual attributes. * In case of multiple values for an attribute, they are indexed using * integers starting with 0. * * $entree["attribut1"] = "value"; * $entree["attribut2"][0] = "value1"; * $entree["attribut2"][1] = "value2"; * *

    * @param array|null $controls Array of LDAP Controls to send with the request. * @return resource|false * @since 7.3 */ #[PhpVersionAware(['8.1' => 'LDAP\Result|false'], default: 'resource|false')] function ldap_add_ext( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $dn, array $entry, #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null ) {} /** * Delete an entry from a directory * @link https://php.net/manual/en/function.ldap-delete.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param string $dn

    * The distinguished name of an LDAP entity. *

    * @param array|null $controls Array of LDAP Controls to send with the request. * @return bool TRUE on success or FALSE on failure. */ function ldap_delete( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $dn, #[Available(from: '7.3')] #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null ): bool {} /** * Delete an entry from a directory * Does the same thing as ldap_delete() but returns the LDAP result resource to be parsed with ldap_parse_result(). * @link https://php.net/manual/en/function.ldap-delete-ext.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param string $dn

    * The distinguished name of an LDAP entity. *

    * @param array|null $controls Array of LDAP Controls to send with the request. * @return resource|false * @since 7.3 */ #[PhpVersionAware(['8.1' => 'LDAP\Result|false'], default: 'resource|false')] function ldap_delete_ext( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $dn, #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null ) {} /** * This function is an alias of: ldap_mod_replace(). * Replace attribute values with new ones * @link https://www.php.net/manual/en/function.ldap-modify.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param string $dn

    * The distinguished name of an LDAP entity. *

    * @param array $entry * @param array|null $controls Array of LDAP Controls to send with the request. * @return bool TRUE on success or FALSE on failure. */ function ldap_modify( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $dn, array $entry, #[Available(from: '7.3')] #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null ): bool {} /** * Add attribute values to current attributes * @link https://php.net/manual/en/function.ldap-mod-add.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param string $dn

    * The distinguished name of an LDAP entity. *

    * @param array $entry * @param array|null $controls Array of LDAP Controls to send with the request. * @return bool TRUE on success or FALSE on failure. */ function ldap_mod_add( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $dn, array $entry, #[Available(from: '7.3')] #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null ): bool {} /** * Add attribute values to current attributes * Does the same thing as ldap_mod_add() but returns the LDAP result resource to be parsed with ldap_parse_result(). * @link https://php.net/manual/en/function.ldap-mod-add-ext.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param string $dn

    * The distinguished name of an LDAP entity. *

    * @param array $entry * @param array|null $controls Array of LDAP Controls to send with the request. * @return resource|false * @since 7.3 */ #[PhpVersionAware(['8.1' => 'LDAP\Result|false'], default: 'resource|false')] function ldap_mod_add_ext( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $dn, array $entry, #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null ) {} /** * Replace attribute values with new ones * @link https://php.net/manual/en/function.ldap-mod-replace.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param string $dn

    * The distinguished name of an LDAP entity. *

    * @param array $entry * @param array|null $controls Array of LDAP Controls to send with the request. * @return bool TRUE on success or FALSE on failure. */ function ldap_mod_replace( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $dn, array $entry, #[Available(from: '7.3')] #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null ): bool {} /** * Replace attribute values with new ones * Does the same thing as ldap_mod_replace() but returns the LDAP result resource to be parsed with ldap_parse_result(). * @link https://php.net/manual/en/function.ldap-mod-replace-ext.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param string $dn

    * The distinguished name of an LDAP entity. *

    * @param array $entry * @param array|null $controls Array of LDAP Controls to send with the request. * @return resource|false * @since 7.3 */ #[PhpVersionAware(['8.1' => 'LDAP\Result|false'], default: 'resource|false')] function ldap_mod_replace_ext(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $dn, array $entry, #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null) {} /** * Delete attribute values from current attributes * @link https://php.net/manual/en/function.ldap-mod-del.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param string $dn

    * The distinguished name of an LDAP entity. *

    * @param array $entry * @param array|null $controls Array of LDAP Controls to send with the request. * @return bool TRUE on success or FALSE on failure. */ function ldap_mod_del( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $dn, array $entry, #[Available(from: '7.3')] #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null ): bool {} /** * Delete attribute values from current attributes * Does the same thing as ldap_mod_del() but returns the LDAP result resource to be parsed with ldap_parse_result(). * @link https://php.net/manual/en/function.ldap-mod-del-ext.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param string $dn

    * The distinguished name of an LDAP entity. *

    * @param array $entry * @param array|null $controls Array of LDAP Controls to send with the request. * @return resource|false * @since 7.3 */ #[PhpVersionAware(['8.1' => 'LDAP\Result|false'], default: 'resource|false')] function ldap_mod_del_ext(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $dn, array $entry, #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null) {} /** * Return the LDAP error number of the last LDAP command * @link https://php.net/manual/en/function.ldap-errno.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @return int Return the LDAP error number of the last LDAP command for this * link. */ function ldap_errno(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap): int {} /** * Convert LDAP error number into string error message * @link https://php.net/manual/en/function.ldap-err2str.php * @param int $errno

    * The error number. *

    * @return string the error message, as a string. */ function ldap_err2str(int $errno): string {} /** * Return the LDAP error message of the last LDAP command * @link https://php.net/manual/en/function.ldap-error.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @return string string error message. */ function ldap_error(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap): string {} /** * Compare value of attribute found in entry specified with DN * @link https://php.net/manual/en/function.ldap-compare.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param string $dn

    * The distinguished name of an LDAP entity. *

    * @param string $attribute

    * The attribute name. *

    * @param string $value

    * The compared value. *

    * @param array|null $controls Array of LDAP Controls to send with the request. * @return int|bool TRUE if value matches otherwise returns * FALSE. Returns -1 on error. */ function ldap_compare( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $dn, string $attribute, string $value, #[Available(from: '7.3')] #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null ): int|bool {} /** * Sort LDAP result entries * @link https://php.net/manual/en/function.ldap-sort.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param resource $result

    * An search result identifier, returned by * ldap_search. *

    * @param string $sortfilter

    * The attribute to use as a key in the sort. *

    * @removed 8.0 * @return bool */ #[Deprecated(since: "7.0")] function ldap_sort(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, $result, string $sortfilter): bool {} /** * Modify the name of an entry * @link https://php.net/manual/en/function.ldap-rename.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param string $dn

    * The distinguished name of an LDAP entity. *

    * @param string $new_rdn

    * The new RDN. *

    * @param string $new_parent

    * The new parent/superior entry. *

    * @param bool $delete_old_rdn

    * If TRUE the old RDN value(s) is removed, else the old RDN value(s) * is retained as non-distinguished values of the entry. *

    * @param array|null $controls Array of LDAP Controls to send with the request. * @return bool TRUE on success or FALSE on failure. */ function ldap_rename( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $dn, string $new_rdn, string $new_parent, bool $delete_old_rdn, #[Available(from: '7.3')] #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null ): bool {} /** * Modify the name of an entry * Does the same thing as ldap_rename() but returns the LDAP result resource to be parsed with ldap_parse_result(). * @link https://php.net/manual/en/function.ldap-rename-ext.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param string $dn

    * The distinguished name of an LDAP entity. *

    * @param string $new_rdn

    * The new RDN. *

    * @param string $new_parent

    * The new parent/superior entry. *

    * @param bool $delete_old_rdn

    * If TRUE the old RDN value(s) is removed, else the old RDN value(s) * is retained as non-distinguished values of the entry. *

    * @param array|null $controls Array of LDAP Controls to send with the request. * @return resource|false * @since 7.3 */ #[PhpVersionAware(['8.1' => 'LDAP\Result|false'], default: 'resource|false')] function ldap_rename_ext(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $dn, string $new_rdn, string $new_parent, bool $delete_old_rdn, #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null) {} /** * Get the current value for given option * @link https://php.net/manual/en/function.ldap-get-option.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param int $option

    * The parameter option can be one of: * * Option * Type * * * LDAP_OPT_DEREF * integer * * * LDAP_OPT_SIZELIMIT * integer * * * LDAP_OPT_TIMELIMIT * integer * * * LDAP_OPT_NETWORK_TIMEOUT * integer * * * LDAP_OPT_PROTOCOL_VERSION * integer * * * LDAP_OPT_ERROR_NUMBER * integer * * * LDAP_OPT_REFERRALS * bool * * * LDAP_OPT_RESTART * bool * * * LDAP_OPT_HOST_NAME * string * * * LDAP_OPT_ERROR_STRING * string * * * LDAP_OPT_MATCHED_DN * string * * * LDAP_OPT_SERVER_CONTROLS * array * * * LDAP_OPT_CLIENT_CONTROLS * array * *

    * @param mixed &$value

    * This will be set to the option value. *

    * @return bool TRUE on success or FALSE on failure. */ function ldap_get_option( #[PhpVersionAware(['8.1' => 'LDAP\Connection', '8.5' => 'LDAP\Connection|null'], default: 'resource')] $ldap, int $option, #[Available(from: '5.3', to: '7.4')] &$value = null, #[Available(from: '8.0')] &$value = null ): bool {} /** * Set the value of the given option * @link https://php.net/manual/en/function.ldap-set-option.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param int $option

    * The parameter option can be one of: * * Option * Type * Available since * * * LDAP_OPT_DEREF * integer * * * * LDAP_OPT_SIZELIMIT * integer * * * * LDAP_OPT_TIMELIMIT * integer * * * * LDAP_OPT_NETWORK_TIMEOUT * integer * PHP 5.3.0 * * * LDAP_OPT_PROTOCOL_VERSION * integer * * * * LDAP_OPT_ERROR_NUMBER * integer * * * * LDAP_OPT_REFERRALS * bool * * * * LDAP_OPT_RESTART * bool * * * * LDAP_OPT_HOST_NAME * string * * * * LDAP_OPT_ERROR_STRING * string * * * * LDAP_OPT_MATCHED_DN * string * * * * LDAP_OPT_SERVER_CONTROLS * array * * * * LDAP_OPT_CLIENT_CONTROLS * array * * *

    *

    * LDAP_OPT_SERVER_CONTROLS and * LDAP_OPT_CLIENT_CONTROLS require a list of * controls, this means that the value must be an array of controls. A * control consists of an oid identifying the control, * an optional value, and an optional flag for * criticality. In PHP a control is given by an * array containing an element with the key oid * and string value, and two optional elements. The optional * elements are key value with string value * and key iscritical with boolean value. * iscritical defaults to FALSE * if not supplied. See draft-ietf-ldapext-ldap-c-api-xx.txt * for details. See also the second example below. *

    * @param mixed $value

    * The new value for the specified option. *

    * @return bool TRUE on success or FALSE on failure. */ function ldap_set_option( #[PhpVersionAware(['8.1' => 'LDAP\Connection|null'], default: 'resource')] $ldap, int $option, $value ): bool {} /** * Return first reference * @link https://php.net/manual/en/function.ldap-first-reference.php * @param resource $ldap * @param resource $result * @return resource */ #[PhpVersionAware(['8.1' => 'LDAP\ResultEntry|false'], default: 'resource')] function ldap_first_reference( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, #[PhpVersionAware(['8.1' => 'LDAP\Result'], default: 'resource')] $result ) {} /** * Get next reference * @link https://php.net/manual/en/function.ldap-next-reference.php * @param resource $ldap * @param resource $entry * @return resource */ #[PhpVersionAware(['8.1' => 'LDAP\ResultEntry|false'], default: 'resource')] function ldap_next_reference( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, #[PhpVersionAware(['8.1' => 'LDAP\ResultEntry'], default: 'resource')] $entry ) {} /** * Extract information from reference entry * @link https://php.net/manual/en/function.ldap-parse-reference.php * @param resource $ldap * @param resource $entry * @param array &$referrals * @return bool */ function ldap_parse_reference( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, #[PhpVersionAware(['8.1' => 'LDAP\ResultEntry'], default: 'resource')] $entry, &$referrals ): bool {} /** * Extract information from result * @link https://php.net/manual/en/function.ldap-parse-result.php * @param resource $ldap * @param resource $result * @param int &$error_code * @param string &$matched_dn [optional] * @param string &$error_message [optional] * @param array &$referrals [optional] * @param array &$controls An array of LDAP Controls which have been sent with the response. * @return bool */ function ldap_parse_result( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, #[PhpVersionAware(['8.1' => 'LDAP\Result'], default: 'resource')] $result, &$error_code, &$matched_dn = null, &$error_message = null, &$referrals = null, #[Available(from: '7.3')] &$controls = null ): bool {} /** * Start TLS * @link https://php.net/manual/en/function.ldap-start-tls.php * @param resource $ldap * @return bool */ function ldap_start_tls(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap): bool {} /** * Set a callback function to do re-binds on referral chasing * @link https://php.net/manual/en/function.ldap-set-rebind-proc.php * @param resource $ldap * @param callable|null $callback * @return bool */ function ldap_set_rebind_proc(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, ?callable $callback): bool {} /** * Send LDAP pagination control * @link https://php.net/manual/en/function.ldap-control-paged-result.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param int $pagesize

    * The number of entries by page. *

    * @param bool $iscritical [optional]

    * Indicates whether the pagination is critical of not. * If true and if the server doesn't support pagination, the search * will return no result. *

    * @param string $cookie [optional]

    * An opaque structure sent by the server * (ldap_control_paged_result_response). *

    * @return bool TRUE on success or FALSE on failure. * @since 5.4 * @removed 8.0 */ #[Deprecated(since: "7.4")] function ldap_control_paged_result(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, int $pagesize, $iscritical = false, $cookie = ""): bool {} /** * Retrieve the LDAP pagination cookie * @link https://php.net/manual/en/function.ldap-control-paged-result-response.php * @param resource $ldap

    * An LDAP link identifier, returned by ldap_connect. *

    * @param resource $result * @param string &$cookie [optional]

    * An opaque structure sent by the server. *

    * @param int &$estimated [optional]

    * The estimated number of entries to retrieve. *

    * @return bool TRUE on success or FALSE on failure. * @since 5.4 * @removed 8.0 */ #[Deprecated(since: "7.4")] function ldap_control_paged_result_response(#[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, $result, &$cookie = null, &$estimated = null): bool {} /** * Escape a string for use in an LDAP filter or DN * @param string $value The value to escape. * @param string $ignore [optional] Characters to ignore when escaping. * @param int $flags [optional] The context the escaped string will be used in: LDAP_ESCAPE_FILTER for filters to be used with ldap_search(), or LDAP_ESCAPE_DN for DNs. If neither flag is passed, all chars are escaped. * @return string * @since 5.6 */ function ldap_escape(string $value, string $ignore = "", int $flags = 0): string {} /** * (PHP 5.4 >= 5.4.26, PHP 5.5 >= 5.5.10, PHP 5.6 >= 5.6.0) * Batch and execute modifications on an LDAP entry * @link https://php.net/manual/en/function.ldap-modify-batch.php * @param $ldap

    * An LDAP link identifier, returned by * {@see ldap_connect()}. *

    * @param string $dn

    The distinguished name of an LDAP entity.

    * @param array $modifications_info

    An array that specifies the modifications to make. Each entry in this * array is an associative array with two or three keys: * attrib maps to the name of the attribute to modify, * modtype maps to the type of modification to perform, * and (depending on the type of modification) values * maps to an array of attribute values relevant to the modification. *

    *

    * Possible values for modtype include: *

    *
    * *
    * LDAP_MODIFY_BATCH_ADD
    *
    *

    * Each value specified through values is added (as * an additional value) to the attribute named by * attrib. *

    *
    * *
    * LDAP_MODIFY_BATCH_REMOVE
    *
    *

    * Each value specified through values is removed * from the attribute named by attrib. Any value of * the attribute not contained in the values array * will remain untouched. *

    *
    * *
    * LDAP_MODIFY_BATCH_REMOVE_ALL
    *
    *

    * All values are removed from the attribute named by * attrib. A values entry must * not be provided. *

    *
    * *
    * LDAP_MODIFY_BATCH_REPLACE
    *
    *

    * All current values of the attribute named by * attrib are replaced with the values specified * through values. *

    *
    * *
    *

    * Note that any value for attrib must be a string, any * value for values must be an array of strings, and * any value for modtype must be one of the * LDAP_MODIFY_BATCH_* constants listed above. *

    * @param array|null $controls Array of LDAP Controls to send with the request. * @return bool TRUE on success or FALSE on failure. * @since 5.4 */ function ldap_modify_batch( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, string $dn, array $modifications_info, #[Available(from: '7.3')] #[PhpVersionAware(["8.0" => "null|array"], default: "array")] $controls = null ): bool {} /** * @param resource $ldap * @param resource $result * @return int returns the number of reference messages in a search result. * @since 8.0 */ function ldap_count_references( #[PhpVersionAware(['8.1' => 'LDAP\Connection'], default: 'resource')] $ldap, #[PhpVersionAware(['8.1' => 'LDAP\Result'], default: 'resource')] $result ): int {} /** * @since 8.3 */ function ldap_exop_sync(LDAP\Connection $ldap, string $request_oid, ?string $request_data = null, ?array $controls = null, &$response_data = null, &$response_oid = null): Result|bool {} define('LDAP_ESCAPE_FILTER', 1); define('LDAP_ESCAPE_DN', 2); define('LDAP_DEREF_NEVER', 0); define('LDAP_DEREF_SEARCHING', 1); define('LDAP_DEREF_FINDING', 2); define('LDAP_DEREF_ALWAYS', 3); define('LDAP_MODIFY_BATCH_REMOVE', 2); define('LDAP_MODIFY_BATCH_ADD', 1); define('LDAP_MODIFY_BATCH_REMOVE_ALL', 18); define('LDAP_MODIFY_BATCH_REPLACE', 3); define('LDAP_OPT_X_TLS_REQUIRE_CERT', 24582); define('LDAP_OPT_X_TLS_NEVER', 0); define('LDAP_OPT_X_TLS_HARD', 1); define('LDAP_OPT_X_TLS_DEMAND', 2); define('LDAP_OPT_X_TLS_ALLOW', 3); define('LDAP_OPT_X_TLS_TRY', 4); define('LDAP_OPT_X_TLS_CERTFILE', 24580); define('LDAP_OPT_X_TLS_CIPHER_SUITE', 24584); define('LDAP_OPT_X_TLS_KEYFILE', 24581); define('LDAP_OPT_X_TLS_DHFILE', 24590); define('LDAP_OPT_X_TLS_CRLFILE', 24592); define('LDAP_OPT_X_TLS_RANDOM_FILE', 24585); define('LDAP_OPT_X_TLS_CRLCHECK', 24587); define('LDAP_OPT_X_TLS_CRL_NONE', 0); define('LDAP_OPT_X_TLS_CRL_PEER', 1); define('LDAP_OPT_X_TLS_CRL_ALL', 2); define('LDAP_OPT_X_TLS_PROTOCOL_MIN', 24583); define('LDAP_OPT_X_TLS_PROTOCOL_SSL2', 512); define('LDAP_OPT_X_TLS_PROTOCOL_SSL3', 768); define('LDAP_OPT_X_TLS_PROTOCOL_TLS1_0', 769); define('LDAP_OPT_X_TLS_PROTOCOL_TLS1_1', 770); define('LDAP_OPT_X_TLS_PROTOCOL_TLS1_2', 771); define('LDAP_OPT_X_TLS_PACKAGE', 24593); define('LDAP_OPT_X_KEEPALIVE_IDLE', 25344); define('LDAP_OPT_X_KEEPALIVE_PROBES', 25345); define('LDAP_OPT_X_KEEPALIVE_INTERVAL', 25346); define('LDAP_OPT_X_SASL_USERNAME', 24844); define('LDAP_OPT_X_SASL_NOCANON', 24843); /** * Specifies alternative rules for following aliases at the server. * @link https://php.net/manual/en/ldap.constants.php */ define('LDAP_OPT_DEREF', 2); /** *

    * Specifies the maximum number of entries that can be * returned on a search operation. *

    * The actual size limit for operations is also bounded * by the server's configured maximum number of return entries. * The lesser of these two settings is the actual size limit. * @link https://php.net/manual/en/ldap.constants.php */ define('LDAP_OPT_SIZELIMIT', 3); /** * Specifies the number of seconds to wait for search results. * The actual time limit for operations is also bounded * by the server's configured maximum time. * The lesser of these two settings is the actual time limit. * @link https://php.net/manual/en/ldap.constants.php */ define('LDAP_OPT_TIMELIMIT', 4); /** * Option for ldap_set_option to allow setting network timeout. * (Available as of PHP 5.3.0) * @link https://php.net/manual/en/ldap.constants.php */ define('LDAP_OPT_NETWORK_TIMEOUT', 20485); /** * Specifies the LDAP protocol to be used (V2 or V3). * @link https://php.net/manual/en/ldap.constants.php */ define('LDAP_OPT_PROTOCOL_VERSION', 17); define('LDAP_OPT_ERROR_NUMBER', 49); /** * Specifies whether to automatically follow referrals returned * by the LDAP server. * @link https://php.net/manual/en/ldap.constants.php */ define('LDAP_OPT_REFERRALS', 8); define('LDAP_OPT_RESTART', 9); define('LDAP_OPT_HOST_NAME', 48); define('LDAP_OPT_ERROR_STRING', 50); define('LDAP_OPT_MATCHED_DN', 51); /** * Specifies a default list of server controls to be sent with each request. * @link https://php.net/manual/en/ldap.constants.php */ define('LDAP_OPT_SERVER_CONTROLS', 18); /** * Specifies a default list of client controls to be processed with each request. * @link https://php.net/manual/en/ldap.constants.php */ define('LDAP_OPT_CLIENT_CONTROLS', 19); /** * Specifies a bitwise level for debug traces. * @link https://php.net/manual/en/ldap.constants.php */ define('LDAP_OPT_DEBUG_LEVEL', 20481); define('LDAP_OPT_X_SASL_MECH', 24832); define('LDAP_OPT_X_SASL_REALM', 24833); define('LDAP_OPT_X_SASL_AUTHCID', 24834); define('LDAP_OPT_X_SASL_AUTHZID', 24835); /** * Specifies the path of the directory containing CA certificates. * @link https://php.net/manual/en/ldap.constants.php * @since 7.1 */ define('LDAP_OPT_X_TLS_CACERTDIR', 24579); /** * Specifies the full-path of the CA certificate file. * @link https://php.net/manual/en/ldap.constants.php * @since 7.1 */ define('LDAP_OPT_X_TLS_CACERTFILE', 24578); define('LDAP_MODIFY_BATCH_ATTRIB', 'attrib'); define('LDAP_MODIFY_BATCH_MODTYPE', 'modtype'); define('LDAP_MODIFY_BATCH_VALUES', 'values'); define('LDAP_OPT_TIMEOUT', 20482); define('LDAP_OPT_DIAGNOSTIC_MESSAGE', 50); /** * Control Constant - Manage DSA IT (» RFC 3296) * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_MANAGEDSAIT", "2.16.840.1.113730.3.4.2"); /** * Control Constant - Proxied Authorization (» RFC 4370) * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_PROXY_AUTHZ", "2.16.840.1.113730.3.4.18"); /** * Control Constant - Subentries (» RFC 3672) * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_SUBENTRIES", "1.3.6.1.4.1.4203.1.10.1"); /** * Control Constant - Filter returned values (» RFC 3876) * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_VALUESRETURNFILTER", "1.2.826.0.1.3344810.2.3"); /** * Control Constant - Assertion (» RFC 4528) * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_ASSERT", "1.3.6.1.1.12"); /** * Control Constant - Pre read (» RFC 4527) * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_PRE_READ", "1.3.6.1.1.13.1"); /** * Control Constant - Post read (» RFC 4527) * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_POST_READ", "1.3.6.1.1.13.2"); /** * Control Constant - Sort request (» RFC 2891) * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_SORTREQUEST", "1.2.840.113556.1.4.473"); /** * Control Constant - Sort response (» RFC 2891) * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_SORTRESPONSE", "1.2.840.113556.1.4.474"); /** * Control Constant - Paged results (» RFC 2696) * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_PAGEDRESULTS", "1.2.840.113556.1.4.319"); /** * Control Constant - Content Synchronization Operation (» RFC 4533) * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_SYNC", "1.3.6.1.4.1.4203.1.9.1.1"); /** * Control Constant - Content Synchronization Operation State (» RFC 4533) * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_SYNC_STATE", "1.3.6.1.4.1.4203.1.9.1.2"); /** * Control Constant - Content Synchronization Operation Done (» RFC 4533) * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_SYNC_DONE", "1.3.6.1.4.1.4203.1.9.1.3"); /** * Control Constant - Don't Use Copy (» RFC 6171) * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_DONTUSECOPY", "1.3.6.1.1.22"); /** * Control Constant - Password Policy Request * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_PASSWORDPOLICYREQUEST", "1.3.6.1.4.1.42.2.27.8.5.1"); /** * Control Constant - Password Policy Response * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_PASSWORDPOLICYRESPONSE", "1.3.6.1.4.1.42.2.27.8.5.1"); /** * Control Constant - Active Directory Incremental Values * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_X_INCREMENTAL_VALUES", "1.2.840.113556.1.4.802"); /** * Control Constant - Active Directory Domain Scope * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_X_DOMAIN_SCOPE", "1.2.840.113556.1.4.1339"); /** * Control Constant - Active Directory Permissive Modify * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_X_PERMISSIVE_MODIFY", "1.2.840.113556.1.4.1413"); /** * Control Constant - Active Directory Search Options * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_X_SEARCH_OPTIONS", "1.2.840.113556.1.4.1340"); /** * Control Constant - Active Directory Tree Delete * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_X_TREE_DELETE", "1.2.840.113556.1.4.805"); /** * Control Constant - Active Directory Extended DN * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_X_EXTENDED_DN", "1.2.840.113556.1.4.529"); /** * Control Constant - Virtual List View Request * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_VLVREQUEST", "2.16.840.1.113730.3.4.9"); /** * Control Constant - Virtual List View Response * @link https://php.net/manual/en/ldap.constants.php * @since 7.2 */ define("LDAP_CONTROL_VLVRESPONSE", "2.16.840.1.113730.3.4.10"); /** * Extended Operation constant - Modify password */ define("LDAP_EXOP_MODIFY_PASSWD", "1.3.6.1.4.1.4203.1.11.1"); /** * Extended Operation Constant - Refresh */ define("LDAP_EXOP_REFRESH", "1.3.6.1.4.1.1466.101.119.1"); /** * Extended Operation constant - Start TLS */ define("LDAP_EXOP_START_TLS", "1.3.6.1.4.1.1466.20037"); /** * Extended Operation Constant - Turn */ define("LDAP_EXOP_TURN", "1.3.6.1.1.19"); /** * Extended Operation Constant - WHOAMI */ define("LDAP_EXOP_WHO_AM_I", "1.3.6.1.4.1.4203.1.11.3"); /** * @since 7.3 */ define('LDAP_CONTROL_AUTHZID_REQUEST', '2.16.840.1.113730.3.4.16'); /** * @since 7.3 */ define('LDAP_CONTROL_AUTHZID_RESPONSE', '2.16.840.1.113730.3.4.15'); /** * @since 8.4 */ define('LDAP_OPT_X_TLS_PROTOCOL_TLS1_3', 772); /** * @since 8.4 */ define('LDAP_OPT_X_TLS_PROTOCOL_MAX', 24603); // End of ldap v. 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 {} 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 dest host control channel Note the less-common spelling that we're stuck with: */ /* VIR_MIGRATE_TUNNELLED should be VIR_MIGRATE_TUNNELED */ const VIR_MIGRATE_PEER2PEER = 2; /* tunnel migration data over libvirtd connection */ const VIR_MIGRATE_TUNNELLED = 4; /* persist the VM on the destination */ const VIR_MIGRATE_PERSIST_DEST = 8; /* undefine the VM on the source */ const VIR_MIGRATE_UNDEFINE_SOURCE = 16; /* pause on remote side */ const VIR_MIGRATE_PAUSED = 32; /* migration with non-shared storage with full disk copy */ const VIR_MIGRATE_NON_SHARED_DISK = 64; /* migration with non-shared storage with incremental copy (same base image shared between source and destination) */ const VIR_MIGRATE_NON_SHARED_INC = 128; /* protect for changing domain configuration through the whole migration process; this will be used automatically when supported */ const VIR_MIGRATE_CHANGE_PROTECTION = 256; /* force migration even if it is considered unsafe */ const VIR_MIGRATE_UNSAFE = 512; /* offline migrate */ const VIR_MIGRATE_OFFLINE = 1024; /* compress data during migration */ const VIR_MIGRATE_COMPRESSED = 2048; /* abort migration on I/O errors happened during migration */ const VIR_MIGRATE_ABORT_ON_ERROR = 4096; /* force convergence */ const VIR_MIGRATE_AUTO_CONVERGE = 8192; /* Modify device allocation based on current domain state */ const VIR_DOMAIN_DEVICE_MODIFY_CURRENT = 0; /* Modify live device allocation */ const VIR_DOMAIN_DEVICE_MODIFY_LIVE = 1; /* Modify persisted device allocation */ const VIR_DOMAIN_DEVICE_MODIFY_CONFIG = 2; /* Forcibly modify device (ex. force eject a cdrom) */ const VIR_DOMAIN_DEVICE_MODIFY_FORCE = 4; /* REGISTER_LONG_CONSTANT */ const VIR_STORAGE_POOL_BUILD_NEW = 0; /* Repair / reinitialize */ const VIR_STORAGE_POOL_BUILD_REPAIR = 1; /* Extend existing pool */ const VIR_STORAGE_POOL_BUILD_RESIZE = 2; /* Domain flags */ const VIR_DOMAIN_FLAG_FEATURE_ACPI = 1; const VIR_DOMAIN_FLAG_FEATURE_APIC = 2; const VIR_DOMAIN_FLAG_FEATURE_PAE = 4; const VIR_DOMAIN_FLAG_CLOCK_LOCALTIME = 8; const VIR_DOMAIN_FLAG_TEST_LOCAL_VNC = 16; const VIR_DOMAIN_FLAG_SOUND_AC97 = 32; const VIR_DOMAIN_DISK_FILE = 1; const VIR_DOMAIN_DISK_BLOCK = 2; const VIR_DOMAIN_DISK_ACCESS_ALL = 4; const VIR_CONNECT_GET_ALL_DOMAINS_STATS_ACTIVE = 1; const VIR_CONNECT_GET_ALL_DOMAINS_STATS_INACTIVE = 2; const VIR_CONNECT_GET_ALL_DOMAINS_STATS_OTHER = 4; const VIR_CONNECT_GET_ALL_DOMAINS_STATS_PAUSED = 8; const VIR_CONNECT_GET_ALL_DOMAINS_STATS_PERSISTENT = 16; const VIR_CONNECT_GET_ALL_DOMAINS_STATS_RUNNING = 32; const VIR_CONNECT_GET_ALL_DOMAINS_STATS_SHUTOFF = 64; const VIR_CONNECT_GET_ALL_DOMAINS_STATS_TRANSIENT = 128; const VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS = 2 ^ 31; const VIR_DOMAIN_MEM_CONFIG = VIR_DOMAIN_AFFECT_CONFIG; const VIR_DOMAIN_MEM_CURRENT = VIR_DOMAIN_AFFECT_CURRENT; const VIR_DOMAIN_MEM_LIVE = VIR_DOMAIN_AFFECT_LIVE; const VIR_DOMAIN_MEM_MAXIMUM = 4; const VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE = 0; const VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT = 1; const VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP = VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE; /* Connect flags */ const VIR_CONNECT_FLAG_SOUNDHW_GET_NAMES = 1; /* Keycodeset constants */ const VIR_KEYCODE_SET_LINUX = 0; const VIR_KEYCODE_SET_XT = 1; const VIR_KEYCODE_SET_ATSET1 = 6; const VIR_KEYCODE_SET_ATSET2 = 2; const VIR_KEYCODE_SET_ATSET3 = 3; const VIR_KEYCODE_SET_OSX = 4; const VIR_KEYCODE_SET_XT_KBD = 5; const VIR_KEYCODE_SET_USB = 6; const VIR_KEYCODE_SET_WIN32 = 7; const VIR_KEYCODE_SET_RFB = 8; /* virDomainUndefineFlagsValues */ const VIR_DOMAIN_UNDEFINE_MANAGED_SAVE = 1; const VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA = 2; const VIR_DOMAIN_UNDEFINE_NVRAM = 4; const VIR_DOMAIN_UNDEFINE_KEEP_NVRAM = 8; /* Connect functions */ /** * Function is used to connect to the specified libvirt daemon using the specified URL, user can also set the readonly * flag and/or set credentials for connection * @param string $url URI for connection * @param bool $readonly [optional] flag whether to use read-only connection or not, default true * @param array $credentials [optional] array of connection credentials * @return resource libvirt connection resource * @since 0.4.1(-1) */ function libvirt_connect(string $url, bool $readonly = true, array $credentials) {} /** * Query statistics for all domains on a given connection * @param resource $conn resource for connection * @param int $stats [optional] the statistic groups from VIR_DOMAIN_STATS_* * @param int $flags [optional] the statistic groups from VIR_DOMAIN_STATS_* * @return array|false assoc array with statistics or false on error * @since 0.5.1(-1) */ function libvirt_connect_get_all_domain_stats($conn, int $stats = 0, int $flags = 0): array|false {} /** * Function is used to get the capabilities information from the connection * @param resource $conn resource for connection * @param string|null $xpath [optional] xPath query to be applied on the result * @return string capabilities XML from the connection or FALSE for error * @since 0.4.1(-2) */ function libvirt_connect_get_capabilities($conn, ?string $xpath): string {} /** * Function is used to get the emulator for requested connection/architecture * @param resource $conn libvirt connection resource * @param string|null $arch [optional] architecture string, can be NULL to get default * @return string path to the emulator * @since 0.4.5 */ function libvirt_connect_get_emulator($conn, ?string $arch): string {} /** * Function is used to get the information whether the connection is encrypted or not * @param resource $conn resource for connection * @return int 1 if encrypted, 0 if not encrypted, -1 on error * @since 0.4.1(-2) */ function libvirt_connect_get_encrypted($conn): int {} /** * Function is used to get the hostname of the guest associated with the connection * @param resource $conn resource for connection * @return string|false hostname of the host node or FALSE for error * @since 0.4.1(-1) */ function libvirt_connect_get_hostname($conn): string|false {} /** * Function is used to get the information about the hypervisor on the connection identified by the connection pointer * @param resource $conn libvirt-php: PHP API Reference guide * @return array array of hypervisor information if available */ function libvirt_connect_get_hypervisor($conn): array {} /** * Function is used to get the information about the connection * @param resource $conn resource for connection * @return array array of information about the connection * @since 0.4.1(-2) */ function libvirt_connect_get_information($conn): array {} /** * Function is used to get machine types supported by hypervisor on the connection * @param resource $conn resource for connection * @return array array of machine types for the connection incl. maxCpus if appropriate * @since 0.4.9 */ function libvirt_connect_get_machine_types($conn): array {} /** * Function is used to get maximum number of VCPUs per VM on the hypervisor connection * @param resource $conn resource for connection * @return int|false number of VCPUs available per VM on the connection or FALSE for error * @since 0.4.1(-2) */ function libvirt_connect_get_maxvcpus($conn): int|false {} /** * Function is used to get NIC models for requested connection/architecture * @param resource $conn libvirt connection resource * @param string|null $arch [optional] architecture string, can be NULL to get default * @return array array of models * @since 0.4.9 */ function libvirt_connect_get_nic_models($conn, ?string $arch): array {} /** * Function is used to get the information whether the connection is secure or not * @param resource $conn resource for connection * @return int 1 if secure, 0 if not secure, -1 on error * @since 0.4.1(-2) */ function libvirt_connect_get_secure($conn): int {} /** * Function is used to get sound hardware models for requested connection/architecture * @param resource $conn libvirt connection resource * @param string|null $arch [optional] architecture string, can be NULL to get default * @param int $flags [optional] flags for getting sound hardware. Can be either 0 or VIR_CONNECT_SOUNDHW_GET_NAMES * @return array array of models * @since 0.4.9 */ function libvirt_connect_get_soundhw_models($conn, ?string $arch, int $flags = 0): array {} /** * Function is used to get the system information from connection if available * @param resource $conn resource for connection * @return string|false XML description of system information from the connection or FALSE for error * @since 0.4.1(-2) */ function libvirt_connect_get_sysinfo($conn): string|false {} /** * Function is used to get the connection URI. This is useful to check the hypervisor type of host machine * when using "null" uri to libvirt_connect() * @param resource $conn resource for connection * @return string|false connection URI string or FALSE for error * @since 0.4.1(-1) */ function libvirt_connect_get_uri($conn): string|false {} /* Domain functions */ /** * Function is used to attach a virtual device to a domain * @param resource $res libvirt domain resource * @param string $xml XML description of one device * @param int $flags [optional] flags * @return bool TRUE for success, FALSE on error * @since 0.5.3 */ function libvirt_domain_attach_device($res, string $xml, int $flags = 0): bool {} /** * Function is used to commit block job * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $disk path to the block device, or device shorthand * @param string|null $base [optional] path to backing file to merge into, or device shorthand, or NULL for default * @param string|null $top [optional] path to file within backing chain that contains data to be merged, * or device shorthand, or NULL to merge all possible data * @param int $bandwidth [optional] specify bandwidth limit; flags determine the unit * @param int $flags [optional] bitwise-OR of VIR_DOMAIN_BLOCK_COMMIT_* * @return bool true on success fail on error * @since 0.5.2(-1) */ function libvirt_domain_block_commit($res, string $disk, ?string $base, ?string $top, int $bandwidth = 0, int $flags = 0): bool {} /** * Function is used to abort block job * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $path device path to resize * @param int $flags [optional] bitwise-OR of VIR_DOMAIN_BLOCK_JOB_ABORT_* * @return bool true on success fail on error * @since 0.5.1(-1) */ function libvirt_domain_block_job_abort($res, string $path, int $flags = 0): bool {} /** * Function is used to attach a virtual device to a domain * @param resource $res libvirt domain resource * @param string $disk path to the block device, or device shorthand * @param int $flags [optional] bitwise-OR of VIR_DOMAIN_BLOCK_COMMIT_* * @return array Array with status virDomainGetBlockJobInfo and blockjob information * @since 0.5.2(-1) */ function libvirt_domain_block_job_info($res, string $disk, int $flags = 0): array {} /** * Function is used to set speed of block job * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $path device path to resize * @param int $bandwidth bandwidth * @param int $flags [optional] bitwise-OR of VIR_DOMAIN_BLOCK_JOB_SPEED_BANDWIDTH_* * @return bool true on success fail on error * @since 0.4.1(-1) */ function libvirt_domain_block_job_set_speed($res, string $path, int $bandwidth, int $flags = 0): bool {} /** * Function is used to resize the domain's block device * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $path device path to resize * @param int $size size of device * @param int $flags [optional] bitwise-OR of VIR_DOMAIN_BLOCK_RESIZE_* * @return bool true on success fail on error * @since 0.5.1(-1) */ function libvirt_domain_block_resize($res, string $path, int $size, int $flags = 0): bool {} /** * Function is used to get the domain's block stats * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $path device path to get statistics about * @return array domain block stats array, fields are rd_req, rd_bytes, wr_req, wr_bytes and errs * @since 0.4.1(-1) */ function libvirt_domain_block_stats($res, string $path): array {} /** * Function is used to change the domain boot devices * @param resource $res libvirt domain resource * @param string $first first boot device to be set * @param string $second second boot device to be set * @param int $flags [optional] flags * @return resource new domain resource * @since 0.4.2 */ function libvirt_domain_change_boot_devices($res, string $first, string $second, int $flags = 0) {} /** * Function is used to change the domain memory allocation * @param resource $res libvirt domain resource * @param int $allocMem number of MiBs to be set as immediate memory value * @param int $allocMax number of MiBs to be set as the maximum allocation * @param int $flags [optional] flags * @return resource new domain resource * @since 0.4.2 */ function libvirt_domain_change_memory($res, int $allocMem, int $allocMax, int $flags = 0) {} /** * Function is used to change the VCPU count for the domain * @param resource $res libvirt domain resource * @param int $numCpus number of VCPUs to be set for the guest * @param int $flags [optional] flags for virDomainSetVcpusFlags * (available at http://libvirt.org/html/libvirt-libvirt.html#virDomainVcpuFlags) * @return bool true on success, false on error * @since 0.4.2 */ function libvirt_domain_change_vcpus($res, int $numCpus, int $flags = 0): bool {} /** * Function is used to dump core of the domain identified by it's resource * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $to to * @return bool TRUE for success, FALSE on error * @since 0.4.1(-2) */ function libvirt_domain_core_dump($res, string $to): bool {} /** * Function is used to create the domain identified by it's resource * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @return bool result of domain creation (startup) * @since 0.4.1(-1) */ function libvirt_domain_create($res): bool {} /** * Function is used to create the domain identified by it's resource * @param resource $conn libvirt connection resource * @param string $xml XML string to create guest from * @param int $flags [optional] flags * @return resource newly started/created domain resource * @since 0.4.1(-1) */ function libvirt_domain_create_xml($conn, string $xml, int $flags = 0) {} /** * Function is used to define the domain from XML string * @param resource $conn libvirt connection resource * @param string $xml XML string to define guest from * @return resource newly defined domain resource * @since 0.4.1(-1) */ function libvirt_domain_define_xml($conn, string $xml) {} /** * Function is used to destroy the domain identified by it's resource * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @return bool result of domain destroy * @since 0.4.1(-1) */ function libvirt_domain_destroy($res): bool {} /** * Function is used to detach a virtual device from a domain * @param resource $res libvirt domain resource * @param string $xml XML description of one device * @param int $flags [optional] flags to control how the device is attached. Defaults to VIR_DOMAIN_AFFECT_LIVE * @return bool TRUE for success, FALSE on error * @since 0.5.3 */ function libvirt_domain_detach_device($res, string $xml, int $flags = VIR_DOMAIN_AFFECT_LIVE): bool {} /** * Function is used to add the disk to the virtual machine using set of API functions to make it as simple * as possible for the user * @param resource $res libvirt domain resource * @param string $img string for the image file on the host system * @param string $dev string for the device to be presented to the guest (e.g. hda) * @param string $typ bus type for the device in the guest, usually 'ide' or 'scsi' * @param string $driver driver type to be specified, like 'raw' or 'qcow2' * @param int $flags [optional] flags for getting the XML description * @return resource new domain resource * @since 0.4.2 */ function libvirt_domain_disk_add($res, string $img, string $dev, string $typ, string $driver, int $flags = 0) {} /** * Function is used to remove the disk from the virtual machine using set of API functions to make it * as simple as possible * @param resource $res libvirt domain resource * @param string $dev string for the device to be removed from the guest (e.g. 'hdb') * @param int $flags [optional] flags for getting the XML description * @return resource new domain resource * @since 0.4.2 */ function libvirt_domain_disk_remove($res, string $dev, int $flags = 0) {} /** * Function is getting the autostart value for the domain * @param resource $res libvirt domain resource * @return int autostart value or -1 * @since 0.4.1(-1) */ function libvirt_domain_get_autostart($res): int {} /** * Function is used to get the domain's block device information * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $dev device to get block information about * @return array domain block device information array of device, file or partition, capacity, * allocation and physical size * @since 0.4.1(-1) */ function libvirt_domain_get_block_info($res, string $dev): array {} /** * Function is used to get the domain's connection resource. This function should *not* be used! * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @return resource libvirt connection resource * @since 0.4.1(-1) */ function libvirt_domain_get_connect($res) {} /** * Function is getting domain counts for all, active and inactive domains * @param resource $conn libvirt connection resource from libvirt_connect() * @return array array of total, active and inactive (but defined) domain counts * @since 0.4.1(-1) */ function libvirt_domain_get_counts($conn): array {} /** * Function is used to get disk devices for the domain * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @return array|false list of domain disk devices * @since 0.4.4 */ function libvirt_domain_get_disk_devices($res): array|false {} /** * Function is used to get the domain's ID, applicable to running guests only * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @return int running domain ID or -1 if not running * @since 0.4.1(-1) */ function libvirt_domain_get_id($res): int {} /** * Function is used to get the domain's information * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @return array domain information array * @since 0.4.4 */ function libvirt_domain_get_info($res): array {} /** * Function is used to get network interface devices for the domain * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @return array|false list of domain interface devices * @since 0.4.4 */ function libvirt_domain_get_interface_devices($res): array|false {} /** * Function is used get job information for the domain * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @return array job information array of type, time, data, mem and file fields * @since 0.4.1(-1) */ function libvirt_domain_get_job_info($res): array {} /** * Function retrieve appropriate domain element given by $type * @param resource $res libvirt domain resource * @param int $type virDomainMetadataType type of description * @param string $uri XML namespace identifier * @param int $flags bitwise-OR of virDomainModificationImpact * @return string|null|false metadata string, NULL on error or FALSE on API not supported * @since 0.4.9 */ function libvirt_domain_get_metadata($res, int $type, string $uri, int $flags = 0): string|null|false {} /** * Function is used to get domain name from it's resource * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @return string domain name string * @since 0.4.1(-1) */ function libvirt_domain_get_name($res): string {} /** * Function is used to get the domain's network information * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $mac mac address of the network device * @return array domain network info array of MAC address, network name and type of NIC card * @since 0.4.1(-1) */ function libvirt_domain_get_network_info($res, string $mac): array {} /** * This functions can be used to get the next free slot if you intend to add a new device identified * by slot to the domain, e.g. NIC device * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @return array next free slot number for the domain * @since 0.4.2 */ function libvirt_domain_get_next_dev_ids($res): array {} /** * Function get screen dimensions of the VNC window * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $server server string of the host machine * @return array|false array of height and width on success, FALSE otherwise * @since 0.4.2 */ function libvirt_domain_get_screen_dimensions($res, string $server): array|false {} /** * Function uses gvnccapture (if available) to get the screenshot of the running domain * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $server server string for the host machine * @param int $scancode [optional] integer value of the scancode to be send to refresh screen, default is 10 * @return string PNG image binary data * @since 0.4.2 */ function libvirt_domain_get_screenshot($res, string $server, int $scancode = 10): string {} /** * Function is trying to get domain screenshot using libvirt virGetDomainScreenshot() API if available * @param resource $res libvirt domain resource, e.g. from libvirt_domain_get_by_*() * @param int $screenID [optional] monitor ID from where to take screenshot * @return array array of filename and mime type as type is hypervisor specific, * caller is responsible for temporary file deletion * @since 0.4.5 */ function libvirt_domain_get_screenshot_api($res, int $screenID = 0): array {} /** * Function is used to get the domain's UUID in binary format * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @return string domain UUID in binary format * @since 0.4.1(-1) */ function libvirt_domain_get_uuid($res): string {} /** * Function is used to get the domain's UUID in string format * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @return string domain UUID string * @since 0.4.1(-1) */ function libvirt_domain_get_uuid_string($res): string {} /** * Function is used to get the domain's XML description * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string|null $xpath xPath expression string to get just this entry, can be NULL * @param int $flags [optional] flags * @return string domain XML description string or result of xPath expression * @since 0.4.2 */ function libvirt_domain_get_xml_desc($res, ?string $xpath, int $flags = 0): string {} /** * Function is used to get network interface addresses for the domain * @param resource $res libvirt domain resource * @param int $source one of the VIR_DOMAIN_ADDRESSES_SRC_* flags * @return array|false interface array of a domain holding information about addresses resembling * the virDomainInterface structure, false on error * @since 0.5.5 */ function libvirt_domain_interface_addresses($res, int $source): array|false {} /** * Function is used to get the domain's interface stats * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $path path to interface device * @return array interface stats array of {tx|rx}_{bytes|packets|errs|drop} fields * @since 0.4.1(-1) */ function libvirt_domain_interface_stats($res, string $path): array {} /** * Function is getting information whether domain identified by resource is active or not * @param resource $res libvirt domain resource * @return bool virDomainIsActive() result on the domain * @since 0.4.1(-1) */ function libvirt_domain_is_active($res): bool {} /** * Function to get information whether domain is persistent or not * @param resource $res libvirt domain resource * @return bool TRUE for persistent, FALSE for not persistent, -1 on error * @since 0.4.9 */ function libvirt_domain_is_persistent($res): bool {} /** * Function is used to get domain by it's ID, applicable only to running guests * @param resource $conn libvirt connection resource from libvirt_connect() * @param string $id domain id to look for * @return resource libvirt domain resource * @since 0.4.1(-1) */ function libvirt_domain_lookup_by_id($conn, string $id) {} /** * Function is used to lookup for domain by it's name * @param resource $res libvirt connection resource from libvirt_connect() * @param string $name domain name to look for * @return resource libvirt domain resource * @since 0.4.1(-1) */ function libvirt_domain_lookup_by_name($res, string $name) {} /** * Function is used to lookup for domain by it's UUID in the binary format * @param resource $res libvirt connection resource from libvirt_connect() * @param string $uuid binary defined UUID to look for * @return resource libvirt domain resource * @since 0.4.1(-1) */ function libvirt_domain_lookup_by_uuid($res, string $uuid) {} /** * Function is used to get the domain by it's UUID that's accepted in string format * @param resource $res libvirt connection resource from libvirt_connect() * @param string $uuid domain UUID [in string format] to look for * @return resource libvirt domain resource * @since 0.4.1(-1) */ function libvirt_domain_lookup_by_uuid_string($res, string $uuid) {} /** * Function is used to managed save the domain (domain was unloaded from memory and it state saved to disk) * identified by it's resource * @param resource $res TRUE for success, FALSE on error * @return bool TRUE for success, FALSE on error * @since 0.4.1(-1) */ function libvirt_domain_managedsave($res): bool {} /** * Function is used to get the domain's memory peek value * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param int $start start * @param int $size size * @param int $flags flags * @return int domain memory peek * @since 0.4.1(-1) */ function libvirt_domain_memory_peek($res, int $start, int $size, int $flags = 0): int {} /** * Function is used to get the domain's memory stats * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param int $flags [optional] flags * @return array domain memory stats array (same fields as virDomainMemoryStats, please see libvirt documentation) * @since 0.4.1(-1) */ function libvirt_domain_memory_stats($res, int $flags = 0): array {} /** * Function is used migrate domain to another domain * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $dest_conn destination host connection object * @param int $flags migration flags * @param string $dname [optional] domain name to rename domain to on destination side * @param int $bandwidth [optional] migration bandwidth in Mbps * @return resource libvirt domain resource for migrated domain * @since 0.4.1(-1) */ function libvirt_domain_migrate($res, string $dest_conn, int $flags, string $dname, int $bandwidth = 0) {} /** * Function is used migrate domain to another libvirt daemon specified by it's URI * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $dest_uri destination URI to migrate to * @param int $flags migration flags * @param string $dname [optional] domain name to rename domain to on destination side * @param int $bandwidth [optional] migration bandwidth in Mbps * @return bool TRUE for success, FALSE on error * @since 0.4.1(-1) */ function libvirt_domain_migrate_to_uri($res, string $dest_uri, int $flags, string $dname, int $bandwidth = 0): bool {} /** * Function is used migrate domain to another libvirt daemon specified by it's URI * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $dconnuri URI for target libvirtd * @param string $miguri URI for invoking the migration * @param string $dxml XML config for launching guest on target * @param int $flags migration flags * @param string $dname [optional] domain name to rename domain to on destination side * @param int $bandwidth [optional] migration bandwidth in Mbps * @return bool TRUE for success, FALSE on error * @since 0.4.6(-1) */ function libvirt_domain_migrate_to_uri2($res, string $dconnuri, string $miguri, string $dxml, int $flags, string $dname, int $bandwidth = 0): bool {} /** * Function is used to install a new virtual machine to the machine * @param resource $conn libvirt connection resource * @param string $name name of the new domain * @param string|null|false $arch optional architecture string, can be NULL to get default (or false) * @param int $memMB number of megabytes of RAM to be allocated for domain * @param int $maxmemMB maximum number of megabytes of RAM to be allocated for domain * @param int $vcpus number of VCPUs to be allocated to domain * @param string $iso_image installation ISO image for domain * @param array $disks array of disk devices for domain, consist of keys as 'path' (storage location), * 'driver' (image type, e.g. 'raw' or 'qcow2'), 'bus' (e.g. 'ide', 'scsi'), * 'dev' (device to be presented to the guest - e.g. 'hda'), * 'size' (with 'M' or 'G' suffixes, like '10G' for 10 gigabytes image etc.) and * 'flags' (VIR_DOMAIN_DISK_FILE or VIR_DOMAIN_DISK_BLOCK, optionally VIR_DOMAIN_DISK_ACCESS_ALL * to allow access to the disk for all users on the host system) * @param array $networks array of network devices for domain, consists of keys as 'mac' (for MAC address), * 'network' (for network name) and optional 'model' for model of NIC device * @param int $flags [optional] bit array of flags * @return resource a new domain resource * @since 0.4.5 */ function libvirt_domain_new($conn, string $name, string|null|false $arch, int $memMB, int $maxmemMB, int $vcpus, string $iso_image, array $disks, array $networks, int $flags = 0) {} /** * Function is used to get the VNC server location for the newly created domain (newly started installation) * @return string|null a VNC server for a newly created domain resource (if any) * @since 0.4.5 */ function libvirt_domain_new_get_vnc(): string|null {} /** * Function is used to add the NIC card to the virtual machine using set of API functions to make it as simple * as possible for the user * @param resource $res libvirt domain resource * @param string $mac libvirt domain resource * @param string $network network name where to connect this NIC * @param string $model string of the NIC model * @param int $flags [optional] flags for getting the XML description * @return resource new domain resource * @since 0.4.2 */ function libvirt_domain_nic_add($res, string $mac, string $network, string $model, int $flags = 0) {} /** * Function is used to remove the NIC from the virtual machine using set of API functions to make it * as simple as possible * @param resource $res libvirt domain resource * @param string $dev string representation of the IP address to be removed (e.g. 54:52:00:xx:yy:zz) * @param int $flags [optional] flags for getting the XML description * @return resource new domain resource * @since 0.4.2 */ function libvirt_domain_nic_remove($res, string $dev, int $flags = 0) {} /** * Function is used to send qemu-ga command * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $cmd command * @param int $timeout [optional] timeout * @param int $flags [optional] unknown * @return string|false String on success and FALSE on error * @since 0.5.2(-1) */ function libvirt_domain_qemu_agent_command($res, string $cmd, $timeout = -1, int $flags = 0): string|false {} /** * Function is used to reboot the domain identified by it's resource * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param int $flags [optional] flags * @return bool TRUE for success, FALSE on error * @since 0.4.1(-1) */ function libvirt_domain_reboot($res, int $flags = 0): bool {} /** * Function is used to reset the domain identified by its resource * @param resource $res libvirt domain resource * @param int $flags [optional] @flags * @return bool true on success, false on error * @since 0.5.5 */ function libvirt_domain_reset($res, int $flags = 0): bool {} /** * Function is used to resume the domain identified by it's resource * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @return resource result of domain resume * @since 0.4.1(-1) */ function libvirt_domain_resume($res) {} /** * Function sends keys to domain via libvirt API * @param resource $res libvirt domain resource * @param int $codeset the codeset of keycodes, from virKeycodeSet * @param int $holdtime the duration (in milliseconds) that the keys will be held * @param array $keycodes array of keycodes * @param int $flags [optional] extra flags; not used yet so callers should always pass 0 * @return bool TRUE for success, FALSE for failure * @since 0.5.3 */ function libvirt_domain_send_key_api($res, int $codeset, int $holdtime, array $keycodes, int $flags = 0): bool {} /** * Function sends keys to the domain's VNC window * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $server server string of the host machine * @param int $scancode integer scancode to be sent to VNC window * @return bool TRUE on success, FALSE otherwise * @since 0.4.2 */ function libvirt_domain_send_keys($res, string $server, int $scancode): bool {} /** * Function sends keys to the domain's VNC window * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $server server string of the host machine * @param int $pos_x position on x-axis * @param int $pos_y position on y-axis * @param int $clicked mask of clicked buttons (0 for none, bit 1 for button #1, bit 8 for button #8) * @param bool $release [optional] boolean value (0 or 1) whether to release the buttons automatically once pressed, * default true * @return bool TRUE on success, FALSE otherwise * @since 0.4.2 */ function libvirt_domain_send_pointer_event($res, string $server, int $pos_x, int $pos_y, int $clicked, bool $release = true): bool {} /** * Function is setting the autostart value for the domain * @param resource $res libvirt domain resource * @param bool $flags flag to enable/disable autostart * @return bool TRUE on success, FALSE on error * @since 0.4.1(-1) */ function libvirt_domain_set_autostart($res, bool $flags): bool {} /** * Function to set max memory for domain * @param resource $res libvirt domain resource * @param int $memory memory size in 1024 bytes (Kb) * @return bool TRUE for success, FALSE for failure * @since 0.5.1 */ function libvirt_domain_set_max_memory($res, int $memory): bool {} /** * Function to set memory for domain * @param resource $res libvirt domain resource * @param int $memory memory size in 1024 bytes (Kb) * @return bool TRUE for success, FALSE for failure * @since 0.5.1 */ function libvirt_domain_set_memory($res, int $memory): bool {} /** * Function to set max memory for domain * @param resource $res libvirt domain resource * @param int $memory memory size in 1024 bytes (Kb) * @param int $flags [optional] bitwise-OR VIR_DOMAIN_MEM_* flags * @return bool TRUE for success, FALSE for failure * @since 0.5.1 */ function libvirt_domain_set_memory_flags($res, int $memory = 0, int $flags = 0): bool {} /** * Function sets the appropriate domain element given by $type to the value of $metadata. No new lines are permitted * @param resource $res libvirt domain resource * @param int $type virDomainMetadataType type of description * @param string $metadata new metadata text * @param string $key XML namespace key or empty string (alias of NULL) * @param string $uri XML namespace identifier or empty string (alias of NULL) * @param int $flags bitwise-OR of virDomainModificationImpact * @return int -1 on error, 0 on success * @since 0.4.9 */ function libvirt_domain_set_metadata($res, int $type, string $metadata, string $key, string $uri, int $flags = 0): int {} /** * Function is used to shutdown the domain identified by it's resource * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @return bool TRUE for success, FALSE on error * @since 0.4.1(-1) */ function libvirt_domain_shutdown($res): bool {} /** * Function is used to suspend the domain identified by it's resource * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @return bool TRUE for success, FALSE on error * @since 0.4.1(-1) */ function libvirt_domain_suspend($res): bool {} /** * Function is used to undefine the domain identified by it's resource * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @return bool TRUE for success, FALSE on error * @since 0.4.1(-1) */ function libvirt_domain_undefine($res): bool {} /** * Function is used to undefine(with flags) the domain identified by it's resource * @param resource $res libvirt domain resource * @param int $flags [optional] flags * @return bool TRUE if success, FALSE on error * @since 999 https://github.com/yzslab/php-libvirt-client */ function libvirt_domain_undefine_flags($res, int $flags = 0): bool {} /** * Function is used to update the domain's devices from the XML string * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $xml XML string for the update * @param int $flags Flags to update the device (VIR_DOMAIN_DEVICE_MODIFY_CURRENT, VIR_DOMAIN_DEVICE_MODIFY_LIVE, * VIR_DOMAIN_DEVICE_MODIFY_CONFIG, VIR_DOMAIN_DEVICE_MODIFY_FORCE) * @return bool TRUE for success, FALSE on error * @since 0.4.1(-1) */ function libvirt_domain_update_device($res, string $xml, int $flags): bool {} /** * Function is used to convert native configuration data to libvirt domain XML * @param resource $conn libvirt connection resource * @param string $format configuration format converting from * @param string $config_data content of the native config file * @return string|false libvirt domain XML, FALSE on error * @since 0.5.3 */ function libvirt_domain_xml_from_native($conn, string $format, string $config_data): string|false {} /** * Function is used to convert libvirt domain XML to native configuration * @param resource $conn libvirt connection resource * @param string $format configuration format converting from * @param string $xml_data content of the libvirt domain xml file * @return string|false contents of the native data file, FALSE on error * @since 0.5.3 */ function libvirt_domain_xml_to_native($conn, string $format, string $xml_data): string|false {} /** * Function is used to get the result of xPath expression that's run against the domain * @param resource $res libvirt domain resource, e.g. from libvirt_domain_lookup_by_*() * @param string $xpath xPath expression to parse against the domain * @param int $flags [optional] flags * @return array result of the expression in an array * @since 0.4.1(-1) */ function libvirt_domain_xml_xpath($res, string $xpath, int $flags = 0): array {} /** * Function is used to list active domain IDs on the connection * @param resource $res libvirt connection resource * @return array libvirt active domain ids array for the connection * @since 0.4.1(-1) */ function libvirt_list_active_domain_ids($res): array {} /** * Function is used to list active domain names on the connection * @param resource $res libvirt connection resource * @return array libvirt active domain names array for the connection * @since 0.4.1(-1) */ function libvirt_list_active_domains($res): array {} /** * Function is used to list domain resources on the connection * @param resource $res libvirt connection resource * @return array libvirt domain resources array for the connection * @since 0.4.1(-1) */ function libvirt_list_domain_resources($res): array {} /** * Function is used to list domains on the connection * @param resource $res libvirt connection resource * @return array libvirt domain names array for the connection * @since 0.4.1(-1) */ function libvirt_list_domains($res): array {} /** * Function is used to list inactive domain names on the connection * @param resource $res libvirt connection resource * @return array libvirt inactive domain names array for the connection * @since 0.4.1(-1) */ function libvirt_list_inactive_domains($res): array {} /* Network functions */ /** * Function is used to list networks on the connection * @param resource $conn libvirt connection resource * @param int $flags [optional] flags to filter the results for a smaller list of targeted networks * (bitwise-OR VIR_CONNECT_LIST_NETWORKS_* constants) * @return array libvirt network resources array for the connection * @since 0.5.3 */ function libvirt_list_all_networks($conn, int $flags = VIR_CONNECT_LIST_NETWORKS_ACTIVE|VIR_CONNECT_LIST_NETWORKS_INACTIVE): array {} /** * Function is used to list networks on the connection * @param resource $res libvirt connection resource * @param int $flags [optional] flags whether to list active, * inactive or all networks (VIR_NETWORKS_{ACTIVE|INACTIVE|ALL} constants) * @return array libvirt network names array for the connection * @since 0.4.1(-1) */ function libvirt_list_networks($res, int $flags = 0): array {} /** * Function is used to define a new virtual network based on the XML description * @param resource $res libvirt connection resource * @param string $xml XML string definition of network to be defined * @return resource libvirt network resource of newly defined network * @since 0.4.2 */ function libvirt_network_define_xml($res, string $xml) {} /** * Function is used to get the network resource from name * @param resource $res libvirt connection resource * @param string $name network name string * @return resource libvirt network resource * @since 0.4.1(-1) */ function libvirt_network_get($res, string $name) {} /** * Function is used to get the activity state of the network * @param resource $res libvirt network resource * @return int|false 1 when active, 0 when inactive, FALSE on error * @since 0.4.1(-1) */ function libvirt_network_get_active($res): int|false {} /** * Function is getting the autostart value for the network * @param resource $res libvirt network resource * @return int autostart value or -1 on error * @since 0.5.4 */ function libvirt_network_get_autostart($res): int {} /** * Function is used to get the bridge associated with the network * @param resource $res libvirt network resource * @return string bridge name string * @since 0.4.1(-1) */ function libvirt_network_get_bridge($res): string {} /** * Function is used to get the network information * @param resource $res libvirt network resource * @return array network information array * @since 0.4.1(-1) */ function libvirt_network_get_information($res): array {} /** * Function is used to get network's name * @param resource $res libvirt network resource * @return string|false network name string or FALSE on failure * @since 0.5.3 */ function libvirt_network_get_name($res): string|false {} /** * Function is used to get network's UUID in binary format * @param resource $res libvirt network resource * @return string|false network UUID in binary format or FALSE on failure * @since 0.5.3 */ function libvirt_network_get_uuid($res): string|false {} /** * Function is used to get network's UUID in string format * @param resource $res libvirt network resource * @return string|false network UUID string or FALSE on failure * @since 0.5.3 */ function libvirt_network_get_uuid_string($res): string|false {} /** * Function is used to get the XML description for the network * @param resource $res libvirt network resource * @param string|null $xpath [optional] xPath expression string to get just this entry, can be NULL * @return string|false network XML string or result of xPath expression * @since 0.4.1(-1) */ function libvirt_network_get_xml_desc($res, ?string $xpath): string|false {} /** * Function is used to set the activity state of the network * @param resource $res libvirt network resource * @param int $flags active * @return bool TRUE if success, FALSE on error * @since 0.4.1(-1) */ function libvirt_network_set_active($res, int $flags): bool {} /** * Function is setting the autostart value for the network * @param resource $res libvirt network resource * @param int $flags flag to enable/disable autostart * @return bool TRUE on success, FALSE on error * @since 0.5.4 */ function libvirt_network_set_autostart($res, int $flags): bool {} /** * Function is used to undefine already defined network * @param resource $res libvirt network resource * @return bool TRUE for success, FALSE on error * @since 0.4.2 */ function libvirt_network_undefine($res): bool {} /* Node functions */ /** * Function is used to get the CPU stats per nodes * @param resource $conn resource for connection * @param int $cpunr [optional] CPU number to get information about, * defaults to VIR_NODE_CPU_STATS_ALL_CPUS to get information about all CPUs * @return array|false array of node CPU statistics including time (in seconds since UNIX epoch), * cpu number and total number of CPUs on node or FALSE for error * @since 0.4.6 */ function libvirt_node_get_cpu_stats($conn, int $cpunr = VIR_NODE_CPU_STATS_ALL_CPUS): array|false {} /** * Function is used to get the CPU stats for each CPU on the host node * @param resource $conn resource for connection * @param int $time [optional] time in seconds to get the information about, without aggregation for further processing * @return array|false array of node CPU statistics for each CPU including time (in seconds since UNIX epoch), * cpu number and total number of CPUs on node or FALSE for error * @since 0.4.6 */ function libvirt_node_get_cpu_stats_for_each_cpu($conn, int $time = 0): array|false {} /** * Function is used to get free memory available on the node * @param resource $conn libvirt connection resource * @return string|false The available free memory in bytes as string or FALSE for error * @since 0.5.3 */ function libvirt_node_get_free_memory($conn): string|false {} /** * Function is used to get the information about host node, mainly total memory installed, * total CPUs installed and model information are useful * @param resource $conn resource for connection * @return array|false array of node information or FALSE for error * @since 0.4.1(-1) */ function libvirt_node_get_info($conn): array|false {} /** * Function is used to get the memory stats per node * @param resource $conn resource for connection * @return array array of node memory statistics including time (in seconds since UNIX epoch) or FALSE for error * @since 0.4.6 */ function libvirt_node_get_mem_stats($conn): array {} /* Nodedev functions */ /** * Function is used to list node devices on the connection * @param resource $res libvirt connection resource * @param string|null $cap [optional] capability string * @return array libvirt nodedev names array for the connection * @since 0.4.1(-1) */ function libvirt_list_nodedevs($res, ?string $cap): array {} /** * Function is used to list node devices by capabilities * @param resource $res libvirt nodedev resource * @return array nodedev capabilities array * @since 0.4.1(-1) */ function libvirt_nodedev_capabilities($res): array {} /** * Function is used to get the node device by it's name * @param resource $res libvirt connection resource * @param string $name name of the nodedev to get resource * @return resource libvirt nodedev resource * @since 0.4.1(-1) */ function libvirt_nodedev_get($res, string $name) {} /** * Function is used to get the node device's information * @param resource $res libvirt nodedev resource * @return array nodedev information array * @since 0.4.1(-1) */ function libvirt_nodedev_get_information($res): array {} /** * Function is used to get the node device's XML description * @param resource $res libvirt nodedev resource * @param string|null $xpath [optional] xPath expression string to get just this entry, can be NULL * @return string nodedev XML description string or result of xPath expression * @since 0.4.2 */ function libvirt_nodedev_get_xml_desc($res, ?string $xpath): string {} /* Nwfilter functions */ /** * Function is used to list nwfilters on the connection * @param resource $res libvirt domain resource * @return array libvirt nwfilter resources array for the connection * @since 0.5.4 */ function libvirt_list_all_nwfilters($res): array {} /** * Function is used to list nwfilters on the connection * @param resource $conn libvirt connection resource * @return array libvirt nwfilter names array for the connection * @since 0.5.4 */ function libvirt_list_nwfilters($conn): array {} /** * Function is used to define a new nwfilter based on the XML description * @param resource $conn libvirt connection resource * @param string $xml XML string definition of nwfilter to be defined * @return resource|false libvirt nwfilter resource of newly defined nwfilter or false on error * @since 0.5.4 */ function libvirt_nwfilter_define_xml($conn, string $xml) {} /** * Function is used to get nwfilter's name * @param resource $res libvirt nwfilter resource * @return string|false nwfilter name string or FALSE on failure * @since 0.5.4 */ function libvirt_nwfilter_get_name($res): string|false {} /** * Function is used to get nwfilter's UUID in binary format * @param resource $res libvirt nwfilter resource * @return string|false nwfilter UUID in binary format or FALSE on failure * @since 0.5.3 */ function libvirt_nwfilter_get_uuid($res): string|false {} /** * Function is used to get nwfilter's UUID in string format * @param resource $res libvirt nwfilter resource * @return string|false nwfilter UUID string or FALSE on failure * @since 0.5.4 */ function libvirt_nwfilter_get_uuid_string($res): string|false {} /** * Function is used to lookup for nwfilter identified by UUID string * @param resource $res libvirt nwfilter resource * @param string|null $xpath [optional] xPath expression string to get just this entry, can be NULL * @return string nwfilter XML string or result of xPath expression * @since 0.5.4 */ function libvirt_nwfilter_get_xml_desc($res, ?string $xpath): string {} /** * This functions is used to lookup for the nwfilter by it's name * @param resource $conn libvirt connection resource * @param string $name name of the nwfilter to get the resource * @return resource|false libvirt nwfilter resource * @since 0.5.4 */ function libvirt_nwfilter_lookup_by_name($conn, string $name) {} /** * Function is used to lookup for nwfilter identified by UUID string * @param resource $conn libvirt connection resource * @param string $uuid UUID string to look for nwfilter * @return resource|false libvirt nwfilter resource * @since 0.5.4 */ function libvirt_nwfilter_lookup_by_uuid_string($conn, string $uuid) {} /** * Function is used to undefine already defined nwfilter * @param resource $res libvirt nwfilter resource * @return bool true on success, false on error * @since 0.5.4 */ function libvirt_nwfilter_undefine($res): bool {} /* Libvirt functions */ /** * Function is used to check major, minor and micro (also sometimes called release) versions of libvirt-php * or libvirt itself. This could useful when you want your application to support only versions of libvirt * or libvirt-php higher than some version specified * @param int $major major version number to check for * @param int $minor minor version number to check for * @param int $micro micro (also release) version number to check for * @param int $type type of checking, VIR_VERSION_BINDING to check against libvirt-php binding or * VIR_VERSION_LIBVIRT to check against libvirt version * @return bool TRUE if version is equal or higher than required, FALSE if not, * FALSE with error [for libvirt_get_last_error()] on unsupported version type check * @since 0.4.1(-1) */ function libvirt_check_version(int $major, int $minor, int $micro, int $type): bool {} /** * Function to get the ISO images on path and return them in the array * @param string $path string of path where to look for the ISO images * @return array|false ISO image array on success, FALSE otherwise */ function libvirt_get_iso_images(string $path): array|false {} /** * This function is used to get the last error coming either from libvirt or the PHP extension itself * @return string last error string */ function libvirt_get_last_error(): string {} /** * This function is used to get the last error code coming either from libvirt or the PHP extension itself * @since 999 https://github.com/yzslab/php-libvirt-client * @return int last error code */ function libvirt_get_last_error_code(): int {} /** * This function is used to get the what part of the library raised the last error * @since 999 https://github.com/yzslab/php-libvirt-client * @return int last error domain */ function libvirt_get_last_error_domain(): int {} /** * Function to check for feature existence for working libvirt instance * @param string $name feature name * @return bool TRUE if feature is supported, FALSE otherwise * @since 0.4.1(-3) */ function libvirt_has_feature(string $name): bool {} /** * Function is used to create the image of desired name, size and format. * The image will be created in the image path (libvirt.image_path INI variable). Works only o * @param resource $conn libvirt connection resource * @param string $name name of the image file that will be created in the libvirt.image_path directory * @param int $size size of the image in MiBs * @param string $format format of the image, may be raw, qcow or qcow2 * @return string|false hostname of the host node or FALSE for error * @since 0.4.2 */ function libvirt_image_create($conn, string $name, int $size, string $format): string|false {} /** * Function is used to create the image of desired name, size and format. * The image will be created in the image path (libvirt.image_path INI variable). Works only on local systems! * @param resource $conn libvirt connection resource * @param string $image name of the image file that should be deleted * @return string|false hostname of the host node or FALSE for error * @since 0.4.2 */ function libvirt_image_remove($conn, string $image): string|false {} /** * Function to set the log file for the libvirt module instance * @param string|null $filename log filename or NULL to disable logging * @param int $maxsize [optional] maximum log file size argument in KiB, default value can be found in PHPInfo() output * @return bool TRUE if log file has been successfully set, FALSE otherwise * @since 0.4.2 */ function libvirt_logfile_set(?string $filename, int $maxsize): bool {} /** * Function to print the binding resources, although the resource information are printed, * they are returned in the return_value * @return resource bindings resource information * @since 0.4.2 */ function libvirt_print_binding_resources() {} /** * Function is used to get libvirt, driver and libvirt-php version numbers. Can be used for information purposes, * for version checking please use libvirt_check_version() defined below * @param string $type [optional] type string to identify driver to look at * @return array libvirt, type (driver) and connector (libvirt-php) version numbers array * @since 0.4.1(-1) */ function libvirt_version(string $type): array {} /* Snapshot functions */ /** * Function is used to get the information whether domain has the current snapshot * @param resource $res libvirt domain resource * @param int $flags [optional] extra flags; not used yet so callers should always pass 0 * @return bool TRUE is domain has the current snapshot, otherwise FALSE (you may need to check * for error using libvirt_get_last_error()) * @since 0.4.1(-2) */ function libvirt_domain_has_current_snapshot($res, int $flags = 0): bool {} /** * This function creates the domain snapshot for the domain identified by it's resource * @param resource $res libvirt domain resource * @param int $flags [optional] libvirt snapshot flags * @return resource domain snapshot resource * @since 0.4.1(-2) */ function libvirt_domain_snapshot_create($res, int $flags = 0) {} /** * Function is used to lookup the current snapshot for given domain * @param resource $res libvirt domain resource * @param int $flags [optional] libvirt snapshot flags * @return resource domain snapshot resource * @since 0.5.6 */ function libvirt_domain_snapshot_current($res, int $flags = 0) {} /** * Function is used to revert the domain state to the state identified by the snapshot * @param resource $res libvirt domain resource * @param int $flags [optional] 0 to delete just snapshot, * VIR_SNAPSHOT_DELETE_CHILDREN to delete snapshot children as well * @return bool TRUE on success, FALSE on error * @since 0.4.1(-2) */ function libvirt_domain_snapshot_delete($res, int $flags = 0): bool {} /** * Function is used to get the XML description of the snapshot identified by it's resource * @param resource $res libvirt snapshot resource * @param int $flags [optional] libvirt snapshot flags * @return string XML description string for the snapshot * @since 0.4.1(-2) */ function libvirt_domain_snapshot_get_xml($res, int $flags = 0): string {} /** * This functions is used to lookup for the snapshot by it's name * @param resource $res libvirt domain resource * @param string $name name of the snapshot to get the resource * @param int $flags [optional] libvirt snapshot flags * @return resource domain snapshot resource * @since 0.4.1(-2) */ function libvirt_domain_snapshot_lookup_by_name($res, string $name, int $flags = 0) {} /** * Function is used to revert the domain state to the state identified by the snapshot * @param resource $res libvirt snapshot resource * @param int $flags [optional] libvirt snapshot flags * @return bool TRUE on success, FALSE on error * @since 0.4.1(-2) */ function libvirt_domain_snapshot_revert($res, int $flags = 0): bool {} /** * Function is used to list domain snapshots for the domain specified by it's resource * @param resource $res libvirt domain resource * @param int $flags [optional] libvirt snapshot flags * @return array libvirt domain snapshot names array * @since 0.4.1(-2) */ function libvirt_list_domain_snapshots($res, int $flags = 0): array {} /* Storage functions */ /** * Function is used to list active storage pools on the connection * @param resource $res libvirt connection resource * @return array libvirt storagepool names array for the connection * @since 0.4.1(-1) */ function libvirt_list_active_storagepools($res): array {} /** * Function is used to list inactive storage pools on the connection * @param resource $res libvirt connection resource * @return array libvirt storagepool names array for the connection * @since 0.4.1(-1) */ function libvirt_list_inactive_storagepools($res): array {} /** * Function is used to list storage pools on the connection * @param resource $res libvirt connection resource * @return array libvirt storagepool names array for the connection * @since 0.4.1(-1) */ function libvirt_list_storagepools($res): array {} /** * Function is used to Build the underlying storage pool, e.g. create the destination directory for NFS * @param resource $res libvirt storagepool resource * @return bool TRUE if success, FALSE on error * @since 0.4.2 */ function libvirt_storagepool_build($res): bool {} /** * Function is used to create/start the storage pool * @param resource $res libvirt storagepool resource * @return bool TRUE if success, FALSE on error * @since 0.4.1(-1) */ function libvirt_storagepool_create($res): bool {} /** * Function is used to define the storage pool from XML string and return it's resource * @param resource $res libvirt connection resource * @param string $xml XML string definition of storagepool * @param int $flags [optional] flags to define XML * @return resource libvirt storagepool resource * @since 0.4.1(-1) */ function libvirt_storagepool_define_xml($res, string $xml, int $flags = 0) {} /** * Function is used to Delete the underlying storage pool, e.g. remove the destination directory for NFS * @param resource $res libvirt storagepool resource * @return bool TRUE if success, FALSE on error * @since 0.4.6 */ function libvirt_storagepool_delete($res): bool {} /** * Function is used to destroy the storage pool * @param resource $res libvirt storagepool resource * @return bool TRUE if success, FALSE on error * @since 0.4.1(-1) */ function libvirt_storagepool_destroy($res): bool {} /** * Function is used to get autostart of the storage pool * @param resource $res libvirt storagepool resource * @return bool TRUE for autostart enabled, FALSE for autostart disabled, FALSE with last_error set for error * @since 0.4.1(-1) */ function libvirt_storagepool_get_autostart($res): bool {} /** * Function is used to get information about the storage pool * @param resource $res libvirt storagepool resource * @return array storage pool information array of state, capacity, allocation and available space * @since 0.4.1(-1) */ function libvirt_storagepool_get_info($res): array {} /** * Function is used to get storage pool name from the storage pool resource * @param resource $res libvirt storagepool resource * @return string storagepool name string * @since 0.4.1(-1) */ function libvirt_storagepool_get_name($res): string {} /** * Function is used to get storage pool by UUID string * @param resource $res libvirt storagepool resource * @return string storagepool UUID string * @since 0.4.1(-1) */ function libvirt_storagepool_get_uuid_string($res): string {} /** * Function is used to get storage volume count in the storage pool * @param resource $res libvirt storagepool resource * @return int number of volumes in the pool * @since 0.4.1(-1) */ function libvirt_storagepool_get_volume_count($res): int {} /** * Function is used to get the XML description for the storage pool identified by res * @param resource $res libvirt storagepool resource * @param string|null $xpath [optional] xPath expression string to get just this entry, can be NULL * @return string storagepool XML description string or result of xPath expression * @since 0.4.2 */ function libvirt_storagepool_get_xml_desc($res, ?string $xpath): string {} /** * Function is used to get information whether storage pool is active or not * @param resource $res libvirt storagepool resource * @return bool result of virStoragePoolIsActive * @since 0.4.1(-1) */ function libvirt_storagepool_is_active($res): bool {} /** * Function is used to list volumes in the specified storage pool * @param resource $res libvirt storagepool resource * @return array list of storage volume names in the storage pool in an array using default keys (indexes) * @since 0.4.1(-1) */ function libvirt_storagepool_list_volumes($res): array {} /** * Function is used to lookup for storage pool by it's name * @param resource $res volume resource of storage pool * @param string $name storage pool name * @return resource libvirt storagepool resource * @since 0.4.1(-1) */ function libvirt_storagepool_lookup_by_name($res, string $name) {} /** * Function is used to lookup for storage pool identified by UUID string * @param resource $res libvirt connection resource * @param string $uuid UUID string to look for storagepool * @return resource libvirt storagepool resource * @since 0.4.1(-1) */ function libvirt_storagepool_lookup_by_uuid_string($res, string $uuid) {} /** * Function is used to lookup for storage pool by a volume * @param resource $res volume resource of storage pool * @return resource libvirt storagepool resource * @since 0.4.1(-1) */ function libvirt_storagepool_lookup_by_volume($res) {} /** * Function is used to refresh the storage pool information * @param resource $res libvirt storagepool resource * @param int $flags [optional] refresh flags * @return bool TRUE if success, FALSE on error * @since 0.4.1(-1) */ function libvirt_storagepool_refresh($res, int $flags = 0): bool {} /** * Function is used to set autostart of the storage pool * @param resource $res libvirt storagepool resource * @param bool $flags flags to set autostart * @return bool result on setting storagepool autostart value */ function libvirt_storagepool_set_autostart($res, bool $flags): bool {} /** * Function is used to undefine the storage pool identified by it's resource * @param resource $res libvirt storagepool resource * @return bool TRUE if success, FALSE on error * @since 0.4.1(-1) */ function libvirt_storagepool_undefine($res): bool {} /** * Function is used to create the new storage pool and return the handle to new storage pool * @param resource $res libvirt storagepool resource * @param string $xml XML string to create the storage volume in the storage pool * @param int $flags [optional] virStorageVolCreateXML flags * @return resource libvirt storagevolume resource * @since 0.4.1(-1) */ function libvirt_storagevolume_create_xml($res, string $xml, int $flags = 0) {} /** * Function is used to clone the new storage volume into pool from the original volume * @param resource $pool libvirt storagepool resource * @param string $xml XML string to create the storage volume in the storage pool * @param resource $original_volume libvirt storagevolume resource * @return resource libvirt storagevolume resource * @since 0.4.1(-2) */ function libvirt_storagevolume_create_xml_from($pool, string $xml, $original_volume) {} /** * Function is used to delete to volume identified by it's resource * @param resource $res libvirt storagevolume resource * @param int $flags [optional] flags for the storage volume deletion for virStorageVolDelete() * @return bool TRUE for success, FALSE on error * @since 0.4.2 */ function libvirt_storagevolume_delete($res, int $flags = 0): bool {} /** * Function is used to download volume identified by it's resource * @param resource $res libvirt storagevolume resource * @param resource $stream stream to use as output * @param int $offset [optional] position to start reading from * @param int $length [optional] limit on amount of data to download * @param int $flags [optional] flags for the storage volume download for virStorageVolDownload() * @return int * @since 0.5.0 */ function libvirt_storagevolume_download($res, $stream, int $offset = 0, int $length = 0, int $flags = 0): int {} /** * Function is used to get the storage volume information * @param resource $res libvirt storagevolume resource * @return array storage volume information array of type, allocation and capacity * @since 0.4.1(-1) */ function libvirt_storagevolume_get_info($res): array {} /** * Function is used to get the storage volume name * @param resource $res libvirt storagevolume resource * @return string storagevolume name * @since 0.4.1(-2) */ function libvirt_storagevolume_get_name($res): string {} /** * Function is used to get the storage volume path * @param resource $res libvirt storagevolume resource * @return string storagevolume path * @since 0.4.1(-2) */ function libvirt_storagevolume_get_path($res): string {} /** * Function is used to get the storage volume XML description * @param resource $res libvirt storagevolume resource * @param string|null $xpath [optional] xPath expression string to get just this entry, can be NULL * @param int $flags [optional] flags * @return string storagevolume XML description or result of xPath expression * @since 0.4.2 */ function libvirt_storagevolume_get_xml_desc($res, ?string $xpath, int $flags = 0): string {} /** * Function is used to lookup for storage volume by it's name * @param resource $res libvirt storagepool resource * @param string $name name of the storage volume to look for * @return resource libvirt storagevolume resource * @since 0.4.1(-1) */ function libvirt_storagevolume_lookup_by_name($res, string $name) {} /** * Function is used to lookup for storage volume by it's path * @param resource $res libvirt connection resource * @param string $path path of the storage volume to look for * @return resource libvirt storagevolume resource * @since 0.4.1(-2) */ function libvirt_storagevolume_lookup_by_path($res, string $path) {} /** * Function is used to resize volume identified by it's resource * @param resource $res libvirt storagevolume resource * @param int $capacity capacity for the storage volume * @param int $flags [optional] flags for the storage volume resize for virStorageVolResize() * @return int * @since 0.5.0 */ function libvirt_storagevolume_resize($res, int $capacity, int $flags = 0): int {} /** * Function is used to upload volume identified by it's resource * @param resource $res libvirt storagevolume resource * @param resource $stream stream to use as input * @param int $offset [optional] position to start writing to * @param int $length [optional] limit on amount of data to upload * @param int $flags [optional] flags for the storage volume upload for virStorageVolUpload() * @return int * @since 0.5.0 */ function libvirt_storagevolume_upload($res, $stream, int $offset = 0, int $length = 0, int $flags = 0): int {} /* Stream functions */ /** * Function is used to abort transfer * @param resource $res libvirt stream resource from libvirt_stream_create() * @return int * @since 0.5.0 */ function libvirt_stream_abort($res): int {} /** * Function is used to close stream * @param resource $res libvirt stream resource from libvirt_stream_create() * @return int * @since 0.5.0 */ function libvirt_stream_close($res): int {} /** * Function is used to create new stream from libvirt conn * @param resource $res libvirt connection resource from libvirt_connect() * @return resource resource libvirt stream resource * @since 0.5.0 */ function libvirt_stream_create($res) {} /** * Function is used to finish transfer * @param resource $res libvirt stream resource from libvirt_stream_create() * @return int * @since 0.5.0 */ function libvirt_stream_finish($res): int {} /** * Function is used to close stream from libvirt conn * @param resource $res libvirt stream resource from libvirt_stream_create() * @param string $data buffer * @param int $len [optional] amount of data to receive * @return int * @since 0.5.0 */ function libvirt_stream_recv($res, string $data, int $len = 0): int {} /** * Function is used to close stream from libvirt conn * @param resource $res libvirt stream resource from libvirt_stream_create() * @param string $data buffer * @param int $length [optional] amount of data to send * @return int * @since 0.5.0 */ function libvirt_stream_send($res, string $data, int $length = 0): int {} * 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 */ #[LanguageLevelTypeAware(['8.5' => 'true'], default: 'bool')] function libxml_set_external_entity_loader(?callable $resolver_function) {} /** * 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); const LIBXML_NO_XXE = 8388608; // End of libxml v. = 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 = null) {} /** * (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 = null) {} /** * (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 = null) {} /** * (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. 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