Version.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. <?php
  2. namespace WhichBrowser\Model;
  3. use WhichBrowser\Model\Primitive\Base;
  4. class Version extends Base
  5. {
  6. /** @var string|null */
  7. public $value = null;
  8. /** @var boolean */
  9. public $hidden = false;
  10. /** @var string */
  11. public $nickname;
  12. /** @var string */
  13. public $alias;
  14. /** @var int */
  15. public $details;
  16. /** @var boolean */
  17. public $builds;
  18. /**
  19. * Determine if the version is lower, equal or higher than the specified value
  20. *
  21. * @param string The operator, must be <, <=, =, >= or >
  22. * @param mixed The value, can be an integer, float or string with a version number
  23. *
  24. * @return boolean
  25. */
  26. public function is()
  27. {
  28. $valid = false;
  29. $arguments = func_get_args();
  30. if (count($arguments)) {
  31. $operator = '=';
  32. $compare = null;
  33. if (count($arguments) == 1) {
  34. $compare = $arguments[0];
  35. }
  36. if (count($arguments) >= 2) {
  37. $operator = $arguments[0];
  38. $compare = $arguments[1];
  39. }
  40. if (!is_null($compare)) {
  41. $min = min(substr_count($this->value, '.'), substr_count($compare, '.')) + 1;
  42. $v1 = $this->toValue($this->value, $min);
  43. $v2 = $this->toValue($compare, $min);
  44. switch ($operator) {
  45. case '<':
  46. $valid = $v1 < $v2;
  47. break;
  48. case '<=':
  49. $valid = $v1 <= $v2;
  50. break;
  51. case '=':
  52. $valid = $v1 == $v2;
  53. break;
  54. case '>':
  55. $valid = $v1 > $v2;
  56. break;
  57. case '>=':
  58. $valid = $v1 >= $v2;
  59. break;
  60. }
  61. }
  62. }
  63. return $valid;
  64. }
  65. /**
  66. * Return an object with each part of the version number
  67. *
  68. * @return object
  69. */
  70. public function getParts()
  71. {
  72. $parts = explode('.', $this->value);
  73. return (object) [
  74. 'major' => !empty($parts[0]) ? intval($parts[0]) : 0,
  75. 'minor' => !empty($parts[1]) ? intval($parts[1]) : 0,
  76. 'patch' => !empty($parts[2]) ? intval($parts[2]) : 0,
  77. ];
  78. }
  79. /**
  80. * Return the major version as an integer
  81. *
  82. * @return integer
  83. */
  84. public function getMajor()
  85. {
  86. return $this->getParts()->major;
  87. }
  88. /**
  89. * Return the minor version as an integer
  90. *
  91. * @return integer
  92. */
  93. public function getMinor()
  94. {
  95. return $this->getParts()->minor;
  96. }
  97. /**
  98. * Return the patch number as an integer
  99. *
  100. * @return integer
  101. */
  102. public function getPatch()
  103. {
  104. return $this->getParts()->patch;
  105. }
  106. /**
  107. * Convert a version string seperated by dots into a float that can be compared
  108. *
  109. * @internal
  110. *
  111. * @param string Version string, with elements seperated by a dot
  112. * @param int The maximum precision
  113. *
  114. * @return float
  115. */
  116. private function toValue($value = null, $count = null)
  117. {
  118. if (is_null($value)) {
  119. $value = $this->value;
  120. }
  121. $parts = explode('.', $value);
  122. if (!is_null($count)) {
  123. $parts = array_slice($parts, 0, $count);
  124. }
  125. $result = $parts[0];
  126. if (count($parts) > 1) {
  127. $result .= '.';
  128. $count = count($parts);
  129. for ($p = 1; $p < $count; $p++) {
  130. $result .= substr('0000' . $parts[$p], -4);
  131. }
  132. }
  133. return floatval($result);
  134. }
  135. /**
  136. * Return the version as a float
  137. *
  138. * @return float
  139. */
  140. public function toFloat()
  141. {
  142. return floatval($this->value);
  143. }
  144. /**
  145. * Return the version as an integer
  146. *
  147. * @return int
  148. */
  149. public function toNumber()
  150. {
  151. return intval($this->value);
  152. }
  153. /**
  154. * Return the version as a human readable string
  155. *
  156. * @return string
  157. */
  158. public function toString()
  159. {
  160. if (!empty($this->alias)) {
  161. return $this->alias;
  162. }
  163. $version = '';
  164. if (!empty($this->nickname)) {
  165. $version .= $this->nickname . ' ';
  166. }
  167. if (!empty($this->value)) {
  168. if (preg_match("/([0-9]+)(?:\.([0-9]+))?(?:\.([0-9]+))?(?:\.([0-9]+))?(?:([ab])([0-9]+))?/", $this->value, $match)) {
  169. $v = [ $match[1] ];
  170. if (array_key_exists(2, $match) && strlen($match[2])) {
  171. $v[] = $match[2];
  172. }
  173. if (array_key_exists(3, $match) && strlen($match[3])) {
  174. $v[] = $match[3];
  175. }
  176. if (array_key_exists(4, $match) && strlen($match[4])) {
  177. $v[] = $match[4];
  178. }
  179. if (!empty($this->details)) {
  180. if ($this->details < 0) {
  181. array_splice($v, $this->details, 0 - $this->details);
  182. }
  183. if ($this->details > 0) {
  184. array_splice($v, $this->details, count($v) - $this->details);
  185. }
  186. }
  187. if (isset($this->builds) && !$this->builds) {
  188. $count = count($v);
  189. for ($i = 0; $i < $count; $i++) {
  190. if ($v[$i] > 999) {
  191. array_splice($v, $i, 1);
  192. }
  193. }
  194. }
  195. $version .= implode($v, '.');
  196. if (array_key_exists(5, $match) && strlen($match[5])) {
  197. $version .= $match[5] . (!empty($match[6]) ? $match[6] : '');
  198. }
  199. }
  200. }
  201. return $version;
  202. }
  203. /**
  204. * Get an array of all defined properties
  205. *
  206. * @internal
  207. *
  208. * @return array
  209. */
  210. public function toArray()
  211. {
  212. $result = [];
  213. if (!empty($this->value)) {
  214. if (!empty($this->details)) {
  215. $parts = explode('.', $this->value);
  216. $result['value'] = join('.', array_slice($parts, 0, $this->details));
  217. } else {
  218. $result['value'] = $this->value;
  219. }
  220. }
  221. if (!empty($this->alias)) {
  222. $result['alias'] = $this->alias;
  223. }
  224. if (!empty($this->nickname)) {
  225. $result['nickname'] = $this->nickname;
  226. }
  227. if (isset($result['value']) && !isset($result['alias']) && !isset($result['nickname'])) {
  228. return $result['value'];
  229. }
  230. return $result;
  231. }
  232. }