← All changes
|
jetpack_vendor/automattic/jetpack-assets/src/class-semver.php
+121
-0
16.2-beta
→
16.3-beta
View file →
| @@ -1,0 +1,121 @@ | ||
| 1 | +<?php | |
| 2 | +/** | |
| 3 | + * Simple semver version handling. | |
| 4 | + * | |
| 5 | + * We use this instead of something like `composer/semver` to avoid | |
| 6 | + * plugins needing to include yet-another dependency package. The | |
| 7 | + * amount of code we need here is pretty small. | |
| 8 | + * | |
| 9 | + * We use this instead of PHP's `version_compare()` because that doesn't | |
| 10 | + * handle prerelease versions in the way anyone other than PHP devs would | |
| 11 | + * expect, and silently breaks on various unexpected input. | |
| 12 | + * | |
| 13 | + * @package automattic/jetpack-assets | |
| 14 | + */ | |
| 15 | + | |
| 16 | +namespace Automattic\Jetpack\Assets; | |
| 17 | + | |
| 18 | +use InvalidArgumentException; | |
| 19 | + | |
| 20 | +/** | |
| 21 | + * Simple semver version handling. | |
| 22 | + */ | |
| 23 | +class Semver { | |
| 24 | + /** | |
| 25 | + * Parse a semver version. | |
| 26 | + * | |
| 27 | + * @param string $version Version. | |
| 28 | + * @return array With components: | |
| 29 | + * - major: (int) Major version. | |
| 30 | + * - minor: (int) Minor version. | |
| 31 | + * - patch: (int) Patch version. | |
| 32 | + * - version: (string) Major.minor.patch. | |
| 33 | + * - prerelease: (string|null) Pre-release string. | |
| 34 | + * - buildinfo: (string|null) Build metadata string. | |
| 35 | + * @throws InvalidArgumentException If the version number is not in a recognized format. | |
| 36 | + */ | |
| 37 | + public static function parse( $version ) { | |
| 38 | + // This is slightly looser than the official version from semver.org, in that leading zeros are allowed. | |
| 39 | + if ( ! preg_match( '/^(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<prerelease>(?:[0-9a-zA-Z-]+)(?:\.(?:[0-9a-zA-Z-]+))*))?(?:\+(?P<buildinfo>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/', $version, $m ) ) { | |
| 40 | + throw new InvalidArgumentException( "Version number \"$version\" is not in a recognized format." ); | |
| 41 | + } | |
| 42 | + $info = array( | |
| 43 | + 'major' => (int) $m['major'], | |
| 44 | + 'minor' => (int) $m['minor'], | |
| 45 | + 'patch' => (int) $m['patch'], | |
| 46 | + 'version' => sprintf( '%d.%d.%d', $m['major'], $m['minor'], $m['patch'] ), | |
| 47 | + 'prerelease' => isset( $m['prerelease'] ) && '' !== $m['prerelease'] ? $m['prerelease'] : null, | |
| 48 | + 'buildinfo' => isset( $m['buildinfo'] ) && '' !== $m['buildinfo'] ? $m['buildinfo'] : null, | |
| 49 | + ); | |
| 50 | + | |
| 51 | + if ( null !== $info['prerelease'] ) { | |
| 52 | + $sep = ''; | |
| 53 | + $prerelease = ''; | |
| 54 | + foreach ( explode( '.', $info['prerelease'] ) as $part ) { | |
| 55 | + if ( ctype_digit( $part ) ) { | |
| 56 | + $part = (int) $part; | |
| 57 | + } | |
| 58 | + $prerelease .= $sep . $part; | |
| 59 | + $sep = '.'; | |
| 60 | + } | |
| 61 | + $info['prerelease'] = $prerelease; | |
| 62 | + } | |
| 63 | + | |
| 64 | + return $info; | |
| 65 | + } | |
| 66 | + | |
| 67 | + /** | |
| 68 | + * Compare two version numbers. | |
| 69 | + * | |
| 70 | + * @param string $a First version. | |
| 71 | + * @param string $b Second version. | |
| 72 | + * @return int Less than, equal to, or greater than 0 depending on whether `$a` is less than, equal to, or greater than `$b`. | |
| 73 | + * @throws InvalidArgumentException If the version numbers are not in a recognized format. | |
| 74 | + */ | |
| 75 | + public static function compare( $a, $b ) { | |
| 76 | + $aa = self::parse( $a ); | |
| 77 | + $bb = self::parse( $b ); | |
| 78 | + if ( $aa['major'] !== $bb['major'] ) { | |
| 79 | + return $aa['major'] - $bb['major']; | |
| 80 | + } | |
| 81 | + if ( $aa['minor'] !== $bb['minor'] ) { | |
| 82 | + return $aa['minor'] - $bb['minor']; | |
| 83 | + } | |
| 84 | + if ( $aa['patch'] !== $bb['patch'] ) { | |
| 85 | + return $aa['patch'] - $bb['patch']; | |
| 86 | + } | |
| 87 | + | |
| 88 | + if ( null === $aa['prerelease'] ) { | |
| 89 | + return null === $bb['prerelease'] ? 0 : 1; | |
| 90 | + } | |
| 91 | + if ( null === $bb['prerelease'] ) { | |
| 92 | + return -1; | |
| 93 | + } | |
| 94 | + | |
| 95 | + $aaa = explode( '.', $aa['prerelease'] ); | |
| 96 | + $bbb = explode( '.', $bb['prerelease'] ); | |
| 97 | + $al = count( $aaa ); | |
| 98 | + $bl = count( $bbb ); | |
| 99 | + for ( $i = 0; $i < $al && $i < $bl; $i++ ) { | |
| 100 | + $a = $aaa[ $i ]; | |
| 101 | + $b = $bbb[ $i ]; | |
| 102 | + if ( ctype_digit( $a ) ) { | |
| 103 | + if ( ctype_digit( $b ) ) { | |
| 104 | + if ( (int) $a !== (int) $b ) { | |
| 105 | + return (int) $a - (int) $b; | |
| 106 | + } | |
| 107 | + } else { | |
| 108 | + return -1; | |
| 109 | + } | |
| 110 | + } elseif ( ctype_digit( $b ) ) { | |
| 111 | + return 1; | |
| 112 | + } else { | |
| 113 | + $tmp = strcmp( $a, $b ); | |
| 114 | + if ( 0 !== $tmp ) { | |
| 115 | + return $tmp; | |
| 116 | + } | |
| 117 | + } | |
| 118 | + } | |
| 119 | + return $al - $bl; | |
| 120 | + } | |
| 121 | +} | |