Derive.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. <?php
  2. namespace WhichBrowser\Analyser;
  3. use WhichBrowser\Constants;
  4. use WhichBrowser\Model\Family;
  5. use WhichBrowser\Model\Using;
  6. use WhichBrowser\Model\Version;
  7. trait Derive
  8. {
  9. private function &deriveInformation()
  10. {
  11. if (isset($this->data->device->flag)) {
  12. $this->deriveBasedOnDeviceFlag();
  13. }
  14. if (isset($this->data->os->name)) {
  15. $this->deriveBasedOnOperatingSystem();
  16. }
  17. if (isset($this->data->browser->name)) {
  18. $this->deriveOperaDevices();
  19. }
  20. if (isset($this->data->browser->name)) {
  21. $this->deriveFirefoxOS();
  22. }
  23. if (isset($this->data->browser->name)) {
  24. $this->deriveTrident();
  25. $this->deriveOperaRenderingEngine();
  26. $this->deriveOmniWebRenderingEngine();
  27. $this->deriveNetFrontRenderingEngine();
  28. }
  29. return $this;
  30. }
  31. private function &deriveDeviceSubType()
  32. {
  33. if ($this->data->device->type == 'mobile' && empty($this->data->device->subtype)) {
  34. $this->data->device->subtype = 'feature';
  35. if (in_array($this->data->os->getName(), [ 'Android', 'Bada', 'BlackBerry', 'BlackBerry OS', 'Firefox OS', 'iOS', 'iPhone OS', 'Kin OS', 'Maemo', 'MeeGo', 'Palm OS', 'Sailfish', 'Series60', 'Series80', 'Tizen', 'Ubuntu Touch', 'Windows Mobile', 'Windows Phone', 'webOS' ])) {
  36. $this->data->device->subtype = 'smart';
  37. }
  38. if (isset($this->data->os->name) && in_array($this->data->os->name, [ 'Windows Phone' ])) {
  39. $this->data->device->subtype = 'smart';
  40. }
  41. if (isset($this->data->os->family) && in_array($this->data->os->family->getName(), [ 'Android' ])) {
  42. $this->data->device->subtype = 'smart';
  43. }
  44. }
  45. return $this;
  46. }
  47. private function deriveOmniWebRenderingEngine()
  48. {
  49. if ($this->data->isBrowser('OmniWeb')) {
  50. $version = $this->data->browser->getVersion();
  51. if ($version < 5) {
  52. $this->data->engine->reset();
  53. }
  54. if ($version >= 5 && $version < 5.5 && !$this->data->isEngine('WebCore')) {
  55. $this->data->engine->reset([ 'name' => 'WebCore' ]);
  56. }
  57. if ($version >= 5.5 && !$this->data->isEngine('WebKit')) {
  58. $this->data->engine->reset([ 'name' => 'WebKit' ]);
  59. }
  60. }
  61. }
  62. private function deriveOperaRenderingEngine()
  63. {
  64. if ($this->data->isBrowser('Opera') || $this->data->isBrowser('Opera Mobile')) {
  65. $version = $this->data->browser->getVersion();
  66. if ($version >= 3.5 && $version < 7 && !$this->data->isEngine('Electra')) {
  67. $this->data->engine->reset([ 'name' => 'Electra' ]);
  68. }
  69. if ($version >= 7 && $version < 13 && !$this->data->isEngine('Presto')) {
  70. $this->data->engine->reset([ 'name' => 'Presto' ]);
  71. }
  72. }
  73. if ($this->data->isBrowser('Opera Mini') && !$this->data->isOs('iOS') && !$this->data->isEngine('Presto')) {
  74. $this->data->engine->reset([ 'name' => 'Presto' ]);
  75. }
  76. }
  77. private function deriveNetFrontRenderingEngine()
  78. {
  79. if ($this->data->isBrowser('NetFront') && !$this->data->isEngine('NetFront')) {
  80. $this->data->engine->reset([ 'name' => 'NetFront' ]);
  81. }
  82. }
  83. private function deriveTrident()
  84. {
  85. if ($this->data->isType('desktop') && $this->data->isBrowser('Internet Explorer') && !$this->data->engine->getName()) {
  86. if ($this->data->isBrowser('Internet Explorer', '>=', 4)) {
  87. $this->data->engine->set([ 'name' => 'Trident' ]);
  88. }
  89. }
  90. if ($this->data->isMobile() && $this->data->isBrowser('Mobile Internet Explorer') && !$this->data->engine->getName()) {
  91. if ($this->data->isBrowser('Mobile Internet Explorer', '=', 6)) {
  92. $this->data->engine->set([ 'name' => 'Trident' ]);
  93. }
  94. if ($this->data->isBrowser('Mobile Internet Explorer', '=', 7)) {
  95. $this->data->engine->set([ 'name' => 'Trident', 'version' => new Version([ 'value' => '3.1' ]) ]);
  96. }
  97. }
  98. }
  99. private function deriveFirefoxOS()
  100. {
  101. if (in_array($this->data->browser->name, [ 'Firefox Mobile', 'Servo Nightly Build' ]) && !isset($this->data->os->name)) {
  102. $this->data->os->name = 'Firefox OS';
  103. }
  104. if (isset($this->data->os->name) && $this->data->os->name == 'Firefox OS' && $this->data->engine->name == 'Gecko') {
  105. switch ($this->data->engine->getVersion()) {
  106. case '18.0':
  107. $this->data->os->version = new Version([ 'value' => '1.0.1' ]);
  108. break;
  109. case '18.1':
  110. $this->data->os->version = new Version([ 'value' => '1.1' ]);
  111. break;
  112. case '26.0':
  113. $this->data->os->version = new Version([ 'value' => '1.2' ]);
  114. break;
  115. case '28.0':
  116. $this->data->os->version = new Version([ 'value' => '1.3' ]);
  117. break;
  118. case '30.0':
  119. $this->data->os->version = new Version([ 'value' => '1.4' ]);
  120. break;
  121. case '32.0':
  122. $this->data->os->version = new Version([ 'value' => '2.0' ]);
  123. break;
  124. case '34.0':
  125. $this->data->os->version = new Version([ 'value' => '2.1' ]);
  126. break;
  127. case '37.0':
  128. $this->data->os->version = new Version([ 'value' => '2.2' ]);
  129. break;
  130. case '44.0':
  131. $this->data->os->version = new Version([ 'value' => '2.5' ]);
  132. break;
  133. }
  134. }
  135. }
  136. private function deriveOperaDevices()
  137. {
  138. if ($this->data->browser->name == 'Opera' && $this->data->device->type == Constants\DeviceType::TELEVISION) {
  139. $this->data->browser->name = 'Opera Devices';
  140. $this->data->browser->version = null;
  141. if ($this->data->engine->getName() == 'Presto') {
  142. $data = [
  143. '2.12' => '3.4',
  144. '2.11' => '3.3',
  145. '2.10' => '3.2',
  146. '2.9' => '3.1',
  147. '2.8' => '3.0',
  148. '2.7' => '2.9',
  149. '2.6' => '2.8',
  150. '2.4' => '10.3',
  151. '2.3' => '10',
  152. '2.2' => '9.7',
  153. '2.1' => '9.6'
  154. ];
  155. $key = implode('.', array_slice(explode('.', $this->data->engine->getVersion()), 0, 2));
  156. if (isset($data[$key])) {
  157. $this->data->browser->version = new Version([ 'value' => $data[$key] ]);
  158. } else {
  159. unset($this->data->browser->version);
  160. }
  161. }
  162. $this->data->os->reset();
  163. }
  164. }
  165. private function deriveBasedOnDeviceFlag()
  166. {
  167. $flag = $this->data->device->flag;
  168. if ($flag == Constants\Flag::NOKIAX) {
  169. $this->data->os->name = 'Nokia X Platform';
  170. $this->data->os->family = new Family([ 'name' => 'Android' ]);
  171. unset($this->data->os->version);
  172. unset($this->data->device->flag);
  173. }
  174. if ($flag == Constants\Flag::FIREOS) {
  175. $this->data->os->name = 'FireOS';
  176. $this->data->os->family = new Family([ 'name' => 'Android' ]);
  177. if (isset($this->data->os->version) && isset($this->data->os->version->value)) {
  178. switch ($this->data->os->version->value) {
  179. case '2.3.3':
  180. case '2.3.4':
  181. $this->data->os->version = new Version([ 'value' => '1' ]);
  182. break;
  183. case '4.0.3':
  184. $this->data->os->version = new Version([ 'value' => '2' ]);
  185. break;
  186. case '4.2.2':
  187. $this->data->os->version = new Version([ 'value' => '3' ]);
  188. break;
  189. case '4.4.2':
  190. $this->data->os->version = new Version([ 'value' => '4' ]);
  191. break;
  192. case '4.4.3':
  193. $this->data->os->version = new Version([ 'value' => '4.5' ]);
  194. break;
  195. case '5.1.1':
  196. $this->data->os->version = new Version([ 'value' => '5' ]);
  197. break;
  198. default:
  199. unset($this->data->os->version);
  200. break;
  201. }
  202. }
  203. if ($this->data->isBrowser('Chrome')) {
  204. $this->data->browser->reset();
  205. $this->data->browser->using = new Using([ 'name' => 'Amazon WebView' ]);
  206. }
  207. if ($this->data->browser->isUsing('Chromium WebView')) {
  208. $this->data->browser->using = new Using([ 'name' => 'Amazon WebView' ]);
  209. }
  210. unset($this->data->device->flag);
  211. }
  212. if ($flag == Constants\Flag::GOOGLETV) {
  213. $this->data->os->name = 'Google TV';
  214. $this->data->os->family = new Family([ 'name' => 'Android' ]);
  215. unset($this->data->os->version);
  216. unset($this->data->device->flag);
  217. }
  218. if ($flag == Constants\Flag::ANDROIDTV) {
  219. $this->data->os->name = 'Android TV';
  220. $this->data->os->family = new Family([ 'name' => 'Android' ]);
  221. unset($this->data->device->flag);
  222. unset($this->data->device->series);
  223. }
  224. if ($flag == Constants\Flag::ANDROIDWEAR) {
  225. $this->data->os->name = 'Android Wear';
  226. $this->data->os->family = new Family([ 'name' => 'Android' ]);
  227. unset($this->data->os->version);
  228. unset($this->data->device->flag);
  229. if ($this->data->browser->isUsing('Chrome Content Shell')) {
  230. $this->data->browser->name = 'Wear Internet Browser';
  231. $this->data->browser->using = null;
  232. }
  233. }
  234. if ($flag == Constants\Flag::GOOGLEGLASS) {
  235. $this->data->os->family = new Family([ 'name' => 'Android' ]);
  236. unset($this->data->os->name);
  237. unset($this->data->os->version);
  238. unset($this->data->device->flag);
  239. }
  240. if ($flag == Constants\Flag::UIQ) {
  241. unset($this->data->device->flag);
  242. if (!$this->data->isOs('UIQ')) {
  243. $this->data->os->name = 'UIQ';
  244. unset($this->data->os->version);
  245. }
  246. }
  247. if ($flag == Constants\Flag::S60) {
  248. unset($this->data->device->flag);
  249. if (!$this->data->isOs('Series60')) {
  250. $this->data->os->name = 'Series60';
  251. unset($this->data->os->version);
  252. }
  253. }
  254. if ($flag == Constants\Flag::MOAPS) {
  255. unset($this->data->device->flag);
  256. $this->data->os->name = 'MOAP(S)';
  257. unset($this->data->os->version);
  258. }
  259. }
  260. private function deriveBasedOnOperatingSystem()
  261. {
  262. /* Derive the default browser on Windows Mobile */
  263. if ($this->data->os->name == 'Windows Mobile' && $this->data->isBrowser('Internet Explorer')) {
  264. $this->data->browser->name = 'Mobile Internet Explorer';
  265. }
  266. /* Derive the default browser on Android */
  267. if ($this->data->os->name == 'Android' && !isset($this->data->browser->using) && !isset($this->data->browser->name) && $this->data->browser->stock) {
  268. $this->data->browser->name = 'Android Browser';
  269. }
  270. /* Derive the default browser on Google TV */
  271. if ($this->data->os->name == 'Google TV' && !isset($this->data->browser->name) && $this->data->browser->stock) {
  272. $this->data->browser->name = 'Chrome';
  273. }
  274. /* Derive the default browser on BlackBerry */
  275. if ($this->data->os->name == 'BlackBerry' && !isset($this->data->browser->name) && $this->data->browser->stock) {
  276. $this->data->browser->name = 'BlackBerry Browser';
  277. $this->data->browser->hidden = true;
  278. }
  279. if ($this->data->os->name == 'BlackBerry OS' && !isset($this->data->browser->name) && $this->data->browser->stock) {
  280. $this->data->browser->name = 'BlackBerry Browser';
  281. $this->data->browser->hidden = true;
  282. }
  283. if ($this->data->os->name == 'BlackBerry Tablet OS' && !isset($this->data->browser->name) && $this->data->browser->stock) {
  284. $this->data->browser->name = 'BlackBerry Browser';
  285. $this->data->browser->hidden = true;
  286. }
  287. /* Derive the default browser on Tizen */
  288. if ($this->data->os->name == 'Tizen' && !isset($this->data->browser->name) && $this->data->browser->stock && in_array($this->data->device->type, [ Constants\DeviceType::MOBILE, Constants\DeviceType::APPLIANCE ])) {
  289. $this->data->browser->name = 'Samsung Browser';
  290. }
  291. /* Derive the default browser on Aliyun OS */
  292. if ($this->data->os->name == 'Aliyun OS' && !isset($this->data->browser->using) && !isset($this->data->browser->name) && $this->data->browser->stock) {
  293. $this->data->browser->name = 'Aliyun Browser';
  294. }
  295. if ($this->data->os->name == 'Aliyun OS' && $this->data->browser->isUsing('Chrome Content Shell')) {
  296. $this->data->browser->name = 'Aliyun Browser';
  297. $this->data->browser->using = null;
  298. $this->data->browser->stock = true;
  299. }
  300. if ($this->data->os->name == 'Aliyun OS' && $this->data->browser->stock) {
  301. $this->data->browser->hidden = true;
  302. }
  303. /* Derive OS/2 nickname */
  304. if ($this->data->os->name == 'OS/2') {
  305. if (!empty($this->data->os->version)) {
  306. if ($this->data->os->version->is('>', '2')) {
  307. $this->data->os->version->nickname = 'Warp';
  308. }
  309. }
  310. }
  311. /* Derive HP TouchPad based on webOS and tablet */
  312. if ($this->data->os->name == 'webOS' && $this->data->device->type == Constants\DeviceType::TABLET) {
  313. $this->data->device->manufacturer = 'HP';
  314. $this->data->device->model = 'TouchPad';
  315. $this->data->device->identified |= Constants\Id::MATCH_UA;
  316. }
  317. /* Derive Windows 10 Mobile edition */
  318. if ($this->data->os->name == 'Windows Phone') {
  319. if (!empty($this->data->os->version)) {
  320. if ($this->data->os->version->is('=', '10')) {
  321. $this->data->os->alias = 'Windows';
  322. $this->data->os->edition = 'Mobile';
  323. $this->data->os->version->alias = '10';
  324. }
  325. }
  326. }
  327. /* Derive manufacturer and model based on MacOS or OS X */
  328. if ($this->data->os->name == 'OS X' || $this->data->os->name == 'Mac OS') {
  329. if (empty($this->data->device->model)) {
  330. $this->data->device->manufacturer = 'Apple';
  331. $this->data->device->model = 'Macintosh';
  332. $this->data->device->identified |= Constants\Id::INFER;
  333. $this->data->device->hidden = true;
  334. }
  335. }
  336. /* Derive manufacturer and model based on MacOS or OS X */
  337. if ($this->data->os->name == 'iOS') {
  338. if (empty($this->data->device->model)) {
  339. $this->data->device->manufacturer = 'Apple';
  340. $this->data->device->identified |= Constants\Id::INFER;
  341. $this->data->device->hidden = true;
  342. }
  343. }
  344. /* Derive iOS and OS X aliases */
  345. if ($this->data->os->name == 'iOS') {
  346. if (!empty($this->data->os->version)) {
  347. if ($this->data->os->version->is('<', '4')) {
  348. $this->data->os->alias = 'iPhone OS';
  349. }
  350. }
  351. }
  352. if ($this->data->os->name == 'OS X') {
  353. if (!empty($this->data->os->version)) {
  354. if ($this->data->os->version->is('<', '10.7')) {
  355. $this->data->os->alias = 'Mac OS X';
  356. }
  357. if ($this->data->os->version->is('>=', '10.12')) {
  358. $this->data->os->alias = 'macOS';
  359. }
  360. if ($this->data->os->version->is('10.7')) {
  361. $this->data->os->version->nickname = 'Lion';
  362. }
  363. if ($this->data->os->version->is('10.8')) {
  364. $this->data->os->version->nickname = 'Mountain Lion';
  365. }
  366. if ($this->data->os->version->is('10.9')) {
  367. $this->data->os->version->nickname = 'Mavericks';
  368. }
  369. if ($this->data->os->version->is('10.10')) {
  370. $this->data->os->version->nickname = 'Yosemite';
  371. }
  372. if ($this->data->os->version->is('10.11')) {
  373. $this->data->os->version->nickname = 'El Capitan';
  374. }
  375. if ($this->data->os->version->is('10.12')) {
  376. $this->data->os->version->nickname = 'Sierra';
  377. }
  378. }
  379. }
  380. }
  381. }