[ 'code' => ' [ 'code' => ' [ 'code' => ' */ } ', ], 'arrayKeyExistsNoSideEffects' => [ 'code' => ' */ } ', ], 'arrayKeyExistsTwice' => [ 'code' => ' [ 'code' => ' ["foo" => true], "b" => [] ]; public function bar(string $key): bool { if (!array_key_exists($key, self::ARR) || !array_key_exists("foo", self::ARR[$key])) { return false; } return self::ARR[$key]["foo"]; } }', 'assertions' => [], 'ignored_issues' => ['MixedReturnStatement', 'MixedInferredReturnType'], ], 'assertSelfClassConstantOffsetsInFunction' => [ 'code' => ' ["foo" => true], "b" => [] ]; public function bar(?string $key): bool { if ($key === null || !array_key_exists($key, self::ARR) || !array_key_exists("foo", self::ARR[$key])) { return false; } return self::ARR[$key]["foo"]; } }', 'assertions' => [], 'ignored_issues' => ['MixedReturnStatement', 'MixedInferredReturnType'], ], 'assertNamedClassConstantOffsetsInFunction' => [ 'code' => ' ["foo" => true], "b" => [], ]; } function bar(?string $key): bool { if ($key === null || !array_key_exists($key, C::ARR) || !array_key_exists("foo", C::ARR[$key])) { return false; } return C::ARR[$key]["foo"]; }', 'assertions' => [], 'ignored_issues' => ['MixedReturnStatement', 'MixedInferredReturnType'], ], 'possiblyUndefinedArrayAccessWithArrayKeyExists' => [ 'code' => ' 1]; } else { $a = [2, 3]; } if (array_key_exists(0, $a)) { echo $a[0]; }', ], 'arrayKeyExistsShoudldNotModifyIntType' => [ 'code' => ' "a", 404 => "b", 500 => "c" ]; } function init(string $code) : string { if (array_key_exists($code, HttpError::ERRS)) { return $code; } return ""; }', ], 'arrayKeyExistsWithClassConst' => [ 'code' => ' [C::class => "foo"], 1 => [D::class => "bar"], ]; private function foo(int $i) : void { if (array_key_exists(C::class, self::FLAGS[$i])) { echo self::FLAGS[$i][C::class]; } } }', ], 'constantArrayKeyExistsWithClassConstant' => [ 'code' => ' [ 'code' => 'format("Y-m-d"); } }', ], 'assertArrayKeyExistsRefinesType' => [ 'code' => ' "mon", 2 => "tue", 3 => "wed", 4 => "thu", 5 => "fri", 6 => "sat", 7 => "sun", ]; /** @param key-of $dayNum*/ private static function doGetDayName(int $dayNum): string { return self::DAYS[$dayNum]; } /** @throws LogicException */ public static function getDayName(int $dayNum): string { if (! array_key_exists($dayNum, self::DAYS)) { throw new \LogicException(); } return self::doGetDayName($dayNum); } }', ], 'arrayKeyExistsInferString' => [ 'code' => ' 1, "b" => 2])) { return $file; } return ""; }', 'assertions' => [], 'ignored_issues' => [], 'php_version' => '8.0', ], 'arrayKeyExistsComplex' => [ 'code' => ' 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6, "g" => 7, "h" => 8, "i" => 9, "j" => 10, "k" => 11, ]; public function doWork(string $a): void { if (!array_key_exists($a, self::MAP)) {} } }', ], 'arrayKeyExistsAccess' => [ 'code' => ' $arr */ function foo(array $arr) : void { if (array_key_exists(1, $arr)) { $a = ($arr[1] === "b") ? true : false; } }', ], 'arrayKeyExistsVariable' => [ 'code' => ' [ 'code' => 'getIterator(); while ($iter->valid() && $count < $numToGet) { $value = $iter->current(); if ($value[0] != $commenter) { if (!array_key_exists($value[0], $posters)) { $posters[$value[0]] = 1; $count++; } } $iter->next(); } return array_keys($posters); } }', 'assertions' => [], 'ignored_issues' => [ 'MixedArrayAccess', 'MixedAssignment', 'MixedArrayOffset', 'MixedArgument', ], ], 'arrayKeyExistsTwoVars' => [ 'code' => ' [ 'code' => ' $arr * @return 1|2|3 */ function checkArrayKeyExistsInt(array $arr, int $int): int { if (array_key_exists($int, $arr)) { return $int; } return 1; }', ], 'comparesStringAndAllIntKeysCorrectly' => [ 'code' => ' $arr * @return bool */ function checkArrayKeyExistsComparison(array $arr, string $key): bool { if (array_key_exists($key, $arr)) { return true; } return false; }', ], 'comparesStringAndAllIntKeysCorrectlyNegated' => [ 'code' => ' $arr * @return bool */ function checkArrayKeyExistsComparisonNegated(array $arr, string $key): bool { if (!array_key_exists($key, $arr)) { return false; } return true; }', ], 'arrayKeyExistsAssertBothWays' => [ 'code' => ' * @psalm-pure */ public static function getStateLabels(): array { return [ self::STATE_A => "A", self::STATE_B => "B", self::STATE_C => "C", ]; } /** * @param self::STATE_* $state */ public static function getStateLabelIf(int $state): string { $states = self::getStateLabels(); if (array_key_exists($state, $states)) { return $states[$state]; } return ""; } }', ], 'arrayKeyExistsComplex2' => [ 'code' => ' * }>, * formatted_address: string, * geometry: array{ * location: array{ lat: float, lng: float }, * location_type: string, * viewport: array{ * northeast: array{ lat: float, lng: float }, * southwest: array{ lat: float, lng: float } * } * }, * partial_match: bool, * types: list * } */ $data = []; $cmp = []; foreach ($data["address_components"] as $component) { foreach ($component["types"] as $type) { $cmp[$type] = $component["long_name"]; } } if (!\array_key_exists("locality", $cmp)) { $cmp["locality"] = ""; } if (!\array_key_exists("administrative_area_level_1", $cmp)) { $cmp["administrative_area_level_1"] = ""; } if ($cmp["administrative_area_level_1"] === "test") { $cmp["administrative_area_level_1"] = ""; }', ], 'arrayKeyExistsPoorPerformance' => [ 'code' => ' [], "name" => [], "geo" => [], "city" => [], "url" => [], "comment_critical" => [], "place" => [], "price" => [], "robot_error" => [], "manual" => [], "contacts" => [], "not_confirmed_by_other_source" => [], ]; public function isCriticalError(int|string $key): bool { if (!\array_key_exists($key, A::CRITICAL_ERRORS)) { return false; } return true; } }', 'assertions' => [], 'ignored_issues' => [], 'php_version' => '8.0', ], 'keyExistsAsAliasForArrayKeyExists' => [ 'code' => <<<'PHP' $arr */ function foo(array $arr): void { if (key_exists("a", $arr)) { echo $arr["a"]; } } PHP, ], ]; } public function providerInvalidCodeParse(): iterable { return [ 'possiblyUndefinedArrayAccessWithArrayKeyExistsOnWrongKey' => [ 'code' => ' 1]; } else { $a = [2, 3]; } if (array_key_exists("a", $a)) { echo $a[0]; }', 'error_message' => 'PossiblyUndefinedArrayOffset', ], 'possiblyUndefinedArrayAccessWithArrayKeyExistsOnMissingKey' => [ 'code' => ' 1]; } else { $a = [2, 3]; } if (array_key_exists("b", $a)) { echo $a[0]; }', 'error_message' => 'PossiblyUndefinedArrayOffset', ], 'dontCreateWeirdString' => [ 'code' => ' 'InvalidArrayOffset', ], ]; } public function testAllowPropertyFetchAsNeedle(): void { Config::getInstance()->ensure_array_int_offsets_exist = true; $this->addFile( 'somefile.php', ' $bar */ $bar = []; if (array_key_exists($foo->status, $bar)) { echo $bar[$foo->status]; }', ); $this->analyzeFile('somefile.php', new Context()); } public function testAllowStaticPropertyFetchAsNeedle(): void { Config::getInstance()->ensure_array_int_offsets_exist = true; $this->addFile( 'somefile.php', ' $bar */ $bar = []; if (array_key_exists(Foo::$status, $bar)) { echo $bar[Foo::$status]; }', ); $this->analyzeFile('somefile.php', new Context()); } }