$rLine) { preg_match_all('/SettingsManager::get(?:Bool|Int|String)?\(\s*[\'"]([a-z0-9_]+)[\'"]/', $rLine, $rM); preg_match_all('/\[\s*[\'"]([a-z0-9_]+)[\'"]\s*\]/', $rLine, $rN); foreach (array_merge($rM[1], $rN[1]) as $rKey) { if (isset($rColumns[$rKey])) { $rFound[$rKey] = true; } } if (in_array($rRel, ACCESSORS, true) || !preg_match('/SettingsManager::get(?:Bool|Int|String)?\(\s*\$|SettingsManager::getAll\(\)\[\s*\$|\$r?[Ss]ettings\[\s*\$/', $rLine)) { continue; } $rNote = null; for ($j = $i; $j >= max(0, $i - 2); $j--) { if (preg_match('/lb-settings:\s*([a-z0-9_, ]+)/', $rLines[$j], $rA)) { $rNote = $rA[1]; break; } } if ($rNote === null) { $rErrors[] = sprintf('%s:%d: dynamic settings read without an `lb-settings: key, …` note', $rRel, $i + 1); continue; } foreach (array_filter(array_map('trim', explode(',', $rNote))) as $rKey) { if (!isset($rColumns[$rKey])) { $rErrors[] = sprintf('%s:%d: lb-settings names `%s`, which is not a settings column', $rRel, $i + 1, $rKey); } $rFound[$rKey] = true; } } } $rKeys = array_keys($rFound); sort($rKeys); $rWithheld = array_values(array_intersect($rKeys, SECRETS)); $rKeys = array_values(array_diff($rKeys, SECRETS)); $rBody = " [\n"; foreach ($rKeys as $rKey) { $rBody .= "\t\t'" . $rKey . "',\n"; } $rBody .= "\t],\n\t'withheld' => [\n"; foreach ($rWithheld as $rKey) { $rBody .= "\t\t'" . $rKey . "',\n"; } $rBody .= "\t],\n];\n"; foreach ($rErrors as $rError) { fwrite(STDERR, 'lb-settings-keys: ' . $rError . "\n"); } if ($rWrite) { file_put_contents($rTarget, $rBody); echo 'lb-settings-keys: wrote ' . count($rKeys) . ' keys (' . count($rWithheld) . " withheld)\n"; exit($rErrors === [] ? 0 : 1); } if ((string) @file_get_contents($rTarget) !== $rBody) { fwrite(STDERR, "lb-settings-keys: src/Core/Cluster/lb_settings_keys.php is stale; run `bash tools/ci/lb-settings-keys.sh --write`\n"); exit(1); } if ($rErrors !== []) { exit(1); } echo 'OK: ' . count($rKeys) . " LB settings keys, allowlist current, every dynamic read annotated.\n";