{ lib, allVersions, }: let inherit (lib) splitString split trim map substring stringToCharacters foldr elemAt filter isString; inherit (lib.lists) findFirstIndex; inherit (lib.strings) charToInt compareVersions; in composerJson: let versionComparesForOperations = { "=" = i: i == 0; ">" = i: i > 0; "<" = i: i < 0; ">=" = i: i >= 0; "<=" = i: i <= 0; }; isInt = c: let ascii = charToInt c; zero = charToInt "0"; nine = charToInt "9"; in ascii >= zero && ascii <= nine; splitConstraint = constraint: let trimmed = trim constraint; startIndex = findFirstIndex isInt 0 (stringToCharacters constraint); in [(substring 0 startIndex trimmed) (substring startIndex (-1) trimmed)]; matchesSingleConstraint = constraint: version: let parts = splitConstraint constraint; cmp = elemAt parts 0; against = elemAt parts 1; in versionComparesForOperations.${cmp} (compareVersions version against); splitOrParts = expr: map trim (splitString "||" expr); splitAndParts = expr: filter isString (split "[, ]+" expr); foldAnd = foldr (a: b: a && b) true; foldOr = foldr (a: b: a || b) false; matchesAnd = expression: version: foldAnd (map (ex: matchesSingleConstraint ex version) (splitAndParts expression)); matchesConstraint = expression: version: foldOr (map (ex: matchesAnd ex version) (splitOrParts expression)); phpConstraint = composerJson.require.php; matches = matchesConstraint phpConstraint; in { inherit (composerJson) name; version = if (composerJson ? version) then composerJson.version else "0.0.0"; phpVersions = filter matches allVersions; }