Main.php 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. <?php
  2. namespace WhichBrowser\Model;
  3. use WhichBrowser\Model\Browser;
  4. use WhichBrowser\Model\Engine;
  5. use WhichBrowser\Model\Os;
  6. use WhichBrowser\Model\Device;
  7. class Main
  8. {
  9. /**
  10. * @var \WhichBrowser\Model\Browser $browser Information about the browser
  11. */
  12. public $browser;
  13. /**
  14. * @var \WhichBrowser\Model\Engine $engine Information about the rendering engine
  15. */
  16. public $engine;
  17. /**
  18. * @var \WhichBrowser\Model\Os $os Information about the operating system
  19. */
  20. public $os;
  21. /**
  22. * @var \WhichBrowser\Model\Device $device Information about the device
  23. */
  24. public $device;
  25. /**
  26. * @var boolean $camouflage Is the browser camouflaged as another browser
  27. */
  28. public $camouflage = false;
  29. /**
  30. * @var int[] $features
  31. */
  32. public $features = [];
  33. /**
  34. * Create default objects
  35. */
  36. public function __construct()
  37. {
  38. $this->browser = new Browser();
  39. $this->engine = new Engine();
  40. $this->os = new Os();
  41. $this->device = new Device();
  42. }
  43. /**
  44. * Check the name of a property and optionally is a specific version
  45. *
  46. * @internal
  47. *
  48. * @param string The name of the property, such as 'browser', 'engine' or 'os'
  49. * @param string The name of the browser that is checked
  50. * @param string Optional, the operator, must be <, <=, =, >= or >
  51. * @param mixed Optional, the value, can be an integer, float or string with a version number
  52. *
  53. * @return boolean
  54. */
  55. private function isX()
  56. {
  57. $arguments = func_get_args();
  58. $x = $arguments[0];
  59. if (count($arguments) < 2) {
  60. return false;
  61. }
  62. if (empty($this->$x->name)) {
  63. return false;
  64. }
  65. if ($this->$x->name != $arguments[1]) {
  66. return false;
  67. }
  68. if (count($arguments) >= 4) {
  69. if (empty($this->$x->version)) {
  70. return false;
  71. }
  72. if (!$this->$x->version->is($arguments[2], $arguments[3])) {
  73. return false;
  74. }
  75. }
  76. return true;
  77. }
  78. /**
  79. * Check the name of the browser and optionally is a specific version
  80. *
  81. * @param string The name of the browser that is checked
  82. * @param string Optional, the operator, must be <, <=, =, >= or >
  83. * @param mixed Optional, the value, can be an integer, float or string with a version number
  84. *
  85. * @return boolean
  86. */
  87. public function isBrowser()
  88. {
  89. $arguments = func_get_args();
  90. array_unshift($arguments, 'browser');
  91. return call_user_func_array([ $this, 'isX' ], $arguments);
  92. }
  93. /**
  94. * Check the name of the rendering engine and optionally is a specific version
  95. *
  96. * @param string The name of the rendering engine that is checked
  97. * @param string Optional, the operator, must be <, <=, =, >= or >
  98. * @param mixed Optional, the value, can be an integer, float or string with a version number
  99. *
  100. * @return boolean
  101. */
  102. public function isEngine()
  103. {
  104. $arguments = func_get_args();
  105. array_unshift($arguments, 'engine');
  106. return call_user_func_array([ $this, 'isX' ], $arguments);
  107. }
  108. /**
  109. * Check the name of the operating system and optionally is a specific version
  110. *
  111. * @param string The name of the operating system that is checked
  112. * @param string Optional, the operator, must be <, <=, =, >= or >
  113. * @param mixed Optional, the value, can be an integer, float or string with a version number
  114. *
  115. * @return boolean
  116. */
  117. public function isOs()
  118. {
  119. $arguments = func_get_args();
  120. array_unshift($arguments, 'os');
  121. return call_user_func_array([ $this, 'isX' ], $arguments);
  122. }
  123. /**
  124. * Check if the detected browser is of the specified type
  125. *
  126. * @param string $model The type, or a combination of type and subtime joined with a semicolon.
  127. *
  128. * @return boolean
  129. */
  130. public function isDevice($model)
  131. {
  132. return (!empty($this->device->series) && $this->device->series == $model) || (!empty($this->device->model) && $this->device->model == $model);
  133. }
  134. /**
  135. * Get the type and subtype, separated by a semicolon (if applicable)
  136. *
  137. * @return string
  138. */
  139. public function getType()
  140. {
  141. return $this->device->type . (!empty($this->device->subtype) ? ':' . $this->device->subtype : '');
  142. }
  143. /**
  144. * Check if the detected browser is of the specified type
  145. *
  146. * @param string The type, or a combination of type and subtype joined with a semicolon.
  147. * @param string Unlimited optional types to check
  148. *
  149. * @return boolean
  150. */
  151. public function isType()
  152. {
  153. $arguments = func_get_args();
  154. $count = count($arguments);
  155. for ($a = 0; $a < $count; $a++) {
  156. if (strpos($arguments[$a], ':') !== false) {
  157. list($type, $subtype) = explode(':', $arguments[$a]);
  158. if ($type == $this->device->type && $subtype == $this->device->subtype) {
  159. return true;
  160. }
  161. } else {
  162. if ($arguments[$a] == $this->device->type) {
  163. return true;
  164. }
  165. }
  166. }
  167. return false;
  168. }
  169. /**
  170. * Check if the detected browser is a mobile device
  171. *
  172. * @return boolean
  173. */
  174. public function isMobile()
  175. {
  176. return $this->isType('mobile', 'tablet', 'ereader', 'media', 'watch', 'camera', 'gaming:portable');
  177. }
  178. /**
  179. * Check if a browser was detected
  180. *
  181. * @return boolean
  182. */
  183. public function isDetected()
  184. {
  185. return $this->browser->isDetected() || $this->os->isDetected() || $this->engine->isDetected() || $this->device->isDetected();
  186. }
  187. /**
  188. * Return the input string prefixed with 'a' or 'an' depending on the first letter of the string
  189. *
  190. * @internal
  191. *
  192. * @param string $s The string that will be prefixed
  193. *
  194. * @return string
  195. */
  196. private function a($s)
  197. {
  198. return (preg_match("/^[aeiou]/i", $s) ? 'an ' : 'a ') . $s;
  199. }
  200. /**
  201. * Get a human readable string of the whole browser identification
  202. *
  203. * @return string
  204. */
  205. public function toString()
  206. {
  207. $prefix = $this->camouflage ? 'an unknown browser that imitates ' : '';
  208. $browser = $this->browser->toString();
  209. $os = $this->os->toString();
  210. $engine = $this->engine->toString();
  211. $device = $this->device->toString();
  212. if (empty($device) && empty($os) && $this->device->type == 'television') {
  213. $device = 'television';
  214. }
  215. if (empty($device) && $this->device->type == 'emulator') {
  216. $device = 'emulator';
  217. }
  218. if (!empty($browser) && !empty($os) && !empty($device)) {
  219. return $prefix . $browser . ' on ' . $this->a($device) . ' running ' . $os;
  220. }
  221. if (!empty($browser) && empty($os) && !empty($device)) {
  222. return $prefix . $browser . ' on ' . $this->a($device);
  223. }
  224. if (!empty($browser) && !empty($os) && empty($device)) {
  225. return $prefix . $browser . ' on ' . $os;
  226. }
  227. if (empty($browser) && !empty($os) && !empty($device)) {
  228. return $prefix . $this->a($device) . ' running ' . $os;
  229. }
  230. if (!empty($browser) && empty($os) && empty($device)) {
  231. return $prefix . $browser;
  232. }
  233. if (empty($browser) && empty($os) && !empty($device)) {
  234. return $prefix . $this->a($device);
  235. }
  236. if ($this->device->type == 'desktop' && !empty($os) && !empty($engine) && empty($device)) {
  237. return 'an unknown browser based on ' . $engine . ' running on ' . $os;
  238. }
  239. if ($this->browser->stock && !empty($os) && empty($device)) {
  240. return $os;
  241. }
  242. if ($this->browser->stock && !empty($engine) && empty($device)) {
  243. return 'an unknown browser based on ' . $engine;
  244. }
  245. if ($this->device->type == 'bot') {
  246. return 'an unknown bot';
  247. }
  248. return 'an unknown browser';
  249. }
  250. /**
  251. * Get a string containing a JavaScript representation of the object
  252. *
  253. * @return string
  254. */
  255. public function toJavaScript()
  256. {
  257. return "this.browser = new Browser({ " . $this->browser->toJavaScript() . " });\n" .
  258. "this.engine = new Engine({ " . $this->engine->toJavaScript() . " });\n" .
  259. "this.os = new Os({ " . $this->os->toJavaScript() . " });\n" .
  260. "this.device = new Device({ " . $this->device->toJavaScript() . " });\n" .
  261. "this.camouflage = " . ($this->camouflage ? 'true' : 'false') . ";\n" .
  262. "this.features = " . json_encode($this->features) . ";\n";
  263. }
  264. /**
  265. * Get an array of all defined properties
  266. *
  267. * @return array
  268. */
  269. public function toArray()
  270. {
  271. $result = [
  272. 'browser' => $this->browser->toArray(),
  273. 'engine' => $this->engine->toArray(),
  274. 'os' => $this->os->toArray(),
  275. 'device' => $this->device->toArray()
  276. ];
  277. if (!count($result['browser'])) {
  278. unset($result['browser']);
  279. }
  280. if (!count($result['engine'])) {
  281. unset($result['engine']);
  282. }
  283. if (!count($result['os'])) {
  284. unset($result['os']);
  285. }
  286. if (!count($result['device'])) {
  287. unset($result['device']);
  288. }
  289. if ($this->camouflage) {
  290. $result['camouflage'] = true;
  291. }
  292. return $result;
  293. }
  294. }