\d+)\.(?P\d+)\.(?P\d+)(?:-(?P(?:[0-9a-zA-Z-]+)(?:\.(?:[0-9a-zA-Z-]+))*))?(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/', $version, $m ) ) { throw new InvalidArgumentException( "Version number \"$version\" is not in a recognized format." ); } $info = array( 'major' => (int) $m['major'], 'minor' => (int) $m['minor'], 'patch' => (int) $m['patch'], 'version' => sprintf( '%d.%d.%d', $m['major'], $m['minor'], $m['patch'] ), 'prerelease' => isset( $m['prerelease'] ) && '' !== $m['prerelease'] ? $m['prerelease'] : null, 'buildinfo' => isset( $m['buildinfo'] ) && '' !== $m['buildinfo'] ? $m['buildinfo'] : null, ); if ( null !== $info['prerelease'] ) { $sep = ''; $prerelease = ''; foreach ( explode( '.', $info['prerelease'] ) as $part ) { if ( ctype_digit( $part ) ) { $part = (int) $part; } $prerelease .= $sep . $part; $sep = '.'; } $info['prerelease'] = $prerelease; } return $info; } /** * Compare two version numbers. * * @param string $a First version. * @param string $b Second version. * @return int Less than, equal to, or greater than 0 depending on whether `$a` is less than, equal to, or greater than `$b`. * @throws InvalidArgumentException If the version numbers are not in a recognized format. */ public static function compare( $a, $b ) { $aa = self::parse( $a ); $bb = self::parse( $b ); if ( $aa['major'] !== $bb['major'] ) { return $aa['major'] - $bb['major']; } if ( $aa['minor'] !== $bb['minor'] ) { return $aa['minor'] - $bb['minor']; } if ( $aa['patch'] !== $bb['patch'] ) { return $aa['patch'] - $bb['patch']; } if ( null === $aa['prerelease'] ) { return null === $bb['prerelease'] ? 0 : 1; } if ( null === $bb['prerelease'] ) { return -1; } $aaa = explode( '.', $aa['prerelease'] ); $bbb = explode( '.', $bb['prerelease'] ); $al = count( $aaa ); $bl = count( $bbb ); for ( $i = 0; $i < $al && $i < $bl; $i++ ) { $a = $aaa[ $i ]; $b = $bbb[ $i ]; if ( ctype_digit( $a ) ) { if ( ctype_digit( $b ) ) { if ( (int) $a !== (int) $b ) { return $a - $b; } } else { return -1; } } elseif ( ctype_digit( $b ) ) { return 1; } else { $tmp = strcmp( $a, $b ); if ( 0 !== $tmp ) { return $tmp; } } } return $al - $bl; } }