Commit fb724c0b7f08e51d20d11ba1f06c9b4b2bdab75c
1 parent
94c48719ea
Exists in
master
test
Showing 9 changed files with 3795 additions and 0 deletions Inline Diff
- k2shop/usr/k2shop/libs/browser/Browser.php
- k2shop/usr/k2shop/libs/browser/Readme.txt
- k2shop/usr/k2shop/libs/detectDevice/DetectDeviceTest.php
- k2shop/usr/k2shop/libs/detectDevice/README.md
- k2shop/usr/k2shop/libs/detectDevice/class.DetectDevice.php
- k2shop/usr/k2shop/libs/nestmenu/index.html
- k2shop/usr/k2shop/libs/nestmenu/jquery.nestable.js
- k2shop/usr/k2shop/libs/nestmenu/nestable.css
- k2shop/usr/k2shop/libs/yaml/Spyc.php
k2shop/usr/k2shop/libs/browser/Browser.php
| File was created | 1 | <?php | |
| 2 | |||
| 3 | /** | ||
| 4 | * File: Browser.php | ||
| 5 | * Author: Chris Schuld (http://chrisschuld.com/) | ||
| 6 | * Last Modified: July 22nd, 2016 | ||
| 7 | * @version 2.0 | ||
| 8 | * @package PegasusPHP | ||
| 9 | * | ||
| 10 | * Copyright (C) 2008-2010 Chris Schuld (chris@chrisschuld.com) | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or | ||
| 13 | * modify it under the terms of the GNU General Public License as | ||
| 14 | * published by the Free Software Foundation; either version 2 of | ||
| 15 | * the License, or (at your option) any later version. | ||
| 16 | * | ||
| 17 | * This program is distributed in the hope that it will be useful, | ||
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | * GNU General Public License for more details at: | ||
| 21 | * http://www.gnu.org/copyleft/gpl.html | ||
| 22 | * | ||
| 23 | * | ||
| 24 | * Typical Usage: | ||
| 25 | * | ||
| 26 | * $browser = new Browser(); | ||
| 27 | * if( $browser->getBrowser() == Browser::BROWSER_FIREFOX && $browser->getVersion() >= 2 ) { | ||
| 28 | * echo 'You have FireFox version 2 or greater'; | ||
| 29 | * } | ||
| 30 | * | ||
| 31 | * User Agents Sampled from: http://www.useragentstring.com/ | ||
| 32 | * | ||
| 33 | * This implementation is based on the original work from Gary White | ||
| 34 | * http://apptools.com/phptools/browser/ | ||
| 35 | * | ||
| 36 | */ | ||
| 37 | class Browser | ||
| 38 | { | ||
| 39 | private $_agent = ''; | ||
| 40 | private $_browser_name = ''; | ||
| 41 | private $_version = ''; | ||
| 42 | private $_platform = ''; | ||
| 43 | private $_os = ''; | ||
| 44 | private $_is_aol = false; | ||
| 45 | private $_is_mobile = false; | ||
| 46 | private $_is_tablet = false; | ||
| 47 | private $_is_robot = false; | ||
| 48 | private $_is_facebook = false; | ||
| 49 | private $_aol_version = ''; | ||
| 50 | |||
| 51 | const BROWSER_UNKNOWN = 'unknown'; | ||
| 52 | const VERSION_UNKNOWN = 'unknown'; | ||
| 53 | |||
| 54 | const BROWSER_OPERA = 'Opera'; // http://www.opera.com/ | ||
| 55 | const BROWSER_OPERA_MINI = 'Opera Mini'; // http://www.opera.com/mini/ | ||
| 56 | const BROWSER_WEBTV = 'WebTV'; // http://www.webtv.net/pc/ | ||
| 57 | const BROWSER_EDGE = 'Edge'; // https://www.microsoft.com/edge | ||
| 58 | const BROWSER_IE = 'Internet Explorer'; // http://www.microsoft.com/ie/ | ||
| 59 | const BROWSER_POCKET_IE = 'Pocket Internet Explorer'; // http://en.wikipedia.org/wiki/Internet_Explorer_Mobile | ||
| 60 | const BROWSER_KONQUEROR = 'Konqueror'; // http://www.konqueror.org/ | ||
| 61 | const BROWSER_ICAB = 'iCab'; // http://www.icab.de/ | ||
| 62 | const BROWSER_OMNIWEB = 'OmniWeb'; // http://www.omnigroup.com/applications/omniweb/ | ||
| 63 | const BROWSER_FIREBIRD = 'Firebird'; // http://www.ibphoenix.com/ | ||
| 64 | const BROWSER_FIREFOX = 'Firefox'; // http://www.mozilla.com/en-US/firefox/firefox.html | ||
| 65 | const BROWSER_ICEWEASEL = 'Iceweasel'; // http://www.geticeweasel.org/ | ||
| 66 | const BROWSER_SHIRETOKO = 'Shiretoko'; // http://wiki.mozilla.org/Projects/shiretoko | ||
| 67 | const BROWSER_MOZILLA = 'Mozilla'; // http://www.mozilla.com/en-US/ | ||
| 68 | const BROWSER_AMAYA = 'Amaya'; // http://www.w3.org/Amaya/ | ||
| 69 | const BROWSER_LYNX = 'Lynx'; // http://en.wikipedia.org/wiki/Lynx | ||
| 70 | const BROWSER_SAFARI = 'Safari'; // http://apple.com | ||
| 71 | const BROWSER_IPHONE = 'iPhone'; // http://apple.com | ||
| 72 | const BROWSER_IPOD = 'iPod'; // http://apple.com | ||
| 73 | const BROWSER_IPAD = 'iPad'; // http://apple.com | ||
| 74 | const BROWSER_CHROME = 'Chrome'; // http://www.google.com/chrome | ||
| 75 | const BROWSER_ANDROID = 'Android'; // http://www.android.com/ | ||
| 76 | const BROWSER_GOOGLEBOT = 'GoogleBot'; // http://en.wikipedia.org/wiki/Googlebot | ||
| 77 | |||
| 78 | const BROWSER_YANDEXBOT = 'YandexBot'; // http://yandex.com/bots | ||
| 79 | const BROWSER_YANDEXIMAGERESIZER_BOT = 'YandexImageResizer'; // http://yandex.com/bots | ||
| 80 | const BROWSER_YANDEXIMAGES_BOT = 'YandexImages'; // http://yandex.com/bots | ||
| 81 | const BROWSER_YANDEXVIDEO_BOT = 'YandexVideo'; // http://yandex.com/bots | ||
| 82 | const BROWSER_YANDEXMEDIA_BOT = 'YandexMedia'; // http://yandex.com/bots | ||
| 83 | const BROWSER_YANDEXBLOGS_BOT = 'YandexBlogs'; // http://yandex.com/bots | ||
| 84 | const BROWSER_YANDEXFAVICONS_BOT = 'YandexFavicons'; // http://yandex.com/bots | ||
| 85 | const BROWSER_YANDEXWEBMASTER_BOT = 'YandexWebmaster'; // http://yandex.com/bots | ||
| 86 | const BROWSER_YANDEXDIRECT_BOT = 'YandexDirect'; // http://yandex.com/bots | ||
| 87 | const BROWSER_YANDEXMETRIKA_BOT = 'YandexMetrika'; // http://yandex.com/bots | ||
| 88 | const BROWSER_YANDEXNEWS_BOT = 'YandexNews'; // http://yandex.com/bots | ||
| 89 | const BROWSER_YANDEXCATALOG_BOT = 'YandexCatalog'; // http://yandex.com/bots | ||
| 90 | |||
| 91 | const BROWSER_SLURP = 'Yahoo! Slurp'; // http://en.wikipedia.org/wiki/Yahoo!_Slurp | ||
| 92 | const BROWSER_W3CVALIDATOR = 'W3C Validator'; // http://validator.w3.org/ | ||
| 93 | const BROWSER_BLACKBERRY = 'BlackBerry'; // http://www.blackberry.com/ | ||
| 94 | const BROWSER_ICECAT = 'IceCat'; // http://en.wikipedia.org/wiki/GNU_IceCat | ||
| 95 | const BROWSER_NOKIA_S60 = 'Nokia S60 OSS Browser'; // http://en.wikipedia.org/wiki/Web_Browser_for_S60 | ||
| 96 | const BROWSER_NOKIA = 'Nokia Browser'; // * all other WAP-based browsers on the Nokia Platform | ||
| 97 | const BROWSER_MSN = 'MSN Browser'; // http://explorer.msn.com/ | ||
| 98 | const BROWSER_MSNBOT = 'MSN Bot'; // http://search.msn.com/msnbot.htm | ||
| 99 | const BROWSER_BINGBOT = 'Bing Bot'; // http://en.wikipedia.org/wiki/Bingbot | ||
| 100 | const BROWSER_VIVALDI = 'Vivalidi'; // https://vivaldi.com/ | ||
| 101 | const BROWSER_YANDEX = 'Yandex'; // https://browser.yandex.ua/ | ||
| 102 | |||
| 103 | const BROWSER_NETSCAPE_NAVIGATOR = 'Netscape Navigator'; // http://browser.netscape.com/ (DEPRECATED) | ||
| 104 | const BROWSER_GALEON = 'Galeon'; // http://galeon.sourceforge.net/ (DEPRECATED) | ||
| 105 | const BROWSER_NETPOSITIVE = 'NetPositive'; // http://en.wikipedia.org/wiki/NetPositive (DEPRECATED) | ||
| 106 | const BROWSER_PHOENIX = 'Phoenix'; // http://en.wikipedia.org/wiki/History_of_Mozilla_Firefox (DEPRECATED) | ||
| 107 | const BROWSER_PLAYSTATION = "PlayStation"; | ||
| 108 | const BROWSER_SAMSUNG = "SamsungBrowser"; | ||
| 109 | const BROWSER_SILK = "Silk"; | ||
| 110 | const BROWSER_I_FRAME = "Iframely"; | ||
| 111 | const BROWSER_COCOA = "CocoaRestClient"; | ||
| 112 | |||
| 113 | const PLATFORM_UNKNOWN = 'unknown'; | ||
| 114 | const PLATFORM_WINDOWS = 'Windows'; | ||
| 115 | const PLATFORM_WINDOWS_CE = 'Windows CE'; | ||
| 116 | const PLATFORM_APPLE = 'Apple'; | ||
| 117 | const PLATFORM_LINUX = 'Linux'; | ||
| 118 | const PLATFORM_OS2 = 'OS/2'; | ||
| 119 | const PLATFORM_BEOS = 'BeOS'; | ||
| 120 | const PLATFORM_IPHONE = 'iPhone'; | ||
| 121 | const PLATFORM_IPOD = 'iPod'; | ||
| 122 | const PLATFORM_IPAD = 'iPad'; | ||
| 123 | const PLATFORM_BLACKBERRY = 'BlackBerry'; | ||
| 124 | const PLATFORM_NOKIA = 'Nokia'; | ||
| 125 | const PLATFORM_FREEBSD = 'FreeBSD'; | ||
| 126 | const PLATFORM_OPENBSD = 'OpenBSD'; | ||
| 127 | const PLATFORM_NETBSD = 'NetBSD'; | ||
| 128 | const PLATFORM_SUNOS = 'SunOS'; | ||
| 129 | const PLATFORM_OPENSOLARIS = 'OpenSolaris'; | ||
| 130 | const PLATFORM_ANDROID = 'Android'; | ||
| 131 | const PLATFORM_PLAYSTATION = "Sony PlayStation"; | ||
| 132 | const PLATFORM_ROKU = "Roku"; | ||
| 133 | const PLATFORM_APPLE_TV = "Apple TV"; | ||
| 134 | const PLATFORM_TERMINAL = "Terminal"; | ||
| 135 | const PLATFORM_FIRE_OS = "Fire OS"; | ||
| 136 | const PLATFORM_SMART_TV = "SMART-TV"; | ||
| 137 | const PLATFORM_CHROME_OS = "Chrome OS"; | ||
| 138 | const PLATFORM_JAVA_ANDROID = "Java/Android"; | ||
| 139 | const PLATFORM_POSTMAN = "Postman"; | ||
| 140 | const PLATFORM_I_FRAME = "Iframely"; | ||
| 141 | |||
| 142 | const OPERATING_SYSTEM_UNKNOWN = 'unknown'; | ||
| 143 | |||
| 144 | /** | ||
| 145 | * Class constructor | ||
| 146 | */ | ||
| 147 | public function __construct($userAgent = "") | ||
| 148 | { | ||
| 149 | $this->reset(); | ||
| 150 | if ($userAgent != "") { | ||
| 151 | $this->setUserAgent($userAgent); | ||
| 152 | } else { | ||
| 153 | $this->determine(); | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | /** | ||
| 158 | * Reset all properties | ||
| 159 | */ | ||
| 160 | public function reset() | ||
| 161 | { | ||
| 162 | $this->_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ""; | ||
| 163 | $this->_browser_name = self::BROWSER_UNKNOWN; | ||
| 164 | $this->_version = self::VERSION_UNKNOWN; | ||
| 165 | $this->_platform = self::PLATFORM_UNKNOWN; | ||
| 166 | $this->_os = self::OPERATING_SYSTEM_UNKNOWN; | ||
| 167 | $this->_is_aol = false; | ||
| 168 | $this->_is_mobile = false; | ||
| 169 | $this->_is_tablet = false; | ||
| 170 | $this->_is_robot = false; | ||
| 171 | $this->_is_facebook = false; | ||
| 172 | $this->_aol_version = self::VERSION_UNKNOWN; | ||
| 173 | } | ||
| 174 | |||
| 175 | /** | ||
| 176 | * Check to see if the specific browser is valid | ||
| 177 | * @param string $browserName | ||
| 178 | * @return bool True if the browser is the specified browser | ||
| 179 | */ | ||
| 180 | function isBrowser($browserName) | ||
| 181 | { | ||
| 182 | return (0 == strcasecmp($this->_browser_name, trim($browserName))); | ||
| 183 | } | ||
| 184 | |||
| 185 | /** | ||
| 186 | * The name of the browser. All return types are from the class contants | ||
| 187 | * @return string Name of the browser | ||
| 188 | */ | ||
| 189 | public function getBrowser() | ||
| 190 | { | ||
| 191 | return $this->_browser_name; | ||
| 192 | } | ||
| 193 | |||
| 194 | /** | ||
| 195 | * Set the name of the browser | ||
| 196 | * @param $browser string The name of the Browser | ||
| 197 | */ | ||
| 198 | public function setBrowser($browser) | ||
| 199 | { | ||
| 200 | $this->_browser_name = $browser; | ||
| 201 | } | ||
| 202 | |||
| 203 | /** | ||
| 204 | * The name of the platform. All return types are from the class contants | ||
| 205 | * @return string Name of the browser | ||
| 206 | */ | ||
| 207 | public function getPlatform() | ||
| 208 | { | ||
| 209 | return $this->_platform; | ||
| 210 | } | ||
| 211 | |||
| 212 | /** | ||
| 213 | * Set the name of the platform | ||
| 214 | * @param string $platform The name of the Platform | ||
| 215 | */ | ||
| 216 | public function setPlatform($platform) | ||
| 217 | { | ||
| 218 | $this->_platform = $platform; | ||
| 219 | } | ||
| 220 | |||
| 221 | /** | ||
| 222 | * The version of the browser. | ||
| 223 | * @return string Version of the browser (will only contain alpha-numeric characters and a period) | ||
| 224 | */ | ||
| 225 | public function getVersion() | ||
| 226 | { | ||
| 227 | return $this->_version; | ||
| 228 | } | ||
| 229 | |||
| 230 | /** | ||
| 231 | * Set the version of the browser | ||
| 232 | * @param string $version The version of the Browser | ||
| 233 | */ | ||
| 234 | public function setVersion($version) | ||
| 235 | { | ||
| 236 | $this->_version = preg_replace('/[^0-9,.,a-z,A-Z-]/', '', $version); | ||
| 237 | } | ||
| 238 | |||
| 239 | /** | ||
| 240 | * The version of AOL. | ||
| 241 | * @return string Version of AOL (will only contain alpha-numeric characters and a period) | ||
| 242 | */ | ||
| 243 | public function getAolVersion() | ||
| 244 | { | ||
| 245 | return $this->_aol_version; | ||
| 246 | } | ||
| 247 | |||
| 248 | /** | ||
| 249 | * Set the version of AOL | ||
| 250 | * @param string $version The version of AOL | ||
| 251 | */ | ||
| 252 | public function setAolVersion($version) | ||
| 253 | { | ||
| 254 | $this->_aol_version = preg_replace('/[^0-9,.,a-z,A-Z]/', '', $version); | ||
| 255 | } | ||
| 256 | |||
| 257 | /** | ||
| 258 | * Is the browser from AOL? | ||
| 259 | * @return boolean True if the browser is from AOL otherwise false | ||
| 260 | */ | ||
| 261 | public function isAol() | ||
| 262 | { | ||
| 263 | return $this->_is_aol; | ||
| 264 | } | ||
| 265 | |||
| 266 | /** | ||
| 267 | * Is the browser from a mobile device? | ||
| 268 | * @return boolean True if the browser is from a mobile device otherwise false | ||
| 269 | */ | ||
| 270 | public function isMobile() | ||
| 271 | { | ||
| 272 | return $this->_is_mobile; | ||
| 273 | } | ||
| 274 | |||
| 275 | /** | ||
| 276 | * Is the browser from a tablet device? | ||
| 277 | * @return boolean True if the browser is from a tablet device otherwise false | ||
| 278 | */ | ||
| 279 | public function isTablet() | ||
| 280 | { | ||
| 281 | return $this->_is_tablet; | ||
| 282 | } | ||
| 283 | |||
| 284 | /** | ||
| 285 | * Is the browser from a robot (ex Slurp,GoogleBot)? | ||
| 286 | * @return boolean True if the browser is from a robot otherwise false | ||
| 287 | */ | ||
| 288 | public function isRobot() | ||
| 289 | { | ||
| 290 | return $this->_is_robot; | ||
| 291 | } | ||
| 292 | |||
| 293 | /** | ||
| 294 | * Is the browser from facebook? | ||
| 295 | * @return boolean True if the browser is from facebook otherwise false | ||
| 296 | */ | ||
| 297 | public function isFacebook() | ||
| 298 | { | ||
| 299 | return $this->_is_facebook; | ||
| 300 | } | ||
| 301 | |||
| 302 | /** | ||
| 303 | * Set the browser to be from AOL | ||
| 304 | * @param $isAol | ||
| 305 | */ | ||
| 306 | public function setAol($isAol) | ||
| 307 | { | ||
| 308 | $this->_is_aol = $isAol; | ||
| 309 | } | ||
| 310 | |||
| 311 | /** | ||
| 312 | * Set the Browser to be mobile | ||
| 313 | * @param boolean $value is the browser a mobile browser or not | ||
| 314 | */ | ||
| 315 | protected function setMobile($value = true) | ||
| 316 | { | ||
| 317 | $this->_is_mobile = $value; | ||
| 318 | } | ||
| 319 | |||
| 320 | /** | ||
| 321 | * Set the Browser to be tablet | ||
| 322 | * @param boolean $value is the browser a tablet browser or not | ||
| 323 | */ | ||
| 324 | protected function setTablet($value = true) | ||
| 325 | { | ||
| 326 | $this->_is_tablet = $value; | ||
| 327 | } | ||
| 328 | |||
| 329 | /** | ||
| 330 | * Set the Browser to be a robot | ||
| 331 | * @param boolean $value is the browser a robot or not | ||
| 332 | */ | ||
| 333 | protected function setRobot($value = true) | ||
| 334 | { | ||
| 335 | $this->_is_robot = $value; | ||
| 336 | } | ||
| 337 | |||
| 338 | /** | ||
| 339 | * Set the Browser to be a Facebook request | ||
| 340 | * @param boolean $value is the browser a robot or not | ||
| 341 | */ | ||
| 342 | protected function setFacebook($value = true) | ||
| 343 | { | ||
| 344 | $this->_is_facebook = $value; | ||
| 345 | } | ||
| 346 | |||
| 347 | /** | ||
| 348 | * Get the user agent value in use to determine the browser | ||
| 349 | * @return string The user agent from the HTTP header | ||
| 350 | */ | ||
| 351 | public function getUserAgent() | ||
| 352 | { | ||
| 353 | return $this->_agent; | ||
| 354 | } | ||
| 355 | |||
| 356 | /** | ||
| 357 | * Set the user agent value (the construction will use the HTTP header value - this will overwrite it) | ||
| 358 | * @param string $agent_string The value for the User Agent | ||
| 359 | */ | ||
| 360 | public function setUserAgent($agent_string) | ||
| 361 | { | ||
| 362 | $this->reset(); | ||
| 363 | $this->_agent = $agent_string; | ||
| 364 | $this->determine(); | ||
| 365 | } | ||
| 366 | |||
| 367 | /** | ||
| 368 | * Used to determine if the browser is actually "chromeframe" | ||
| 369 | * @since 1.7 | ||
| 370 | * @return boolean True if the browser is using chromeframe | ||
| 371 | */ | ||
| 372 | public function isChromeFrame() | ||
| 373 | { | ||
| 374 | return (strpos($this->_agent, "chromeframe") !== false); | ||
| 375 | } | ||
| 376 | |||
| 377 | /** | ||
| 378 | * Returns a formatted string with a summary of the details of the browser. | ||
| 379 | * @return string formatted string with a summary of the browser | ||
| 380 | */ | ||
| 381 | public function __toString() | ||
| 382 | { | ||
| 383 | return "<strong>Browser Name:</strong> {$this->getBrowser()}<br/>\n" . | ||
| 384 | "<strong>Browser Version:</strong> {$this->getVersion()}<br/>\n" . | ||
| 385 | "<strong>Browser User Agent String:</strong> {$this->getUserAgent()}<br/>\n" . | ||
| 386 | "<strong>Platform:</strong> {$this->getPlatform()}<br/>"; | ||
| 387 | } | ||
| 388 | |||
| 389 | /** | ||
| 390 | * Protected routine to calculate and determine what the browser is in use (including platform) | ||
| 391 | */ | ||
| 392 | protected function determine() | ||
| 393 | { | ||
| 394 | $this->checkPlatform(); | ||
| 395 | $this->checkBrowsers(); | ||
| 396 | $this->checkForAol(); | ||
| 397 | } | ||
| 398 | |||
| 399 | /** | ||
| 400 | * Protected routine to determine the browser type | ||
| 401 | * @return boolean True if the browser was detected otherwise false | ||
| 402 | */ | ||
| 403 | protected function checkBrowsers() | ||
| 404 | { | ||
| 405 | return ( | ||
| 406 | // well-known, well-used | ||
| 407 | // Special Notes: | ||
| 408 | // (1) Opera must be checked before FireFox due to the odd | ||
| 409 | // user agents used in some older versions of Opera | ||
| 410 | // (2) WebTV is strapped onto Internet Explorer so we must | ||
| 411 | // check for WebTV before IE | ||
| 412 | // (3) (deprecated) Galeon is based on Firefox and needs to be | ||
| 413 | // tested before Firefox is tested | ||
| 414 | // (4) OmniWeb is based on Safari so OmniWeb check must occur | ||
| 415 | // before Safari | ||
| 416 | // (5) Netscape 9+ is based on Firefox so Netscape checks | ||
| 417 | // before FireFox are necessary | ||
| 418 | // (6) Vivalid is UA contains both Firefox and Chrome so Vivalid checks | ||
| 419 | // before Firefox and Chrome | ||
| 420 | $this->checkBrowserWebTv() || | ||
| 421 | $this->checkBrowserEdge() || | ||
| 422 | $this->checkBrowserInternetExplorer() || | ||
| 423 | $this->checkBrowserOpera() || | ||
| 424 | $this->checkBrowserGaleon() || | ||
| 425 | $this->checkBrowserNetscapeNavigator9Plus() || | ||
| 426 | $this->checkBrowserVivaldi() || | ||
| 427 | $this->checkBrowserYandex() || | ||
| 428 | $this->checkBrowserFirefox() || | ||
| 429 | $this->checkBrowserChrome() || | ||
| 430 | $this->checkBrowserOmniWeb() || | ||
| 431 | |||
| 432 | // common mobile | ||
| 433 | $this->checkBrowserAndroid() || | ||
| 434 | $this->checkBrowseriPad() || | ||
| 435 | $this->checkBrowseriPod() || | ||
| 436 | $this->checkBrowseriPhone() || | ||
| 437 | $this->checkBrowserBlackBerry() || | ||
| 438 | $this->checkBrowserNokia() || | ||
| 439 | |||
| 440 | // common bots | ||
| 441 | $this->checkBrowserGoogleBot() || | ||
| 442 | $this->checkBrowserMSNBot() || | ||
| 443 | $this->checkBrowserBingBot() || | ||
| 444 | $this->checkBrowserSlurp() || | ||
| 445 | |||
| 446 | // Yandex bots | ||
| 447 | $this->checkBrowserYandexBot() || | ||
| 448 | $this->checkBrowserYandexImageResizerBot() || | ||
| 449 | $this->checkBrowserYandexBlogsBot() || | ||
| 450 | $this->checkBrowserYandexCatalogBot() || | ||
| 451 | $this->checkBrowserYandexDirectBot() || | ||
| 452 | $this->checkBrowserYandexFaviconsBot() || | ||
| 453 | $this->checkBrowserYandexImagesBot() || | ||
| 454 | $this->checkBrowserYandexMediaBot() || | ||
| 455 | $this->checkBrowserYandexMetrikaBot() || | ||
| 456 | $this->checkBrowserYandexNewsBot() || | ||
| 457 | $this->checkBrowserYandexVideoBot() || | ||
| 458 | $this->checkBrowserYandexWebmasterBot() || | ||
| 459 | |||
| 460 | // check for facebook external hit when loading URL | ||
| 461 | $this->checkFacebookExternalHit() || | ||
| 462 | |||
| 463 | // WebKit base check (post mobile and others) | ||
| 464 | $this->checkBrowserSamsung() || | ||
| 465 | $this->checkBrowserSilk() || | ||
| 466 | $this->checkBrowserSafari() || | ||
| 467 | |||
| 468 | // everyone else | ||
| 469 | $this->checkBrowserNetPositive() || | ||
| 470 | $this->checkBrowserFirebird() || | ||
| 471 | $this->checkBrowserKonqueror() || | ||
| 472 | $this->checkBrowserIcab() || | ||
| 473 | $this->checkBrowserPhoenix() || | ||
| 474 | $this->checkBrowserAmaya() || | ||
| 475 | $this->checkBrowserLynx() || | ||
| 476 | $this->checkBrowserShiretoko() || | ||
| 477 | $this->checkBrowserIceCat() || | ||
| 478 | $this->checkBrowserIceweasel() || | ||
| 479 | $this->checkBrowserW3CValidator() || | ||
| 480 | $this->checkBrowserPlayStation() || | ||
| 481 | $this->checkBrowserIframely() || | ||
| 482 | $this->checkBrowserCocoa() || | ||
| 483 | $this->checkBrowserMozilla() /* Mozilla is such an open standard that you must check it last */ | ||
| 484 | |||
| 485 | |||
| 486 | ); | ||
| 487 | } | ||
| 488 | |||
| 489 | /** | ||
| 490 | * Determine if the user is using a BlackBerry (last updated 1.7) | ||
| 491 | * @return boolean True if the browser is the BlackBerry browser otherwise false | ||
| 492 | */ | ||
| 493 | protected function checkBrowserBlackBerry() | ||
| 494 | { | ||
| 495 | if (stripos($this->_agent, 'blackberry') !== false) { | ||
| 496 | $aresult = explode("/", stristr($this->_agent, "BlackBerry")); | ||
| 497 | if (isset($aresult[1])) { | ||
| 498 | $aversion = explode(' ', $aresult[1]); | ||
| 499 | $this->setVersion($aversion[0]); | ||
| 500 | $this->_browser_name = self::BROWSER_BLACKBERRY; | ||
| 501 | $this->setMobile(true); | ||
| 502 | return true; | ||
| 503 | } | ||
| 504 | } | ||
| 505 | return false; | ||
| 506 | } | ||
| 507 | |||
| 508 | /** | ||
| 509 | * Determine if the user is using an AOL User Agent (last updated 1.7) | ||
| 510 | * @return boolean True if the browser is from AOL otherwise false | ||
| 511 | */ | ||
| 512 | protected function checkForAol() | ||
| 513 | { | ||
| 514 | $this->setAol(false); | ||
| 515 | $this->setAolVersion(self::VERSION_UNKNOWN); | ||
| 516 | |||
| 517 | if (stripos($this->_agent, 'aol') !== false) { | ||
| 518 | $aversion = explode(' ', stristr($this->_agent, 'AOL')); | ||
| 519 | if (isset($aversion[1])) { | ||
| 520 | $this->setAol(true); | ||
| 521 | $this->setAolVersion(preg_replace('/[^0-9\.a-z]/i', '', $aversion[1])); | ||
| 522 | return true; | ||
| 523 | } | ||
| 524 | } | ||
| 525 | return false; | ||
| 526 | } | ||
| 527 | |||
| 528 | /** | ||
| 529 | * Determine if the browser is the GoogleBot or not (last updated 1.7) | ||
| 530 | * @return boolean True if the browser is the GoogletBot otherwise false | ||
| 531 | */ | ||
| 532 | protected function checkBrowserGoogleBot() | ||
| 533 | { | ||
| 534 | if (stripos($this->_agent, 'googlebot') !== false) { | ||
| 535 | $aresult = explode('/', stristr($this->_agent, 'googlebot')); | ||
| 536 | if (isset($aresult[1])) { | ||
| 537 | $aversion = explode(' ', $aresult[1]); | ||
| 538 | $this->setVersion(str_replace(';', '', $aversion[0])); | ||
| 539 | $this->_browser_name = self::BROWSER_GOOGLEBOT; | ||
| 540 | $this->setRobot(true); | ||
| 541 | return true; | ||
| 542 | } | ||
| 543 | } | ||
| 544 | return false; | ||
| 545 | } | ||
| 546 | |||
| 547 | /** | ||
| 548 | * Determine if the browser is the YandexBot or not | ||
| 549 | * @return boolean True if the browser is the YandexBot otherwise false | ||
| 550 | */ | ||
| 551 | protected function checkBrowserYandexBot() | ||
| 552 | { | ||
| 553 | if (stripos($this->_agent, 'YandexBot') !== false) { | ||
| 554 | $aresult = explode('/', stristr($this->_agent, 'YandexBot')); | ||
| 555 | if (isset($aresult[1])) { | ||
| 556 | $aversion = explode(' ', $aresult[1]); | ||
| 557 | $this->setVersion(str_replace(';', '', $aversion[0])); | ||
| 558 | $this->_browser_name = self::BROWSER_YANDEXBOT; | ||
| 559 | $this->setRobot(true); | ||
| 560 | return true; | ||
| 561 | } | ||
| 562 | } | ||
| 563 | return false; | ||
| 564 | } | ||
| 565 | |||
| 566 | /** | ||
| 567 | * Determine if the browser is the YandexImageResizer or not | ||
| 568 | * @return boolean True if the browser is the YandexImageResizer otherwise false | ||
| 569 | */ | ||
| 570 | protected function checkBrowserYandexImageResizerBot() | ||
| 571 | { | ||
| 572 | if (stripos($this->_agent, 'YandexImageResizer') !== false) { | ||
| 573 | $aresult = explode('/', stristr($this->_agent, 'YandexImageResizer')); | ||
| 574 | if (isset($aresult[1])) { | ||
| 575 | $aversion = explode(' ', $aresult[1]); | ||
| 576 | $this->setVersion(str_replace(';', '', $aversion[0])); | ||
| 577 | $this->_browser_name = self::BROWSER_YANDEXIMAGERESIZER_BOT; | ||
| 578 | $this->setRobot(true); | ||
| 579 | return true; | ||
| 580 | } | ||
| 581 | } | ||
| 582 | return false; | ||
| 583 | } | ||
| 584 | |||
| 585 | /** | ||
| 586 | * Determine if the browser is the YandexCatalog or not | ||
| 587 | * @return boolean True if the browser is the YandexCatalog otherwise false | ||
| 588 | */ | ||
| 589 | protected function checkBrowserYandexCatalogBot() | ||
| 590 | { | ||
| 591 | if (stripos($this->_agent, 'YandexCatalog') !== false) { | ||
| 592 | $aresult = explode('/', stristr($this->_agent, 'YandexCatalog')); | ||
| 593 | if (isset($aresult[1])) { | ||
| 594 | $aversion = explode(' ', $aresult[1]); | ||
| 595 | $this->setVersion(str_replace(';', '', $aversion[0])); | ||
| 596 | $this->_browser_name = self::BROWSER_YANDEXCATALOG_BOT; | ||
| 597 | $this->setRobot(true); | ||
| 598 | return true; | ||
| 599 | } | ||
| 600 | } | ||
| 601 | return false; | ||
| 602 | } | ||
| 603 | |||
| 604 | /** | ||
| 605 | * Determine if the browser is the YandexNews or not | ||
| 606 | * @return boolean True if the browser is the YandexNews otherwise false | ||
| 607 | */ | ||
| 608 | protected function checkBrowserYandexNewsBot() | ||
| 609 | { | ||
| 610 | if (stripos($this->_agent, 'YandexNews') !== false) { | ||
| 611 | $aresult = explode('/', stristr($this->_agent, 'YandexNews')); | ||
| 612 | if (isset($aresult[1])) { | ||
| 613 | $aversion = explode(' ', $aresult[1]); | ||
| 614 | $this->setVersion(str_replace(';', '', $aversion[0])); | ||
| 615 | $this->_browser_name = self::BROWSER_YANDEXNEWS_BOT; | ||
| 616 | $this->setRobot(true); | ||
| 617 | return true; | ||
| 618 | } | ||
| 619 | } | ||
| 620 | return false; | ||
| 621 | } | ||
| 622 | |||
| 623 | /** | ||
| 624 | * Determine if the browser is the YandexMetrika or not | ||
| 625 | * @return boolean True if the browser is the YandexMetrika otherwise false | ||
| 626 | */ | ||
| 627 | protected function checkBrowserYandexMetrikaBot() | ||
| 628 | { | ||
| 629 | if (stripos($this->_agent, 'YandexMetrika') !== false) { | ||
| 630 | $aresult = explode('/', stristr($this->_agent, 'YandexMetrika')); | ||
| 631 | if (isset($aresult[1])) { | ||
| 632 | $aversion = explode(' ', $aresult[1]); | ||
| 633 | $this->setVersion(str_replace(';', '', $aversion[0])); | ||
| 634 | $this->_browser_name = self::BROWSER_YANDEXMETRIKA_BOT; | ||
| 635 | $this->setRobot(true); | ||
| 636 | return true; | ||
| 637 | } | ||
| 638 | } | ||
| 639 | return false; | ||
| 640 | } | ||
| 641 | |||
| 642 | /** | ||
| 643 | * Determine if the browser is the YandexDirect or not | ||
| 644 | * @return boolean True if the browser is the YandexDirect otherwise false | ||
| 645 | */ | ||
| 646 | protected function checkBrowserYandexDirectBot() | ||
| 647 | { | ||
| 648 | if (stripos($this->_agent, 'YandexDirect') !== false) { | ||
| 649 | $aresult = explode('/', stristr($this->_agent, 'YandexDirect')); | ||
| 650 | if (isset($aresult[1])) { | ||
| 651 | $aversion = explode(' ', $aresult[1]); | ||
| 652 | $this->setVersion(str_replace(';', '', $aversion[0])); | ||
| 653 | $this->_browser_name = self::BROWSER_YANDEXDIRECT_BOT; | ||
| 654 | $this->setRobot(true); | ||
| 655 | return true; | ||
| 656 | } | ||
| 657 | } | ||
| 658 | return false; | ||
| 659 | } | ||
| 660 | |||
| 661 | /** | ||
| 662 | * Determine if the browser is the YandexWebmaster or not | ||
| 663 | * @return boolean True if the browser is the YandexWebmaster otherwise false | ||
| 664 | */ | ||
| 665 | protected function checkBrowserYandexWebmasterBot() | ||
| 666 | { | ||
| 667 | if (stripos($this->_agent, 'YandexWebmaster') !== false) { | ||
| 668 | $aresult = explode('/', stristr($this->_agent, 'YandexWebmaster')); | ||
| 669 | if (isset($aresult[1])) { | ||
| 670 | $aversion = explode(' ', $aresult[1]); | ||
| 671 | $this->setVersion(str_replace(';', '', $aversion[0])); | ||
| 672 | $this->_browser_name = self::BROWSER_YANDEXWEBMASTER_BOT; | ||
| 673 | $this->setRobot(true); | ||
| 674 | return true; | ||
| 675 | } | ||
| 676 | } | ||
| 677 | return false; | ||
| 678 | } | ||
| 679 | |||
| 680 | /** | ||
| 681 | * Determine if the browser is the YandexFavicons or not | ||
| 682 | * @return boolean True if the browser is the YandexFavicons otherwise false | ||
| 683 | */ | ||
| 684 | protected function checkBrowserYandexFaviconsBot() | ||
| 685 | { | ||
| 686 | if (stripos($this->_agent, 'YandexFavicons') !== false) { | ||
| 687 | $aresult = explode('/', stristr($this->_agent, 'YandexFavicons')); | ||
| 688 | if (isset($aresult[1])) { | ||
| 689 | $aversion = explode(' ', $aresult[1]); | ||
| 690 | $this->setVersion(str_replace(';', '', $aversion[0])); | ||
| 691 | $this->_browser_name = self::BROWSER_YANDEXFAVICONS_BOT; | ||
| 692 | $this->setRobot(true); | ||
| 693 | return true; | ||
| 694 | } | ||
| 695 | } | ||
| 696 | return false; | ||
| 697 | } | ||
| 698 | |||
| 699 | /** | ||
| 700 | * Determine if the browser is the YandexBlogs or not | ||
| 701 | * @return boolean True if the browser is the YandexBlogs otherwise false | ||
| 702 | */ | ||
| 703 | protected function checkBrowserYandexBlogsBot() | ||
| 704 | { | ||
| 705 | if (stripos($this->_agent, 'YandexBlogs') !== false) { | ||
| 706 | $aresult = explode('/', stristr($this->_agent, 'YandexBlogs')); | ||
| 707 | if (isset($aresult[1])) { | ||
| 708 | $aversion = explode(' ', $aresult[1]); | ||
| 709 | $this->setVersion(str_replace(';', '', $aversion[0])); | ||
| 710 | $this->_browser_name = self::BROWSER_YANDEXBLOGS_BOT; | ||
| 711 | $this->setRobot(true); | ||
| 712 | return true; | ||
| 713 | } | ||
| 714 | } | ||
| 715 | return false; | ||
| 716 | } | ||
| 717 | |||
| 718 | /** | ||
| 719 | * Determine if the browser is the YandexMedia or not | ||
| 720 | * @return boolean True if the browser is the YandexMedia otherwise false | ||
| 721 | */ | ||
| 722 | protected function checkBrowserYandexMediaBot() | ||
| 723 | { | ||
| 724 | if (stripos($this->_agent, 'YandexMedia') !== false) { | ||
| 725 | $aresult = explode('/', stristr($this->_agent, 'YandexMedia')); | ||
| 726 | if (isset($aresult[1])) { | ||
| 727 | $aversion = explode(' ', $aresult[1]); | ||
| 728 | $this->setVersion(str_replace(';', '', $aversion[0])); | ||
| 729 | $this->_browser_name = self::BROWSER_YANDEXMEDIA_BOT; | ||
| 730 | $this->setRobot(true); | ||
| 731 | return true; | ||
| 732 | } | ||
| 733 | } | ||
| 734 | return false; | ||
| 735 | } | ||
| 736 | |||
| 737 | /** | ||
| 738 | * Determine if the browser is the YandexVideo or not | ||
| 739 | * @return boolean True if the browser is the YandexVideo otherwise false | ||
| 740 | */ | ||
| 741 | protected function checkBrowserYandexVideoBot() | ||
| 742 | { | ||
| 743 | if (stripos($this->_agent, 'YandexVideo') !== false) { | ||
| 744 | $aresult = explode('/', stristr($this->_agent, 'YandexVideo')); | ||
| 745 | if (isset($aresult[1])) { | ||
| 746 | $aversion = explode(' ', $aresult[1]); | ||
| 747 | $this->setVersion(str_replace(';', '', $aversion[0])); | ||
| 748 | $this->_browser_name = self::BROWSER_YANDEXVIDEO_BOT; | ||
| 749 | $this->setRobot(true); | ||
| 750 | return true; | ||
| 751 | } | ||
| 752 | } | ||
| 753 | return false; | ||
| 754 | } | ||
| 755 | |||
| 756 | /** | ||
| 757 | * Determine if the browser is the YandexImages or not | ||
| 758 | * @return boolean True if the browser is the YandexImages otherwise false | ||
| 759 | */ | ||
| 760 | protected function checkBrowserYandexImagesBot() | ||
| 761 | { | ||
| 762 | if (stripos($this->_agent, 'YandexImages') !== false) { | ||
| 763 | $aresult = explode('/', stristr($this->_agent, 'YandexImages')); | ||
| 764 | if (isset($aresult[1])) { | ||
| 765 | $aversion = explode(' ', $aresult[1]); | ||
| 766 | $this->setVersion(str_replace(';', '', $aversion[0])); | ||
| 767 | $this->_browser_name = self::BROWSER_YANDEXIMAGES_BOT; | ||
| 768 | $this->setRobot(true); | ||
| 769 | return true; | ||
| 770 | } | ||
| 771 | } | ||
| 772 | return false; | ||
| 773 | } | ||
| 774 | |||
| 775 | /** | ||
| 776 | * Determine if the browser is the MSNBot or not (last updated 1.9) | ||
| 777 | * @return boolean True if the browser is the MSNBot otherwise false | ||
| 778 | */ | ||
| 779 | protected function checkBrowserMSNBot() | ||
| 780 | { | ||
| 781 | if (stripos($this->_agent, "msnbot") !== false) { | ||
| 782 | $aresult = explode("/", stristr($this->_agent, "msnbot")); | ||
| 783 | if (isset($aresult[1])) { | ||
| 784 | $aversion = explode(" ", $aresult[1]); | ||
| 785 | $this->setVersion(str_replace(";", "", $aversion[0])); | ||
| 786 | $this->_browser_name = self::BROWSER_MSNBOT; | ||
| 787 | $this->setRobot(true); | ||
| 788 | return true; | ||
| 789 | } | ||
| 790 | } | ||
| 791 | return false; | ||
| 792 | } | ||
| 793 | |||
| 794 | /** | ||
| 795 | * Determine if the browser is the BingBot or not (last updated 1.9) | ||
| 796 | * @return boolean True if the browser is the BingBot otherwise false | ||
| 797 | */ | ||
| 798 | protected function checkBrowserBingBot() | ||
| 799 | { | ||
| 800 | if (stripos($this->_agent, "bingbot") !== false) { | ||
| 801 | $aresult = explode("/", stristr($this->_agent, "bingbot")); | ||
| 802 | if (isset($aresult[1])) { | ||
| 803 | $aversion = explode(" ", $aresult[1]); | ||
| 804 | $this->setVersion(str_replace(";", "", $aversion[0])); | ||
| 805 | $this->_browser_name = self::BROWSER_BINGBOT; | ||
| 806 | $this->setRobot(true); | ||
| 807 | return true; | ||
| 808 | } | ||
| 809 | } | ||
| 810 | return false; | ||
| 811 | } | ||
| 812 | |||
| 813 | /** | ||
| 814 | * Determine if the browser is the W3C Validator or not (last updated 1.7) | ||
| 815 | * @return boolean True if the browser is the W3C Validator otherwise false | ||
| 816 | */ | ||
| 817 | protected function checkBrowserW3CValidator() | ||
| 818 | { | ||
| 819 | if (stripos($this->_agent, 'W3C-checklink') !== false) { | ||
| 820 | $aresult = explode('/', stristr($this->_agent, 'W3C-checklink')); | ||
| 821 | if (isset($aresult[1])) { | ||
| 822 | $aversion = explode(' ', $aresult[1]); | ||
| 823 | $this->setVersion($aversion[0]); | ||
| 824 | $this->_browser_name = self::BROWSER_W3CVALIDATOR; | ||
| 825 | return true; | ||
| 826 | } | ||
| 827 | } else if (stripos($this->_agent, 'W3C_Validator') !== false) { | ||
| 828 | // Some of the Validator versions do not delineate w/ a slash - add it back in | ||
| 829 | $ua = str_replace("W3C_Validator ", "W3C_Validator/", $this->_agent); | ||
| 830 | $aresult = explode('/', stristr($ua, 'W3C_Validator')); | ||
| 831 | if (isset($aresult[1])) { | ||
| 832 | $aversion = explode(' ', $aresult[1]); | ||
| 833 | $this->setVersion($aversion[0]); | ||
| 834 | $this->_browser_name = self::BROWSER_W3CVALIDATOR; | ||
| 835 | return true; | ||
| 836 | } | ||
| 837 | } else if (stripos($this->_agent, 'W3C-mobileOK') !== false) { | ||
| 838 | $this->_browser_name = self::BROWSER_W3CVALIDATOR; | ||
| 839 | $this->setMobile(true); | ||
| 840 | return true; | ||
| 841 | } | ||
| 842 | return false; | ||
| 843 | } | ||
| 844 | |||
| 845 | /** | ||
| 846 | * Determine if the browser is the Yahoo! Slurp Robot or not (last updated 1.7) | ||
| 847 | * @return boolean True if the browser is the Yahoo! Slurp Robot otherwise false | ||
| 848 | */ | ||
| 849 | protected function checkBrowserSlurp() | ||
| 850 | { | ||
| 851 | if (stripos($this->_agent, 'slurp') !== false) { | ||
| 852 | $aresult = explode('/', stristr($this->_agent, 'Slurp')); | ||
| 853 | if (isset($aresult[1])) { | ||
| 854 | $aversion = explode(' ', $aresult[1]); | ||
| 855 | $this->setVersion($aversion[0]); | ||
| 856 | $this->_browser_name = self::BROWSER_SLURP; | ||
| 857 | $this->setRobot(true); | ||
| 858 | $this->setMobile(false); | ||
| 859 | return true; | ||
| 860 | } | ||
| 861 | } | ||
| 862 | return false; | ||
| 863 | } | ||
| 864 | |||
| 865 | /** | ||
| 866 | * Determine if the browser is Edge or not | ||
| 867 | * @return boolean True if the browser is Edge otherwise false | ||
| 868 | */ | ||
| 869 | protected function checkBrowserEdge() | ||
| 870 | { | ||
| 871 | if (stripos($this->_agent, 'Edge/') !== false) { | ||
| 872 | $aresult = explode('/', stristr($this->_agent, 'Edge')); | ||
| 873 | if (isset($aresult[1])) { | ||
| 874 | $aversion = explode(' ', $aresult[1]); | ||
| 875 | $this->setVersion($aversion[0]); | ||
| 876 | $this->setBrowser(self::BROWSER_EDGE); | ||
| 877 | if (stripos($this->_agent, 'Windows Phone') !== false || stripos($this->_agent, 'Android') !== false) { | ||
| 878 | $this->setMobile(true); | ||
| 879 | } | ||
| 880 | return true; | ||
| 881 | } | ||
| 882 | } | ||
| 883 | return false; | ||
| 884 | } | ||
| 885 | |||
| 886 | /** | ||
| 887 | * Determine if the browser is Internet Explorer or not (last updated 1.7) | ||
| 888 | * @return boolean True if the browser is Internet Explorer otherwise false | ||
| 889 | */ | ||
| 890 | protected function checkBrowserInternetExplorer() | ||
| 891 | { | ||
| 892 | // Test for IE11 | ||
| 893 | if (stripos($this->_agent, 'Trident/7.0; rv:11.0') !== false) { | ||
| 894 | $this->setBrowser(self::BROWSER_IE); | ||
| 895 | $this->setVersion('11.0'); | ||
| 896 | return true; | ||
| 897 | } // Test for v1 - v1.5 IE | ||
| 898 | else if (stripos($this->_agent, 'microsoft internet explorer') !== false) { | ||
| 899 | $this->setBrowser(self::BROWSER_IE); | ||
| 900 | $this->setVersion('1.0'); | ||
| 901 | $aresult = stristr($this->_agent, '/'); | ||
| 902 | if (preg_match('/308|425|426|474|0b1/i', $aresult)) { | ||
| 903 | $this->setVersion('1.5'); | ||
| 904 | } | ||
| 905 | return true; | ||
| 906 | } // Test for versions > 1.5 | ||
| 907 | else if (stripos($this->_agent, 'msie') !== false && stripos($this->_agent, 'opera') === false) { | ||
| 908 | // See if the browser is the odd MSN Explorer | ||
| 909 | if (stripos($this->_agent, 'msnb') !== false) { | ||
| 910 | $aresult = explode(' ', stristr(str_replace(';', '; ', $this->_agent), 'MSN')); | ||
| 911 | if (isset($aresult[1])) { | ||
| 912 | $this->setBrowser(self::BROWSER_MSN); | ||
| 913 | $this->setVersion(str_replace(array('(', ')', ';'), '', $aresult[1])); | ||
| 914 | return true; | ||
| 915 | } | ||
| 916 | } | ||
| 917 | $aresult = explode(' ', stristr(str_replace(';', '; ', $this->_agent), 'msie')); | ||
| 918 | if (isset($aresult[1])) { | ||
| 919 | $this->setBrowser(self::BROWSER_IE); | ||
| 920 | $this->setVersion(str_replace(array('(', ')', ';'), '', $aresult[1])); | ||
| 921 | if(preg_match('#trident/([0-9\.]+);#i', $this->_agent, $aresult)){ | ||
| 922 | if($aresult[1] == '3.1'){ | ||
| 923 | $this->setVersion('7.0'); | ||
| 924 | } | ||
| 925 | else if($aresult[1] == '4.0'){ | ||
| 926 | $this->setVersion('8.0'); | ||
| 927 | } | ||
| 928 | else if($aresult[1] == '5.0'){ | ||
| 929 | $this->setVersion('9.0'); | ||
| 930 | } | ||
| 931 | else if($aresult[1] == '6.0'){ | ||
| 932 | $this->setVersion('10.0'); | ||
| 933 | } | ||
| 934 | else if($aresult[1] == '7.0'){ | ||
| 935 | $this->setVersion('11.0'); | ||
| 936 | } | ||
| 937 | else if($aresult[1] == '8.0'){ | ||
| 938 | $this->setVersion('11.0'); | ||
| 939 | } | ||
| 940 | } | ||
| 941 | if(stripos($this->_agent, 'IEMobile') !== false) { | ||
| 942 | $this->setBrowser(self::BROWSER_POCKET_IE); | ||
| 943 | $this->setMobile(true); | ||
| 944 | } | ||
| 945 | return true; | ||
| 946 | } | ||
| 947 | } // Test for versions > IE 10 | ||
| 948 | else if (stripos($this->_agent, 'trident') !== false) { | ||
| 949 | $this->setBrowser(self::BROWSER_IE); | ||
| 950 | $result = explode('rv:', $this->_agent); | ||
| 951 | if (isset($result[1])) { | ||
| 952 | $this->setVersion(preg_replace('/[^0-9.]+/', '', $result[1])); | ||
| 953 | $this->_agent = str_replace(array("Mozilla", "Gecko"), "MSIE", $this->_agent); | ||
| 954 | } | ||
| 955 | } // Test for Pocket IE | ||
| 956 | else if (stripos($this->_agent, 'mspie') !== false || stripos($this->_agent, 'pocket') !== false) { | ||
| 957 | $aresult = explode(' ', stristr($this->_agent, 'mspie')); | ||
| 958 | if (isset($aresult[1])) { | ||
| 959 | $this->setPlatform(self::PLATFORM_WINDOWS_CE); | ||
| 960 | $this->setBrowser(self::BROWSER_POCKET_IE); | ||
| 961 | $this->setMobile(true); | ||
| 962 | |||
| 963 | if (stripos($this->_agent, 'mspie') !== false) { | ||
| 964 | $this->setVersion($aresult[1]); | ||
| 965 | } else { | ||
| 966 | $aversion = explode('/', $this->_agent); | ||
| 967 | if (isset($aversion[1])) { | ||
| 968 | $this->setVersion($aversion[1]); | ||
| 969 | } | ||
| 970 | } | ||
| 971 | return true; | ||
| 972 | } | ||
| 973 | } | ||
| 974 | return false; | ||
| 975 | } | ||
| 976 | |||
| 977 | /** | ||
| 978 | * Determine if the browser is Opera or not (last updated 1.7) | ||
| 979 | * @return boolean True if the browser is Opera otherwise false | ||
| 980 | */ | ||
| 981 | protected function checkBrowserOpera() | ||
| 982 | { | ||
| 983 | if (stripos($this->_agent, 'opera mini') !== false) { | ||
| 984 | $resultant = stristr($this->_agent, 'opera mini'); | ||
| 985 | if (preg_match('/\//', $resultant)) { | ||
| 986 | $aresult = explode('/', $resultant); | ||
| 987 | if (isset($aresult[1])) { | ||
| 988 | $aversion = explode(' ', $aresult[1]); | ||
| 989 | $this->setVersion($aversion[0]); | ||
| 990 | } | ||
| 991 | } else { | ||
| 992 | $aversion = explode(' ', stristr($resultant, 'opera mini')); | ||
| 993 | if (isset($aversion[1])) { | ||
| 994 | $this->setVersion($aversion[1]); | ||
| 995 | } | ||
| 996 | } | ||
| 997 | $this->_browser_name = self::BROWSER_OPERA_MINI; | ||
| 998 | $this->setMobile(true); | ||
| 999 | return true; | ||
| 1000 | } else if (stripos($this->_agent, 'opera') !== false) { | ||
| 1001 | $resultant = stristr($this->_agent, 'opera'); | ||
| 1002 | if (preg_match('/Version\/(1*.*)$/', $resultant, $matches)) { | ||
| 1003 | $this->setVersion($matches[1]); | ||
| 1004 | } else if (preg_match('/\//', $resultant)) { | ||
| 1005 | $aresult = explode('/', str_replace("(", " ", $resultant)); | ||
| 1006 | if (isset($aresult[1])) { | ||
| 1007 | $aversion = explode(' ', $aresult[1]); | ||
| 1008 | $this->setVersion($aversion[0]); | ||
| 1009 | } | ||
| 1010 | } else { | ||
| 1011 | $aversion = explode(' ', stristr($resultant, 'opera')); | ||
| 1012 | $this->setVersion(isset($aversion[1]) ? $aversion[1] : ""); | ||
| 1013 | } | ||
| 1014 | if (stripos($this->_agent, 'Opera Mobi') !== false) { | ||
| 1015 | $this->setMobile(true); | ||
| 1016 | } | ||
| 1017 | $this->_browser_name = self::BROWSER_OPERA; | ||
| 1018 | return true; | ||
| 1019 | } else if (stripos($this->_agent, 'OPR') !== false) { | ||
| 1020 | $resultant = stristr($this->_agent, 'OPR'); | ||
| 1021 | if (preg_match('/\//', $resultant)) { | ||
| 1022 | $aresult = explode('/', str_replace("(", " ", $resultant)); | ||
| 1023 | if (isset($aresult[1])) { | ||
| 1024 | $aversion = explode(' ', $aresult[1]); | ||
| 1025 | $this->setVersion($aversion[0]); | ||
| 1026 | } | ||
| 1027 | } | ||
| 1028 | if (stripos($this->_agent, 'Mobile') !== false) { | ||
| 1029 | $this->setMobile(true); | ||
| 1030 | } | ||
| 1031 | $this->_browser_name = self::BROWSER_OPERA; | ||
| 1032 | return true; | ||
| 1033 | } | ||
| 1034 | return false; | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | /** | ||
| 1038 | * Determine if the browser is Chrome or not (last updated 1.7) | ||
| 1039 | * @return boolean True if the browser is Chrome otherwise false | ||
| 1040 | */ | ||
| 1041 | protected function checkBrowserChrome() | ||
| 1042 | { | ||
| 1043 | if (stripos($this->_agent, 'Chrome') !== false) { | ||
| 1044 | $aresult = explode('/', stristr($this->_agent, 'Chrome')); | ||
| 1045 | if (isset($aresult[1])) { | ||
| 1046 | $aversion = explode(' ', $aresult[1]); | ||
| 1047 | $this->setVersion($aversion[0]); | ||
| 1048 | $this->setBrowser(self::BROWSER_CHROME); | ||
| 1049 | //Chrome on Android | ||
| 1050 | if (stripos($this->_agent, 'Android') !== false) { | ||
| 1051 | if (stripos($this->_agent, 'Mobile') !== false) { | ||
| 1052 | $this->setMobile(true); | ||
| 1053 | } else { | ||
| 1054 | $this->setTablet(true); | ||
| 1055 | } | ||
| 1056 | } | ||
| 1057 | return true; | ||
| 1058 | } | ||
| 1059 | } | ||
| 1060 | return false; | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | |||
| 1064 | /** | ||
| 1065 | * Determine if the browser is WebTv or not (last updated 1.7) | ||
| 1066 | * @return boolean True if the browser is WebTv otherwise false | ||
| 1067 | */ | ||
| 1068 | protected function checkBrowserWebTv() | ||
| 1069 | { | ||
| 1070 | if (stripos($this->_agent, 'webtv') !== false) { | ||
| 1071 | $aresult = explode('/', stristr($this->_agent, 'webtv')); | ||
| 1072 | if (isset($aresult[1])) { | ||
| 1073 | $aversion = explode(' ', $aresult[1]); | ||
| 1074 | $this->setVersion($aversion[0]); | ||
| 1075 | $this->setBrowser(self::BROWSER_WEBTV); | ||
| 1076 | return true; | ||
| 1077 | } | ||
| 1078 | } | ||
| 1079 | return false; | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | /** | ||
| 1083 | * Determine if the browser is NetPositive or not (last updated 1.7) | ||
| 1084 | * @return boolean True if the browser is NetPositive otherwise false | ||
| 1085 | */ | ||
| 1086 | protected function checkBrowserNetPositive() | ||
| 1087 | { | ||
| 1088 | if (stripos($this->_agent, 'NetPositive') !== false) { | ||
| 1089 | $aresult = explode('/', stristr($this->_agent, 'NetPositive')); | ||
| 1090 | if (isset($aresult[1])) { | ||
| 1091 | $aversion = explode(' ', $aresult[1]); | ||
| 1092 | $this->setVersion(str_replace(array('(', ')', ';'), '', $aversion[0])); | ||
| 1093 | $this->setBrowser(self::BROWSER_NETPOSITIVE); | ||
| 1094 | return true; | ||
| 1095 | } | ||
| 1096 | } | ||
| 1097 | return false; | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | /** | ||
| 1101 | * Determine if the browser is Galeon or not (last updated 1.7) | ||
| 1102 | * @return boolean True if the browser is Galeon otherwise false | ||
| 1103 | */ | ||
| 1104 | protected function checkBrowserGaleon() | ||
| 1105 | { | ||
| 1106 | if (stripos($this->_agent, 'galeon') !== false) { | ||
| 1107 | $aresult = explode(' ', stristr($this->_agent, 'galeon')); | ||
| 1108 | $aversion = explode('/', $aresult[0]); | ||
| 1109 | if (isset($aversion[1])) { | ||
| 1110 | $this->setVersion($aversion[1]); | ||
| 1111 | $this->setBrowser(self::BROWSER_GALEON); | ||
| 1112 | return true; | ||
| 1113 | } | ||
| 1114 | } | ||
| 1115 | return false; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | /** | ||
| 1119 | * Determine if the browser is Konqueror or not (last updated 1.7) | ||
| 1120 | * @return boolean True if the browser is Konqueror otherwise false | ||
| 1121 | */ | ||
| 1122 | protected function checkBrowserKonqueror() | ||
| 1123 | { | ||
| 1124 | if (stripos($this->_agent, 'Konqueror') !== false) { | ||
| 1125 | $aresult = explode(' ', stristr($this->_agent, 'Konqueror')); | ||
| 1126 | $aversion = explode('/', $aresult[0]); | ||
| 1127 | if (isset($aversion[1])) { | ||
| 1128 | $this->setVersion($aversion[1]); | ||
| 1129 | $this->setBrowser(self::BROWSER_KONQUEROR); | ||
| 1130 | return true; | ||
| 1131 | } | ||
| 1132 | } | ||
| 1133 | return false; | ||
| 1134 | } | ||
| 1135 | |||
| 1136 | /** | ||
| 1137 | * Determine if the browser is iCab or not (last updated 1.7) | ||
| 1138 | * @return boolean True if the browser is iCab otherwise false | ||
| 1139 | */ | ||
| 1140 | protected function checkBrowserIcab() | ||
| 1141 | { | ||
| 1142 | if (stripos($this->_agent, 'icab') !== false) { | ||
| 1143 | $aversion = explode(' ', stristr(str_replace('/', ' ', $this->_agent), 'icab')); | ||
| 1144 | if (isset($aversion[1])) { | ||
| 1145 | $this->setVersion($aversion[1]); | ||
| 1146 | $this->setBrowser(self::BROWSER_ICAB); | ||
| 1147 | return true; | ||
| 1148 | } | ||
| 1149 | } | ||
| 1150 | return false; | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | /** | ||
| 1154 | * Determine if the browser is OmniWeb or not (last updated 1.7) | ||
| 1155 | * @return boolean True if the browser is OmniWeb otherwise false | ||
| 1156 | */ | ||
| 1157 | protected function checkBrowserOmniWeb() | ||
| 1158 | { | ||
| 1159 | if (stripos($this->_agent, 'omniweb') !== false) { | ||
| 1160 | $aresult = explode('/', stristr($this->_agent, 'omniweb')); | ||
| 1161 | $aversion = explode(' ', isset($aresult[1]) ? $aresult[1] : ""); | ||
| 1162 | $this->setVersion($aversion[0]); | ||
| 1163 | $this->setBrowser(self::BROWSER_OMNIWEB); | ||
| 1164 | return true; | ||
| 1165 | } | ||
| 1166 | return false; | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | /** | ||
| 1170 | * Determine if the browser is Phoenix or not (last updated 1.7) | ||
| 1171 | * @return boolean True if the browser is Phoenix otherwise false | ||
| 1172 | */ | ||
| 1173 | protected function checkBrowserPhoenix() | ||
| 1174 | { | ||
| 1175 | if (stripos($this->_agent, 'Phoenix') !== false) { | ||
| 1176 | $aversion = explode('/', stristr($this->_agent, 'Phoenix')); | ||
| 1177 | if (isset($aversion[1])) { | ||
| 1178 | $this->setVersion($aversion[1]); | ||
| 1179 | $this->setBrowser(self::BROWSER_PHOENIX); | ||
| 1180 | return true; | ||
| 1181 | } | ||
| 1182 | } | ||
| 1183 | return false; | ||
| 1184 | } | ||
| 1185 | |||
| 1186 | /** | ||
| 1187 | * Determine if the browser is Firebird or not (last updated 1.7) | ||
| 1188 | * @return boolean True if the browser is Firebird otherwise false | ||
| 1189 | */ | ||
| 1190 | protected function checkBrowserFirebird() | ||
| 1191 | { | ||
| 1192 | if (stripos($this->_agent, 'Firebird') !== false) { | ||
| 1193 | $aversion = explode('/', stristr($this->_agent, 'Firebird')); | ||
| 1194 | if (isset($aversion[1])) { | ||
| 1195 | $this->setVersion($aversion[1]); | ||
| 1196 | $this->setBrowser(self::BROWSER_FIREBIRD); | ||
| 1197 | return true; | ||
| 1198 | } | ||
| 1199 | } | ||
| 1200 | return false; | ||
| 1201 | } | ||
| 1202 | |||
| 1203 | /** | ||
| 1204 | * Determine if the browser is Netscape Navigator 9+ or not (last updated 1.7) | ||
| 1205 | * NOTE: (http://browser.netscape.com/ - Official support ended on March 1st, 2008) | ||
| 1206 | * @return boolean True if the browser is Netscape Navigator 9+ otherwise false | ||
| 1207 | */ | ||
| 1208 | protected function checkBrowserNetscapeNavigator9Plus() | ||
| 1209 | { | ||
| 1210 | if (stripos($this->_agent, 'Firefox') !== false && preg_match('/Navigator\/([^ ]*)/i', $this->_agent, $matches)) { | ||
| 1211 | $this->setVersion($matches[1]); | ||
| 1212 | $this->setBrowser(self::BROWSER_NETSCAPE_NAVIGATOR); | ||
| 1213 | return true; | ||
| 1214 | } else if (stripos($this->_agent, 'Firefox') === false && preg_match('/Netscape6?\/([^ ]*)/i', $this->_agent, $matches)) { | ||
| 1215 | $this->setVersion($matches[1]); | ||
| 1216 | $this->setBrowser(self::BROWSER_NETSCAPE_NAVIGATOR); | ||
| 1217 | return true; | ||
| 1218 | } | ||
| 1219 | return false; | ||
| 1220 | } | ||
| 1221 | |||
| 1222 | /** | ||
| 1223 | * Determine if the browser is Shiretoko or not (https://wiki.mozilla.org/Projects/shiretoko) (last updated 1.7) | ||
| 1224 | * @return boolean True if the browser is Shiretoko otherwise false | ||
| 1225 | */ | ||
| 1226 | protected function checkBrowserShiretoko() | ||
| 1227 | { | ||
| 1228 | if (stripos($this->_agent, 'Mozilla') !== false && preg_match('/Shiretoko\/([^ ]*)/i', $this->_agent, $matches)) { | ||
| 1229 | $this->setVersion($matches[1]); | ||
| 1230 | $this->setBrowser(self::BROWSER_SHIRETOKO); | ||
| 1231 | return true; | ||
| 1232 | } | ||
| 1233 | return false; | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | /** | ||
| 1237 | * Determine if the browser is Ice Cat or not (http://en.wikipedia.org/wiki/GNU_IceCat) (last updated 1.7) | ||
| 1238 | * @return boolean True if the browser is Ice Cat otherwise false | ||
| 1239 | */ | ||
| 1240 | protected function checkBrowserIceCat() | ||
| 1241 | { | ||
| 1242 | if (stripos($this->_agent, 'Mozilla') !== false && preg_match('/IceCat\/([^ ]*)/i', $this->_agent, $matches)) { | ||
| 1243 | $this->setVersion($matches[1]); | ||
| 1244 | $this->setBrowser(self::BROWSER_ICECAT); | ||
| 1245 | return true; | ||
| 1246 | } | ||
| 1247 | return false; | ||
| 1248 | } | ||
| 1249 | |||
| 1250 | /** | ||
| 1251 | * Determine if the browser is Nokia or not (last updated 1.7) | ||
| 1252 | * @return boolean True if the browser is Nokia otherwise false | ||
| 1253 | */ | ||
| 1254 | protected function checkBrowserNokia() | ||
| 1255 | { | ||
| 1256 | if (preg_match("/Nokia([^\/]+)\/([^ SP]+)/i", $this->_agent, $matches)) { | ||
| 1257 | $this->setVersion($matches[2]); | ||
| 1258 | if (stripos($this->_agent, 'Series60') !== false || strpos($this->_agent, 'S60') !== false) { | ||
| 1259 | $this->setBrowser(self::BROWSER_NOKIA_S60); | ||
| 1260 | } else { | ||
| 1261 | $this->setBrowser(self::BROWSER_NOKIA); | ||
| 1262 | } | ||
| 1263 | $this->setMobile(true); | ||
| 1264 | return true; | ||
| 1265 | } | ||
| 1266 | return false; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | /** | ||
| 1270 | * Determine if the browser is Firefox or not (last updated 1.7) | ||
| 1271 | * @return boolean True if the browser is Firefox otherwise false | ||
| 1272 | */ | ||
| 1273 | protected function checkBrowserFirefox() | ||
| 1274 | { | ||
| 1275 | if (stripos($this->_agent, 'safari') === false) { | ||
| 1276 | if (preg_match("/Firefox[\/ \(]([^ ;\)]+)/i", $this->_agent, $matches)) { | ||
| 1277 | $this->setVersion($matches[1]); | ||
| 1278 | $this->setBrowser(self::BROWSER_FIREFOX); | ||
| 1279 | //Firefox on Android | ||
| 1280 | if (stripos($this->_agent, 'Android') !== false) { | ||
| 1281 | if (stripos($this->_agent, 'Mobile') !== false) { | ||
| 1282 | $this->setMobile(true); | ||
| 1283 | } else { | ||
| 1284 | $this->setTablet(true); | ||
| 1285 | } | ||
| 1286 | } | ||
| 1287 | return true; | ||
| 1288 | } else if (preg_match("/Firefox$/i", $this->_agent, $matches)) { | ||
| 1289 | $this->setVersion(""); | ||
| 1290 | $this->setBrowser(self::BROWSER_FIREFOX); | ||
| 1291 | return true; | ||
| 1292 | } | ||
| 1293 | } | ||
| 1294 | return false; | ||
| 1295 | } | ||
| 1296 | |||
| 1297 | /** | ||
| 1298 | * Determine if the browser is Firefox or not (last updated 1.7) | ||
| 1299 | * @return boolean True if the browser is Firefox otherwise false | ||
| 1300 | */ | ||
| 1301 | protected function checkBrowserIceweasel() | ||
| 1302 | { | ||
| 1303 | if (stripos($this->_agent, 'Iceweasel') !== false) { | ||
| 1304 | $aresult = explode('/', stristr($this->_agent, 'Iceweasel')); | ||
| 1305 | if (isset($aresult[1])) { | ||
| 1306 | $aversion = explode(' ', $aresult[1]); | ||
| 1307 | $this->setVersion($aversion[0]); | ||
| 1308 | $this->setBrowser(self::BROWSER_ICEWEASEL); | ||
| 1309 | return true; | ||
| 1310 | } | ||
| 1311 | } | ||
| 1312 | return false; | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | /** | ||
| 1316 | * Determine if the browser is Mozilla or not (last updated 1.7) | ||
| 1317 | * @return boolean True if the browser is Mozilla otherwise false | ||
| 1318 | */ | ||
| 1319 | protected function checkBrowserMozilla() | ||
| 1320 | { | ||
| 1321 | if (stripos($this->_agent, 'mozilla') !== false && preg_match('/rv:[0-9].[0-9][a-b]?/i', $this->_agent) && stripos($this->_agent, 'netscape') === false) { | ||
| 1322 | $aversion = explode(' ', stristr($this->_agent, 'rv:')); | ||
| 1323 | preg_match('/rv:[0-9].[0-9][a-b]?/i', $this->_agent, $aversion); | ||
| 1324 | $this->setVersion(str_replace('rv:', '', $aversion[0])); | ||
| 1325 | $this->setBrowser(self::BROWSER_MOZILLA); | ||
| 1326 | return true; | ||
| 1327 | } else if (stripos($this->_agent, 'mozilla') !== false && preg_match('/rv:[0-9]\.[0-9]/i', $this->_agent) && stripos($this->_agent, 'netscape') === false) { | ||
| 1328 | $aversion = explode('', stristr($this->_agent, 'rv:')); | ||
| 1329 | $this->setVersion(str_replace('rv:', '', $aversion[0])); | ||
| 1330 | $this->setBrowser(self::BROWSER_MOZILLA); | ||
| 1331 | return true; | ||
| 1332 | } else if (stripos($this->_agent, 'mozilla') !== false && preg_match('/mozilla\/([^ ]*)/i', $this->_agent, $matches) && stripos($this->_agent, 'netscape') === false) { | ||
| 1333 | $this->setVersion($matches[1]); | ||
| 1334 | $this->setBrowser(self::BROWSER_MOZILLA); | ||
| 1335 | return true; | ||
| 1336 | } | ||
| 1337 | return false; | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | /** | ||
| 1341 | * Determine if the browser is Lynx or not (last updated 1.7) | ||
| 1342 | * @return boolean True if the browser is Lynx otherwise false | ||
| 1343 | */ | ||
| 1344 | protected function checkBrowserLynx() | ||
| 1345 | { | ||
| 1346 | if (stripos($this->_agent, 'lynx') !== false) { | ||
| 1347 | $aresult = explode('/', stristr($this->_agent, 'Lynx')); | ||
| 1348 | $aversion = explode(' ', (isset($aresult[1]) ? $aresult[1] : "")); | ||
| 1349 | $this->setVersion($aversion[0]); | ||
| 1350 | $this->setBrowser(self::BROWSER_LYNX); | ||
| 1351 | return true; | ||
| 1352 | } | ||
| 1353 | return false; | ||
| 1354 | } | ||
| 1355 | |||
| 1356 | /** | ||
| 1357 | * Determine if the browser is Amaya or not (last updated 1.7) | ||
| 1358 | * @return boolean True if the browser is Amaya otherwise false | ||
| 1359 | */ | ||
| 1360 | protected function checkBrowserAmaya() | ||
| 1361 | { | ||
| 1362 | if (stripos($this->_agent, 'amaya') !== false) { | ||
| 1363 | $aresult = explode('/', stristr($this->_agent, 'Amaya')); | ||
| 1364 | if (isset($aresult[1])) { | ||
| 1365 | $aversion = explode(' ', $aresult[1]); | ||
| 1366 | $this->setVersion($aversion[0]); | ||
| 1367 | $this->setBrowser(self::BROWSER_AMAYA); | ||
| 1368 | return true; | ||
| 1369 | } | ||
| 1370 | } | ||
| 1371 | return false; | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | /** | ||
| 1375 | * Determine if the browser is Safari or not (last updated 1.7) | ||
| 1376 | * @return boolean True if the browser is Safari otherwise false | ||
| 1377 | */ | ||
| 1378 | protected function checkBrowserSafari() | ||
| 1379 | { | ||
| 1380 | if (stripos($this->_agent, 'Safari') !== false | ||
| 1381 | && stripos($this->_agent, 'iPhone') === false | ||
| 1382 | && stripos($this->_agent, 'iPod') === false | ||
| 1383 | ) { | ||
| 1384 | |||
| 1385 | $aresult = explode('/', stristr($this->_agent, 'Version')); | ||
| 1386 | if (isset($aresult[1])) { | ||
| 1387 | $aversion = explode(' ', $aresult[1]); | ||
| 1388 | $this->setVersion($aversion[0]); | ||
| 1389 | } else { | ||
| 1390 | $this->setVersion(self::VERSION_UNKNOWN); | ||
| 1391 | } | ||
| 1392 | $this->setBrowser(self::BROWSER_SAFARI); | ||
| 1393 | return true; | ||
| 1394 | } | ||
| 1395 | return false; | ||
| 1396 | } | ||
| 1397 | |||
| 1398 | protected function checkBrowserSamsung() | ||
| 1399 | { | ||
| 1400 | if (stripos($this->_agent, 'SamsungBrowser') !== false) { | ||
| 1401 | |||
| 1402 | $aresult = explode('/', stristr($this->_agent, 'SamsungBrowser')); | ||
| 1403 | if (isset($aresult[1])) { | ||
| 1404 | $aversion = explode(' ', $aresult[1]); | ||
| 1405 | $this->setVersion($aversion[0]); | ||
| 1406 | } else { | ||
| 1407 | $this->setVersion(self::VERSION_UNKNOWN); | ||
| 1408 | } | ||
| 1409 | $this->setBrowser(self::BROWSER_SAMSUNG); | ||
| 1410 | return true; | ||
| 1411 | } | ||
| 1412 | return false; | ||
| 1413 | } | ||
| 1414 | |||
| 1415 | protected function checkBrowserSilk() | ||
| 1416 | { | ||
| 1417 | if (stripos($this->_agent, 'Silk') !== false) { | ||
| 1418 | $aresult = explode('/', stristr($this->_agent, 'Silk')); | ||
| 1419 | if (isset($aresult[1])) { | ||
| 1420 | $aversion = explode(' ', $aresult[1]); | ||
| 1421 | $this->setVersion($aversion[0]); | ||
| 1422 | } else { | ||
| 1423 | $this->setVersion(self::VERSION_UNKNOWN); | ||
| 1424 | } | ||
| 1425 | $this->setBrowser(self::BROWSER_SILK); | ||
| 1426 | return true; | ||
| 1427 | } | ||
| 1428 | return false; | ||
| 1429 | } | ||
| 1430 | |||
| 1431 | protected function checkBrowserIframely() | ||
| 1432 | { | ||
| 1433 | if (stripos($this->_agent, 'Iframely') !== false) { | ||
| 1434 | $aresult = explode('/', stristr($this->_agent, 'Iframely')); | ||
| 1435 | if (isset($aresult[1])) { | ||
| 1436 | $aversion = explode(' ', $aresult[1]); | ||
| 1437 | $this->setVersion($aversion[0]); | ||
| 1438 | } else { | ||
| 1439 | $this->setVersion(self::VERSION_UNKNOWN); | ||
| 1440 | } | ||
| 1441 | $this->setBrowser(self::BROWSER_I_FRAME); | ||
| 1442 | return true; | ||
| 1443 | } | ||
| 1444 | return false; | ||
| 1445 | } | ||
| 1446 | |||
| 1447 | protected function checkBrowserCocoa() | ||
| 1448 | { | ||
| 1449 | if (stripos($this->_agent, 'CocoaRestClient') !== false) { | ||
| 1450 | $aresult = explode('/', stristr($this->_agent, 'CocoaRestClient')); | ||
| 1451 | if (isset($aresult[1])) { | ||
| 1452 | $aversion = explode(' ', $aresult[1]); | ||
| 1453 | $this->setVersion($aversion[0]); | ||
| 1454 | } else { | ||
| 1455 | $this->setVersion(self::VERSION_UNKNOWN); | ||
| 1456 | } | ||
| 1457 | $this->setBrowser(self::BROWSER_COCOA); | ||
| 1458 | return true; | ||
| 1459 | } | ||
| 1460 | return false; | ||
| 1461 | } | ||
| 1462 | |||
| 1463 | /** | ||
| 1464 | * Detect if URL is loaded from FacebookExternalHit | ||
| 1465 | * @return boolean True if it detects FacebookExternalHit otherwise false | ||
| 1466 | */ | ||
| 1467 | protected function checkFacebookExternalHit() | ||
| 1468 | { | ||
| 1469 | if (stristr($this->_agent, 'FacebookExternalHit')) { | ||
| 1470 | $this->setRobot(true); | ||
| 1471 | $this->setFacebook(true); | ||
| 1472 | return true; | ||
| 1473 | } | ||
| 1474 | return false; | ||
| 1475 | } | ||
| 1476 | |||
| 1477 | /** | ||
| 1478 | * Detect if URL is being loaded from internal Facebook browser | ||
| 1479 | * @return boolean True if it detects internal Facebook browser otherwise false | ||
| 1480 | */ | ||
| 1481 | protected function checkForFacebookIos() | ||
| 1482 | { | ||
| 1483 | if (stristr($this->_agent, 'FBIOS')) { | ||
| 1484 | $this->setFacebook(true); | ||
| 1485 | return true; | ||
| 1486 | } | ||
| 1487 | return false; | ||
| 1488 | } | ||
| 1489 | |||
| 1490 | /** | ||
| 1491 | * Detect Version for the Safari browser on iOS devices | ||
| 1492 | * @return boolean True if it detects the version correctly otherwise false | ||
| 1493 | */ | ||
| 1494 | protected function getSafariVersionOnIos() | ||
| 1495 | { | ||
| 1496 | $aresult = explode('/', stristr($this->_agent, 'Version')); | ||
| 1497 | if (isset($aresult[1])) { | ||
| 1498 | $aversion = explode(' ', $aresult[1]); | ||
| 1499 | $this->setVersion($aversion[0]); | ||
| 1500 | return true; | ||
| 1501 | } | ||
| 1502 | return false; | ||
| 1503 | } | ||
| 1504 | |||
| 1505 | /** | ||
| 1506 | * Detect Version for the Chrome browser on iOS devices | ||
| 1507 | * @return boolean True if it detects the version correctly otherwise false | ||
| 1508 | */ | ||
| 1509 | protected function getChromeVersionOnIos() | ||
| 1510 | { | ||
| 1511 | $aresult = explode('/', stristr($this->_agent, 'CriOS')); | ||
| 1512 | if (isset($aresult[1])) { | ||
| 1513 | $aversion = explode(' ', $aresult[1]); | ||
| 1514 | $this->setVersion($aversion[0]); | ||
| 1515 | $this->setBrowser(self::BROWSER_CHROME); | ||
| 1516 | return true; | ||
| 1517 | } | ||
| 1518 | return false; | ||
| 1519 | } | ||
| 1520 | |||
| 1521 | /** | ||
| 1522 | * Determine if the browser is iPhone or not (last updated 1.7) | ||
| 1523 | * @return boolean True if the browser is iPhone otherwise false | ||
| 1524 | */ | ||
| 1525 | protected function checkBrowseriPhone() | ||
| 1526 | { | ||
| 1527 | if (stripos($this->_agent, 'iPhone') !== false) { | ||
| 1528 | $this->setVersion(self::VERSION_UNKNOWN); | ||
| 1529 | $this->setBrowser(self::BROWSER_IPHONE); | ||
| 1530 | $this->getSafariVersionOnIos(); | ||
| 1531 | $this->getChromeVersionOnIos(); | ||
| 1532 | $this->checkForFacebookIos(); | ||
| 1533 | $this->setMobile(true); | ||
| 1534 | return true; | ||
| 1535 | |||
| 1536 | } | ||
| 1537 | return false; | ||
| 1538 | } | ||
| 1539 | |||
| 1540 | /** | ||
| 1541 | * Determine if the browser is iPad or not (last updated 1.7) | ||
| 1542 | * @return boolean True if the browser is iPad otherwise false | ||
| 1543 | */ | ||
| 1544 | protected function checkBrowseriPad() | ||
| 1545 | { | ||
| 1546 | if (stripos($this->_agent, 'iPad') !== false) { | ||
| 1547 | $this->setVersion(self::VERSION_UNKNOWN); | ||
| 1548 | $this->setBrowser(self::BROWSER_IPAD); | ||
| 1549 | $this->getSafariVersionOnIos(); | ||
| 1550 | $this->getChromeVersionOnIos(); | ||
| 1551 | $this->checkForFacebookIos(); | ||
| 1552 | $this->setTablet(true); | ||
| 1553 | return true; | ||
| 1554 | } | ||
| 1555 | return false; | ||
| 1556 | } | ||
| 1557 | |||
| 1558 | /** | ||
| 1559 | * Determine if the browser is iPod or not (last updated 1.7) | ||
| 1560 | * @return boolean True if the browser is iPod otherwise false | ||
| 1561 | */ | ||
| 1562 | protected function checkBrowseriPod() | ||
| 1563 | { | ||
| 1564 | if (stripos($this->_agent, 'iPod') !== false) { | ||
| 1565 | $this->setVersion(self::VERSION_UNKNOWN); | ||
| 1566 | $this->setBrowser(self::BROWSER_IPOD); | ||
| 1567 | $this->getSafariVersionOnIos(); | ||
| 1568 | $this->getChromeVersionOnIos(); | ||
| 1569 | $this->checkForFacebookIos(); | ||
| 1570 | $this->setMobile(true); | ||
| 1571 | return true; | ||
| 1572 | } | ||
| 1573 | return false; | ||
| 1574 | } | ||
| 1575 | |||
| 1576 | /** | ||
| 1577 | * Determine if the browser is Android or not (last updated 1.7) | ||
| 1578 | * @return boolean True if the browser is Android otherwise false | ||
| 1579 | */ | ||
| 1580 | protected function checkBrowserAndroid() | ||
| 1581 | { | ||
| 1582 | if (stripos($this->_agent, 'Android') !== false) { | ||
| 1583 | $aresult = explode(' ', stristr($this->_agent, 'Android')); | ||
| 1584 | if (isset($aresult[1])) { | ||
| 1585 | $aversion = explode(' ', $aresult[1]); | ||
| 1586 | $this->setVersion($aversion[0]); | ||
| 1587 | } else { | ||
| 1588 | $this->setVersion(self::VERSION_UNKNOWN); | ||
| 1589 | } | ||
| 1590 | if (stripos($this->_agent, 'Mobile') !== false) { | ||
| 1591 | $this->setMobile(true); | ||
| 1592 | } else { | ||
| 1593 | $this->setTablet(true); | ||
| 1594 | } | ||
| 1595 | $this->setBrowser(self::BROWSER_ANDROID); | ||
| 1596 | return true; | ||
| 1597 | } | ||
| 1598 | return false; | ||
| 1599 | } | ||
| 1600 | |||
| 1601 | /** | ||
| 1602 | * Determine if the browser is Vivaldi | ||
| 1603 | * @return boolean True if the browser is Vivaldi otherwise false | ||
| 1604 | */ | ||
| 1605 | protected function checkBrowserVivaldi() | ||
| 1606 | { | ||
| 1607 | if (stripos($this->_agent, 'Vivaldi') !== false) { | ||
| 1608 | $aresult = explode('/', stristr($this->_agent, 'Vivaldi')); | ||
| 1609 | if (isset($aresult[1])) { | ||
| 1610 | $aversion = explode(' ', $aresult[1]); | ||
| 1611 | $this->setVersion($aversion[0]); | ||
| 1612 | $this->setBrowser(self::BROWSER_VIVALDI); | ||
| 1613 | return true; | ||
| 1614 | } | ||
| 1615 | } | ||
| 1616 | return false; | ||
| 1617 | } | ||
| 1618 | |||
| 1619 | /** | ||
| 1620 | * Determine if the browser is Yandex | ||
| 1621 | * @return boolean True if the browser is Yandex otherwise false | ||
| 1622 | */ | ||
| 1623 | protected function checkBrowserYandex() | ||
| 1624 | { | ||
| 1625 | if (stripos($this->_agent, 'YaBrowser') !== false) { | ||
| 1626 | $aresult = explode('/', stristr($this->_agent, 'YaBrowser')); | ||
| 1627 | if (isset($aresult[1])) { | ||
| 1628 | $aversion = explode(' ', $aresult[1]); | ||
| 1629 | $this->setVersion($aversion[0]); | ||
| 1630 | $this->setBrowser(self::BROWSER_YANDEX); | ||
| 1631 | |||
| 1632 | if (stripos($this->_agent, 'iPad') !== false) { | ||
| 1633 | $this->setTablet(true); | ||
| 1634 | } elseif (stripos($this->_agent, 'Mobile') !== false) { | ||
| 1635 | $this->setMobile(true); | ||
| 1636 | } elseif (stripos($this->_agent, 'Android') !== false) { | ||
| 1637 | $this->setTablet(true); | ||
| 1638 | } | ||
| 1639 | |||
| 1640 | return true; | ||
| 1641 | } | ||
| 1642 | } | ||
| 1643 | |||
| 1644 | return false; | ||
| 1645 | } | ||
| 1646 | |||
| 1647 | /** | ||
| 1648 | * Determine if the browser is a PlayStation | ||
| 1649 | * @return boolean True if the browser is PlayStation otherwise false | ||
| 1650 | */ | ||
| 1651 | protected function checkBrowserPlayStation() | ||
| 1652 | { | ||
| 1653 | if (stripos($this->_agent, 'PlayStation ') !== false) { | ||
| 1654 | $aresult = explode(' ', stristr($this->_agent, 'PlayStation ')); | ||
| 1655 | $this->setBrowser(self::BROWSER_PLAYSTATION); | ||
| 1656 | if (isset($aresult[0])) { | ||
| 1657 | $aversion = explode(')', $aresult[2]); | ||
| 1658 | $this->setVersion($aversion[0]); | ||
| 1659 | if (stripos($this->_agent, 'Portable)') !== false || stripos($this->_agent, 'Vita') !== false) { | ||
| 1660 | $this->setMobile(true); | ||
| 1661 | } | ||
| 1662 | return true; | ||
| 1663 | } | ||
| 1664 | } | ||
| 1665 | return false; | ||
| 1666 | } | ||
| 1667 | |||
| 1668 | /** | ||
| 1669 | * Determine the user's platform (last updated 2.0) | ||
| 1670 | */ | ||
| 1671 | protected function checkPlatform() | ||
| 1672 | { | ||
| 1673 | if (stripos($this->_agent, 'windows') !== false) { | ||
| 1674 | $this->_platform = self::PLATFORM_WINDOWS; | ||
| 1675 | } else if (stripos($this->_agent, 'iPad') !== false) { | ||
| 1676 | $this->_platform = self::PLATFORM_IPAD; | ||
| 1677 | } else if (stripos($this->_agent, 'iPod') !== false) { | ||
| 1678 | $this->_platform = self::PLATFORM_IPOD; | ||
| 1679 | } else if (stripos($this->_agent, 'iPhone') !== false) { | ||
| 1680 | $this->_platform = self::PLATFORM_IPHONE; | ||
| 1681 | } elseif (stripos($this->_agent, 'mac') !== false) { | ||
| 1682 | $this->_platform = self::PLATFORM_APPLE; | ||
| 1683 | } elseif (stripos($this->_agent, 'android') !== false) { | ||
| 1684 | $this->_platform = self::PLATFORM_ANDROID; | ||
| 1685 | } elseif (stripos($this->_agent, 'Silk') !== false) { | ||
| 1686 | $this->_platform = self::PLATFORM_FIRE_OS; | ||
| 1687 | } elseif (stripos($this->_agent, 'linux') !== false && stripos($this->_agent, 'SMART-TV') !== false ) { | ||
| 1688 | $this->_platform = self::PLATFORM_LINUX .'/'.self::PLATFORM_SMART_TV; | ||
| 1689 | } elseif (stripos($this->_agent, 'linux') !== false) { | ||
| 1690 | $this->_platform = self::PLATFORM_LINUX; | ||
| 1691 | } else if (stripos($this->_agent, 'Nokia') !== false) { | ||
| 1692 | $this->_platform = self::PLATFORM_NOKIA; | ||
| 1693 | } else if (stripos($this->_agent, 'BlackBerry') !== false) { | ||
| 1694 | $this->_platform = self::PLATFORM_BLACKBERRY; | ||
| 1695 | } elseif (stripos($this->_agent, 'FreeBSD') !== false) { | ||
| 1696 | $this->_platform = self::PLATFORM_FREEBSD; | ||
| 1697 | } elseif (stripos($this->_agent, 'OpenBSD') !== false) { | ||
| 1698 | $this->_platform = self::PLATFORM_OPENBSD; | ||
| 1699 | } elseif (stripos($this->_agent, 'NetBSD') !== false) { | ||
| 1700 | $this->_platform = self::PLATFORM_NETBSD; | ||
| 1701 | } elseif (stripos($this->_agent, 'OpenSolaris') !== false) { | ||
| 1702 | $this->_platform = self::PLATFORM_OPENSOLARIS; | ||
| 1703 | } elseif (stripos($this->_agent, 'SunOS') !== false) { | ||
| 1704 | $this->_platform = self::PLATFORM_SUNOS; | ||
| 1705 | } elseif (stripos($this->_agent, 'OS\/2') !== false) { | ||
| 1706 | $this->_platform = self::PLATFORM_OS2; | ||
| 1707 | } elseif (stripos($this->_agent, 'BeOS') !== false) { | ||
| 1708 | $this->_platform = self::PLATFORM_BEOS; | ||
| 1709 | } elseif (stripos($this->_agent, 'win') !== false) { | ||
| 1710 | $this->_platform = self::PLATFORM_WINDOWS; | ||
| 1711 | } elseif (stripos($this->_agent, 'Playstation') !== false) { | ||
| 1712 | $this->_platform = self::PLATFORM_PLAYSTATION; | ||
| 1713 | } elseif (stripos($this->_agent, 'Roku') !== false) { | ||
| 1714 | $this->_platform = self::PLATFORM_ROKU; | ||
| 1715 | } elseif (stripos($this->_agent, 'iOS') !== false) { | ||
| 1716 | $this->_platform = self::PLATFORM_IPHONE . '/' . self::PLATFORM_IPAD; | ||
| 1717 | } elseif (stripos($this->_agent, 'tvOS') !== false) { | ||
| 1718 | $this->_platform = self::PLATFORM_APPLE_TV; | ||
| 1719 | } elseif (stripos($this->_agent, 'curl') !== false) { | ||
| 1720 | $this->_platform = self::PLATFORM_TERMINAL; | ||
| 1721 | } elseif (stripos($this->_agent, 'CrOS') !== false) { | ||
| 1722 | $this->_platform = self::PLATFORM_CHROME_OS; | ||
| 1723 | } elseif (stripos($this->_agent, 'okhttp') !== false) { | ||
| 1724 | $this->_platform = self::PLATFORM_JAVA_ANDROID; | ||
| 1725 | } elseif (stripos($this->_agent, 'PostmanRuntime') !== false) { | ||
| 1726 | $this->_platform = self::PLATFORM_POSTMAN; | ||
| 1727 | } elseif (stripos($this->_agent, 'Iframely') !== false) { | ||
| 1728 | $this->_platform = self::PLATFORM_I_FRAME; | ||
| 1729 | } | ||
| 1730 | |||
| 1731 | } | ||
| 1732 | } | ||
| 1733 |
k2shop/usr/k2shop/libs/browser/Readme.txt
| File was created | 1 | Определение версии и типа браузера. | |
| 2 | Постоянно обновляется по адресу: https://github.com/cbschuld/Browser.php | ||
| 3 | Статья по данной теме: https://ruseller.com/adds.php?rub=11&id=1914 | ||
| 4 | |||
| 5 | Пример использования: | ||
| 6 | $browser = new Browser(); | ||
| 7 | if( $browser->getBrowser() == Browser::BROWSER_FIREFOX && $browser->getVersion() >= 2 ) { | ||
| 8 | echo 'Вы используете браузер FireFox версии 2 или выше'; | ||
| 9 | } |
k2shop/usr/k2shop/libs/detectDevice/DetectDeviceTest.php
| File was created | 1 | <?php | |
| 2 | require "class.DetectDevice.php"; | ||
| 3 | |||
| 4 | class DetectDeviceTest extends PHPUnit_Framework_TestCase { | ||
| 5 | |||
| 6 | private $device; | ||
| 7 | |||
| 8 | public function __construct() { | ||
| 9 | $this->device = new DetectDevice("Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36"); | ||
| 10 | } | ||
| 11 | |||
| 12 | public function testComputer() { | ||
| 13 | // Google Chrome 29 on Windows 8 x64 | ||
| 14 | $this->device->setUserAgent("Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36"); | ||
| 15 | $this->assertEquals(true, $this->device->isComputer()); | ||
| 16 | |||
| 17 | // Mozilla Firefox 22 on Windows 8 x64 | ||
| 18 | $this->device->setUserAgent("Mozilla/5.0 (Windows NT 6.2; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"); | ||
| 19 | $this->assertEquals(true, $this->device->isComputer()); | ||
| 20 | } | ||
| 21 | |||
| 22 | public function testMobile() { | ||
| 23 | // LGE Nexus 4 | ||
| 24 | $this->device->setUserAgent("Mozilla/5.0 (Linux; Android 4.2; Nexus 4 Build/JVP15Q) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19"); | ||
| 25 | $this->assertEquals(true, $this->device->isMobile()); | ||
| 26 | |||
| 27 | // Samsung Galaxy S4 | ||
| 28 | $this->device->setUserAgent("Mozilla/5.0 (Linux; U; Android 4.0.4; en-gb; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30"); | ||
| 29 | $this->assertEquals(true, $this->device->isMobile()); | ||
| 30 | } | ||
| 31 | |||
| 32 | public function testTablet() { | ||
| 33 | // Asus Nexus 7 | ||
| 34 | $this->device->setUserAgent("Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19"); | ||
| 35 | $this->assertEquals(true, $this->device->isTablet()); | ||
| 36 | |||
| 37 | // Samsung Galaxy Note 10.1 | ||
| 38 | $this->device->setUserAgent("Mozilla/5.0 (Linux; U; Android 4.0; xx-xx; GT-N8000 Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30"); | ||
| 39 | $this->assertEquals(true, $this->device->isTablet()); | ||
| 40 | } | ||
| 41 | |||
| 42 | public function testBot() { | ||
| 43 | // GoogleBot | ||
| 44 | $this->device->setUserAgent("Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"); | ||
| 45 | $this->assertEquals(true, $this->device->isBot()); | ||
| 46 | |||
| 47 | // BingBot | ||
| 48 | $this->device->setUserAgent("Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"); | ||
| 49 | $this->assertEquals(true, $this->device->isBot()); | ||
| 50 | } | ||
| 51 | |||
| 52 | public function testConsole() { | ||
| 53 | // PS3 | ||
| 54 | $this->device->setUserAgent("Mozilla/5.0 (PLAYSTATION 3; 3.55)"); | ||
| 55 | $this->assertEquals(true, $this->device->isConsole()); | ||
| 56 | |||
| 57 | // XBox | ||
| 58 | $this->device->setUserAgent("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)"); | ||
| 59 | $this->assertEquals(true, $this->device->isConsole()); | ||
| 60 | } | ||
| 61 | |||
| 62 | public function testIs() { | ||
| 63 | // Google Chrome | ||
| 64 | $this->device->setUserAgent("Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36"); | ||
| 65 | $this->assertEquals(true, $this->device->is("chrome")); | ||
| 66 | |||
| 67 | // Nintendo DS | ||
| 68 | $this->device->setUserAgent("Mozilla/5.0 (Windows NT 6.2; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"); | ||
| 69 | $this->assertEquals(true, $this->device->is("firefox")); | ||
| 70 | } | ||
| 71 | } |
k2shop/usr/k2shop/libs/detectDevice/README.md
| File was created | 1 | DetectDevice | |
| 2 | ============ | ||
| 3 | [](https://travis-ci.org/Kocal/DetectDevice) | ||
| 4 | |||
| 5 | DetectDevice is a little (~70 lines), simply, and functional PHP class which detect what kind of device is used to navigate on your website, a pc, a mobile, a tablet or a bot. | ||
| 6 | |||
| 7 | |||
| 8 | How use? | ||
| 9 | -------- | ||
| 10 | #### Firstly, include DetectDevice class and initialize it | ||
| 11 | ```php | ||
| 12 | <?php | ||
| 13 | require "class.DetectDevice.php"; | ||
| 14 | $device = new DetectDevice(); | ||
| 15 | // ... | ||
| 16 | ``` | ||
| 17 | |||
| 18 | #### Optional : If you want, you can set an other user-agent | ||
| 19 | ```php | ||
| 20 | <?php | ||
| 21 | $userAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36"; | ||
| 22 | |||
| 23 | // in the constructor | ||
| 24 | $device = new DetectDevice($userAgent); | ||
| 25 | |||
| 26 | // or with the "setUserAgent()" method | ||
| 27 | $device->setUserAgent($userAgent); | ||
| 28 | ``` | ||
| 29 | |||
| 30 | #### Use methods to find what kind of device is used | ||
| 31 | ```php | ||
| 32 | <?php | ||
| 33 | // return a boolean (true or false) | ||
| 34 | echo $device->isComputer(); | ||
| 35 | echo $device->isMobile(); | ||
| 36 | echo $device->isTablet(); | ||
| 37 | echo $device->isBot(); | ||
| 38 | echo $device->isConsole(); | ||
| 39 | |||
| 40 | // You can use the "getDeviceType()" to return a string | ||
| 41 | echo $device->getDeviceType(); // may return "computer", "mobile, "tablet", "bot" or "console" | ||
| 42 | // ... | ||
| 43 | ``` | ||
| 44 | |||
| 45 | #### Or use "is()" | ||
| 46 | ```php | ||
| 47 | <?php | ||
| 48 | // The "is()" method match $str in UserAgent $str, and return true or false | ||
| 49 | |||
| 50 | $str = "msie"; | ||
| 51 | |||
| 52 | if($device->is($str)) { | ||
| 53 | // do stuff for Internet Explorer only | ||
| 54 | } | ||
| 55 | |||
| 56 | ``` |
k2shop/usr/k2shop/libs/detectDevice/class.DetectDevice.php
| File was created | 1 | <?php class DetectDevice { | |
| 2 | |||
| 3 | private $userAgent = ""; | ||
| 4 | |||
| 5 | private $devices = array( | ||
| 6 | "computer" => array("msie 10", "msie 9", "msie 8", "windows.*firefox", "windows.*chrome", "x11.*chrome", "x11.*firefox", "macintosh.*chrome", "macintosh.*firefox", "opera"), | ||
| 7 | "tablet" => array("tablet", "android", "ipad", "tablet.*firefox"), | ||
| 8 | "mobile" => array("mobile ", "android.*mobile", "iphone", "ipod", "opera mobi", "opera mini"), | ||
| 9 | "bot" => array("googlebot", "mediapartners-google", "adsbot-google", "duckduckbot", "msnbot", "bingbot", "ask", "facebook", "yahoo", "addthis"), | ||
| 10 | "console" => array("ps2", "playstation", "xbox", "wii", "nintendo 3?ds") | ||
| 11 | ); | ||
| 12 | |||
| 13 | |||
| 14 | private $deviceType = ""; | ||
| 15 | |||
| 16 | private $isComputer = false; | ||
| 17 | private $isMobile = false; | ||
| 18 | private $isTablet = false; | ||
| 19 | private $isBot = false; | ||
| 20 | private $isConsole = false; | ||
| 21 | |||
| 22 | |||
| 23 | public function __construct($userAgent = "") { | ||
| 24 | if(!empty($userAgent)) { | ||
| 25 | $this->userAgent = $userAgent; | ||
| 26 | } else { | ||
| 27 | $this->userAgent = $_SERVER["HTTP_USER_AGENT"]; | ||
| 28 | } | ||
| 29 | |||
| 30 | $this->detectDevice(); | ||
| 31 | } | ||
| 32 | |||
| 33 | public function detectDevice() { | ||
| 34 | foreach($this->devices as $deviceType => $devices) { | ||
| 35 | foreach($devices as $device) { | ||
| 36 | if(preg_match("/" . $device . "/i", $this->userAgent)) { | ||
| 37 | $this->deviceType = $deviceType; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | $d = "is" . ucfirst($this->deviceType); | ||
| 43 | $this->$d = true; | ||
| 44 | } | ||
| 45 | |||
| 46 | public function setUserAgent($userAgent) { | ||
| 47 | $this->userAgent = $userAgent; | ||
| 48 | $this->resetDevices(); | ||
| 49 | $this->detectDevice(); | ||
| 50 | } | ||
| 51 | |||
| 52 | public function resetDevices() { | ||
| 53 | $this->isComputer = false; | ||
| 54 | $this->isMobile = false; | ||
| 55 | $this->isTablet = false; | ||
| 56 | $this->isBot = false; | ||
| 57 | } | ||
| 58 | |||
| 59 | public function is($str, $userAgent = null) { | ||
| 60 | if(!$userAgent) { | ||
| 61 | $userAgent = $this->userAgent; | ||
| 62 | } | ||
| 63 | |||
| 64 | return preg_match('/' . $str . '/i', $userAgent); | ||
| 65 | } | ||
| 66 | |||
| 67 | public function getDeviceType() { return $this->deviceType; } | ||
| 68 | public function isComputer() { return $this->isComputer; } | ||
| 69 | public function isMobile() { return $this->isMobile; } | ||
| 70 | public function isTablet() { return $this->isTablet; } | ||
| 71 | public function isBot() { return $this->isBot; } | ||
| 72 | public function isConsole() { return $this->isConsole; } | ||
| 73 | public function getUserAgent() { return $this->userAgent; } | ||
| 74 | |||
| 75 | |||
| 76 | } | ||
| 77 |
k2shop/usr/k2shop/libs/nestmenu/index.html
| File was created | 1 | <!DOCTYPE html> | |
| 2 | <!--[if lt IE 7]> <html lang="en" class="lt-ie9 lt-ie8 lt-ie7"> <![endif]--> | ||
| 3 | <!--[if IE 7]> <html lang="en" class="lt-ie9 lt-ie8"> <![endif]--> | ||
| 4 | <!--[if IE 8]> <html lang="en" class="lt-ie9"> <![endif]--> | ||
| 5 | <!--[if IE 9]> <html lang="en" class="ie9"> <![endif]--> | ||
| 6 | <!--[if gt IE 9]><!--> <html lang="en"> <!--<![endif]--> | ||
| 7 | <head> | ||
| 8 | <meta charset="utf-8"> | ||
| 9 | <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> | ||
| 10 | <title>Nestable</title> | ||
| 11 | <style type="text/css"> | ||
| 12 | .cf:after { visibility: hidden; display: block; font-size: 0; content: " "; clear: both; height: 0; } | ||
| 13 | * html .cf { zoom: 1; } | ||
| 14 | *:first-child+html .cf { zoom: 1; } | ||
| 15 | html { margin: 0; padding: 0; } | ||
| 16 | body { font-size: 100%; margin: 0; padding: 1.75em; font-family: 'Helvetica Neue', Arial, sans-serif; } | ||
| 17 | h1 { font-size: 1.75em; margin: 0 0 0.6em 0; } | ||
| 18 | a { color: #2996cc; } | ||
| 19 | a:hover { text-decoration: none; } | ||
| 20 | p { line-height: 1.5em; } | ||
| 21 | .small { color: #666; font-size: 0.875em; } | ||
| 22 | .large { font-size: 1.25em; } | ||
| 23 | /** | ||
| 24 | * Nestable | ||
| 25 | */ | ||
| 26 | .dd { position: relative; display: block; margin: 0; padding: 0; max-width: 600px; list-style: none; font-size: 13px; line-height: 20px; } | ||
| 27 | .dd-list { display: block; position: relative; margin: 0; padding: 0; list-style: none; } | ||
| 28 | .dd-list .dd-list { padding-left: 30px; } | ||
| 29 | .dd-collapsed .dd-list { display: none; } | ||
| 30 | .dd-item, | ||
| 31 | .dd-empty, | ||
| 32 | .dd-placeholder { display: block; position: relative; margin: 0; padding: 0; min-height: 20px; font-size: 13px; line-height: 20px; } | ||
| 33 | .dd-handle { display: block; height: 30px; margin: 5px 0; padding: 5px 10px; color: #333; text-decoration: none; font-weight: bold; border: 1px solid #ccc; | ||
| 34 | background: #fafafa; | ||
| 35 | background: -webkit-linear-gradient(top, #fafafa 0%, #eee 100%); | ||
| 36 | background: -moz-linear-gradient(top, #fafafa 0%, #eee 100%); | ||
| 37 | background: linear-gradient(top, #fafafa 0%, #eee 100%); | ||
| 38 | -webkit-border-radius: 3px; | ||
| 39 | border-radius: 3px; | ||
| 40 | box-sizing: border-box; -moz-box-sizing: border-box; | ||
| 41 | } | ||
| 42 | .dd-handle:hover { color: #2ea8e5; background: #fff; } | ||
| 43 | .dd-item > button { display: block; position: relative; cursor: pointer; float: left; width: 25px; height: 20px; margin: 5px 0; padding: 0; text-indent: 100%; white-space: nowrap; overflow: hidden; border: 0; background: transparent; font-size: 12px; line-height: 1; text-align: center; font-weight: bold; } | ||
| 44 | .dd-item > button:before { content: '+'; display: block; position: absolute; width: 100%; text-align: center; text-indent: 0; } | ||
| 45 | .dd-item > button[data-action="collapse"]:before { content: '-'; } | ||
| 46 | .dd-placeholder, | ||
| 47 | .dd-empty { margin: 5px 0; padding: 0; min-height: 30px; background: #f2fbff; border: 1px dashed #b6bcbf; box-sizing: border-box; -moz-box-sizing: border-box; } | ||
| 48 | .dd-empty { border: 1px dashed #bbb; min-height: 100px; background-color: #e5e5e5; | ||
| 49 | background-image: -webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), | ||
| 50 | -webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff); | ||
| 51 | background-image: -moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), | ||
| 52 | -moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff); | ||
| 53 | background-image: linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), | ||
| 54 | linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff); | ||
| 55 | background-size: 60px 60px; | ||
| 56 | background-position: 0 0, 30px 30px; | ||
| 57 | } | ||
| 58 | .dd-dragel { position: absolute; pointer-events: none; z-index: 9999; } | ||
| 59 | .dd-dragel > .dd-item .dd-handle { margin-top: 0; } | ||
| 60 | .dd-dragel .dd-handle { | ||
| 61 | -webkit-box-shadow: 2px 4px 6px 0 rgba(0,0,0,.1); | ||
| 62 | box-shadow: 2px 4px 6px 0 rgba(0,0,0,.1); | ||
| 63 | } | ||
| 64 | /** | ||
| 65 | * Nestable Extras | ||
| 66 | */ | ||
| 67 | .nestable-lists { display: block; clear: both; padding: 30px 0; width: 100%; border: 0; border-top: 2px solid #ddd; border-bottom: 2px solid #ddd; } | ||
| 68 | #nestable-menu { padding: 0; margin: 20px 0; } | ||
| 69 | #nestable-output, | ||
| 70 | #nestable2-output { width: 100%; height: 7em; font-size: 0.75em; line-height: 1.333333em; font-family: Consolas, monospace; padding: 5px; box-sizing: border-box; -moz-box-sizing: border-box; } | ||
| 71 | #nestable2 .dd-handle { | ||
| 72 | color: #fff; | ||
| 73 | border: 1px solid #999; | ||
| 74 | background: #bbb; | ||
| 75 | background: -webkit-linear-gradient(top, #bbb 0%, #999 100%); | ||
| 76 | background: -moz-linear-gradient(top, #bbb 0%, #999 100%); | ||
| 77 | background: linear-gradient(top, #bbb 0%, #999 100%); | ||
| 78 | } | ||
| 79 | #nestable2 .dd-handle:hover { background: #bbb; } | ||
| 80 | #nestable2 .dd-item > button:before { color: #fff; } | ||
| 81 | @media only screen and (min-width: 700px) { | ||
| 82 | .dd { float: left; width: 48%; } | ||
| 83 | .dd + .dd { margin-left: 2%; } | ||
| 84 | } | ||
| 85 | .dd-hover > .dd-handle { background: #2ea8e5 !important; } | ||
| 86 | /** | ||
| 87 | * Nestable Draggable Handles | ||
| 88 | */ | ||
| 89 | .dd3-content { display: block; height: 30px; margin: 5px 0; padding: 5px 10px 5px 40px; color: #333; text-decoration: none; font-weight: bold; border: 1px solid #ccc; | ||
| 90 | background: #fafafa; | ||
| 91 | background: -webkit-linear-gradient(top, #fafafa 0%, #eee 100%); | ||
| 92 | background: -moz-linear-gradient(top, #fafafa 0%, #eee 100%); | ||
| 93 | background: linear-gradient(top, #fafafa 0%, #eee 100%); | ||
| 94 | -webkit-border-radius: 3px; | ||
| 95 | border-radius: 3px; | ||
| 96 | box-sizing: border-box; -moz-box-sizing: border-box; | ||
| 97 | } | ||
| 98 | .dd3-content:hover { color: #2ea8e5; background: #fff; } | ||
| 99 | .dd-dragel > .dd3-item > .dd3-content { margin: 0; } | ||
| 100 | .dd3-item > button { margin-left: 30px; } | ||
| 101 | .dd3-handle { position: absolute; margin: 0; left: 0; top: 0; cursor: pointer; width: 30px; text-indent: 100%; white-space: nowrap; overflow: hidden; | ||
| 102 | border: 1px solid #aaa; | ||
| 103 | background: #ddd; | ||
| 104 | background: -webkit-linear-gradient(top, #ddd 0%, #bbb 100%); | ||
| 105 | background: -moz-linear-gradient(top, #ddd 0%, #bbb 100%); | ||
| 106 | background: linear-gradient(top, #ddd 0%, #bbb 100%); | ||
| 107 | border-top-right-radius: 0; | ||
| 108 | border-bottom-right-radius: 0; | ||
| 109 | } | ||
| 110 | .dd3-handle:before { content: '?'; display: block; position: absolute; left: 0; top: 3px; width: 100%; text-align: center; text-indent: 0; color: #fff; font-size: 20px; font-weight: normal; } | ||
| 111 | .dd3-handle:hover { background: #ddd; } | ||
| 112 | /** | ||
| 113 | * Socialite | ||
| 114 | */ | ||
| 115 | .socialite { display: block; float: left; height: 35px; } | ||
| 116 | </style> | ||
| 117 | </head> | ||
| 118 | <body> | ||
| 119 | |||
| 120 | <h1>Nestable</h1> | ||
| 121 | |||
| 122 | <p>Drag & drop hierarchical list with mouse and touch compatibility (jQuery plugin)</p> | ||
| 123 | |||
| 124 | <p><strong><a href="https://github.com/dbushell/Nestable">Download on GitHub</a></strong></p> | ||
| 125 | |||
| 126 | <div class="cf"> | ||
| 127 | <a href="http://twitter.com/share" class="socialite twitter-share" data-via="dbushell" data-text="jQuery Nestable plugin" data-url="http://dbushell.github.com/Nestable/" data-size="large" rel="nofollow" target="_blank"> | ||
| 128 | <span class="vhidden">Share on Twitter</span> | ||
| 129 | </a> | ||
| 130 | </div> | ||
| 131 | |||
| 132 | |||
| 133 | <p><strong>PLEASE NOTE: I cannot provide any support or guidance beyond this README. If this code helps you that's great but I have no plans to develop Nestable beyond this demo (it's not a final product and has limited functionality). I cannot reply to any requests for help.</strong></p> | ||
| 134 | |||
| 135 | <menu id="nestable-menu"> | ||
| 136 | <button type="button" data-action="expand-all">Expand All</button> | ||
| 137 | <button type="button" data-action="collapse-all">Collapse All</button> | ||
| 138 | </menu> | ||
| 139 | |||
| 140 | <div class="cf nestable-lists"> | ||
| 141 | |||
| 142 | <div class="dd" id="nestable"> | ||
| 143 | <ol class="dd-list"> | ||
| 144 | <li class="dd-item" data-id="1"> | ||
| 145 | <div class="dd-handle">Item 1</div> | ||
| 146 | </li> | ||
| 147 | <li class="dd-item" data-id="2"> | ||
| 148 | <div class="dd-handle">Item 2</div> | ||
| 149 | <ol class="dd-list"> | ||
| 150 | <li class="dd-item" data-id="3"><div class="dd-handle">Item 3</div></li> | ||
| 151 | <li class="dd-item" data-id="4"><div class="dd-handle">Item 4</div></li> | ||
| 152 | <li class="dd-item" data-id="5"> | ||
| 153 | <div class="dd-handle">Item 5</div> | ||
| 154 | <ol class="dd-list"> | ||
| 155 | <li class="dd-item" data-id="6"><div class="dd-handle">Item 6</div></li> | ||
| 156 | <li class="dd-item" data-id="7"><div class="dd-handle">Item 7</div></li> | ||
| 157 | <li class="dd-item" data-id="8"><div class="dd-handle">Item 8</div></li> | ||
| 158 | </ol> | ||
| 159 | </li> | ||
| 160 | <li class="dd-item" data-id="9"><div class="dd-handle">Item 9</div></li> | ||
| 161 | <li class="dd-item" data-id="10"><div class="dd-handle">Item 10</div></li> | ||
| 162 | </ol> | ||
| 163 | </li> | ||
| 164 | <li class="dd-item" data-id="11"> | ||
| 165 | <div class="dd-handle">Item 11</div> | ||
| 166 | </li> | ||
| 167 | <li class="dd-item" data-id="12"> | ||
| 168 | <div class="dd-handle">Item 12</div> | ||
| 169 | </li> | ||
| 170 | </ol> | ||
| 171 | </div> | ||
| 172 | |||
| 173 | <div class="dd" id="nestable2"> | ||
| 174 | <ol class="dd-list"> | ||
| 175 | <li class="dd-item" data-id="13"> | ||
| 176 | <div class="dd-handle">Item 13</div> | ||
| 177 | </li> | ||
| 178 | <li class="dd-item" data-id="14"> | ||
| 179 | <div class="dd-handle">Item 14</div> | ||
| 180 | </li> | ||
| 181 | <li class="dd-item" data-id="15"> | ||
| 182 | <div class="dd-handle">Item 15</div> | ||
| 183 | <ol class="dd-list"> | ||
| 184 | <li class="dd-item" data-id="16"><div class="dd-handle">Item 16</div></li> | ||
| 185 | <li class="dd-item" data-id="17"><div class="dd-handle">Item 17</div></li> | ||
| 186 | <li class="dd-item" data-id="18"><div class="dd-handle">Item 18</div></li> | ||
| 187 | </ol> | ||
| 188 | </li> | ||
| 189 | </ol> | ||
| 190 | </div> | ||
| 191 | |||
| 192 | </div> | ||
| 193 | |||
| 194 | <p><strong>Serialised Output (per list)</strong></p> | ||
| 195 | |||
| 196 | <textarea id="nestable-output"></textarea> | ||
| 197 | <textarea id="nestable2-output"></textarea> | ||
| 198 | |||
| 199 | <p> </p> | ||
| 200 | |||
| 201 | <div class="cf nestable-lists"> | ||
| 202 | |||
| 203 | <p><strong>Draggable Handles</strong></p> | ||
| 204 | |||
| 205 | <p>If you're clever with your CSS and markup this can be achieved without any JavaScript changes.</p> | ||
| 206 | |||
| 207 | <div class="dd" id="nestable3"> | ||
| 208 | <ol class="dd-list"> | ||
| 209 | <li class="dd-item dd3-item" data-id="13"> | ||
| 210 | <div class="dd-handle dd3-handle">Drag</div><div class="dd3-content">Item 13</div> | ||
| 211 | </li> | ||
| 212 | <li class="dd-item dd3-item" data-id="14"> | ||
| 213 | <div class="dd-handle dd3-handle">Drag</div><div class="dd3-content">Item 14</div> | ||
| 214 | </li> | ||
| 215 | <li class="dd-item dd3-item" data-id="15"> | ||
| 216 | <div class="dd-handle dd3-handle">Drag</div><div class="dd3-content">Item 15</div> | ||
| 217 | <ol class="dd-list"> | ||
| 218 | <li class="dd-item dd3-item" data-id="16"> | ||
| 219 | <div class="dd-handle dd3-handle">Drag</div><div class="dd3-content">Item 16</div> | ||
| 220 | </li> | ||
| 221 | <li class="dd-item dd3-item" data-id="17"> | ||
| 222 | <div class="dd-handle dd3-handle">Drag</div><div class="dd3-content">Item 17</div> | ||
| 223 | </li> | ||
| 224 | <li class="dd-item dd3-item" data-id="18"> | ||
| 225 | <div class="dd-handle dd3-handle">Drag</div><div class="dd3-content">Item 18</div> | ||
| 226 | </li> | ||
| 227 | </ol> | ||
| 228 | </li> | ||
| 229 | </ol> | ||
| 230 | </div> | ||
| 231 | |||
| 232 | </div> | ||
| 233 | |||
| 234 | <p class="small">Copyright © <a href="https://dbushell.com/">David Bushell</a> | Made for <a href="http://www.browserlondon.com/">Browser</a></p> | ||
| 235 | |||
| 236 | <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> | ||
| 237 | <script src="jquery.nestable.js"></script> | ||
| 238 | <script> | ||
| 239 | $(document).ready(function() | ||
| 240 | { | ||
| 241 | var updateOutput = function(e) | ||
| 242 | { | ||
| 243 | var list = e.length ? e : $(e.target), | ||
| 244 | output = list.data('output'); | ||
| 245 | if (window.JSON) { | ||
| 246 | output.val(window.JSON.stringify(list.nestable('serialize')));//, null, 2)); | ||
| 247 | } else { | ||
| 248 | output.val('JSON browser support required for this demo.'); | ||
| 249 | } | ||
| 250 | }; | ||
| 251 | // activate Nestable for list 1 | ||
| 252 | $('#nestable').nestable({ | ||
| 253 | group: 1 | ||
| 254 | }) | ||
| 255 | .on('change', updateOutput); | ||
| 256 | // activate Nestable for list 2 | ||
| 257 | $('#nestable2').nestable({ | ||
| 258 | group: 1 | ||
| 259 | }) | ||
| 260 | .on('change', updateOutput); | ||
| 261 | // output initial serialised data | ||
| 262 | updateOutput($('#nestable').data('output', $('#nestable-output'))); | ||
| 263 | updateOutput($('#nestable2').data('output', $('#nestable2-output'))); | ||
| 264 | $('#nestable-menu').on('click', function(e) | ||
| 265 | { | ||
| 266 | var target = $(e.target), | ||
| 267 | action = target.data('action'); | ||
| 268 | if (action === 'expand-all') { | ||
| 269 | $('.dd').nestable('expandAll'); | ||
| 270 | } | ||
| 271 | if (action === 'collapse-all') { | ||
| 272 | $('.dd').nestable('collapseAll'); | ||
| 273 | } | ||
| 274 | }); | ||
| 275 | $('#nestable3').nestable(); | ||
| 276 | }); | ||
| 277 | </script> | ||
| 278 | </body> | ||
| 279 | </html> |
k2shop/usr/k2shop/libs/nestmenu/jquery.nestable.js
| File was created | 1 | /*! | |
| 2 | * Nestable jQuery Plugin - Copyright (c) 2012 David Bushell - http://dbushell.com/ | ||
| 3 | * Dual-licensed under the BSD or MIT licenses | ||
| 4 | */ | ||
| 5 | ;(function($, window, document, undefined) | ||
| 6 | { | ||
| 7 | var hasTouch = 'ontouchstart' in document; | ||
| 8 | |||
| 9 | /** | ||
| 10 | * Detect CSS pointer-events property | ||
| 11 | * events are normally disabled on the dragging element to avoid conflicts | ||
| 12 | * https://github.com/ausi/Feature-detection-technique-for-pointer-events/blob/master/modernizr-pointerevents.js | ||
| 13 | */ | ||
| 14 | var hasPointerEvents = (function() | ||
| 15 | { | ||
| 16 | var el = document.createElement('div'), | ||
| 17 | docEl = document.documentElement; | ||
| 18 | if (!('pointerEvents' in el.style)) { | ||
| 19 | return false; | ||
| 20 | } | ||
| 21 | el.style.pointerEvents = 'auto'; | ||
| 22 | el.style.pointerEvents = 'x'; | ||
| 23 | docEl.appendChild(el); | ||
| 24 | var supports = window.getComputedStyle && window.getComputedStyle(el, '').pointerEvents === 'auto'; | ||
| 25 | docEl.removeChild(el); | ||
| 26 | return !!supports; | ||
| 27 | })(); | ||
| 28 | |||
| 29 | var defaults = { | ||
| 30 | listNodeName : 'ol', | ||
| 31 | itemNodeName : 'li', | ||
| 32 | rootClass : 'dd', | ||
| 33 | listClass : 'dd-list', | ||
| 34 | itemClass : 'dd-item', | ||
| 35 | dragClass : 'dd-dragel', | ||
| 36 | handleClass : 'dd-handle', | ||
| 37 | collapsedClass : 'dd-collapsed', | ||
| 38 | placeClass : 'dd-placeholder', | ||
| 39 | noDragClass : 'dd-nodrag', | ||
| 40 | emptyClass : 'dd-empty', | ||
| 41 | expandBtnHTML : '<button data-action="expand" type="button">Expand</button>', | ||
| 42 | collapseBtnHTML : '<button data-action="collapse" type="button">Collapse</button>', | ||
| 43 | group : 0, | ||
| 44 | maxDepth : 5, | ||
| 45 | threshold : 20 | ||
| 46 | }; | ||
| 47 | |||
| 48 | function Plugin(element, options) | ||
| 49 | { | ||
| 50 | this.w = $(document); | ||
| 51 | this.el = $(element); | ||
| 52 | this.options = $.extend({}, defaults, options); | ||
| 53 | this.init(); | ||
| 54 | } | ||
| 55 | |||
| 56 | Plugin.prototype = { | ||
| 57 | |||
| 58 | init: function() | ||
| 59 | { | ||
| 60 | var list = this; | ||
| 61 | |||
| 62 | list.reset(); | ||
| 63 | |||
| 64 | list.el.data('nestable-group', this.options.group); | ||
| 65 | |||
| 66 | list.placeEl = $('<div class="' + list.options.placeClass + '"/>'); | ||
| 67 | |||
| 68 | $.each(this.el.find(list.options.itemNodeName), function(k, el) { | ||
| 69 | list.setParent($(el)); | ||
| 70 | }); | ||
| 71 | |||
| 72 | list.el.on('click', 'button', function(e) { | ||
| 73 | if (list.dragEl) { | ||
| 74 | return; | ||
| 75 | } | ||
| 76 | var target = $(e.currentTarget), | ||
| 77 | action = target.data('action'), | ||
| 78 | item = target.parent(list.options.itemNodeName); | ||
| 79 | if (action === 'collapse') { | ||
| 80 | list.collapseItem(item); | ||
| 81 | } | ||
| 82 | if (action === 'expand') { | ||
| 83 | list.expandItem(item); | ||
| 84 | } | ||
| 85 | }); | ||
| 86 | |||
| 87 | var onStartEvent = function(e) | ||
| 88 | { | ||
| 89 | var handle = $(e.target); | ||
| 90 | if (!handle.hasClass(list.options.handleClass)) { | ||
| 91 | if (handle.closest('.' + list.options.noDragClass).length) { | ||
| 92 | return; | ||
| 93 | } | ||
| 94 | handle = handle.closest('.' + list.options.handleClass); | ||
| 95 | } | ||
| 96 | |||
| 97 | if (!handle.length || list.dragEl) { | ||
| 98 | return; | ||
| 99 | } | ||
| 100 | |||
| 101 | list.isTouch = /^touch/.test(e.type); | ||
| 102 | if (list.isTouch && e.touches.length !== 1) { | ||
| 103 | return; | ||
| 104 | } | ||
| 105 | |||
| 106 | e.preventDefault(); | ||
| 107 | list.dragStart(e.touches ? e.touches[0] : e); | ||
| 108 | }; | ||
| 109 | |||
| 110 | var onMoveEvent = function(e) | ||
| 111 | { | ||
| 112 | if (list.dragEl) { | ||
| 113 | e.preventDefault(); | ||
| 114 | list.dragMove(e.touches ? e.touches[0] : e); | ||
| 115 | } | ||
| 116 | }; | ||
| 117 | |||
| 118 | var onEndEvent = function(e) | ||
| 119 | { | ||
| 120 | if (list.dragEl) { | ||
| 121 | e.preventDefault(); | ||
| 122 | list.dragStop(e.touches ? e.touches[0] : e); | ||
| 123 | } | ||
| 124 | }; | ||
| 125 | |||
| 126 | if (hasTouch) { | ||
| 127 | list.el[0].addEventListener('touchstart', onStartEvent, false); | ||
| 128 | window.addEventListener('touchmove', onMoveEvent, false); | ||
| 129 | window.addEventListener('touchend', onEndEvent, false); | ||
| 130 | window.addEventListener('touchcancel', onEndEvent, false); | ||
| 131 | } | ||
| 132 | |||
| 133 | list.el.on('mousedown', onStartEvent); | ||
| 134 | list.w.on('mousemove', onMoveEvent); | ||
| 135 | list.w.on('mouseup', onEndEvent); | ||
| 136 | |||
| 137 | }, | ||
| 138 | |||
| 139 | serialize: function() | ||
| 140 | { | ||
| 141 | var data, | ||
| 142 | depth = 0, | ||
| 143 | list = this; | ||
| 144 | step = function(level, depth) | ||
| 145 | { | ||
| 146 | var array = [ ], | ||
| 147 | items = level.children(list.options.itemNodeName); | ||
| 148 | items.each(function() | ||
| 149 | { | ||
| 150 | var li = $(this), | ||
| 151 | item = $.extend({}, li.data()), | ||
| 152 | sub = li.children(list.options.listNodeName); | ||
| 153 | if (sub.length) { | ||
| 154 | item.children = step(sub, depth + 1); | ||
| 155 | } | ||
| 156 | array.push(item); | ||
| 157 | }); | ||
| 158 | return array; | ||
| 159 | }; | ||
| 160 | data = step(list.el.find(list.options.listNodeName).first(), depth); | ||
| 161 | return data; | ||
| 162 | }, | ||
| 163 | |||
| 164 | serialise: function() | ||
| 165 | { | ||
| 166 | return this.serialize(); | ||
| 167 | }, | ||
| 168 | |||
| 169 | reset: function() | ||
| 170 | { | ||
| 171 | this.mouse = { | ||
| 172 | offsetX : 0, | ||
| 173 | offsetY : 0, | ||
| 174 | startX : 0, | ||
| 175 | startY : 0, | ||
| 176 | lastX : 0, | ||
| 177 | lastY : 0, | ||
| 178 | nowX : 0, | ||
| 179 | nowY : 0, | ||
| 180 | distX : 0, | ||
| 181 | distY : 0, | ||
| 182 | dirAx : 0, | ||
| 183 | dirX : 0, | ||
| 184 | dirY : 0, | ||
| 185 | lastDirX : 0, | ||
| 186 | lastDirY : 0, | ||
| 187 | distAxX : 0, | ||
| 188 | distAxY : 0 | ||
| 189 | }; | ||
| 190 | this.isTouch = false; | ||
| 191 | this.moving = false; | ||
| 192 | this.dragEl = null; | ||
| 193 | this.dragRootEl = null; | ||
| 194 | this.dragDepth = 0; | ||
| 195 | this.hasNewRoot = false; | ||
| 196 | this.pointEl = null; | ||
| 197 | }, | ||
| 198 | |||
| 199 | expandItem: function(li) | ||
| 200 | { | ||
| 201 | li.removeClass(this.options.collapsedClass); | ||
| 202 | li.children('[data-action="expand"]').hide(); | ||
| 203 | li.children('[data-action="collapse"]').show(); | ||
| 204 | li.children(this.options.listNodeName).show(); | ||
| 205 | }, | ||
| 206 | |||
| 207 | collapseItem: function(li) | ||
| 208 | { | ||
| 209 | var lists = li.children(this.options.listNodeName); | ||
| 210 | if (lists.length) { | ||
| 211 | li.addClass(this.options.collapsedClass); | ||
| 212 | li.children('[data-action="collapse"]').hide(); | ||
| 213 | li.children('[data-action="expand"]').show(); | ||
| 214 | li.children(this.options.listNodeName).hide(); | ||
| 215 | } | ||
| 216 | }, | ||
| 217 | |||
| 218 | expandAll: function() | ||
| 219 | { | ||
| 220 | var list = this; | ||
| 221 | list.el.find(list.options.itemNodeName).each(function() { | ||
| 222 | list.expandItem($(this)); | ||
| 223 | }); | ||
| 224 | }, | ||
| 225 | |||
| 226 | collapseAll: function() | ||
| 227 | { | ||
| 228 | var list = this; | ||
| 229 | list.el.find(list.options.itemNodeName).each(function() { | ||
| 230 | list.collapseItem($(this)); | ||
| 231 | }); | ||
| 232 | }, | ||
| 233 | |||
| 234 | setParent: function(li) | ||
| 235 | { | ||
| 236 | if (li.children(this.options.listNodeName).length) { | ||
| 237 | li.prepend($(this.options.expandBtnHTML)); | ||
| 238 | li.prepend($(this.options.collapseBtnHTML)); | ||
| 239 | } | ||
| 240 | li.children('[data-action="expand"]').hide(); | ||
| 241 | }, | ||
| 242 | |||
| 243 | unsetParent: function(li) | ||
| 244 | { | ||
| 245 | li.removeClass(this.options.collapsedClass); | ||
| 246 | li.children('[data-action]').remove(); | ||
| 247 | li.children(this.options.listNodeName).remove(); | ||
| 248 | }, | ||
| 249 | |||
| 250 | dragStart: function(e) | ||
| 251 | { | ||
| 252 | var mouse = this.mouse, | ||
| 253 | target = $(e.target), | ||
| 254 | dragItem = target.closest(this.options.itemNodeName); | ||
| 255 | |||
| 256 | this.placeEl.css('height', dragItem.height()); | ||
| 257 | |||
| 258 | mouse.offsetX = e.offsetX !== undefined ? e.offsetX : e.pageX - target.offset().left; | ||
| 259 | mouse.offsetY = e.offsetY !== undefined ? e.offsetY : e.pageY - target.offset().top; | ||
| 260 | mouse.startX = mouse.lastX = e.pageX; | ||
| 261 | mouse.startY = mouse.lastY = e.pageY; | ||
| 262 | |||
| 263 | this.dragRootEl = this.el; | ||
| 264 | |||
| 265 | this.dragEl = $(document.createElement(this.options.listNodeName)).addClass(this.options.listClass + ' ' + this.options.dragClass); | ||
| 266 | this.dragEl.css('width', dragItem.width()); | ||
| 267 | |||
| 268 | dragItem.after(this.placeEl); | ||
| 269 | dragItem[0].parentNode.removeChild(dragItem[0]); | ||
| 270 | dragItem.appendTo(this.dragEl); | ||
| 271 | |||
| 272 | $(document.body).append(this.dragEl); | ||
| 273 | this.dragEl.css({ | ||
| 274 | 'left' : e.pageX - mouse.offsetX, | ||
| 275 | 'top' : e.pageY - mouse.offsetY | ||
| 276 | }); | ||
| 277 | // total depth of dragging item | ||
| 278 | var i, depth, | ||
| 279 | items = this.dragEl.find(this.options.itemNodeName); | ||
| 280 | for (i = 0; i < items.length; i++) { | ||
| 281 | depth = $(items[i]).parents(this.options.listNodeName).length; | ||
| 282 | if (depth > this.dragDepth) { | ||
| 283 | this.dragDepth = depth; | ||
| 284 | } | ||
| 285 | } | ||
| 286 | }, | ||
| 287 | |||
| 288 | dragStop: function(e) | ||
| 289 | { | ||
| 290 | var el = this.dragEl.children(this.options.itemNodeName).first(); | ||
| 291 | el[0].parentNode.removeChild(el[0]); | ||
| 292 | this.placeEl.replaceWith(el); | ||
| 293 | |||
| 294 | this.dragEl.remove(); | ||
| 295 | this.el.trigger('change'); | ||
| 296 | if (this.hasNewRoot) { | ||
| 297 | this.dragRootEl.trigger('change'); | ||
| 298 | } | ||
| 299 | this.reset(); | ||
| 300 | }, | ||
| 301 | |||
| 302 | dragMove: function(e) | ||
| 303 | { | ||
| 304 | var list, parent, prev, next, depth, | ||
| 305 | opt = this.options, | ||
| 306 | mouse = this.mouse; | ||
| 307 | |||
| 308 | this.dragEl.css({ | ||
| 309 | 'left' : e.pageX - mouse.offsetX, | ||
| 310 | 'top' : e.pageY - mouse.offsetY | ||
| 311 | }); | ||
| 312 | |||
| 313 | // mouse position last events | ||
| 314 | mouse.lastX = mouse.nowX; | ||
| 315 | mouse.lastY = mouse.nowY; | ||
| 316 | // mouse position this events | ||
| 317 | mouse.nowX = e.pageX; | ||
| 318 | mouse.nowY = e.pageY; | ||
| 319 | // distance mouse moved between events | ||
| 320 | mouse.distX = mouse.nowX - mouse.lastX; | ||
| 321 | mouse.distY = mouse.nowY - mouse.lastY; | ||
| 322 | // direction mouse was moving | ||
| 323 | mouse.lastDirX = mouse.dirX; | ||
| 324 | mouse.lastDirY = mouse.dirY; | ||
| 325 | // direction mouse is now moving (on both axis) | ||
| 326 | mouse.dirX = mouse.distX === 0 ? 0 : mouse.distX > 0 ? 1 : -1; | ||
| 327 | mouse.dirY = mouse.distY === 0 ? 0 : mouse.distY > 0 ? 1 : -1; | ||
| 328 | // axis mouse is now moving on | ||
| 329 | var newAx = Math.abs(mouse.distX) > Math.abs(mouse.distY) ? 1 : 0; | ||
| 330 | |||
| 331 | // do nothing on first move | ||
| 332 | if (!mouse.moving) { | ||
| 333 | mouse.dirAx = newAx; | ||
| 334 | mouse.moving = true; | ||
| 335 | return; | ||
| 336 | } | ||
| 337 | |||
| 338 | // calc distance moved on this axis (and direction) | ||
| 339 | if (mouse.dirAx !== newAx) { | ||
| 340 | mouse.distAxX = 0; | ||
| 341 | mouse.distAxY = 0; | ||
| 342 | } else { | ||
| 343 | mouse.distAxX += Math.abs(mouse.distX); | ||
| 344 | if (mouse.dirX !== 0 && mouse.dirX !== mouse.lastDirX) { | ||
| 345 | mouse.distAxX = 0; | ||
| 346 | } | ||
| 347 | mouse.distAxY += Math.abs(mouse.distY); | ||
| 348 | if (mouse.dirY !== 0 && mouse.dirY !== mouse.lastDirY) { | ||
| 349 | mouse.distAxY = 0; | ||
| 350 | } | ||
| 351 | } | ||
| 352 | mouse.dirAx = newAx; | ||
| 353 | |||
| 354 | /** | ||
| 355 | * move horizontal | ||
| 356 | */ | ||
| 357 | if (mouse.dirAx && mouse.distAxX >= opt.threshold) { | ||
| 358 | // reset move distance on x-axis for new phase | ||
| 359 | mouse.distAxX = 0; | ||
| 360 | prev = this.placeEl.prev(opt.itemNodeName); | ||
| 361 | // increase horizontal level if previous sibling exists and is not collapsed | ||
| 362 | if (mouse.distX > 0 && prev.length && !prev.hasClass(opt.collapsedClass)) { | ||
| 363 | // cannot increase level when item above is collapsed | ||
| 364 | list = prev.find(opt.listNodeName).last(); | ||
| 365 | // check if depth limit has reached | ||
| 366 | depth = this.placeEl.parents(opt.listNodeName).length; | ||
| 367 | if (depth + this.dragDepth <= opt.maxDepth) { | ||
| 368 | // create new sub-level if one doesn't exist | ||
| 369 | if (!list.length) { | ||
| 370 | list = $('<' + opt.listNodeName + '/>').addClass(opt.listClass); | ||
| 371 | list.append(this.placeEl); | ||
| 372 | prev.append(list); | ||
| 373 | this.setParent(prev); | ||
| 374 | } else { | ||
| 375 | // else append to next level up | ||
| 376 | list = prev.children(opt.listNodeName).last(); | ||
| 377 | list.append(this.placeEl); | ||
| 378 | } | ||
| 379 | } | ||
| 380 | } | ||
| 381 | // decrease horizontal level | ||
| 382 | if (mouse.distX < 0) { | ||
| 383 | // we can't decrease a level if an item preceeds the current one | ||
| 384 | next = this.placeEl.next(opt.itemNodeName); | ||
| 385 | if (!next.length) { | ||
| 386 | parent = this.placeEl.parent(); | ||
| 387 | this.placeEl.closest(opt.itemNodeName).after(this.placeEl); | ||
| 388 | if (!parent.children().length) { | ||
| 389 | this.unsetParent(parent.parent()); | ||
| 390 | } | ||
| 391 | } | ||
| 392 | } | ||
| 393 | } | ||
| 394 | |||
| 395 | var isEmpty = false; | ||
| 396 | |||
| 397 | // find list item under cursor | ||
| 398 | if (!hasPointerEvents) { | ||
| 399 | this.dragEl[0].style.visibility = 'hidden'; | ||
| 400 | } | ||
| 401 | this.pointEl = $(document.elementFromPoint(e.pageX - document.body.scrollLeft, e.pageY - (window.pageYOffset || document.documentElement.scrollTop))); | ||
| 402 | if (!hasPointerEvents) { | ||
| 403 | this.dragEl[0].style.visibility = 'visible'; | ||
| 404 | } | ||
| 405 | if (this.pointEl.hasClass(opt.handleClass)) { | ||
| 406 | this.pointEl = this.pointEl.parent(opt.itemNodeName); | ||
| 407 | } | ||
| 408 | if (this.pointEl.hasClass(opt.emptyClass)) { | ||
| 409 | isEmpty = true; | ||
| 410 | } | ||
| 411 | else if (!this.pointEl.length || !this.pointEl.hasClass(opt.itemClass)) { | ||
| 412 | return; | ||
| 413 | } | ||
| 414 | |||
| 415 | // find parent list of item under cursor | ||
| 416 | var pointElRoot = this.pointEl.closest('.' + opt.rootClass), | ||
| 417 | isNewRoot = this.dragRootEl.data('nestable-id') !== pointElRoot.data('nestable-id'); | ||
| 418 | |||
| 419 | /** | ||
| 420 | * move vertical | ||
| 421 | */ | ||
| 422 | if (!mouse.dirAx || isNewRoot || isEmpty) { | ||
| 423 | // check if groups match if dragging over new root | ||
| 424 | if (isNewRoot && opt.group !== pointElRoot.data('nestable-group')) { | ||
| 425 | return; | ||
| 426 | } | ||
| 427 | // check depth limit | ||
| 428 | depth = this.dragDepth - 1 + this.pointEl.parents(opt.listNodeName).length; | ||
| 429 | if (depth > opt.maxDepth) { | ||
| 430 | return; | ||
| 431 | } | ||
| 432 | var before = e.pageY < (this.pointEl.offset().top + this.pointEl.height() / 2); | ||
| 433 | parent = this.placeEl.parent(); | ||
| 434 | // if empty create new list to replace empty placeholder | ||
| 435 | if (isEmpty) { | ||
| 436 | list = $(document.createElement(opt.listNodeName)).addClass(opt.listClass); | ||
| 437 | list.append(this.placeEl); | ||
| 438 | this.pointEl.replaceWith(list); | ||
| 439 | } | ||
| 440 | else if (before) { | ||
| 441 | this.pointEl.before(this.placeEl); | ||
| 442 | } | ||
| 443 | else { | ||
| 444 | this.pointEl.after(this.placeEl); | ||
| 445 | } | ||
| 446 | if (!parent.children().length) { | ||
| 447 | this.unsetParent(parent.parent()); | ||
| 448 | } | ||
| 449 | if (!this.dragRootEl.find(opt.itemNodeName).length) { | ||
| 450 | this.dragRootEl.append('<div class="' + opt.emptyClass + '"/>'); | ||
| 451 | } | ||
| 452 | // parent root list has changed | ||
| 453 | if (isNewRoot) { | ||
| 454 | this.dragRootEl = pointElRoot; | ||
| 455 | this.hasNewRoot = this.el[0] !== this.dragRootEl[0]; | ||
| 456 | } | ||
| 457 | } | ||
| 458 | } | ||
| 459 | |||
| 460 | }; | ||
| 461 | |||
| 462 | $.fn.nestable = function(params) | ||
| 463 | { | ||
| 464 | var lists = this, | ||
| 465 | retval = this; | ||
| 466 | |||
| 467 | lists.each(function() | ||
| 468 | { | ||
| 469 | var plugin = $(this).data("nestable"); | ||
| 470 | |||
| 471 | if (!plugin) { | ||
| 472 | $(this).data("nestable", new Plugin(this, params)); | ||
| 473 | $(this).data("nestable-id", new Date().getTime()); | ||
| 474 | } else { | ||
| 475 | if (typeof params === 'string' && typeof plugin[params] === 'function') { | ||
| 476 | retval = plugin[params](); | ||
| 477 | } | ||
| 478 | } | ||
| 479 | }); | ||
| 480 | |||
| 481 | return retval || lists; | ||
| 482 | }; | ||
| 483 | |||
| 484 | })(window.jQuery || window.Zepto, window, document); |
k2shop/usr/k2shop/libs/nestmenu/nestable.css
| File was created | 1 | ||
| 2 | /** | ||
| 3 | * Nestable | ||
| 4 | */ | ||
| 5 | .dd { position: relative; display: block; margin: 0; padding: 0; /*max-width: 600px;*/ list-style: none; font-size: 13px; line-height: 20px; overflow:scroll; height:600px; } | ||
| 6 | .dd-list { display: block; position: relative; margin: 0; padding: 0; list-style: none; } | ||
| 7 | .dd-list .dd-list { padding-left: 30px; } | ||
| 8 | .dd-collapsed .dd-list { display: none; } | ||
| 9 | .dd-item, | ||
| 10 | .dd-empty, | ||
| 11 | .dd-placeholder { display: block; position: relative; margin: 0; padding: 0; min-height: 20px; font-size: 13px; line-height: 20px; } | ||
| 12 | .dd-handle { display: block; height: 30px; margin: 5px 0; padding: 5px 10px; color: #333; text-decoration: none; font-weight: bold; border: 1px solid #ccc; width:650px; | ||
| 13 | background: #fafafa; | ||
| 14 | background: -webkit-linear-gradient(top, #fafafa 0%, #eee 100%); | ||
| 15 | background: -moz-linear-gradient(top, #fafafa 0%, #eee 100%); | ||
| 16 | background: linear-gradient(top, #fafafa 0%, #eee 100%); | ||
| 17 | -webkit-border-radius: 3px; | ||
| 18 | border-radius: 3px; | ||
| 19 | box-sizing: border-box; -moz-box-sizing: border-box; | ||
| 20 | } | ||
| 21 | .dd-handle:hover { color: #2ea8e5; background: #fff; } | ||
| 22 | .dd-item > button { display: block; position: relative; cursor: pointer; float: left; width: 25px; height: 20px; margin: 5px 0; padding: 0; text-indent: 100%; white-space: nowrap; overflow: hidden; border: 0; background: transparent; font-size: 12px; line-height: 1; text-align: center; font-weight: bold; } | ||
| 23 | .dd-item > button:before { content: '+'; display: block; position: absolute; width: 100%; text-align: center; text-indent: 0; } | ||
| 24 | .dd-item > button[data-action="collapse"]:before { content: '-'; } | ||
| 25 | .dd-placeholder, | ||
| 26 | .dd-empty { margin: 5px 0; padding: 0; min-height: 30px; background: #f2fbff; border: 1px dashed #b6bcbf; box-sizing: border-box; -moz-box-sizing: border-box; } | ||
| 27 | .dd-empty { border: 1px dashed #bbb; min-height: 100px; background-color: #e5e5e5; | ||
| 28 | background-image: -webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), | ||
| 29 | -webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff); | ||
| 30 | background-image: -moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), | ||
| 31 | -moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff); | ||
| 32 | background-image: linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), | ||
| 33 | linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff); | ||
| 34 | background-size: 60px 60px; | ||
| 35 | background-position: 0 0, 30px 30px; | ||
| 36 | } | ||
| 37 | .dd-dragel { position: absolute; pointer-events: none; z-index: 9999; } | ||
| 38 | .dd-dragel > .dd-item .dd-handle { margin-top: 0; } | ||
| 39 | .dd-dragel .dd-handle { | ||
| 40 | -webkit-box-shadow: 2px 4px 6px 0 rgba(0,0,0,.1); | ||
| 41 | box-shadow: 2px 4px 6px 0 rgba(0,0,0,.1); | ||
| 42 | } | ||
| 43 | /** | ||
| 44 | * Nestable Extras | ||
| 45 | */ | ||
| 46 | .nestable-lists { display: block; clear: both; padding: 30px 0; width: 100%; border: 0; border-top: 2px solid #ddd; border-bottom: 2px solid #ddd; } | ||
| 47 | #nestable-menu { padding: 0; margin: 20px 0; } | ||
| 48 | #nestable-output, | ||
| 49 | #nestable2-output { width: 100%; height: 7em; font-size: 0.75em; line-height: 1.333333em; font-family: Consolas, monospace; padding: 5px; box-sizing: border-box; -moz-box-sizing: border-box; } | ||
| 50 | #nestable2 .dd-handle { | ||
| 51 | color: #fff; | ||
| 52 | border: 1px solid #999; | ||
| 53 | background: #bbb; | ||
| 54 | background: -webkit-linear-gradient(top, #bbb 0%, #999 100%); | ||
| 55 | background: -moz-linear-gradient(top, #bbb 0%, #999 100%); | ||
| 56 | background: linear-gradient(top, #bbb 0%, #999 100%); | ||
| 57 | } | ||
| 58 | #nestable2 .dd-handle:hover { background: #bbb; } | ||
| 59 | #nestable2 .dd-item > button:before { color: #fff; } | ||
| 60 | @media only screen and (min-width: 700px) { | ||
| 61 | /*.dd { float: left; width: 48%; }*/ | ||
| 62 | .dd + .dd { margin-left: 2%; } | ||
| 63 | } | ||
| 64 | .dd-hover > .dd-handle { background: #2ea8e5 !important; } | ||
| 65 | /** | ||
| 66 | * Nestable Draggable Handles | ||
| 67 | */ | ||
| 68 | .dd3-content { display: block; height: 30px; margin: 5px 0; padding: 5px 10px 5px 40px; color: #333; text-decoration: none; font-weight: bold; border: 1px solid #ccc; | ||
| 69 | background: #fafafa; | ||
| 70 | background: -webkit-linear-gradient(top, #fafafa 0%, #eee 100%); | ||
| 71 | background: -moz-linear-gradient(top, #fafafa 0%, #eee 100%); | ||
| 72 | background: linear-gradient(top, #fafafa 0%, #eee 100%); | ||
| 73 | -webkit-border-radius: 3px; | ||
| 74 | border-radius: 3px; | ||
| 75 | box-sizing: border-box; -moz-box-sizing: border-box; | ||
| 76 | } | ||
| 77 | .dd3-content:hover { color: #2ea8e5; background: #fff; } | ||
| 78 | .dd-dragel > .dd3-item > .dd3-content { margin: 0; } | ||
| 79 | .dd3-item > button { margin-left: 30px; } | ||
| 80 | .dd3-handle { position: absolute; margin: 0; left: 0; top: 0; cursor: pointer; width: 30px; text-indent: 100%; white-space: nowrap; overflow: hidden; | ||
| 81 | border: 1px solid #aaa; | ||
| 82 | background: #ddd; | ||
| 83 | background: -webkit-linear-gradient(top, #ddd 0%, #bbb 100%); | ||
| 84 | background: -moz-linear-gradient(top, #ddd 0%, #bbb 100%); | ||
| 85 | background: linear-gradient(top, #ddd 0%, #bbb 100%); | ||
| 86 | border-top-right-radius: 0; | ||
| 87 | border-bottom-right-radius: 0; | ||
| 88 | } | ||
| 89 | .dd3-handle:before { content: '?'; display: block; position: absolute; left: 0; top: 3px; width: 100%; text-align: center; text-indent: 0; color: #fff; font-size: 20px; font-weight: normal; } | ||
| 90 | .dd3-handle:hover { background: #ddd; } | ||
| 91 | /** | ||
| 92 | * Socialite | ||
| 93 | */ | ||
| 94 | .socialite { display: block; float: left; height: 35px; } |
k2shop/usr/k2shop/libs/yaml/Spyc.php
| File was created | 1 | <?php | |
| 2 | /** | ||
| 3 | * Spyc -- A Simple PHP YAML Class | ||
| 4 | * @version 0.6.2 | ||
| 5 | * @author Vlad Andersen <vlad.andersen@gmail.com> | ||
| 6 | * @author Chris Wanstrath <chris@ozmm.org> | ||
| 7 | * @link https://github.com/mustangostang/spyc/ | ||
| 8 | * @copyright Copyright 2005-2006 Chris Wanstrath, 2006-2011 Vlad Andersen | ||
| 9 | * @license http://www.opensource.org/licenses/mit-license.php MIT License | ||
| 10 | * @package Spyc | ||
| 11 | */ | ||
| 12 | if (!function_exists('spyc_load')) { | ||
| 13 | /** | ||
| 14 | * Parses YAML to array. | ||
| 15 | * @param string $string YAML string. | ||
| 16 | * @return array | ||
| 17 | */ | ||
| 18 | function spyc_load ($string) { | ||
| 19 | return Spyc::YAMLLoadString($string); | ||
| 20 | } | ||
| 21 | } | ||
| 22 | if (!function_exists('spyc_load_file')) { | ||
| 23 | /** | ||
| 24 | * Parses YAML to array. | ||
| 25 | * @param string $file Path to YAML file. | ||
| 26 | * @return array | ||
| 27 | */ | ||
| 28 | function spyc_load_file ($file) { | ||
| 29 | return Spyc::YAMLLoad($file); | ||
| 30 | } | ||
| 31 | } | ||
| 32 | if (!function_exists('spyc_dump')) { | ||
| 33 | /** | ||
| 34 | * Dumps array to YAML. | ||
| 35 | * @param array $data Array. | ||
| 36 | * @return string | ||
| 37 | */ | ||
| 38 | function spyc_dump ($data) { | ||
| 39 | return Spyc::YAMLDump($data, false, false, true); | ||
| 40 | } | ||
| 41 | } | ||
| 42 | if (!class_exists('Spyc')) { | ||
| 43 | /** | ||
| 44 | * The Simple PHP YAML Class. | ||
| 45 | * | ||
| 46 | * This class can be used to read a YAML file and convert its contents | ||
| 47 | * into a PHP array. It currently supports a very limited subsection of | ||
| 48 | * the YAML spec. | ||
| 49 | * | ||
| 50 | * Usage: | ||
| 51 | * <code> | ||
| 52 | * $Spyc = new Spyc; | ||
| 53 | * $array = $Spyc->load($file); | ||
| 54 | * </code> | ||
| 55 | * or: | ||
| 56 | * <code> | ||
| 57 | * $array = Spyc::YAMLLoad($file); | ||
| 58 | * </code> | ||
| 59 | * or: | ||
| 60 | * <code> | ||
| 61 | * $array = spyc_load_file($file); | ||
| 62 | * </code> | ||
| 63 | * @package Spyc | ||
| 64 | */ | ||
| 65 | class Spyc { | ||
| 66 | // SETTINGS | ||
| 67 | const REMPTY = "\0\0\0\0\0"; | ||
| 68 | /** | ||
| 69 | * Setting this to true will force YAMLDump to enclose any string value in | ||
| 70 | * quotes. False by default. | ||
| 71 | * | ||
| 72 | * @var bool | ||
| 73 | */ | ||
| 74 | public $setting_dump_force_quotes = false; | ||
| 75 | /** | ||
| 76 | * Setting this to true will forse YAMLLoad to use syck_load function when | ||
| 77 | * possible. False by default. | ||
| 78 | * @var bool | ||
| 79 | */ | ||
| 80 | public $setting_use_syck_is_possible = false; | ||
| 81 | /**#@+ | ||
| 82 | * @access private | ||
| 83 | * @var mixed | ||
| 84 | */ | ||
| 85 | private $_dumpIndent; | ||
| 86 | private $_dumpWordWrap; | ||
| 87 | private $_containsGroupAnchor = false; | ||
| 88 | private $_containsGroupAlias = false; | ||
| 89 | private $path; | ||
| 90 | private $result; | ||
| 91 | private $LiteralPlaceHolder = '___YAML_Literal_Block___'; | ||
| 92 | private $SavedGroups = array(); | ||
| 93 | private $indent; | ||
| 94 | /** | ||
| 95 | * Path modifier that should be applied after adding current element. | ||
| 96 | * @var array | ||
| 97 | */ | ||
| 98 | private $delayedPath = array(); | ||
| 99 | /**#@+ | ||
| 100 | * @access public | ||
| 101 | * @var mixed | ||
| 102 | */ | ||
| 103 | public $_nodeId; | ||
| 104 | /** | ||
| 105 | * Load a valid YAML string to Spyc. | ||
| 106 | * @param string $input | ||
| 107 | * @return array | ||
| 108 | */ | ||
| 109 | public function load ($input) { | ||
| 110 | return $this->_loadString($input); | ||
| 111 | } | ||
| 112 | /** | ||
| 113 | * Load a valid YAML file to Spyc. | ||
| 114 | * @param string $file | ||
| 115 | * @return array | ||
| 116 | */ | ||
| 117 | public function loadFile ($file) { | ||
| 118 | return $this->_load($file); | ||
| 119 | } | ||
| 120 | /** | ||
| 121 | * Load YAML into a PHP array statically | ||
| 122 | * | ||
| 123 | * The load method, when supplied with a YAML stream (string or file), | ||
| 124 | * will do its best to convert YAML in a file into a PHP array. Pretty | ||
| 125 | * simple. | ||
| 126 | * Usage: | ||
| 127 | * <code> | ||
| 128 | * $array = Spyc::YAMLLoad('lucky.yaml'); | ||
| 129 | * print_r($array); | ||
| 130 | * </code> | ||
| 131 | * @access public | ||
| 132 | * @return array | ||
| 133 | * @param string $input Path of YAML file or string containing YAML | ||
| 134 | */ | ||
| 135 | public static function YAMLLoad($input) { | ||
| 136 | $Spyc = new Spyc; | ||
| 137 | return $Spyc->_load($input); | ||
| 138 | } | ||
| 139 | /** | ||
| 140 | * Load a string of YAML into a PHP array statically | ||
| 141 | * | ||
| 142 | * The load method, when supplied with a YAML string, will do its best | ||
| 143 | * to convert YAML in a string into a PHP array. Pretty simple. | ||
| 144 | * | ||
| 145 | * Note: use this function if you don't want files from the file system | ||
| 146 | * loaded and processed as YAML. This is of interest to people concerned | ||
| 147 | * about security whose input is from a string. | ||
| 148 | * | ||
| 149 | * Usage: | ||
| 150 | * <code> | ||
| 151 | * $array = Spyc::YAMLLoadString("---\n0: hello world\n"); | ||
| 152 | * print_r($array); | ||
| 153 | * </code> | ||
| 154 | * @access public | ||
| 155 | * @return array | ||
| 156 | * @param string $input String containing YAML | ||
| 157 | */ | ||
| 158 | public static function YAMLLoadString($input) { | ||
| 159 | $Spyc = new Spyc; | ||
| 160 | return $Spyc->_loadString($input); | ||
| 161 | } | ||
| 162 | /** | ||
| 163 | * Dump YAML from PHP array statically | ||
| 164 | * | ||
| 165 | * The dump method, when supplied with an array, will do its best | ||
| 166 | * to convert the array into friendly YAML. Pretty simple. Feel free to | ||
| 167 | * save the returned string as nothing.yaml and pass it around. | ||
| 168 | * | ||
| 169 | * Oh, and you can decide how big the indent is and what the wordwrap | ||
| 170 | * for folding is. Pretty cool -- just pass in 'false' for either if | ||
| 171 | * you want to use the default. | ||
| 172 | * | ||
| 173 | * Indent's default is 2 spaces, wordwrap's default is 40 characters. And | ||
| 174 | * you can turn off wordwrap by passing in 0. | ||
| 175 | * | ||
| 176 | * @access public | ||
| 177 | * @return string | ||
| 178 | * @param array|\stdClass $array PHP array | ||
| 179 | * @param int $indent Pass in false to use the default, which is 2 | ||
| 180 | * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40) | ||
| 181 | * @param bool $no_opening_dashes Do not start YAML file with "---\n" | ||
| 182 | */ | ||
| 183 | public static function YAMLDump($array, $indent = false, $wordwrap = false, $no_opening_dashes = false) { | ||
| 184 | $spyc = new Spyc; | ||
| 185 | return $spyc->dump($array, $indent, $wordwrap, $no_opening_dashes); | ||
| 186 | } | ||
| 187 | /** | ||
| 188 | * Dump PHP array to YAML | ||
| 189 | * | ||
| 190 | * The dump method, when supplied with an array, will do its best | ||
| 191 | * to convert the array into friendly YAML. Pretty simple. Feel free to | ||
| 192 | * save the returned string as tasteful.yaml and pass it around. | ||
| 193 | * | ||
| 194 | * Oh, and you can decide how big the indent is and what the wordwrap | ||
| 195 | * for folding is. Pretty cool -- just pass in 'false' for either if | ||
| 196 | * you want to use the default. | ||
| 197 | * | ||
| 198 | * Indent's default is 2 spaces, wordwrap's default is 40 characters. And | ||
| 199 | * you can turn off wordwrap by passing in 0. | ||
| 200 | * | ||
| 201 | * @access public | ||
| 202 | * @return string | ||
| 203 | * @param array $array PHP array | ||
| 204 | * @param int $indent Pass in false to use the default, which is 2 | ||
| 205 | * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40) | ||
| 206 | */ | ||
| 207 | public function dump($array,$indent = false,$wordwrap = false, $no_opening_dashes = false) { | ||
| 208 | // Dumps to some very clean YAML. We'll have to add some more features | ||
| 209 | // and options soon. And better support for folding. | ||
| 210 | // New features and options. | ||
| 211 | if ($indent === false or !is_numeric($indent)) { | ||
| 212 | $this->_dumpIndent = 2; | ||
| 213 | } else { | ||
| 214 | $this->_dumpIndent = $indent; | ||
| 215 | } | ||
| 216 | if ($wordwrap === false or !is_numeric($wordwrap)) { | ||
| 217 | $this->_dumpWordWrap = 40; | ||
| 218 | } else { | ||
| 219 | $this->_dumpWordWrap = $wordwrap; | ||
| 220 | } | ||
| 221 | // New YAML document | ||
| 222 | $string = ""; | ||
| 223 | if (!$no_opening_dashes) $string = "---\n"; | ||
| 224 | // Start at the base of the array and move through it. | ||
| 225 | if ($array) { | ||
| 226 | $array = (array)$array; | ||
| 227 | $previous_key = -1; | ||
| 228 | foreach ($array as $key => $value) { | ||
| 229 | if (!isset($first_key)) $first_key = $key; | ||
| 230 | $string .= $this->_yamlize($key,$value,0,$previous_key, $first_key, $array); | ||
| 231 | $previous_key = $key; | ||
| 232 | } | ||
| 233 | } | ||
| 234 | return $string; | ||
| 235 | } | ||
| 236 | /** | ||
| 237 | * Attempts to convert a key / value array item to YAML | ||
| 238 | * @access private | ||
| 239 | * @return string | ||
| 240 | * @param $key The name of the key | ||
| 241 | * @param $value The value of the item | ||
| 242 | * @param $indent The indent of the current node | ||
| 243 | */ | ||
| 244 | private function _yamlize($key,$value,$indent, $previous_key = -1, $first_key = 0, $source_array = null) { | ||
| 245 | if(is_object($value)) $value = (array)$value; | ||
| 246 | if (is_array($value)) { | ||
| 247 | if (empty ($value)) | ||
| 248 | return $this->_dumpNode($key, array(), $indent, $previous_key, $first_key, $source_array); | ||
| 249 | // It has children. What to do? | ||
| 250 | // Make it the right kind of item | ||
| 251 | $string = $this->_dumpNode($key, self::REMPTY, $indent, $previous_key, $first_key, $source_array); | ||
| 252 | // Add the indent | ||
| 253 | $indent += $this->_dumpIndent; | ||
| 254 | // Yamlize the array | ||
| 255 | $string .= $this->_yamlizeArray($value,$indent); | ||
| 256 | } elseif (!is_array($value)) { | ||
| 257 | // It doesn't have children. Yip. | ||
| 258 | $string = $this->_dumpNode($key, $value, $indent, $previous_key, $first_key, $source_array); | ||
| 259 | } | ||
| 260 | return $string; | ||
| 261 | } | ||
| 262 | /** | ||
| 263 | * Attempts to convert an array to YAML | ||
| 264 | * @access private | ||
| 265 | * @return string | ||
| 266 | * @param $array The array you want to convert | ||
| 267 | * @param $indent The indent of the current level | ||
| 268 | */ | ||
| 269 | private function _yamlizeArray($array,$indent) { | ||
| 270 | if (is_array($array)) { | ||
| 271 | $string = ''; | ||
| 272 | $previous_key = -1; | ||
| 273 | foreach ($array as $key => $value) { | ||
| 274 | if (!isset($first_key)) $first_key = $key; | ||
| 275 | $string .= $this->_yamlize($key, $value, $indent, $previous_key, $first_key, $array); | ||
| 276 | $previous_key = $key; | ||
| 277 | } | ||
| 278 | return $string; | ||
| 279 | } else { | ||
| 280 | return false; | ||
| 281 | } | ||
| 282 | } | ||
| 283 | /** | ||
| 284 | * Returns YAML from a key and a value | ||
| 285 | * @access private | ||
| 286 | * @return string | ||
| 287 | * @param $key The name of the key | ||
| 288 | * @param $value The value of the item | ||
| 289 | * @param $indent The indent of the current node | ||
| 290 | */ | ||
| 291 | private function _dumpNode($key, $value, $indent, $previous_key = -1, $first_key = 0, $source_array = null) { | ||
| 292 | // do some folding here, for blocks | ||
| 293 | if (is_string ($value) && ((strpos($value,"\n") !== false || strpos($value,": ") !== false || strpos($value,"- ") !== false || | ||
| 294 | strpos($value,"*") !== false || strpos($value,"#") !== false || strpos($value,"<") !== false || strpos($value,">") !== false || strpos ($value, '%') !== false || strpos ($value, ' ') !== false || | ||
| 295 | strpos($value,"[") !== false || strpos($value,"]") !== false || strpos($value,"{") !== false || strpos($value,"}") !== false) || strpos($value,"&") !== false || strpos($value, "'") !== false || strpos($value, "!") === 0 || | ||
| 296 | substr ($value, -1, 1) == ':') | ||
| 297 | ) { | ||
| 298 | $value = $this->_doLiteralBlock($value,$indent); | ||
| 299 | } else { | ||
| 300 | $value = $this->_doFolding($value,$indent); | ||
| 301 | } | ||
| 302 | if ($value === array()) $value = '[ ]'; | ||
| 303 | if ($value === "") $value = '""'; | ||
| 304 | if (self::isTranslationWord($value)) { | ||
| 305 | $value = $this->_doLiteralBlock($value, $indent); | ||
| 306 | } | ||
| 307 | if (trim ($value) != $value) | ||
| 308 | $value = $this->_doLiteralBlock($value,$indent); | ||
| 309 | if (is_bool($value)) { | ||
| 310 | $value = $value ? "true" : "false"; | ||
| 311 | } | ||
| 312 | if ($value === null) $value = 'null'; | ||
| 313 | if ($value === "'" . self::REMPTY . "'") $value = null; | ||
| 314 | $spaces = str_repeat(' ',$indent); | ||
| 315 | //if (is_int($key) && $key - 1 == $previous_key && $first_key===0) { | ||
| 316 | if (is_array ($source_array) && array_keys($source_array) === range(0, count($source_array) - 1)) { | ||
| 317 | // It's a sequence | ||
| 318 | $string = $spaces.'- '.$value."\n"; | ||
| 319 | } else { | ||
| 320 | // if ($first_key===0) throw new Exception('Keys are all screwy. The first one was zero, now it\'s "'. $key .'"'); | ||
| 321 | // It's mapped | ||
| 322 | if (strpos($key, ":") !== false || strpos($key, "#") !== false) { $key = '"' . $key . '"'; } | ||
| 323 | $string = rtrim ($spaces.$key.': '.$value)."\n"; | ||
| 324 | } | ||
| 325 | return $string; | ||
| 326 | } | ||
| 327 | /** | ||
| 328 | * Creates a literal block for dumping | ||
| 329 | * @access private | ||
| 330 | * @return string | ||
| 331 | * @param $value | ||
| 332 | * @param $indent int The value of the indent | ||
| 333 | */ | ||
| 334 | private function _doLiteralBlock($value,$indent) { | ||
| 335 | if ($value === "\n") return '\n'; | ||
| 336 | if (strpos($value, "\n") === false && strpos($value, "'") === false) { | ||
| 337 | return sprintf ("'%s'", $value); | ||
| 338 | } | ||
| 339 | if (strpos($value, "\n") === false && strpos($value, '"') === false) { | ||
| 340 | return sprintf ('"%s"', $value); | ||
| 341 | } | ||
| 342 | $exploded = explode("\n",$value); | ||
| 343 | $newValue = '|'; | ||
| 344 | if (isset($exploded[0]) && ($exploded[0] == "|" || $exploded[0] == "|-" || $exploded[0] == ">")) { | ||
| 345 | $newValue = $exploded[0]; | ||
| 346 | unset($exploded[0]); | ||
| 347 | } | ||
| 348 | $indent += $this->_dumpIndent; | ||
| 349 | $spaces = str_repeat(' ',$indent); | ||
| 350 | foreach ($exploded as $line) { | ||
| 351 | $line = trim($line); | ||
| 352 | if (strpos($line, '"') === 0 && strrpos($line, '"') == (strlen($line)-1) || strpos($line, "'") === 0 && strrpos($line, "'") == (strlen($line)-1)) { | ||
| 353 | $line = substr($line, 1, -1); | ||
| 354 | } | ||
| 355 | $newValue .= "\n" . $spaces . ($line); | ||
| 356 | } | ||
| 357 | return $newValue; | ||
| 358 | } | ||
| 359 | /** | ||
| 360 | * Folds a string of text, if necessary | ||
| 361 | * @access private | ||
| 362 | * @return string | ||
| 363 | * @param $value The string you wish to fold | ||
| 364 | */ | ||
| 365 | private function _doFolding($value,$indent) { | ||
| 366 | // Don't do anything if wordwrap is set to 0 | ||
| 367 | if ($this->_dumpWordWrap !== 0 && is_string ($value) && strlen($value) > $this->_dumpWordWrap) { | ||
| 368 | $indent += $this->_dumpIndent; | ||
| 369 | $indent = str_repeat(' ',$indent); | ||
| 370 | $wrapped = wordwrap($value,$this->_dumpWordWrap,"\n$indent"); | ||
| 371 | $value = ">\n".$indent.$wrapped; | ||
| 372 | } else { | ||
| 373 | if ($this->setting_dump_force_quotes && is_string ($value) && $value !== self::REMPTY) | ||
| 374 | $value = '"' . $value . '"'; | ||
| 375 | if (is_numeric($value) && is_string($value)) | ||
| 376 | $value = '"' . $value . '"'; | ||
| 377 | } | ||
| 378 | return $value; | ||
| 379 | } | ||
| 380 | private function isTrueWord($value) { | ||
| 381 | $words = self::getTranslations(array('true', 'on', 'yes', 'y')); | ||
| 382 | return in_array($value, $words, true); | ||
| 383 | } | ||
| 384 | private function isFalseWord($value) { | ||
| 385 | $words = self::getTranslations(array('false', 'off', 'no', 'n')); | ||
| 386 | return in_array($value, $words, true); | ||
| 387 | } | ||
| 388 | private function isNullWord($value) { | ||
| 389 | $words = self::getTranslations(array('null', '~')); | ||
| 390 | return in_array($value, $words, true); | ||
| 391 | } | ||
| 392 | private function isTranslationWord($value) { | ||
| 393 | return ( | ||
| 394 | self::isTrueWord($value) || | ||
| 395 | self::isFalseWord($value) || | ||
| 396 | self::isNullWord($value) | ||
| 397 | ); | ||
| 398 | } | ||
| 399 | /** | ||
| 400 | * Coerce a string into a native type | ||
| 401 | * Reference: http://yaml.org/type/bool.html | ||
| 402 | * TODO: Use only words from the YAML spec. | ||
| 403 | * @access private | ||
| 404 | * @param $value The value to coerce | ||
| 405 | */ | ||
| 406 | private function coerceValue(&$value) { | ||
| 407 | if (self::isTrueWord($value)) { | ||
| 408 | $value = true; | ||
| 409 | } else if (self::isFalseWord($value)) { | ||
| 410 | $value = false; | ||
| 411 | } else if (self::isNullWord($value)) { | ||
| 412 | $value = null; | ||
| 413 | } | ||
| 414 | } | ||
| 415 | /** | ||
| 416 | * Given a set of words, perform the appropriate translations on them to | ||
| 417 | * match the YAML 1.1 specification for type coercing. | ||
| 418 | * @param $words The words to translate | ||
| 419 | * @access private | ||
| 420 | */ | ||
| 421 | private static function getTranslations(array $words) { | ||
| 422 | $result = array(); | ||
| 423 | foreach ($words as $i) { | ||
| 424 | $result = array_merge($result, array(ucfirst($i), strtoupper($i), strtolower($i))); | ||
| 425 | } | ||
| 426 | return $result; | ||
| 427 | } | ||
| 428 | // LOADING FUNCTIONS | ||
| 429 | private function _load($input) { | ||
| 430 | $Source = $this->loadFromSource($input); | ||
| 431 | return $this->loadWithSource($Source); | ||
| 432 | } | ||
| 433 | private function _loadString($input) { | ||
| 434 | $Source = $this->loadFromString($input); | ||
| 435 | return $this->loadWithSource($Source); | ||
| 436 | } | ||
| 437 | private function loadWithSource($Source) { | ||
| 438 | if (empty ($Source)) return array(); | ||
| 439 | if ($this->setting_use_syck_is_possible && function_exists ('syck_load')) { | ||
| 440 | $array = syck_load (implode ("\n", $Source)); | ||
| 441 | return is_array($array) ? $array : array(); | ||
| 442 | } | ||
| 443 | $this->path = array(); | ||
| 444 | $this->result = array(); | ||
| 445 | $cnt = count($Source); | ||
| 446 | for ($i = 0; $i < $cnt; $i++) { | ||
| 447 | $line = $Source[$i]; | ||
| 448 | $this->indent = strlen($line) - strlen(ltrim($line)); | ||
| 449 | $tempPath = $this->getParentPathByIndent($this->indent); | ||
| 450 | $line = self::stripIndent($line, $this->indent); | ||
| 451 | if (self::isComment($line)) continue; | ||
| 452 | if (self::isEmpty($line)) continue; | ||
| 453 | $this->path = $tempPath; | ||
| 454 | $literalBlockStyle = self::startsLiteralBlock($line); | ||
| 455 | if ($literalBlockStyle) { | ||
| 456 | $line = rtrim ($line, $literalBlockStyle . " \n"); | ||
| 457 | $literalBlock = ''; | ||
| 458 | $line .= ' '.$this->LiteralPlaceHolder; | ||
| 459 | $literal_block_indent = strlen($Source[$i+1]) - strlen(ltrim($Source[$i+1])); | ||
| 460 | while (++$i < $cnt && $this->literalBlockContinues($Source[$i], $this->indent)) { | ||
| 461 | $literalBlock = $this->addLiteralLine($literalBlock, $Source[$i], $literalBlockStyle, $literal_block_indent); | ||
| 462 | } | ||
| 463 | $i--; | ||
| 464 | } | ||
| 465 | // Strip out comments | ||
| 466 | if (strpos ($line, '#')) { | ||
| 467 | $line = preg_replace('/\s*#([^"\']+)$/','',$line); | ||
| 468 | } | ||
| 469 | while (++$i < $cnt && self::greedilyNeedNextLine($line)) { | ||
| 470 | $line = rtrim ($line, " \n\t\r") . ' ' . ltrim ($Source[$i], " \t"); | ||
| 471 | } | ||
| 472 | $i--; | ||
| 473 | $lineArray = $this->_parseLine($line); | ||
| 474 | if ($literalBlockStyle) | ||
| 475 | $lineArray = $this->revertLiteralPlaceHolder ($lineArray, $literalBlock); | ||
| 476 | $this->addArray($lineArray, $this->indent); | ||
| 477 | foreach ($this->delayedPath as $indent => $delayedPath) | ||
| 478 | $this->path[$indent] = $delayedPath; | ||
| 479 | $this->delayedPath = array(); | ||
| 480 | } | ||
| 481 | return $this->result; | ||
| 482 | } | ||
| 483 | private function loadFromSource ($input) { | ||
| 484 | if (!empty($input) && strpos($input, "\n") === false && file_exists($input)) | ||
| 485 | $input = file_get_contents($input); | ||
| 486 | return $this->loadFromString($input); | ||
| 487 | } | ||
| 488 | private function loadFromString ($input) { | ||
| 489 | $lines = explode("\n",$input); | ||
| 490 | foreach ($lines as $k => $_) { | ||
| 491 | $lines[$k] = rtrim ($_, "\r"); | ||
| 492 | } | ||
| 493 | return $lines; | ||
| 494 | } | ||
| 495 | /** | ||
| 496 | * Parses YAML code and returns an array for a node | ||
| 497 | * @access private | ||
| 498 | * @return array | ||
| 499 | * @param string $line A line from the YAML file | ||
| 500 | */ | ||
| 501 | private function _parseLine($line) { | ||
| 502 | if (!$line) return array(); | ||
| 503 | $line = trim($line); | ||
| 504 | if (!$line) return array(); | ||
| 505 | $array = array(); | ||
| 506 | $group = $this->nodeContainsGroup($line); | ||
| 507 | if ($group) { | ||
| 508 | $this->addGroup($line, $group); | ||
| 509 | $line = $this->stripGroup ($line, $group); | ||
| 510 | } | ||
| 511 | if ($this->startsMappedSequence($line)) | ||
| 512 | return $this->returnMappedSequence($line); | ||
| 513 | if ($this->startsMappedValue($line)) | ||
| 514 | return $this->returnMappedValue($line); | ||
| 515 | if ($this->isArrayElement($line)) | ||
| 516 | return $this->returnArrayElement($line); | ||
| 517 | if ($this->isPlainArray($line)) | ||
| 518 | return $this->returnPlainArray($line); | ||
| 519 | return $this->returnKeyValuePair($line); | ||
| 520 | } | ||
| 521 | /** | ||
| 522 | * Finds the type of the passed value, returns the value as the new type. | ||
| 523 | * @access private | ||
| 524 | * @param string $value | ||
| 525 | * @return mixed | ||
| 526 | */ | ||
| 527 | private function _toType($value) { | ||
| 528 | if ($value === '') return ""; | ||
| 529 | $first_character = $value[0]; | ||
| 530 | $last_character = substr($value, -1, 1); | ||
| 531 | $is_quoted = false; | ||
| 532 | do { | ||
| 533 | if (!$value) break; | ||
| 534 | if ($first_character != '"' && $first_character != "'") break; | ||
| 535 | if ($last_character != '"' && $last_character != "'") break; | ||
| 536 | $is_quoted = true; | ||
| 537 | } while (0); | ||
| 538 | if ($is_quoted) { | ||
| 539 | $value = str_replace('\n', "\n", $value); | ||
| 540 | if ($first_character == "'") | ||
| 541 | return strtr(substr ($value, 1, -1), array ('\'\'' => '\'', '\\\''=> '\'')); | ||
| 542 | return strtr(substr ($value, 1, -1), array ('\\"' => '"', '\\\''=> '\'')); | ||
| 543 | } | ||
| 544 | if (strpos($value, ' #') !== false && !$is_quoted) | ||
| 545 | $value = preg_replace('/\s+#(.+)$/','',$value); | ||
| 546 | if ($first_character == '[' && $last_character == ']') { | ||
| 547 | // Take out strings sequences and mappings | ||
| 548 | $innerValue = trim(substr ($value, 1, -1)); | ||
| 549 | if ($innerValue === '') return array(); | ||
| 550 | $explode = $this->_inlineEscape($innerValue); | ||
| 551 | // Propagate value array | ||
| 552 | $value = array(); | ||
| 553 | foreach ($explode as $v) { | ||
| 554 | $value[] = $this->_toType($v); | ||
| 555 | } | ||
| 556 | return $value; | ||
| 557 | } | ||
| 558 | if (strpos($value,': ')!==false && $first_character != '{') { | ||
| 559 | $array = explode(': ',$value); | ||
| 560 | $key = trim($array[0]); | ||
| 561 | array_shift($array); | ||
| 562 | $value = trim(implode(': ',$array)); | ||
| 563 | $value = $this->_toType($value); | ||
| 564 | return array($key => $value); | ||
| 565 | } | ||
| 566 | if ($first_character == '{' && $last_character == '}') { | ||
| 567 | $innerValue = trim(substr ($value, 1, -1)); | ||
| 568 | if ($innerValue === '') return array(); | ||
| 569 | // Inline Mapping | ||
| 570 | // Take out strings sequences and mappings | ||
| 571 | $explode = $this->_inlineEscape($innerValue); | ||
| 572 | // Propagate value array | ||
| 573 | $array = array(); | ||
| 574 | foreach ($explode as $v) { | ||
| 575 | $SubArr = $this->_toType($v); | ||
| 576 | if (empty($SubArr)) continue; | ||
| 577 | if (is_array ($SubArr)) { | ||
| 578 | $array[key($SubArr)] = $SubArr[key($SubArr)]; continue; | ||
| 579 | } | ||
| 580 | $array[] = $SubArr; | ||
| 581 | } | ||
| 582 | return $array; | ||
| 583 | } | ||
| 584 | if ($value == 'null' || $value == 'NULL' || $value == 'Null' || $value == '' || $value == '~') { | ||
| 585 | return null; | ||
| 586 | } | ||
| 587 | if ( is_numeric($value) && preg_match ('/^(-|)[1-9]+[0-9]*$/', $value) ){ | ||
| 588 | $intvalue = (int)$value; | ||
| 589 | if ($intvalue != PHP_INT_MAX && $intvalue != ~PHP_INT_MAX) | ||
| 590 | $value = $intvalue; | ||
| 591 | return $value; | ||
| 592 | } | ||
| 593 | if ( is_string($value) && preg_match('/^0[xX][0-9a-fA-F]+$/', $value)) { | ||
| 594 | // Hexadecimal value. | ||
| 595 | return hexdec($value); | ||
| 596 | } | ||
| 597 | $this->coerceValue($value); | ||
| 598 | if (is_numeric($value)) { | ||
| 599 | if ($value === '0') return 0; | ||
| 600 | if (rtrim ($value, 0) === $value) | ||
| 601 | $value = (float)$value; | ||
| 602 | return $value; | ||
| 603 | } | ||
| 604 | return $value; | ||
| 605 | } | ||
| 606 | /** | ||
| 607 | * Used in inlines to check for more inlines or quoted strings | ||
| 608 | * @access private | ||
| 609 | * @return array | ||
| 610 | */ | ||
| 611 | private function _inlineEscape($inline) { | ||
| 612 | // There's gotta be a cleaner way to do this... | ||
| 613 | // While pure sequences seem to be nesting just fine, | ||
| 614 | // pure mappings and mappings with sequences inside can't go very | ||
| 615 | // deep. This needs to be fixed. | ||
| 616 | $seqs = array(); | ||
| 617 | $maps = array(); | ||
| 618 | $saved_strings = array(); | ||
| 619 | $saved_empties = array(); | ||
| 620 | // Check for empty strings | ||
| 621 | $regex = '/("")|(\'\')/'; | ||
| 622 | if (preg_match_all($regex,$inline,$strings)) { | ||
| 623 | $saved_empties = $strings[0]; | ||
| 624 | $inline = preg_replace($regex,'YAMLEmpty',$inline); | ||
| 625 | } | ||
| 626 | unset($regex); | ||
| 627 | // Check for strings | ||
| 628 | $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/'; | ||
| 629 | if (preg_match_all($regex,$inline,$strings)) { | ||
| 630 | $saved_strings = $strings[0]; | ||
| 631 | $inline = preg_replace($regex,'YAMLString',$inline); | ||
| 632 | } | ||
| 633 | unset($regex); | ||
| 634 | // echo $inline; | ||
| 635 | $i = 0; | ||
| 636 | do { | ||
| 637 | // Check for sequences | ||
| 638 | while (preg_match('/\[([^{}\[\]]+)\]/U',$inline,$matchseqs)) { | ||
| 639 | $seqs[] = $matchseqs[0]; | ||
| 640 | $inline = preg_replace('/\[([^{}\[\]]+)\]/U', ('YAMLSeq' . (count($seqs) - 1) . 's'), $inline, 1); | ||
| 641 | } | ||
| 642 | // Check for mappings | ||
| 643 | while (preg_match('/{([^\[\]{}]+)}/U',$inline,$matchmaps)) { | ||
| 644 | $maps[] = $matchmaps[0]; | ||
| 645 | $inline = preg_replace('/{([^\[\]{}]+)}/U', ('YAMLMap' . (count($maps) - 1) . 's'), $inline, 1); | ||
| 646 | } | ||
| 647 | if ($i++ >= 10) break; | ||
| 648 | } while (strpos ($inline, '[') !== false || strpos ($inline, '{') !== false); | ||
| 649 | $explode = explode(',',$inline); | ||
| 650 | $explode = array_map('trim', $explode); | ||
| 651 | $stringi = 0; $i = 0; | ||
| 652 | while (1) { | ||
| 653 | // Re-add the sequences | ||
| 654 | if (!empty($seqs)) { | ||
| 655 | foreach ($explode as $key => $value) { | ||
| 656 | if (strpos($value,'YAMLSeq') !== false) { | ||
| 657 | foreach ($seqs as $seqk => $seq) { | ||
| 658 | $explode[$key] = str_replace(('YAMLSeq'.$seqk.'s'),$seq,$value); | ||
| 659 | $value = $explode[$key]; | ||
| 660 | } | ||
| 661 | } | ||
| 662 | } | ||
| 663 | } | ||
| 664 | // Re-add the mappings | ||
| 665 | if (!empty($maps)) { | ||
| 666 | foreach ($explode as $key => $value) { | ||
| 667 | if (strpos($value,'YAMLMap') !== false) { | ||
| 668 | foreach ($maps as $mapk => $map) { | ||
| 669 | $explode[$key] = str_replace(('YAMLMap'.$mapk.'s'), $map, $value); | ||
| 670 | $value = $explode[$key]; | ||
| 671 | } | ||
| 672 | } | ||
| 673 | } | ||
| 674 | } | ||
| 675 | // Re-add the strings | ||
| 676 | if (!empty($saved_strings)) { | ||
| 677 | foreach ($explode as $key => $value) { | ||
| 678 | while (strpos($value,'YAMLString') !== false) { | ||
| 679 | $explode[$key] = preg_replace('/YAMLString/',$saved_strings[$stringi],$value, 1); | ||
| 680 | unset($saved_strings[$stringi]); | ||
| 681 | ++$stringi; | ||
| 682 | $value = $explode[$key]; | ||
| 683 | } | ||
| 684 | } | ||
| 685 | } | ||
| 686 | // Re-add the empties | ||
| 687 | if (!empty($saved_empties)) { | ||
| 688 | foreach ($explode as $key => $value) { | ||
| 689 | while (strpos($value,'YAMLEmpty') !== false) { | ||
| 690 | $explode[$key] = preg_replace('/YAMLEmpty/', '', $value, 1); | ||
| 691 | $value = $explode[$key]; | ||
| 692 | } | ||
| 693 | } | ||
| 694 | } | ||
| 695 | $finished = true; | ||
| 696 | foreach ($explode as $key => $value) { | ||
| 697 | if (strpos($value,'YAMLSeq') !== false) { | ||
| 698 | $finished = false; break; | ||
| 699 | } | ||
| 700 | if (strpos($value,'YAMLMap') !== false) { | ||
| 701 | $finished = false; break; | ||
| 702 | } | ||
| 703 | if (strpos($value,'YAMLString') !== false) { | ||
| 704 | $finished = false; break; | ||
| 705 | } | ||
| 706 | if (strpos($value,'YAMLEmpty') !== false) { | ||
| 707 | $finished = false; break; | ||
| 708 | } | ||
| 709 | } | ||
| 710 | if ($finished) break; | ||
| 711 | $i++; | ||
| 712 | if ($i > 10) | ||
| 713 | break; // Prevent infinite loops. | ||
| 714 | } | ||
| 715 | return $explode; | ||
| 716 | } | ||
| 717 | private function literalBlockContinues ($line, $lineIndent) { | ||
| 718 | if (!trim($line)) return true; | ||
| 719 | if (strlen($line) - strlen(ltrim($line)) > $lineIndent) return true; | ||
| 720 | return false; | ||
| 721 | } | ||
| 722 | private function referenceContentsByAlias ($alias) { | ||
| 723 | do { | ||
| 724 | if (!isset($this->SavedGroups[$alias])) { echo "Bad group name: $alias."; break; } | ||
| 725 | $groupPath = $this->SavedGroups[$alias]; | ||
| 726 | $value = $this->result; | ||
| 727 | foreach ($groupPath as $k) { | ||
| 728 | $value = $value[$k]; | ||
| 729 | } | ||
| 730 | } while (false); | ||
| 731 | return $value; | ||
| 732 | } | ||
| 733 | private function addArrayInline ($array, $indent) { | ||
| 734 | $CommonGroupPath = $this->path; | ||
| 735 | if (empty ($array)) return false; | ||
| 736 | foreach ($array as $k => $_) { | ||
| 737 | $this->addArray(array($k => $_), $indent); | ||
| 738 | $this->path = $CommonGroupPath; | ||
| 739 | } | ||
| 740 | return true; | ||
| 741 | } | ||
| 742 | private function addArray ($incoming_data, $incoming_indent) { | ||
| 743 | // print_r ($incoming_data); | ||
| 744 | if (count ($incoming_data) > 1) | ||
| 745 | return $this->addArrayInline ($incoming_data, $incoming_indent); | ||
| 746 | $key = key ($incoming_data); | ||
| 747 | $value = isset($incoming_data[$key]) ? $incoming_data[$key] : null; | ||
| 748 | if ($key === '__!YAMLZero') $key = '0'; | ||
| 749 | if ($incoming_indent == 0 && !$this->_containsGroupAlias && !$this->_containsGroupAnchor) { // Shortcut for root-level values. | ||
| 750 | if ($key || $key === '' || $key === '0') { | ||
| 751 | $this->result[$key] = $value; | ||
| 752 | } else { | ||
| 753 | $this->result[] = $value; end ($this->result); $key = key ($this->result); | ||
| 754 | } | ||
| 755 | $this->path[$incoming_indent] = $key; | ||
| 756 | return; | ||
| 757 | } | ||
| 758 | $history = array(); | ||
| 759 | // Unfolding inner array tree. | ||
| 760 | $history[] = $_arr = $this->result; | ||
| 761 | foreach ($this->path as $k) { | ||
| 762 | $history[] = $_arr = $_arr[$k]; | ||
| 763 | } | ||
| 764 | if ($this->_containsGroupAlias) { | ||
| 765 | $value = $this->referenceContentsByAlias($this->_containsGroupAlias); | ||
| 766 | $this->_containsGroupAlias = false; | ||
| 767 | } | ||
| 768 | // Adding string or numeric key to the innermost level or $this->arr. | ||
| 769 | if (is_string($key) && $key == '<<') { | ||
| 770 | if (!is_array ($_arr)) { $_arr = array (); } | ||
| 771 | $_arr = array_merge ($_arr, $value); | ||
| 772 | } else if ($key || $key === '' || $key === '0') { | ||
| 773 | if (!is_array ($_arr)) | ||
| 774 | $_arr = array ($key=>$value); | ||
| 775 | else | ||
| 776 | $_arr[$key] = $value; | ||
| 777 | } else { | ||
| 778 | if (!is_array ($_arr)) { $_arr = array ($value); $key = 0; } | ||
| 779 | else { $_arr[] = $value; end ($_arr); $key = key ($_arr); } | ||
| 780 | } | ||
| 781 | $reverse_path = array_reverse($this->path); | ||
| 782 | $reverse_history = array_reverse ($history); | ||
| 783 | $reverse_history[0] = $_arr; | ||
| 784 | $cnt = count($reverse_history) - 1; | ||
| 785 | for ($i = 0; $i < $cnt; $i++) { | ||
| 786 | $reverse_history[$i+1][$reverse_path[$i]] = $reverse_history[$i]; | ||
| 787 | } | ||
| 788 | $this->result = $reverse_history[$cnt]; | ||
| 789 | $this->path[$incoming_indent] = $key; | ||
| 790 | if ($this->_containsGroupAnchor) { | ||
| 791 | $this->SavedGroups[$this->_containsGroupAnchor] = $this->path; | ||
| 792 | if (is_array ($value)) { | ||
| 793 | $k = key ($value); | ||
| 794 | if (!is_int ($k)) { | ||
| 795 | $this->SavedGroups[$this->_containsGroupAnchor][$incoming_indent + 2] = $k; | ||
| 796 | } | ||
| 797 | } | ||
| 798 | $this->_containsGroupAnchor = false; | ||
| 799 | } | ||
| 800 | } | ||
| 801 | private static function startsLiteralBlock ($line) { | ||
| 802 | $lastChar = substr (trim($line), -1); | ||
| 803 | if ($lastChar != '>' && $lastChar != '|') return false; | ||
| 804 | if ($lastChar == '|') return $lastChar; | ||
| 805 | // HTML tags should not be counted as literal blocks. | ||
| 806 | if (preg_match ('#<.*?>$#', $line)) return false; | ||
| 807 | return $lastChar; | ||
| 808 | } | ||
| 809 | private static function greedilyNeedNextLine($line) { | ||
| 810 | $line = trim ($line); | ||
| 811 | if (!strlen($line)) return false; | ||
| 812 | if (substr ($line, -1, 1) == ']') return false; | ||
| 813 | if ($line[0] == '[') return true; | ||
| 814 | if (preg_match ('#^[^:]+?:\s*\[#', $line)) return true; | ||
| 815 | return false; | ||
| 816 | } | ||
| 817 | private function addLiteralLine ($literalBlock, $line, $literalBlockStyle, $indent = -1) { | ||
| 818 | $line = self::stripIndent($line, $indent); | ||
| 819 | if ($literalBlockStyle !== '|') { | ||
| 820 | $line = self::stripIndent($line); | ||
| 821 | } | ||
| 822 | $line = rtrim ($line, "\r\n\t ") . "\n"; | ||
| 823 | if ($literalBlockStyle == '|') { | ||
| 824 | return $literalBlock . $line; | ||
| 825 | } | ||
| 826 | if (strlen($line) == 0) | ||
| 827 | return rtrim($literalBlock, ' ') . "\n"; | ||
| 828 | if ($line == "\n" && $literalBlockStyle == '>') { | ||
| 829 | return rtrim ($literalBlock, " \t") . "\n"; | ||
| 830 | } | ||
| 831 | if ($line != "\n") | ||
| 832 | $line = trim ($line, "\r\n ") . " "; | ||
| 833 | return $literalBlock . $line; | ||
| 834 | } | ||
| 835 | function revertLiteralPlaceHolder ($lineArray, $literalBlock) { | ||
| 836 | foreach ($lineArray as $k => $_) { | ||
| 837 | if (is_array($_)) | ||
| 838 | $lineArray[$k] = $this->revertLiteralPlaceHolder ($_, $literalBlock); | ||
| 839 | else if (substr($_, -1 * strlen ($this->LiteralPlaceHolder)) == $this->LiteralPlaceHolder) | ||
| 840 | $lineArray[$k] = rtrim ($literalBlock, " \r\n"); | ||
| 841 | } | ||
| 842 | return $lineArray; | ||
| 843 | } | ||
| 844 | private static function stripIndent ($line, $indent = -1) { | ||
| 845 | if ($indent == -1) $indent = strlen($line) - strlen(ltrim($line)); | ||
| 846 | return substr ($line, $indent); | ||
| 847 | } | ||
| 848 | private function getParentPathByIndent ($indent) { | ||
| 849 | if ($indent == 0) return array(); | ||
| 850 | $linePath = $this->path; | ||
| 851 | do { | ||
| 852 | end($linePath); $lastIndentInParentPath = key($linePath); | ||
| 853 | if ($indent <= $lastIndentInParentPath) array_pop ($linePath); | ||
| 854 | } while ($indent <= $lastIndentInParentPath); | ||
| 855 | return $linePath; | ||
| 856 | } | ||
| 857 | private function clearBiggerPathValues ($indent) { | ||
| 858 | if ($indent == 0) $this->path = array(); | ||
| 859 | if (empty ($this->path)) return true; | ||
| 860 | foreach ($this->path as $k => $_) { | ||
| 861 | if ($k > $indent) unset ($this->path[$k]); | ||
| 862 | } | ||
| 863 | return true; | ||
| 864 | } | ||
| 865 | private static function isComment ($line) { | ||
| 866 | if (!$line) return false; | ||
| 867 | if ($line[0] == '#') return true; | ||
| 868 | if (trim($line, " \r\n\t") == '---') return true; | ||
| 869 | return false; | ||
| 870 | } | ||
| 871 | private static function isEmpty ($line) { | ||
| 872 | return (trim ($line) === ''); | ||
| 873 | } | ||
| 874 | private function isArrayElement ($line) { | ||
| 875 | if (!$line || !is_scalar($line)) return false; | ||
| 876 | if (substr($line, 0, 2) != '- ') return false; | ||
| 877 | if (strlen ($line) > 3) | ||
| 878 | if (substr($line,0,3) == '---') return false; | ||
| 879 | return true; | ||
| 880 | } | ||
| 881 | private function isHashElement ($line) { | ||
| 882 | return strpos($line, ':'); | ||
| 883 | } | ||
| 884 | private function isLiteral ($line) { | ||
| 885 | if ($this->isArrayElement($line)) return false; | ||
| 886 | if ($this->isHashElement($line)) return false; | ||
| 887 | return true; | ||
| 888 | } | ||
| 889 | private static function unquote ($value) { | ||
| 890 | if (!$value) return $value; | ||
| 891 | if (!is_string($value)) return $value; | ||
| 892 | if ($value[0] == '\'') return trim ($value, '\''); | ||
| 893 | if ($value[0] == '"') return trim ($value, '"'); | ||
| 894 | return $value; | ||
| 895 | } | ||
| 896 | private function startsMappedSequence ($line) { | ||
| 897 | return (substr($line, 0, 2) == '- ' && substr ($line, -1, 1) == ':'); | ||
| 898 | } | ||
| 899 | private function returnMappedSequence ($line) { | ||
| 900 | $array = array(); | ||
| 901 | $key = self::unquote(trim(substr($line,1,-1))); | ||
| 902 | $array[$key] = array(); | ||
| 903 | $this->delayedPath = array(strpos ($line, $key) + $this->indent => $key); | ||
| 904 | return array($array); | ||
| 905 | } | ||
| 906 | private function checkKeysInValue($value) { | ||
| 907 | if (strchr('[{"\'', $value[0]) === false) { | ||
| 908 | if (strchr($value, ': ') !== false) { | ||
| 909 | throw new Exception('Too many keys: '.$value); | ||
| 910 | } | ||
| 911 | } | ||
| 912 | } | ||
| 913 | private function returnMappedValue ($line) { | ||
| 914 | $this->checkKeysInValue($line); | ||
| 915 | $array = array(); | ||
| 916 | $key = self::unquote (trim(substr($line,0,-1))); | ||
| 917 | $array[$key] = ''; | ||
| 918 | return $array; | ||
| 919 | } | ||
| 920 | private function startsMappedValue ($line) { | ||
| 921 | return (substr ($line, -1, 1) == ':'); | ||
| 922 | } | ||
| 923 | private function isPlainArray ($line) { | ||
| 924 | return ($line[0] == '[' && substr ($line, -1, 1) == ']'); | ||
| 925 | } | ||
| 926 | private function returnPlainArray ($line) { | ||
| 927 | return $this->_toType($line); | ||
| 928 | } | ||
| 929 | private function returnKeyValuePair ($line) { | ||
| 930 | $array = array(); | ||
| 931 | $key = ''; | ||
| 932 | if (strpos ($line, ': ')) { | ||
| 933 | // It's a key/value pair most likely | ||
| 934 | // If the key is in double quotes pull it out | ||
| 935 | if (($line[0] == '"' || $line[0] == "'") && preg_match('/^(["\'](.*)["\'](\s)*:)/',$line,$matches)) { | ||
| 936 | $value = trim(str_replace($matches[1],'',$line)); | ||
| 937 | $key = $matches[2]; | ||
| 938 | } else { | ||
| 939 | // Do some guesswork as to the key and the value | ||
| 940 | $explode = explode(': ', $line); | ||
| 941 | $key = trim(array_shift($explode)); | ||
| 942 | $value = trim(implode(': ', $explode)); | ||
| 943 | $this->checkKeysInValue($value); | ||
| 944 | } | ||
| 945 | // Set the type of the value. Int, string, etc | ||
| 946 | $value = $this->_toType($value); | ||
| 947 | if ($key === '0') $key = '__!YAMLZero'; | ||
| 948 | $array[$key] = $value; | ||
| 949 | } else { | ||
| 950 | $array = array ($line); | ||
| 951 | } | ||
| 952 | return $array; | ||
| 953 | } | ||
| 954 | private function returnArrayElement ($line) { | ||
| 955 | if (strlen($line) <= 1) return array(array()); // Weird %) | ||
| 956 | $array = array(); | ||
| 957 | $value = trim(substr($line,1)); | ||
| 958 | $value = $this->_toType($value); | ||
| 959 | if ($this->isArrayElement($value)) { | ||
| 960 | $value = $this->returnArrayElement($value); | ||
| 961 | } | ||
| 962 | $array[] = $value; | ||
| 963 | return $array; | ||
| 964 | } | ||
| 965 | private function nodeContainsGroup ($line) { | ||
| 966 | $symbolsForReference = 'A-z0-9_\-'; | ||
| 967 | if (strpos($line, '&') === false && strpos($line, '*') === false) return false; // Please die fast ;-) | ||
| 968 | if ($line[0] == '&' && preg_match('/^(&['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1]; | ||
| 969 | if ($line[0] == '*' && preg_match('/^(\*['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1]; | ||
| 970 | if (preg_match('/(&['.$symbolsForReference.']+)$/', $line, $matches)) return $matches[1]; | ||
| 971 | if (preg_match('/(\*['.$symbolsForReference.']+$)/', $line, $matches)) return $matches[1]; | ||
| 972 | if (preg_match ('#^\s*<<\s*:\s*(\*[^\s]+).*$#', $line, $matches)) return $matches[1]; | ||
| 973 | return false; | ||
| 974 | } | ||
| 975 | private function addGroup ($line, $group) { | ||
| 976 | if ($group[0] == '&') $this->_containsGroupAnchor = substr ($group, 1); | ||
| 977 | if ($group[0] == '*') $this->_containsGroupAlias = substr ($group, 1); | ||
| 978 | //print_r ($this->path); | ||
| 979 | } | ||
| 980 | private function stripGroup ($line, $group) { | ||
| 981 | $line = trim(str_replace($group, '', $line)); | ||
| 982 | return $line; | ||
| 983 | } | ||
| 984 | } | ||
| 985 | } | ||
| 986 | // Enable use of Spyc from command line | ||
| 987 | // The syntax is the following: php Spyc.php spyc.yaml | ||
| 988 | do { | ||
| 989 | if (PHP_SAPI != 'cli') break; | ||
| 990 | if (empty ($_SERVER['argc']) || $_SERVER['argc'] < 2) break; | ||
| 991 | if (empty ($_SERVER['PHP_SELF']) || FALSE === strpos ($_SERVER['PHP_SELF'], 'Spyc.php') ) break; | ||
| 992 | $file = $argv[1]; | ||
| 993 | echo json_encode (spyc_load_file ($file)); | ||
| 994 | } while (0); |