From fb724c0b7f08e51d20d11ba1f06c9b4b2bdab75c Mon Sep 17 00:00:00 2001 From: renz78 Date: Wed, 24 May 2023 14:01:17 +0300 Subject: [PATCH] test --- k2shop/usr/k2shop/libs/browser/Browser.php | 1732 ++++++++++++++++++++ k2shop/usr/k2shop/libs/browser/Readme.txt | 9 + .../k2shop/libs/detectDevice/DetectDeviceTest.php | 71 + k2shop/usr/k2shop/libs/detectDevice/README.md | 56 + .../libs/detectDevice/class.DetectDevice.php | 76 + k2shop/usr/k2shop/libs/nestmenu/index.html | 279 ++++ k2shop/usr/k2shop/libs/nestmenu/jquery.nestable.js | 484 ++++++ k2shop/usr/k2shop/libs/nestmenu/nestable.css | 94 ++ k2shop/usr/k2shop/libs/yaml/Spyc.php | 994 +++++++++++ 9 files changed, 3795 insertions(+) create mode 100644 k2shop/usr/k2shop/libs/browser/Browser.php create mode 100644 k2shop/usr/k2shop/libs/browser/Readme.txt create mode 100644 k2shop/usr/k2shop/libs/detectDevice/DetectDeviceTest.php create mode 100644 k2shop/usr/k2shop/libs/detectDevice/README.md create mode 100644 k2shop/usr/k2shop/libs/detectDevice/class.DetectDevice.php create mode 100644 k2shop/usr/k2shop/libs/nestmenu/index.html create mode 100644 k2shop/usr/k2shop/libs/nestmenu/jquery.nestable.js create mode 100644 k2shop/usr/k2shop/libs/nestmenu/nestable.css create mode 100644 k2shop/usr/k2shop/libs/yaml/Spyc.php diff --git a/k2shop/usr/k2shop/libs/browser/Browser.php b/k2shop/usr/k2shop/libs/browser/Browser.php new file mode 100644 index 0000000..2acf548 --- /dev/null +++ b/k2shop/usr/k2shop/libs/browser/Browser.php @@ -0,0 +1,1732 @@ +getBrowser() == Browser::BROWSER_FIREFOX && $browser->getVersion() >= 2 ) { + * echo 'You have FireFox version 2 or greater'; + * } + * + * User Agents Sampled from: http://www.useragentstring.com/ + * + * This implementation is based on the original work from Gary White + * http://apptools.com/phptools/browser/ + * + */ +class Browser +{ + private $_agent = ''; + private $_browser_name = ''; + private $_version = ''; + private $_platform = ''; + private $_os = ''; + private $_is_aol = false; + private $_is_mobile = false; + private $_is_tablet = false; + private $_is_robot = false; + private $_is_facebook = false; + private $_aol_version = ''; + + const BROWSER_UNKNOWN = 'unknown'; + const VERSION_UNKNOWN = 'unknown'; + + const BROWSER_OPERA = 'Opera'; // http://www.opera.com/ + const BROWSER_OPERA_MINI = 'Opera Mini'; // http://www.opera.com/mini/ + const BROWSER_WEBTV = 'WebTV'; // http://www.webtv.net/pc/ + const BROWSER_EDGE = 'Edge'; // https://www.microsoft.com/edge + const BROWSER_IE = 'Internet Explorer'; // http://www.microsoft.com/ie/ + const BROWSER_POCKET_IE = 'Pocket Internet Explorer'; // http://en.wikipedia.org/wiki/Internet_Explorer_Mobile + const BROWSER_KONQUEROR = 'Konqueror'; // http://www.konqueror.org/ + const BROWSER_ICAB = 'iCab'; // http://www.icab.de/ + const BROWSER_OMNIWEB = 'OmniWeb'; // http://www.omnigroup.com/applications/omniweb/ + const BROWSER_FIREBIRD = 'Firebird'; // http://www.ibphoenix.com/ + const BROWSER_FIREFOX = 'Firefox'; // http://www.mozilla.com/en-US/firefox/firefox.html + const BROWSER_ICEWEASEL = 'Iceweasel'; // http://www.geticeweasel.org/ + const BROWSER_SHIRETOKO = 'Shiretoko'; // http://wiki.mozilla.org/Projects/shiretoko + const BROWSER_MOZILLA = 'Mozilla'; // http://www.mozilla.com/en-US/ + const BROWSER_AMAYA = 'Amaya'; // http://www.w3.org/Amaya/ + const BROWSER_LYNX = 'Lynx'; // http://en.wikipedia.org/wiki/Lynx + const BROWSER_SAFARI = 'Safari'; // http://apple.com + const BROWSER_IPHONE = 'iPhone'; // http://apple.com + const BROWSER_IPOD = 'iPod'; // http://apple.com + const BROWSER_IPAD = 'iPad'; // http://apple.com + const BROWSER_CHROME = 'Chrome'; // http://www.google.com/chrome + const BROWSER_ANDROID = 'Android'; // http://www.android.com/ + const BROWSER_GOOGLEBOT = 'GoogleBot'; // http://en.wikipedia.org/wiki/Googlebot + + const BROWSER_YANDEXBOT = 'YandexBot'; // http://yandex.com/bots + const BROWSER_YANDEXIMAGERESIZER_BOT = 'YandexImageResizer'; // http://yandex.com/bots + const BROWSER_YANDEXIMAGES_BOT = 'YandexImages'; // http://yandex.com/bots + const BROWSER_YANDEXVIDEO_BOT = 'YandexVideo'; // http://yandex.com/bots + const BROWSER_YANDEXMEDIA_BOT = 'YandexMedia'; // http://yandex.com/bots + const BROWSER_YANDEXBLOGS_BOT = 'YandexBlogs'; // http://yandex.com/bots + const BROWSER_YANDEXFAVICONS_BOT = 'YandexFavicons'; // http://yandex.com/bots + const BROWSER_YANDEXWEBMASTER_BOT = 'YandexWebmaster'; // http://yandex.com/bots + const BROWSER_YANDEXDIRECT_BOT = 'YandexDirect'; // http://yandex.com/bots + const BROWSER_YANDEXMETRIKA_BOT = 'YandexMetrika'; // http://yandex.com/bots + const BROWSER_YANDEXNEWS_BOT = 'YandexNews'; // http://yandex.com/bots + const BROWSER_YANDEXCATALOG_BOT = 'YandexCatalog'; // http://yandex.com/bots + + const BROWSER_SLURP = 'Yahoo! Slurp'; // http://en.wikipedia.org/wiki/Yahoo!_Slurp + const BROWSER_W3CVALIDATOR = 'W3C Validator'; // http://validator.w3.org/ + const BROWSER_BLACKBERRY = 'BlackBerry'; // http://www.blackberry.com/ + const BROWSER_ICECAT = 'IceCat'; // http://en.wikipedia.org/wiki/GNU_IceCat + const BROWSER_NOKIA_S60 = 'Nokia S60 OSS Browser'; // http://en.wikipedia.org/wiki/Web_Browser_for_S60 + const BROWSER_NOKIA = 'Nokia Browser'; // * all other WAP-based browsers on the Nokia Platform + const BROWSER_MSN = 'MSN Browser'; // http://explorer.msn.com/ + const BROWSER_MSNBOT = 'MSN Bot'; // http://search.msn.com/msnbot.htm + const BROWSER_BINGBOT = 'Bing Bot'; // http://en.wikipedia.org/wiki/Bingbot + const BROWSER_VIVALDI = 'Vivalidi'; // https://vivaldi.com/ + const BROWSER_YANDEX = 'Yandex'; // https://browser.yandex.ua/ + + const BROWSER_NETSCAPE_NAVIGATOR = 'Netscape Navigator'; // http://browser.netscape.com/ (DEPRECATED) + const BROWSER_GALEON = 'Galeon'; // http://galeon.sourceforge.net/ (DEPRECATED) + const BROWSER_NETPOSITIVE = 'NetPositive'; // http://en.wikipedia.org/wiki/NetPositive (DEPRECATED) + const BROWSER_PHOENIX = 'Phoenix'; // http://en.wikipedia.org/wiki/History_of_Mozilla_Firefox (DEPRECATED) + const BROWSER_PLAYSTATION = "PlayStation"; + const BROWSER_SAMSUNG = "SamsungBrowser"; + const BROWSER_SILK = "Silk"; + const BROWSER_I_FRAME = "Iframely"; + const BROWSER_COCOA = "CocoaRestClient"; + + const PLATFORM_UNKNOWN = 'unknown'; + const PLATFORM_WINDOWS = 'Windows'; + const PLATFORM_WINDOWS_CE = 'Windows CE'; + const PLATFORM_APPLE = 'Apple'; + const PLATFORM_LINUX = 'Linux'; + const PLATFORM_OS2 = 'OS/2'; + const PLATFORM_BEOS = 'BeOS'; + const PLATFORM_IPHONE = 'iPhone'; + const PLATFORM_IPOD = 'iPod'; + const PLATFORM_IPAD = 'iPad'; + const PLATFORM_BLACKBERRY = 'BlackBerry'; + const PLATFORM_NOKIA = 'Nokia'; + const PLATFORM_FREEBSD = 'FreeBSD'; + const PLATFORM_OPENBSD = 'OpenBSD'; + const PLATFORM_NETBSD = 'NetBSD'; + const PLATFORM_SUNOS = 'SunOS'; + const PLATFORM_OPENSOLARIS = 'OpenSolaris'; + const PLATFORM_ANDROID = 'Android'; + const PLATFORM_PLAYSTATION = "Sony PlayStation"; + const PLATFORM_ROKU = "Roku"; + const PLATFORM_APPLE_TV = "Apple TV"; + const PLATFORM_TERMINAL = "Terminal"; + const PLATFORM_FIRE_OS = "Fire OS"; + const PLATFORM_SMART_TV = "SMART-TV"; + const PLATFORM_CHROME_OS = "Chrome OS"; + const PLATFORM_JAVA_ANDROID = "Java/Android"; + const PLATFORM_POSTMAN = "Postman"; + const PLATFORM_I_FRAME = "Iframely"; + + const OPERATING_SYSTEM_UNKNOWN = 'unknown'; + + /** + * Class constructor + */ + public function __construct($userAgent = "") + { + $this->reset(); + if ($userAgent != "") { + $this->setUserAgent($userAgent); + } else { + $this->determine(); + } + } + + /** + * Reset all properties + */ + public function reset() + { + $this->_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ""; + $this->_browser_name = self::BROWSER_UNKNOWN; + $this->_version = self::VERSION_UNKNOWN; + $this->_platform = self::PLATFORM_UNKNOWN; + $this->_os = self::OPERATING_SYSTEM_UNKNOWN; + $this->_is_aol = false; + $this->_is_mobile = false; + $this->_is_tablet = false; + $this->_is_robot = false; + $this->_is_facebook = false; + $this->_aol_version = self::VERSION_UNKNOWN; + } + + /** + * Check to see if the specific browser is valid + * @param string $browserName + * @return bool True if the browser is the specified browser + */ + function isBrowser($browserName) + { + return (0 == strcasecmp($this->_browser_name, trim($browserName))); + } + + /** + * The name of the browser. All return types are from the class contants + * @return string Name of the browser + */ + public function getBrowser() + { + return $this->_browser_name; + } + + /** + * Set the name of the browser + * @param $browser string The name of the Browser + */ + public function setBrowser($browser) + { + $this->_browser_name = $browser; + } + + /** + * The name of the platform. All return types are from the class contants + * @return string Name of the browser + */ + public function getPlatform() + { + return $this->_platform; + } + + /** + * Set the name of the platform + * @param string $platform The name of the Platform + */ + public function setPlatform($platform) + { + $this->_platform = $platform; + } + + /** + * The version of the browser. + * @return string Version of the browser (will only contain alpha-numeric characters and a period) + */ + public function getVersion() + { + return $this->_version; + } + + /** + * Set the version of the browser + * @param string $version The version of the Browser + */ + public function setVersion($version) + { + $this->_version = preg_replace('/[^0-9,.,a-z,A-Z-]/', '', $version); + } + + /** + * The version of AOL. + * @return string Version of AOL (will only contain alpha-numeric characters and a period) + */ + public function getAolVersion() + { + return $this->_aol_version; + } + + /** + * Set the version of AOL + * @param string $version The version of AOL + */ + public function setAolVersion($version) + { + $this->_aol_version = preg_replace('/[^0-9,.,a-z,A-Z]/', '', $version); + } + + /** + * Is the browser from AOL? + * @return boolean True if the browser is from AOL otherwise false + */ + public function isAol() + { + return $this->_is_aol; + } + + /** + * Is the browser from a mobile device? + * @return boolean True if the browser is from a mobile device otherwise false + */ + public function isMobile() + { + return $this->_is_mobile; + } + + /** + * Is the browser from a tablet device? + * @return boolean True if the browser is from a tablet device otherwise false + */ + public function isTablet() + { + return $this->_is_tablet; + } + + /** + * Is the browser from a robot (ex Slurp,GoogleBot)? + * @return boolean True if the browser is from a robot otherwise false + */ + public function isRobot() + { + return $this->_is_robot; + } + + /** + * Is the browser from facebook? + * @return boolean True if the browser is from facebook otherwise false + */ + public function isFacebook() + { + return $this->_is_facebook; + } + + /** + * Set the browser to be from AOL + * @param $isAol + */ + public function setAol($isAol) + { + $this->_is_aol = $isAol; + } + + /** + * Set the Browser to be mobile + * @param boolean $value is the browser a mobile browser or not + */ + protected function setMobile($value = true) + { + $this->_is_mobile = $value; + } + + /** + * Set the Browser to be tablet + * @param boolean $value is the browser a tablet browser or not + */ + protected function setTablet($value = true) + { + $this->_is_tablet = $value; + } + + /** + * Set the Browser to be a robot + * @param boolean $value is the browser a robot or not + */ + protected function setRobot($value = true) + { + $this->_is_robot = $value; + } + + /** + * Set the Browser to be a Facebook request + * @param boolean $value is the browser a robot or not + */ + protected function setFacebook($value = true) + { + $this->_is_facebook = $value; + } + + /** + * Get the user agent value in use to determine the browser + * @return string The user agent from the HTTP header + */ + public function getUserAgent() + { + return $this->_agent; + } + + /** + * Set the user agent value (the construction will use the HTTP header value - this will overwrite it) + * @param string $agent_string The value for the User Agent + */ + public function setUserAgent($agent_string) + { + $this->reset(); + $this->_agent = $agent_string; + $this->determine(); + } + + /** + * Used to determine if the browser is actually "chromeframe" + * @since 1.7 + * @return boolean True if the browser is using chromeframe + */ + public function isChromeFrame() + { + return (strpos($this->_agent, "chromeframe") !== false); + } + + /** + * Returns a formatted string with a summary of the details of the browser. + * @return string formatted string with a summary of the browser + */ + public function __toString() + { + return "Browser Name: {$this->getBrowser()}
\n" . + "Browser Version: {$this->getVersion()}
\n" . + "Browser User Agent String: {$this->getUserAgent()}
\n" . + "Platform: {$this->getPlatform()}
"; + } + + /** + * Protected routine to calculate and determine what the browser is in use (including platform) + */ + protected function determine() + { + $this->checkPlatform(); + $this->checkBrowsers(); + $this->checkForAol(); + } + + /** + * Protected routine to determine the browser type + * @return boolean True if the browser was detected otherwise false + */ + protected function checkBrowsers() + { + return ( + // well-known, well-used + // Special Notes: + // (1) Opera must be checked before FireFox due to the odd + // user agents used in some older versions of Opera + // (2) WebTV is strapped onto Internet Explorer so we must + // check for WebTV before IE + // (3) (deprecated) Galeon is based on Firefox and needs to be + // tested before Firefox is tested + // (4) OmniWeb is based on Safari so OmniWeb check must occur + // before Safari + // (5) Netscape 9+ is based on Firefox so Netscape checks + // before FireFox are necessary + // (6) Vivalid is UA contains both Firefox and Chrome so Vivalid checks + // before Firefox and Chrome + $this->checkBrowserWebTv() || + $this->checkBrowserEdge() || + $this->checkBrowserInternetExplorer() || + $this->checkBrowserOpera() || + $this->checkBrowserGaleon() || + $this->checkBrowserNetscapeNavigator9Plus() || + $this->checkBrowserVivaldi() || + $this->checkBrowserYandex() || + $this->checkBrowserFirefox() || + $this->checkBrowserChrome() || + $this->checkBrowserOmniWeb() || + + // common mobile + $this->checkBrowserAndroid() || + $this->checkBrowseriPad() || + $this->checkBrowseriPod() || + $this->checkBrowseriPhone() || + $this->checkBrowserBlackBerry() || + $this->checkBrowserNokia() || + + // common bots + $this->checkBrowserGoogleBot() || + $this->checkBrowserMSNBot() || + $this->checkBrowserBingBot() || + $this->checkBrowserSlurp() || + + // Yandex bots + $this->checkBrowserYandexBot() || + $this->checkBrowserYandexImageResizerBot() || + $this->checkBrowserYandexBlogsBot() || + $this->checkBrowserYandexCatalogBot() || + $this->checkBrowserYandexDirectBot() || + $this->checkBrowserYandexFaviconsBot() || + $this->checkBrowserYandexImagesBot() || + $this->checkBrowserYandexMediaBot() || + $this->checkBrowserYandexMetrikaBot() || + $this->checkBrowserYandexNewsBot() || + $this->checkBrowserYandexVideoBot() || + $this->checkBrowserYandexWebmasterBot() || + + // check for facebook external hit when loading URL + $this->checkFacebookExternalHit() || + + // WebKit base check (post mobile and others) + $this->checkBrowserSamsung() || + $this->checkBrowserSilk() || + $this->checkBrowserSafari() || + + // everyone else + $this->checkBrowserNetPositive() || + $this->checkBrowserFirebird() || + $this->checkBrowserKonqueror() || + $this->checkBrowserIcab() || + $this->checkBrowserPhoenix() || + $this->checkBrowserAmaya() || + $this->checkBrowserLynx() || + $this->checkBrowserShiretoko() || + $this->checkBrowserIceCat() || + $this->checkBrowserIceweasel() || + $this->checkBrowserW3CValidator() || + $this->checkBrowserPlayStation() || + $this->checkBrowserIframely() || + $this->checkBrowserCocoa() || + $this->checkBrowserMozilla() /* Mozilla is such an open standard that you must check it last */ + + + ); + } + + /** + * Determine if the user is using a BlackBerry (last updated 1.7) + * @return boolean True if the browser is the BlackBerry browser otherwise false + */ + protected function checkBrowserBlackBerry() + { + if (stripos($this->_agent, 'blackberry') !== false) { + $aresult = explode("/", stristr($this->_agent, "BlackBerry")); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->_browser_name = self::BROWSER_BLACKBERRY; + $this->setMobile(true); + return true; + } + } + return false; + } + + /** + * Determine if the user is using an AOL User Agent (last updated 1.7) + * @return boolean True if the browser is from AOL otherwise false + */ + protected function checkForAol() + { + $this->setAol(false); + $this->setAolVersion(self::VERSION_UNKNOWN); + + if (stripos($this->_agent, 'aol') !== false) { + $aversion = explode(' ', stristr($this->_agent, 'AOL')); + if (isset($aversion[1])) { + $this->setAol(true); + $this->setAolVersion(preg_replace('/[^0-9\.a-z]/i', '', $aversion[1])); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the GoogleBot or not (last updated 1.7) + * @return boolean True if the browser is the GoogletBot otherwise false + */ + protected function checkBrowserGoogleBot() + { + if (stripos($this->_agent, 'googlebot') !== false) { + $aresult = explode('/', stristr($this->_agent, 'googlebot')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion(str_replace(';', '', $aversion[0])); + $this->_browser_name = self::BROWSER_GOOGLEBOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the YandexBot or not + * @return boolean True if the browser is the YandexBot otherwise false + */ + protected function checkBrowserYandexBot() + { + if (stripos($this->_agent, 'YandexBot') !== false) { + $aresult = explode('/', stristr($this->_agent, 'YandexBot')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion(str_replace(';', '', $aversion[0])); + $this->_browser_name = self::BROWSER_YANDEXBOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the YandexImageResizer or not + * @return boolean True if the browser is the YandexImageResizer otherwise false + */ + protected function checkBrowserYandexImageResizerBot() + { + if (stripos($this->_agent, 'YandexImageResizer') !== false) { + $aresult = explode('/', stristr($this->_agent, 'YandexImageResizer')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion(str_replace(';', '', $aversion[0])); + $this->_browser_name = self::BROWSER_YANDEXIMAGERESIZER_BOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the YandexCatalog or not + * @return boolean True if the browser is the YandexCatalog otherwise false + */ + protected function checkBrowserYandexCatalogBot() + { + if (stripos($this->_agent, 'YandexCatalog') !== false) { + $aresult = explode('/', stristr($this->_agent, 'YandexCatalog')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion(str_replace(';', '', $aversion[0])); + $this->_browser_name = self::BROWSER_YANDEXCATALOG_BOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the YandexNews or not + * @return boolean True if the browser is the YandexNews otherwise false + */ + protected function checkBrowserYandexNewsBot() + { + if (stripos($this->_agent, 'YandexNews') !== false) { + $aresult = explode('/', stristr($this->_agent, 'YandexNews')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion(str_replace(';', '', $aversion[0])); + $this->_browser_name = self::BROWSER_YANDEXNEWS_BOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the YandexMetrika or not + * @return boolean True if the browser is the YandexMetrika otherwise false + */ + protected function checkBrowserYandexMetrikaBot() + { + if (stripos($this->_agent, 'YandexMetrika') !== false) { + $aresult = explode('/', stristr($this->_agent, 'YandexMetrika')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion(str_replace(';', '', $aversion[0])); + $this->_browser_name = self::BROWSER_YANDEXMETRIKA_BOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the YandexDirect or not + * @return boolean True if the browser is the YandexDirect otherwise false + */ + protected function checkBrowserYandexDirectBot() + { + if (stripos($this->_agent, 'YandexDirect') !== false) { + $aresult = explode('/', stristr($this->_agent, 'YandexDirect')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion(str_replace(';', '', $aversion[0])); + $this->_browser_name = self::BROWSER_YANDEXDIRECT_BOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the YandexWebmaster or not + * @return boolean True if the browser is the YandexWebmaster otherwise false + */ + protected function checkBrowserYandexWebmasterBot() + { + if (stripos($this->_agent, 'YandexWebmaster') !== false) { + $aresult = explode('/', stristr($this->_agent, 'YandexWebmaster')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion(str_replace(';', '', $aversion[0])); + $this->_browser_name = self::BROWSER_YANDEXWEBMASTER_BOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the YandexFavicons or not + * @return boolean True if the browser is the YandexFavicons otherwise false + */ + protected function checkBrowserYandexFaviconsBot() + { + if (stripos($this->_agent, 'YandexFavicons') !== false) { + $aresult = explode('/', stristr($this->_agent, 'YandexFavicons')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion(str_replace(';', '', $aversion[0])); + $this->_browser_name = self::BROWSER_YANDEXFAVICONS_BOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the YandexBlogs or not + * @return boolean True if the browser is the YandexBlogs otherwise false + */ + protected function checkBrowserYandexBlogsBot() + { + if (stripos($this->_agent, 'YandexBlogs') !== false) { + $aresult = explode('/', stristr($this->_agent, 'YandexBlogs')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion(str_replace(';', '', $aversion[0])); + $this->_browser_name = self::BROWSER_YANDEXBLOGS_BOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the YandexMedia or not + * @return boolean True if the browser is the YandexMedia otherwise false + */ + protected function checkBrowserYandexMediaBot() + { + if (stripos($this->_agent, 'YandexMedia') !== false) { + $aresult = explode('/', stristr($this->_agent, 'YandexMedia')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion(str_replace(';', '', $aversion[0])); + $this->_browser_name = self::BROWSER_YANDEXMEDIA_BOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the YandexVideo or not + * @return boolean True if the browser is the YandexVideo otherwise false + */ + protected function checkBrowserYandexVideoBot() + { + if (stripos($this->_agent, 'YandexVideo') !== false) { + $aresult = explode('/', stristr($this->_agent, 'YandexVideo')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion(str_replace(';', '', $aversion[0])); + $this->_browser_name = self::BROWSER_YANDEXVIDEO_BOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the YandexImages or not + * @return boolean True if the browser is the YandexImages otherwise false + */ + protected function checkBrowserYandexImagesBot() + { + if (stripos($this->_agent, 'YandexImages') !== false) { + $aresult = explode('/', stristr($this->_agent, 'YandexImages')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion(str_replace(';', '', $aversion[0])); + $this->_browser_name = self::BROWSER_YANDEXIMAGES_BOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the MSNBot or not (last updated 1.9) + * @return boolean True if the browser is the MSNBot otherwise false + */ + protected function checkBrowserMSNBot() + { + if (stripos($this->_agent, "msnbot") !== false) { + $aresult = explode("/", stristr($this->_agent, "msnbot")); + if (isset($aresult[1])) { + $aversion = explode(" ", $aresult[1]); + $this->setVersion(str_replace(";", "", $aversion[0])); + $this->_browser_name = self::BROWSER_MSNBOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the BingBot or not (last updated 1.9) + * @return boolean True if the browser is the BingBot otherwise false + */ + protected function checkBrowserBingBot() + { + if (stripos($this->_agent, "bingbot") !== false) { + $aresult = explode("/", stristr($this->_agent, "bingbot")); + if (isset($aresult[1])) { + $aversion = explode(" ", $aresult[1]); + $this->setVersion(str_replace(";", "", $aversion[0])); + $this->_browser_name = self::BROWSER_BINGBOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the W3C Validator or not (last updated 1.7) + * @return boolean True if the browser is the W3C Validator otherwise false + */ + protected function checkBrowserW3CValidator() + { + if (stripos($this->_agent, 'W3C-checklink') !== false) { + $aresult = explode('/', stristr($this->_agent, 'W3C-checklink')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->_browser_name = self::BROWSER_W3CVALIDATOR; + return true; + } + } else if (stripos($this->_agent, 'W3C_Validator') !== false) { + // Some of the Validator versions do not delineate w/ a slash - add it back in + $ua = str_replace("W3C_Validator ", "W3C_Validator/", $this->_agent); + $aresult = explode('/', stristr($ua, 'W3C_Validator')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->_browser_name = self::BROWSER_W3CVALIDATOR; + return true; + } + } else if (stripos($this->_agent, 'W3C-mobileOK') !== false) { + $this->_browser_name = self::BROWSER_W3CVALIDATOR; + $this->setMobile(true); + return true; + } + return false; + } + + /** + * Determine if the browser is the Yahoo! Slurp Robot or not (last updated 1.7) + * @return boolean True if the browser is the Yahoo! Slurp Robot otherwise false + */ + protected function checkBrowserSlurp() + { + if (stripos($this->_agent, 'slurp') !== false) { + $aresult = explode('/', stristr($this->_agent, 'Slurp')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->_browser_name = self::BROWSER_SLURP; + $this->setRobot(true); + $this->setMobile(false); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Edge or not + * @return boolean True if the browser is Edge otherwise false + */ + protected function checkBrowserEdge() + { + if (stripos($this->_agent, 'Edge/') !== false) { + $aresult = explode('/', stristr($this->_agent, 'Edge')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_EDGE); + if (stripos($this->_agent, 'Windows Phone') !== false || stripos($this->_agent, 'Android') !== false) { + $this->setMobile(true); + } + return true; + } + } + return false; + } + + /** + * Determine if the browser is Internet Explorer or not (last updated 1.7) + * @return boolean True if the browser is Internet Explorer otherwise false + */ + protected function checkBrowserInternetExplorer() + { + // Test for IE11 + if (stripos($this->_agent, 'Trident/7.0; rv:11.0') !== false) { + $this->setBrowser(self::BROWSER_IE); + $this->setVersion('11.0'); + return true; + } // Test for v1 - v1.5 IE + else if (stripos($this->_agent, 'microsoft internet explorer') !== false) { + $this->setBrowser(self::BROWSER_IE); + $this->setVersion('1.0'); + $aresult = stristr($this->_agent, '/'); + if (preg_match('/308|425|426|474|0b1/i', $aresult)) { + $this->setVersion('1.5'); + } + return true; + } // Test for versions > 1.5 + else if (stripos($this->_agent, 'msie') !== false && stripos($this->_agent, 'opera') === false) { + // See if the browser is the odd MSN Explorer + if (stripos($this->_agent, 'msnb') !== false) { + $aresult = explode(' ', stristr(str_replace(';', '; ', $this->_agent), 'MSN')); + if (isset($aresult[1])) { + $this->setBrowser(self::BROWSER_MSN); + $this->setVersion(str_replace(array('(', ')', ';'), '', $aresult[1])); + return true; + } + } + $aresult = explode(' ', stristr(str_replace(';', '; ', $this->_agent), 'msie')); + if (isset($aresult[1])) { + $this->setBrowser(self::BROWSER_IE); + $this->setVersion(str_replace(array('(', ')', ';'), '', $aresult[1])); + if(preg_match('#trident/([0-9\.]+);#i', $this->_agent, $aresult)){ + if($aresult[1] == '3.1'){ + $this->setVersion('7.0'); + } + else if($aresult[1] == '4.0'){ + $this->setVersion('8.0'); + } + else if($aresult[1] == '5.0'){ + $this->setVersion('9.0'); + } + else if($aresult[1] == '6.0'){ + $this->setVersion('10.0'); + } + else if($aresult[1] == '7.0'){ + $this->setVersion('11.0'); + } + else if($aresult[1] == '8.0'){ + $this->setVersion('11.0'); + } + } + if(stripos($this->_agent, 'IEMobile') !== false) { + $this->setBrowser(self::BROWSER_POCKET_IE); + $this->setMobile(true); + } + return true; + } + } // Test for versions > IE 10 + else if (stripos($this->_agent, 'trident') !== false) { + $this->setBrowser(self::BROWSER_IE); + $result = explode('rv:', $this->_agent); + if (isset($result[1])) { + $this->setVersion(preg_replace('/[^0-9.]+/', '', $result[1])); + $this->_agent = str_replace(array("Mozilla", "Gecko"), "MSIE", $this->_agent); + } + } // Test for Pocket IE + else if (stripos($this->_agent, 'mspie') !== false || stripos($this->_agent, 'pocket') !== false) { + $aresult = explode(' ', stristr($this->_agent, 'mspie')); + if (isset($aresult[1])) { + $this->setPlatform(self::PLATFORM_WINDOWS_CE); + $this->setBrowser(self::BROWSER_POCKET_IE); + $this->setMobile(true); + + if (stripos($this->_agent, 'mspie') !== false) { + $this->setVersion($aresult[1]); + } else { + $aversion = explode('/', $this->_agent); + if (isset($aversion[1])) { + $this->setVersion($aversion[1]); + } + } + return true; + } + } + return false; + } + + /** + * Determine if the browser is Opera or not (last updated 1.7) + * @return boolean True if the browser is Opera otherwise false + */ + protected function checkBrowserOpera() + { + if (stripos($this->_agent, 'opera mini') !== false) { + $resultant = stristr($this->_agent, 'opera mini'); + if (preg_match('/\//', $resultant)) { + $aresult = explode('/', $resultant); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + } + } else { + $aversion = explode(' ', stristr($resultant, 'opera mini')); + if (isset($aversion[1])) { + $this->setVersion($aversion[1]); + } + } + $this->_browser_name = self::BROWSER_OPERA_MINI; + $this->setMobile(true); + return true; + } else if (stripos($this->_agent, 'opera') !== false) { + $resultant = stristr($this->_agent, 'opera'); + if (preg_match('/Version\/(1*.*)$/', $resultant, $matches)) { + $this->setVersion($matches[1]); + } else if (preg_match('/\//', $resultant)) { + $aresult = explode('/', str_replace("(", " ", $resultant)); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + } + } else { + $aversion = explode(' ', stristr($resultant, 'opera')); + $this->setVersion(isset($aversion[1]) ? $aversion[1] : ""); + } + if (stripos($this->_agent, 'Opera Mobi') !== false) { + $this->setMobile(true); + } + $this->_browser_name = self::BROWSER_OPERA; + return true; + } else if (stripos($this->_agent, 'OPR') !== false) { + $resultant = stristr($this->_agent, 'OPR'); + if (preg_match('/\//', $resultant)) { + $aresult = explode('/', str_replace("(", " ", $resultant)); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + } + } + if (stripos($this->_agent, 'Mobile') !== false) { + $this->setMobile(true); + } + $this->_browser_name = self::BROWSER_OPERA; + return true; + } + return false; + } + + /** + * Determine if the browser is Chrome or not (last updated 1.7) + * @return boolean True if the browser is Chrome otherwise false + */ + protected function checkBrowserChrome() + { + if (stripos($this->_agent, 'Chrome') !== false) { + $aresult = explode('/', stristr($this->_agent, 'Chrome')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_CHROME); + //Chrome on Android + if (stripos($this->_agent, 'Android') !== false) { + if (stripos($this->_agent, 'Mobile') !== false) { + $this->setMobile(true); + } else { + $this->setTablet(true); + } + } + return true; + } + } + return false; + } + + + /** + * Determine if the browser is WebTv or not (last updated 1.7) + * @return boolean True if the browser is WebTv otherwise false + */ + protected function checkBrowserWebTv() + { + if (stripos($this->_agent, 'webtv') !== false) { + $aresult = explode('/', stristr($this->_agent, 'webtv')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_WEBTV); + return true; + } + } + return false; + } + + /** + * Determine if the browser is NetPositive or not (last updated 1.7) + * @return boolean True if the browser is NetPositive otherwise false + */ + protected function checkBrowserNetPositive() + { + if (stripos($this->_agent, 'NetPositive') !== false) { + $aresult = explode('/', stristr($this->_agent, 'NetPositive')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion(str_replace(array('(', ')', ';'), '', $aversion[0])); + $this->setBrowser(self::BROWSER_NETPOSITIVE); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Galeon or not (last updated 1.7) + * @return boolean True if the browser is Galeon otherwise false + */ + protected function checkBrowserGaleon() + { + if (stripos($this->_agent, 'galeon') !== false) { + $aresult = explode(' ', stristr($this->_agent, 'galeon')); + $aversion = explode('/', $aresult[0]); + if (isset($aversion[1])) { + $this->setVersion($aversion[1]); + $this->setBrowser(self::BROWSER_GALEON); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Konqueror or not (last updated 1.7) + * @return boolean True if the browser is Konqueror otherwise false + */ + protected function checkBrowserKonqueror() + { + if (stripos($this->_agent, 'Konqueror') !== false) { + $aresult = explode(' ', stristr($this->_agent, 'Konqueror')); + $aversion = explode('/', $aresult[0]); + if (isset($aversion[1])) { + $this->setVersion($aversion[1]); + $this->setBrowser(self::BROWSER_KONQUEROR); + return true; + } + } + return false; + } + + /** + * Determine if the browser is iCab or not (last updated 1.7) + * @return boolean True if the browser is iCab otherwise false + */ + protected function checkBrowserIcab() + { + if (stripos($this->_agent, 'icab') !== false) { + $aversion = explode(' ', stristr(str_replace('/', ' ', $this->_agent), 'icab')); + if (isset($aversion[1])) { + $this->setVersion($aversion[1]); + $this->setBrowser(self::BROWSER_ICAB); + return true; + } + } + return false; + } + + /** + * Determine if the browser is OmniWeb or not (last updated 1.7) + * @return boolean True if the browser is OmniWeb otherwise false + */ + protected function checkBrowserOmniWeb() + { + if (stripos($this->_agent, 'omniweb') !== false) { + $aresult = explode('/', stristr($this->_agent, 'omniweb')); + $aversion = explode(' ', isset($aresult[1]) ? $aresult[1] : ""); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_OMNIWEB); + return true; + } + return false; + } + + /** + * Determine if the browser is Phoenix or not (last updated 1.7) + * @return boolean True if the browser is Phoenix otherwise false + */ + protected function checkBrowserPhoenix() + { + if (stripos($this->_agent, 'Phoenix') !== false) { + $aversion = explode('/', stristr($this->_agent, 'Phoenix')); + if (isset($aversion[1])) { + $this->setVersion($aversion[1]); + $this->setBrowser(self::BROWSER_PHOENIX); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Firebird or not (last updated 1.7) + * @return boolean True if the browser is Firebird otherwise false + */ + protected function checkBrowserFirebird() + { + if (stripos($this->_agent, 'Firebird') !== false) { + $aversion = explode('/', stristr($this->_agent, 'Firebird')); + if (isset($aversion[1])) { + $this->setVersion($aversion[1]); + $this->setBrowser(self::BROWSER_FIREBIRD); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Netscape Navigator 9+ or not (last updated 1.7) + * NOTE: (http://browser.netscape.com/ - Official support ended on March 1st, 2008) + * @return boolean True if the browser is Netscape Navigator 9+ otherwise false + */ + protected function checkBrowserNetscapeNavigator9Plus() + { + if (stripos($this->_agent, 'Firefox') !== false && preg_match('/Navigator\/([^ ]*)/i', $this->_agent, $matches)) { + $this->setVersion($matches[1]); + $this->setBrowser(self::BROWSER_NETSCAPE_NAVIGATOR); + return true; + } else if (stripos($this->_agent, 'Firefox') === false && preg_match('/Netscape6?\/([^ ]*)/i', $this->_agent, $matches)) { + $this->setVersion($matches[1]); + $this->setBrowser(self::BROWSER_NETSCAPE_NAVIGATOR); + return true; + } + return false; + } + + /** + * Determine if the browser is Shiretoko or not (https://wiki.mozilla.org/Projects/shiretoko) (last updated 1.7) + * @return boolean True if the browser is Shiretoko otherwise false + */ + protected function checkBrowserShiretoko() + { + if (stripos($this->_agent, 'Mozilla') !== false && preg_match('/Shiretoko\/([^ ]*)/i', $this->_agent, $matches)) { + $this->setVersion($matches[1]); + $this->setBrowser(self::BROWSER_SHIRETOKO); + return true; + } + return false; + } + + /** + * Determine if the browser is Ice Cat or not (http://en.wikipedia.org/wiki/GNU_IceCat) (last updated 1.7) + * @return boolean True if the browser is Ice Cat otherwise false + */ + protected function checkBrowserIceCat() + { + if (stripos($this->_agent, 'Mozilla') !== false && preg_match('/IceCat\/([^ ]*)/i', $this->_agent, $matches)) { + $this->setVersion($matches[1]); + $this->setBrowser(self::BROWSER_ICECAT); + return true; + } + return false; + } + + /** + * Determine if the browser is Nokia or not (last updated 1.7) + * @return boolean True if the browser is Nokia otherwise false + */ + protected function checkBrowserNokia() + { + if (preg_match("/Nokia([^\/]+)\/([^ SP]+)/i", $this->_agent, $matches)) { + $this->setVersion($matches[2]); + if (stripos($this->_agent, 'Series60') !== false || strpos($this->_agent, 'S60') !== false) { + $this->setBrowser(self::BROWSER_NOKIA_S60); + } else { + $this->setBrowser(self::BROWSER_NOKIA); + } + $this->setMobile(true); + return true; + } + return false; + } + + /** + * Determine if the browser is Firefox or not (last updated 1.7) + * @return boolean True if the browser is Firefox otherwise false + */ + protected function checkBrowserFirefox() + { + if (stripos($this->_agent, 'safari') === false) { + if (preg_match("/Firefox[\/ \(]([^ ;\)]+)/i", $this->_agent, $matches)) { + $this->setVersion($matches[1]); + $this->setBrowser(self::BROWSER_FIREFOX); + //Firefox on Android + if (stripos($this->_agent, 'Android') !== false) { + if (stripos($this->_agent, 'Mobile') !== false) { + $this->setMobile(true); + } else { + $this->setTablet(true); + } + } + return true; + } else if (preg_match("/Firefox$/i", $this->_agent, $matches)) { + $this->setVersion(""); + $this->setBrowser(self::BROWSER_FIREFOX); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Firefox or not (last updated 1.7) + * @return boolean True if the browser is Firefox otherwise false + */ + protected function checkBrowserIceweasel() + { + if (stripos($this->_agent, 'Iceweasel') !== false) { + $aresult = explode('/', stristr($this->_agent, 'Iceweasel')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_ICEWEASEL); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Mozilla or not (last updated 1.7) + * @return boolean True if the browser is Mozilla otherwise false + */ + protected function checkBrowserMozilla() + { + if (stripos($this->_agent, 'mozilla') !== false && preg_match('/rv:[0-9].[0-9][a-b]?/i', $this->_agent) && stripos($this->_agent, 'netscape') === false) { + $aversion = explode(' ', stristr($this->_agent, 'rv:')); + preg_match('/rv:[0-9].[0-9][a-b]?/i', $this->_agent, $aversion); + $this->setVersion(str_replace('rv:', '', $aversion[0])); + $this->setBrowser(self::BROWSER_MOZILLA); + return true; + } else if (stripos($this->_agent, 'mozilla') !== false && preg_match('/rv:[0-9]\.[0-9]/i', $this->_agent) && stripos($this->_agent, 'netscape') === false) { + $aversion = explode('', stristr($this->_agent, 'rv:')); + $this->setVersion(str_replace('rv:', '', $aversion[0])); + $this->setBrowser(self::BROWSER_MOZILLA); + return true; + } else if (stripos($this->_agent, 'mozilla') !== false && preg_match('/mozilla\/([^ ]*)/i', $this->_agent, $matches) && stripos($this->_agent, 'netscape') === false) { + $this->setVersion($matches[1]); + $this->setBrowser(self::BROWSER_MOZILLA); + return true; + } + return false; + } + + /** + * Determine if the browser is Lynx or not (last updated 1.7) + * @return boolean True if the browser is Lynx otherwise false + */ + protected function checkBrowserLynx() + { + if (stripos($this->_agent, 'lynx') !== false) { + $aresult = explode('/', stristr($this->_agent, 'Lynx')); + $aversion = explode(' ', (isset($aresult[1]) ? $aresult[1] : "")); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_LYNX); + return true; + } + return false; + } + + /** + * Determine if the browser is Amaya or not (last updated 1.7) + * @return boolean True if the browser is Amaya otherwise false + */ + protected function checkBrowserAmaya() + { + if (stripos($this->_agent, 'amaya') !== false) { + $aresult = explode('/', stristr($this->_agent, 'Amaya')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_AMAYA); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Safari or not (last updated 1.7) + * @return boolean True if the browser is Safari otherwise false + */ + protected function checkBrowserSafari() + { + if (stripos($this->_agent, 'Safari') !== false + && stripos($this->_agent, 'iPhone') === false + && stripos($this->_agent, 'iPod') === false + ) { + + $aresult = explode('/', stristr($this->_agent, 'Version')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + } else { + $this->setVersion(self::VERSION_UNKNOWN); + } + $this->setBrowser(self::BROWSER_SAFARI); + return true; + } + return false; + } + + protected function checkBrowserSamsung() + { + if (stripos($this->_agent, 'SamsungBrowser') !== false) { + + $aresult = explode('/', stristr($this->_agent, 'SamsungBrowser')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + } else { + $this->setVersion(self::VERSION_UNKNOWN); + } + $this->setBrowser(self::BROWSER_SAMSUNG); + return true; + } + return false; + } + + protected function checkBrowserSilk() + { + if (stripos($this->_agent, 'Silk') !== false) { + $aresult = explode('/', stristr($this->_agent, 'Silk')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + } else { + $this->setVersion(self::VERSION_UNKNOWN); + } + $this->setBrowser(self::BROWSER_SILK); + return true; + } + return false; + } + + protected function checkBrowserIframely() + { + if (stripos($this->_agent, 'Iframely') !== false) { + $aresult = explode('/', stristr($this->_agent, 'Iframely')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + } else { + $this->setVersion(self::VERSION_UNKNOWN); + } + $this->setBrowser(self::BROWSER_I_FRAME); + return true; + } + return false; + } + + protected function checkBrowserCocoa() + { + if (stripos($this->_agent, 'CocoaRestClient') !== false) { + $aresult = explode('/', stristr($this->_agent, 'CocoaRestClient')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + } else { + $this->setVersion(self::VERSION_UNKNOWN); + } + $this->setBrowser(self::BROWSER_COCOA); + return true; + } + return false; + } + + /** + * Detect if URL is loaded from FacebookExternalHit + * @return boolean True if it detects FacebookExternalHit otherwise false + */ + protected function checkFacebookExternalHit() + { + if (stristr($this->_agent, 'FacebookExternalHit')) { + $this->setRobot(true); + $this->setFacebook(true); + return true; + } + return false; + } + + /** + * Detect if URL is being loaded from internal Facebook browser + * @return boolean True if it detects internal Facebook browser otherwise false + */ + protected function checkForFacebookIos() + { + if (stristr($this->_agent, 'FBIOS')) { + $this->setFacebook(true); + return true; + } + return false; + } + + /** + * Detect Version for the Safari browser on iOS devices + * @return boolean True if it detects the version correctly otherwise false + */ + protected function getSafariVersionOnIos() + { + $aresult = explode('/', stristr($this->_agent, 'Version')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + return true; + } + return false; + } + + /** + * Detect Version for the Chrome browser on iOS devices + * @return boolean True if it detects the version correctly otherwise false + */ + protected function getChromeVersionOnIos() + { + $aresult = explode('/', stristr($this->_agent, 'CriOS')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_CHROME); + return true; + } + return false; + } + + /** + * Determine if the browser is iPhone or not (last updated 1.7) + * @return boolean True if the browser is iPhone otherwise false + */ + protected function checkBrowseriPhone() + { + if (stripos($this->_agent, 'iPhone') !== false) { + $this->setVersion(self::VERSION_UNKNOWN); + $this->setBrowser(self::BROWSER_IPHONE); + $this->getSafariVersionOnIos(); + $this->getChromeVersionOnIos(); + $this->checkForFacebookIos(); + $this->setMobile(true); + return true; + + } + return false; + } + + /** + * Determine if the browser is iPad or not (last updated 1.7) + * @return boolean True if the browser is iPad otherwise false + */ + protected function checkBrowseriPad() + { + if (stripos($this->_agent, 'iPad') !== false) { + $this->setVersion(self::VERSION_UNKNOWN); + $this->setBrowser(self::BROWSER_IPAD); + $this->getSafariVersionOnIos(); + $this->getChromeVersionOnIos(); + $this->checkForFacebookIos(); + $this->setTablet(true); + return true; + } + return false; + } + + /** + * Determine if the browser is iPod or not (last updated 1.7) + * @return boolean True if the browser is iPod otherwise false + */ + protected function checkBrowseriPod() + { + if (stripos($this->_agent, 'iPod') !== false) { + $this->setVersion(self::VERSION_UNKNOWN); + $this->setBrowser(self::BROWSER_IPOD); + $this->getSafariVersionOnIos(); + $this->getChromeVersionOnIos(); + $this->checkForFacebookIos(); + $this->setMobile(true); + return true; + } + return false; + } + + /** + * Determine if the browser is Android or not (last updated 1.7) + * @return boolean True if the browser is Android otherwise false + */ + protected function checkBrowserAndroid() + { + if (stripos($this->_agent, 'Android') !== false) { + $aresult = explode(' ', stristr($this->_agent, 'Android')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + } else { + $this->setVersion(self::VERSION_UNKNOWN); + } + if (stripos($this->_agent, 'Mobile') !== false) { + $this->setMobile(true); + } else { + $this->setTablet(true); + } + $this->setBrowser(self::BROWSER_ANDROID); + return true; + } + return false; + } + + /** + * Determine if the browser is Vivaldi + * @return boolean True if the browser is Vivaldi otherwise false + */ + protected function checkBrowserVivaldi() + { + if (stripos($this->_agent, 'Vivaldi') !== false) { + $aresult = explode('/', stristr($this->_agent, 'Vivaldi')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_VIVALDI); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Yandex + * @return boolean True if the browser is Yandex otherwise false + */ + protected function checkBrowserYandex() + { + if (stripos($this->_agent, 'YaBrowser') !== false) { + $aresult = explode('/', stristr($this->_agent, 'YaBrowser')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_YANDEX); + + if (stripos($this->_agent, 'iPad') !== false) { + $this->setTablet(true); + } elseif (stripos($this->_agent, 'Mobile') !== false) { + $this->setMobile(true); + } elseif (stripos($this->_agent, 'Android') !== false) { + $this->setTablet(true); + } + + return true; + } + } + + return false; + } + + /** + * Determine if the browser is a PlayStation + * @return boolean True if the browser is PlayStation otherwise false + */ + protected function checkBrowserPlayStation() + { + if (stripos($this->_agent, 'PlayStation ') !== false) { + $aresult = explode(' ', stristr($this->_agent, 'PlayStation ')); + $this->setBrowser(self::BROWSER_PLAYSTATION); + if (isset($aresult[0])) { + $aversion = explode(')', $aresult[2]); + $this->setVersion($aversion[0]); + if (stripos($this->_agent, 'Portable)') !== false || stripos($this->_agent, 'Vita') !== false) { + $this->setMobile(true); + } + return true; + } + } + return false; + } + + /** + * Determine the user's platform (last updated 2.0) + */ + protected function checkPlatform() + { + if (stripos($this->_agent, 'windows') !== false) { + $this->_platform = self::PLATFORM_WINDOWS; + } else if (stripos($this->_agent, 'iPad') !== false) { + $this->_platform = self::PLATFORM_IPAD; + } else if (stripos($this->_agent, 'iPod') !== false) { + $this->_platform = self::PLATFORM_IPOD; + } else if (stripos($this->_agent, 'iPhone') !== false) { + $this->_platform = self::PLATFORM_IPHONE; + } elseif (stripos($this->_agent, 'mac') !== false) { + $this->_platform = self::PLATFORM_APPLE; + } elseif (stripos($this->_agent, 'android') !== false) { + $this->_platform = self::PLATFORM_ANDROID; + } elseif (stripos($this->_agent, 'Silk') !== false) { + $this->_platform = self::PLATFORM_FIRE_OS; + } elseif (stripos($this->_agent, 'linux') !== false && stripos($this->_agent, 'SMART-TV') !== false ) { + $this->_platform = self::PLATFORM_LINUX .'/'.self::PLATFORM_SMART_TV; + } elseif (stripos($this->_agent, 'linux') !== false) { + $this->_platform = self::PLATFORM_LINUX; + } else if (stripos($this->_agent, 'Nokia') !== false) { + $this->_platform = self::PLATFORM_NOKIA; + } else if (stripos($this->_agent, 'BlackBerry') !== false) { + $this->_platform = self::PLATFORM_BLACKBERRY; + } elseif (stripos($this->_agent, 'FreeBSD') !== false) { + $this->_platform = self::PLATFORM_FREEBSD; + } elseif (stripos($this->_agent, 'OpenBSD') !== false) { + $this->_platform = self::PLATFORM_OPENBSD; + } elseif (stripos($this->_agent, 'NetBSD') !== false) { + $this->_platform = self::PLATFORM_NETBSD; + } elseif (stripos($this->_agent, 'OpenSolaris') !== false) { + $this->_platform = self::PLATFORM_OPENSOLARIS; + } elseif (stripos($this->_agent, 'SunOS') !== false) { + $this->_platform = self::PLATFORM_SUNOS; + } elseif (stripos($this->_agent, 'OS\/2') !== false) { + $this->_platform = self::PLATFORM_OS2; + } elseif (stripos($this->_agent, 'BeOS') !== false) { + $this->_platform = self::PLATFORM_BEOS; + } elseif (stripos($this->_agent, 'win') !== false) { + $this->_platform = self::PLATFORM_WINDOWS; + } elseif (stripos($this->_agent, 'Playstation') !== false) { + $this->_platform = self::PLATFORM_PLAYSTATION; + } elseif (stripos($this->_agent, 'Roku') !== false) { + $this->_platform = self::PLATFORM_ROKU; + } elseif (stripos($this->_agent, 'iOS') !== false) { + $this->_platform = self::PLATFORM_IPHONE . '/' . self::PLATFORM_IPAD; + } elseif (stripos($this->_agent, 'tvOS') !== false) { + $this->_platform = self::PLATFORM_APPLE_TV; + } elseif (stripos($this->_agent, 'curl') !== false) { + $this->_platform = self::PLATFORM_TERMINAL; + } elseif (stripos($this->_agent, 'CrOS') !== false) { + $this->_platform = self::PLATFORM_CHROME_OS; + } elseif (stripos($this->_agent, 'okhttp') !== false) { + $this->_platform = self::PLATFORM_JAVA_ANDROID; + } elseif (stripos($this->_agent, 'PostmanRuntime') !== false) { + $this->_platform = self::PLATFORM_POSTMAN; + } elseif (stripos($this->_agent, 'Iframely') !== false) { + $this->_platform = self::PLATFORM_I_FRAME; + } + + } +} diff --git a/k2shop/usr/k2shop/libs/browser/Readme.txt b/k2shop/usr/k2shop/libs/browser/Readme.txt new file mode 100644 index 0000000..3a76660 --- /dev/null +++ b/k2shop/usr/k2shop/libs/browser/Readme.txt @@ -0,0 +1,9 @@ +Îïðåäåëåíèå âåðñèè è òèïà áðàóçåðà. +Ïîñòîÿííî îáíîâëÿåòñÿ ïî àäðåñó: https://github.com/cbschuld/Browser.php +Ñòàòüÿ ïî äàííîé òåìå: https://ruseller.com/adds.php?rub=11&id=1914 + +Ïðèìåð èñïîëüçîâàíèÿ: +$browser = new Browser(); +if( $browser->getBrowser() == Browser::BROWSER_FIREFOX && $browser->getVersion() >= 2 ) { + echo 'Âû èñïîëüçóåòå áðàóçåð FireFox âåðñèè 2 èëè âûøå'; +} \ No newline at end of file diff --git a/k2shop/usr/k2shop/libs/detectDevice/DetectDeviceTest.php b/k2shop/usr/k2shop/libs/detectDevice/DetectDeviceTest.php new file mode 100644 index 0000000..5ac4ce0 --- /dev/null +++ b/k2shop/usr/k2shop/libs/detectDevice/DetectDeviceTest.php @@ -0,0 +1,71 @@ +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"); + } + + public function testComputer() { + // Google Chrome 29 on Windows 8 x64 + $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"); + $this->assertEquals(true, $this->device->isComputer()); + + // Mozilla Firefox 22 on Windows 8 x64 + $this->device->setUserAgent("Mozilla/5.0 (Windows NT 6.2; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"); + $this->assertEquals(true, $this->device->isComputer()); + } + + public function testMobile() { + // LGE Nexus 4 + $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"); + $this->assertEquals(true, $this->device->isMobile()); + + // Samsung Galaxy S4 + $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"); + $this->assertEquals(true, $this->device->isMobile()); + } + + public function testTablet() { + // Asus Nexus 7 + $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"); + $this->assertEquals(true, $this->device->isTablet()); + + // Samsung Galaxy Note 10.1 + $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"); + $this->assertEquals(true, $this->device->isTablet()); + } + + public function testBot() { + // GoogleBot + $this->device->setUserAgent("Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"); + $this->assertEquals(true, $this->device->isBot()); + + // BingBot + $this->device->setUserAgent("Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"); + $this->assertEquals(true, $this->device->isBot()); + } + + public function testConsole() { + // PS3 + $this->device->setUserAgent("Mozilla/5.0 (PLAYSTATION 3; 3.55)"); + $this->assertEquals(true, $this->device->isConsole()); + + // XBox + $this->device->setUserAgent("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)"); + $this->assertEquals(true, $this->device->isConsole()); + } + + public function testIs() { + // Google Chrome + $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"); + $this->assertEquals(true, $this->device->is("chrome")); + + // Nintendo DS + $this->device->setUserAgent("Mozilla/5.0 (Windows NT 6.2; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"); + $this->assertEquals(true, $this->device->is("firefox")); + } +} \ No newline at end of file diff --git a/k2shop/usr/k2shop/libs/detectDevice/README.md b/k2shop/usr/k2shop/libs/detectDevice/README.md new file mode 100644 index 0000000..90eb4f6 --- /dev/null +++ b/k2shop/usr/k2shop/libs/detectDevice/README.md @@ -0,0 +1,56 @@ +DetectDevice +============ +[![Build Status](https://travis-ci.org/Kocal/DetectDevice.png?branch=master)](https://travis-ci.org/Kocal/DetectDevice) + +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. + + +How use? +-------- +#### Firstly, include DetectDevice class and initialize it +```php +setUserAgent($userAgent); +``` + +#### Use methods to find what kind of device is used +```php +isComputer(); +echo $device->isMobile(); +echo $device->isTablet(); +echo $device->isBot(); +echo $device->isConsole(); + +// You can use the "getDeviceType()" to return a string +echo $device->getDeviceType(); // may return "computer", "mobile, "tablet", "bot" or "console" +// ... +``` + +#### Or use "is()" +```php +is($str)) { + // do stuff for Internet Explorer only +} + +``` \ No newline at end of file diff --git a/k2shop/usr/k2shop/libs/detectDevice/class.DetectDevice.php b/k2shop/usr/k2shop/libs/detectDevice/class.DetectDevice.php new file mode 100644 index 0000000..823150a --- /dev/null +++ b/k2shop/usr/k2shop/libs/detectDevice/class.DetectDevice.php @@ -0,0 +1,76 @@ + array("msie 10", "msie 9", "msie 8", "windows.*firefox", "windows.*chrome", "x11.*chrome", "x11.*firefox", "macintosh.*chrome", "macintosh.*firefox", "opera"), + "tablet" => array("tablet", "android", "ipad", "tablet.*firefox"), + "mobile" => array("mobile ", "android.*mobile", "iphone", "ipod", "opera mobi", "opera mini"), + "bot" => array("googlebot", "mediapartners-google", "adsbot-google", "duckduckbot", "msnbot", "bingbot", "ask", "facebook", "yahoo", "addthis"), + "console" => array("ps2", "playstation", "xbox", "wii", "nintendo 3?ds") + ); + + + private $deviceType = ""; + + private $isComputer = false; + private $isMobile = false; + private $isTablet = false; + private $isBot = false; + private $isConsole = false; + + + public function __construct($userAgent = "") { + if(!empty($userAgent)) { + $this->userAgent = $userAgent; + } else { + $this->userAgent = $_SERVER["HTTP_USER_AGENT"]; + } + + $this->detectDevice(); + } + + public function detectDevice() { + foreach($this->devices as $deviceType => $devices) { + foreach($devices as $device) { + if(preg_match("/" . $device . "/i", $this->userAgent)) { + $this->deviceType = $deviceType; + } + } + } + + $d = "is" . ucfirst($this->deviceType); + $this->$d = true; + } + + public function setUserAgent($userAgent) { + $this->userAgent = $userAgent; + $this->resetDevices(); + $this->detectDevice(); + } + + public function resetDevices() { + $this->isComputer = false; + $this->isMobile = false; + $this->isTablet = false; + $this->isBot = false; + } + + public function is($str, $userAgent = null) { + if(!$userAgent) { + $userAgent = $this->userAgent; + } + + return preg_match('/' . $str . '/i', $userAgent); + } + + public function getDeviceType() { return $this->deviceType; } + public function isComputer() { return $this->isComputer; } + public function isMobile() { return $this->isMobile; } + public function isTablet() { return $this->isTablet; } + public function isBot() { return $this->isBot; } + public function isConsole() { return $this->isConsole; } + public function getUserAgent() { return $this->userAgent; } + + +} diff --git a/k2shop/usr/k2shop/libs/nestmenu/index.html b/k2shop/usr/k2shop/libs/nestmenu/index.html new file mode 100644 index 0000000..fe53bfe --- /dev/null +++ b/k2shop/usr/k2shop/libs/nestmenu/index.html @@ -0,0 +1,279 @@ + + + + + + + + + + Nestable + + + + +

Nestable

+ +

Drag & drop hierarchical list with mouse and touch compatibility (jQuery plugin)

+ +

Download on GitHub

+ +
+ +
+ + +

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.

+ + + + + + +
+ +
+
    +
  1. +
    Item 1
    +
  2. +
  3. +
    Item 2
    +
      +
    1. Item 3
    2. +
    3. Item 4
    4. +
    5. +
      Item 5
      +
        +
      1. Item 6
      2. +
      3. Item 7
      4. +
      5. Item 8
      6. +
      +
    6. +
    7. Item 9
    8. +
    9. Item 10
    10. +
    +
  4. +
  5. +
    Item 11
    +
  6. +
  7. +
    Item 12
    +
  8. +
+
+ +
+
    +
  1. +
    Item 13
    +
  2. +
  3. +
    Item 14
    +
  4. +
  5. +
    Item 15
    +
      +
    1. Item 16
    2. +
    3. Item 17
    4. +
    5. Item 18
    6. +
    +
  6. +
+
+ +
+ +

Serialised Output (per list)

+ + + + +

 

+ +
+ +

Draggable Handles

+ +

If you're clever with your CSS and markup this can be achieved without any JavaScript changes.

+ +
+
    +
  1. +
    Drag
    Item 13
    +
  2. +
  3. +
    Drag
    Item 14
    +
  4. +
  5. +
    Drag
    Item 15
    +
      +
    1. +
      Drag
      Item 16
      +
    2. +
    3. +
      Drag
      Item 17
      +
    4. +
    5. +
      Drag
      Item 18
      +
    6. +
    +
  6. +
+
+ +
+ +

Copyright © David Bushell | Made for Browser

+ + + + + + \ No newline at end of file diff --git a/k2shop/usr/k2shop/libs/nestmenu/jquery.nestable.js b/k2shop/usr/k2shop/libs/nestmenu/jquery.nestable.js new file mode 100644 index 0000000..2908465 --- /dev/null +++ b/k2shop/usr/k2shop/libs/nestmenu/jquery.nestable.js @@ -0,0 +1,484 @@ +/*! + * Nestable jQuery Plugin - Copyright (c) 2012 David Bushell - http://dbushell.com/ + * Dual-licensed under the BSD or MIT licenses + */ +;(function($, window, document, undefined) +{ + var hasTouch = 'ontouchstart' in document; + + /** + * Detect CSS pointer-events property + * events are normally disabled on the dragging element to avoid conflicts + * https://github.com/ausi/Feature-detection-technique-for-pointer-events/blob/master/modernizr-pointerevents.js + */ + var hasPointerEvents = (function() + { + var el = document.createElement('div'), + docEl = document.documentElement; + if (!('pointerEvents' in el.style)) { + return false; + } + el.style.pointerEvents = 'auto'; + el.style.pointerEvents = 'x'; + docEl.appendChild(el); + var supports = window.getComputedStyle && window.getComputedStyle(el, '').pointerEvents === 'auto'; + docEl.removeChild(el); + return !!supports; + })(); + + var defaults = { + listNodeName : 'ol', + itemNodeName : 'li', + rootClass : 'dd', + listClass : 'dd-list', + itemClass : 'dd-item', + dragClass : 'dd-dragel', + handleClass : 'dd-handle', + collapsedClass : 'dd-collapsed', + placeClass : 'dd-placeholder', + noDragClass : 'dd-nodrag', + emptyClass : 'dd-empty', + expandBtnHTML : '', + collapseBtnHTML : '', + group : 0, + maxDepth : 5, + threshold : 20 + }; + + function Plugin(element, options) + { + this.w = $(document); + this.el = $(element); + this.options = $.extend({}, defaults, options); + this.init(); + } + + Plugin.prototype = { + + init: function() + { + var list = this; + + list.reset(); + + list.el.data('nestable-group', this.options.group); + + list.placeEl = $('
'); + + $.each(this.el.find(list.options.itemNodeName), function(k, el) { + list.setParent($(el)); + }); + + list.el.on('click', 'button', function(e) { + if (list.dragEl) { + return; + } + var target = $(e.currentTarget), + action = target.data('action'), + item = target.parent(list.options.itemNodeName); + if (action === 'collapse') { + list.collapseItem(item); + } + if (action === 'expand') { + list.expandItem(item); + } + }); + + var onStartEvent = function(e) + { + var handle = $(e.target); + if (!handle.hasClass(list.options.handleClass)) { + if (handle.closest('.' + list.options.noDragClass).length) { + return; + } + handle = handle.closest('.' + list.options.handleClass); + } + + if (!handle.length || list.dragEl) { + return; + } + + list.isTouch = /^touch/.test(e.type); + if (list.isTouch && e.touches.length !== 1) { + return; + } + + e.preventDefault(); + list.dragStart(e.touches ? e.touches[0] : e); + }; + + var onMoveEvent = function(e) + { + if (list.dragEl) { + e.preventDefault(); + list.dragMove(e.touches ? e.touches[0] : e); + } + }; + + var onEndEvent = function(e) + { + if (list.dragEl) { + e.preventDefault(); + list.dragStop(e.touches ? e.touches[0] : e); + } + }; + + if (hasTouch) { + list.el[0].addEventListener('touchstart', onStartEvent, false); + window.addEventListener('touchmove', onMoveEvent, false); + window.addEventListener('touchend', onEndEvent, false); + window.addEventListener('touchcancel', onEndEvent, false); + } + + list.el.on('mousedown', onStartEvent); + list.w.on('mousemove', onMoveEvent); + list.w.on('mouseup', onEndEvent); + + }, + + serialize: function() + { + var data, + depth = 0, + list = this; + step = function(level, depth) + { + var array = [ ], + items = level.children(list.options.itemNodeName); + items.each(function() + { + var li = $(this), + item = $.extend({}, li.data()), + sub = li.children(list.options.listNodeName); + if (sub.length) { + item.children = step(sub, depth + 1); + } + array.push(item); + }); + return array; + }; + data = step(list.el.find(list.options.listNodeName).first(), depth); + return data; + }, + + serialise: function() + { + return this.serialize(); + }, + + reset: function() + { + this.mouse = { + offsetX : 0, + offsetY : 0, + startX : 0, + startY : 0, + lastX : 0, + lastY : 0, + nowX : 0, + nowY : 0, + distX : 0, + distY : 0, + dirAx : 0, + dirX : 0, + dirY : 0, + lastDirX : 0, + lastDirY : 0, + distAxX : 0, + distAxY : 0 + }; + this.isTouch = false; + this.moving = false; + this.dragEl = null; + this.dragRootEl = null; + this.dragDepth = 0; + this.hasNewRoot = false; + this.pointEl = null; + }, + + expandItem: function(li) + { + li.removeClass(this.options.collapsedClass); + li.children('[data-action="expand"]').hide(); + li.children('[data-action="collapse"]').show(); + li.children(this.options.listNodeName).show(); + }, + + collapseItem: function(li) + { + var lists = li.children(this.options.listNodeName); + if (lists.length) { + li.addClass(this.options.collapsedClass); + li.children('[data-action="collapse"]').hide(); + li.children('[data-action="expand"]').show(); + li.children(this.options.listNodeName).hide(); + } + }, + + expandAll: function() + { + var list = this; + list.el.find(list.options.itemNodeName).each(function() { + list.expandItem($(this)); + }); + }, + + collapseAll: function() + { + var list = this; + list.el.find(list.options.itemNodeName).each(function() { + list.collapseItem($(this)); + }); + }, + + setParent: function(li) + { + if (li.children(this.options.listNodeName).length) { + li.prepend($(this.options.expandBtnHTML)); + li.prepend($(this.options.collapseBtnHTML)); + } + li.children('[data-action="expand"]').hide(); + }, + + unsetParent: function(li) + { + li.removeClass(this.options.collapsedClass); + li.children('[data-action]').remove(); + li.children(this.options.listNodeName).remove(); + }, + + dragStart: function(e) + { + var mouse = this.mouse, + target = $(e.target), + dragItem = target.closest(this.options.itemNodeName); + + this.placeEl.css('height', dragItem.height()); + + mouse.offsetX = e.offsetX !== undefined ? e.offsetX : e.pageX - target.offset().left; + mouse.offsetY = e.offsetY !== undefined ? e.offsetY : e.pageY - target.offset().top; + mouse.startX = mouse.lastX = e.pageX; + mouse.startY = mouse.lastY = e.pageY; + + this.dragRootEl = this.el; + + this.dragEl = $(document.createElement(this.options.listNodeName)).addClass(this.options.listClass + ' ' + this.options.dragClass); + this.dragEl.css('width', dragItem.width()); + + dragItem.after(this.placeEl); + dragItem[0].parentNode.removeChild(dragItem[0]); + dragItem.appendTo(this.dragEl); + + $(document.body).append(this.dragEl); + this.dragEl.css({ + 'left' : e.pageX - mouse.offsetX, + 'top' : e.pageY - mouse.offsetY + }); + // total depth of dragging item + var i, depth, + items = this.dragEl.find(this.options.itemNodeName); + for (i = 0; i < items.length; i++) { + depth = $(items[i]).parents(this.options.listNodeName).length; + if (depth > this.dragDepth) { + this.dragDepth = depth; + } + } + }, + + dragStop: function(e) + { + var el = this.dragEl.children(this.options.itemNodeName).first(); + el[0].parentNode.removeChild(el[0]); + this.placeEl.replaceWith(el); + + this.dragEl.remove(); + this.el.trigger('change'); + if (this.hasNewRoot) { + this.dragRootEl.trigger('change'); + } + this.reset(); + }, + + dragMove: function(e) + { + var list, parent, prev, next, depth, + opt = this.options, + mouse = this.mouse; + + this.dragEl.css({ + 'left' : e.pageX - mouse.offsetX, + 'top' : e.pageY - mouse.offsetY + }); + + // mouse position last events + mouse.lastX = mouse.nowX; + mouse.lastY = mouse.nowY; + // mouse position this events + mouse.nowX = e.pageX; + mouse.nowY = e.pageY; + // distance mouse moved between events + mouse.distX = mouse.nowX - mouse.lastX; + mouse.distY = mouse.nowY - mouse.lastY; + // direction mouse was moving + mouse.lastDirX = mouse.dirX; + mouse.lastDirY = mouse.dirY; + // direction mouse is now moving (on both axis) + mouse.dirX = mouse.distX === 0 ? 0 : mouse.distX > 0 ? 1 : -1; + mouse.dirY = mouse.distY === 0 ? 0 : mouse.distY > 0 ? 1 : -1; + // axis mouse is now moving on + var newAx = Math.abs(mouse.distX) > Math.abs(mouse.distY) ? 1 : 0; + + // do nothing on first move + if (!mouse.moving) { + mouse.dirAx = newAx; + mouse.moving = true; + return; + } + + // calc distance moved on this axis (and direction) + if (mouse.dirAx !== newAx) { + mouse.distAxX = 0; + mouse.distAxY = 0; + } else { + mouse.distAxX += Math.abs(mouse.distX); + if (mouse.dirX !== 0 && mouse.dirX !== mouse.lastDirX) { + mouse.distAxX = 0; + } + mouse.distAxY += Math.abs(mouse.distY); + if (mouse.dirY !== 0 && mouse.dirY !== mouse.lastDirY) { + mouse.distAxY = 0; + } + } + mouse.dirAx = newAx; + + /** + * move horizontal + */ + if (mouse.dirAx && mouse.distAxX >= opt.threshold) { + // reset move distance on x-axis for new phase + mouse.distAxX = 0; + prev = this.placeEl.prev(opt.itemNodeName); + // increase horizontal level if previous sibling exists and is not collapsed + if (mouse.distX > 0 && prev.length && !prev.hasClass(opt.collapsedClass)) { + // cannot increase level when item above is collapsed + list = prev.find(opt.listNodeName).last(); + // check if depth limit has reached + depth = this.placeEl.parents(opt.listNodeName).length; + if (depth + this.dragDepth <= opt.maxDepth) { + // create new sub-level if one doesn't exist + if (!list.length) { + list = $('<' + opt.listNodeName + '/>').addClass(opt.listClass); + list.append(this.placeEl); + prev.append(list); + this.setParent(prev); + } else { + // else append to next level up + list = prev.children(opt.listNodeName).last(); + list.append(this.placeEl); + } + } + } + // decrease horizontal level + if (mouse.distX < 0) { + // we can't decrease a level if an item preceeds the current one + next = this.placeEl.next(opt.itemNodeName); + if (!next.length) { + parent = this.placeEl.parent(); + this.placeEl.closest(opt.itemNodeName).after(this.placeEl); + if (!parent.children().length) { + this.unsetParent(parent.parent()); + } + } + } + } + + var isEmpty = false; + + // find list item under cursor + if (!hasPointerEvents) { + this.dragEl[0].style.visibility = 'hidden'; + } + this.pointEl = $(document.elementFromPoint(e.pageX - document.body.scrollLeft, e.pageY - (window.pageYOffset || document.documentElement.scrollTop))); + if (!hasPointerEvents) { + this.dragEl[0].style.visibility = 'visible'; + } + if (this.pointEl.hasClass(opt.handleClass)) { + this.pointEl = this.pointEl.parent(opt.itemNodeName); + } + if (this.pointEl.hasClass(opt.emptyClass)) { + isEmpty = true; + } + else if (!this.pointEl.length || !this.pointEl.hasClass(opt.itemClass)) { + return; + } + + // find parent list of item under cursor + var pointElRoot = this.pointEl.closest('.' + opt.rootClass), + isNewRoot = this.dragRootEl.data('nestable-id') !== pointElRoot.data('nestable-id'); + + /** + * move vertical + */ + if (!mouse.dirAx || isNewRoot || isEmpty) { + // check if groups match if dragging over new root + if (isNewRoot && opt.group !== pointElRoot.data('nestable-group')) { + return; + } + // check depth limit + depth = this.dragDepth - 1 + this.pointEl.parents(opt.listNodeName).length; + if (depth > opt.maxDepth) { + return; + } + var before = e.pageY < (this.pointEl.offset().top + this.pointEl.height() / 2); + parent = this.placeEl.parent(); + // if empty create new list to replace empty placeholder + if (isEmpty) { + list = $(document.createElement(opt.listNodeName)).addClass(opt.listClass); + list.append(this.placeEl); + this.pointEl.replaceWith(list); + } + else if (before) { + this.pointEl.before(this.placeEl); + } + else { + this.pointEl.after(this.placeEl); + } + if (!parent.children().length) { + this.unsetParent(parent.parent()); + } + if (!this.dragRootEl.find(opt.itemNodeName).length) { + this.dragRootEl.append('
'); + } + // parent root list has changed + if (isNewRoot) { + this.dragRootEl = pointElRoot; + this.hasNewRoot = this.el[0] !== this.dragRootEl[0]; + } + } + } + + }; + + $.fn.nestable = function(params) + { + var lists = this, + retval = this; + + lists.each(function() + { + var plugin = $(this).data("nestable"); + + if (!plugin) { + $(this).data("nestable", new Plugin(this, params)); + $(this).data("nestable-id", new Date().getTime()); + } else { + if (typeof params === 'string' && typeof plugin[params] === 'function') { + retval = plugin[params](); + } + } + }); + + return retval || lists; + }; + +})(window.jQuery || window.Zepto, window, document); \ No newline at end of file diff --git a/k2shop/usr/k2shop/libs/nestmenu/nestable.css b/k2shop/usr/k2shop/libs/nestmenu/nestable.css new file mode 100644 index 0000000..e128b61 --- /dev/null +++ b/k2shop/usr/k2shop/libs/nestmenu/nestable.css @@ -0,0 +1,94 @@ + +/** + * Nestable + */ +.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; } +.dd-list { display: block; position: relative; margin: 0; padding: 0; list-style: none; } +.dd-list .dd-list { padding-left: 30px; } +.dd-collapsed .dd-list { display: none; } +.dd-item, +.dd-empty, +.dd-placeholder { display: block; position: relative; margin: 0; padding: 0; min-height: 20px; font-size: 13px; line-height: 20px; } +.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; + background: #fafafa; + background: -webkit-linear-gradient(top, #fafafa 0%, #eee 100%); + background: -moz-linear-gradient(top, #fafafa 0%, #eee 100%); + background: linear-gradient(top, #fafafa 0%, #eee 100%); + -webkit-border-radius: 3px; + border-radius: 3px; + box-sizing: border-box; -moz-box-sizing: border-box; +} +.dd-handle:hover { color: #2ea8e5; background: #fff; } +.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; } +.dd-item > button:before { content: '+'; display: block; position: absolute; width: 100%; text-align: center; text-indent: 0; } +.dd-item > button[data-action="collapse"]:before { content: '-'; } +.dd-placeholder, +.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; } +.dd-empty { border: 1px dashed #bbb; min-height: 100px; background-color: #e5e5e5; + background-image: -webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), + -webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff); + background-image: -moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), + -moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff); + background-image: linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), + linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff); + background-size: 60px 60px; + background-position: 0 0, 30px 30px; +} +.dd-dragel { position: absolute; pointer-events: none; z-index: 9999; } +.dd-dragel > .dd-item .dd-handle { margin-top: 0; } +.dd-dragel .dd-handle { + -webkit-box-shadow: 2px 4px 6px 0 rgba(0,0,0,.1); + box-shadow: 2px 4px 6px 0 rgba(0,0,0,.1); +} +/** + * Nestable Extras + */ +.nestable-lists { display: block; clear: both; padding: 30px 0; width: 100%; border: 0; border-top: 2px solid #ddd; border-bottom: 2px solid #ddd; } +#nestable-menu { padding: 0; margin: 20px 0; } +#nestable-output, +#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; } +#nestable2 .dd-handle { + color: #fff; + border: 1px solid #999; + background: #bbb; + background: -webkit-linear-gradient(top, #bbb 0%, #999 100%); + background: -moz-linear-gradient(top, #bbb 0%, #999 100%); + background: linear-gradient(top, #bbb 0%, #999 100%); +} +#nestable2 .dd-handle:hover { background: #bbb; } +#nestable2 .dd-item > button:before { color: #fff; } +@media only screen and (min-width: 700px) { + /*.dd { float: left; width: 48%; }*/ + .dd + .dd { margin-left: 2%; } +} +.dd-hover > .dd-handle { background: #2ea8e5 !important; } +/** + * Nestable Draggable Handles + */ +.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; + background: #fafafa; + background: -webkit-linear-gradient(top, #fafafa 0%, #eee 100%); + background: -moz-linear-gradient(top, #fafafa 0%, #eee 100%); + background: linear-gradient(top, #fafafa 0%, #eee 100%); + -webkit-border-radius: 3px; + border-radius: 3px; + box-sizing: border-box; -moz-box-sizing: border-box; +} +.dd3-content:hover { color: #2ea8e5; background: #fff; } +.dd-dragel > .dd3-item > .dd3-content { margin: 0; } +.dd3-item > button { margin-left: 30px; } +.dd3-handle { position: absolute; margin: 0; left: 0; top: 0; cursor: pointer; width: 30px; text-indent: 100%; white-space: nowrap; overflow: hidden; + border: 1px solid #aaa; + background: #ddd; + background: -webkit-linear-gradient(top, #ddd 0%, #bbb 100%); + background: -moz-linear-gradient(top, #ddd 0%, #bbb 100%); + background: linear-gradient(top, #ddd 0%, #bbb 100%); + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.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; } +.dd3-handle:hover { background: #ddd; } +/** + * Socialite + */ +.socialite { display: block; float: left; height: 35px; } \ No newline at end of file diff --git a/k2shop/usr/k2shop/libs/yaml/Spyc.php b/k2shop/usr/k2shop/libs/yaml/Spyc.php new file mode 100644 index 0000000..f9ba561 --- /dev/null +++ b/k2shop/usr/k2shop/libs/yaml/Spyc.php @@ -0,0 +1,994 @@ + + * @author Chris Wanstrath + * @link https://github.com/mustangostang/spyc/ + * @copyright Copyright 2005-2006 Chris Wanstrath, 2006-2011 Vlad Andersen + * @license http://www.opensource.org/licenses/mit-license.php MIT License + * @package Spyc + */ +if (!function_exists('spyc_load')) { + /** + * Parses YAML to array. + * @param string $string YAML string. + * @return array + */ + function spyc_load ($string) { + return Spyc::YAMLLoadString($string); + } +} +if (!function_exists('spyc_load_file')) { + /** + * Parses YAML to array. + * @param string $file Path to YAML file. + * @return array + */ + function spyc_load_file ($file) { + return Spyc::YAMLLoad($file); + } +} +if (!function_exists('spyc_dump')) { + /** + * Dumps array to YAML. + * @param array $data Array. + * @return string + */ + function spyc_dump ($data) { + return Spyc::YAMLDump($data, false, false, true); + } +} +if (!class_exists('Spyc')) { +/** + * The Simple PHP YAML Class. + * + * This class can be used to read a YAML file and convert its contents + * into a PHP array. It currently supports a very limited subsection of + * the YAML spec. + * + * Usage: + * + * $Spyc = new Spyc; + * $array = $Spyc->load($file); + * + * or: + * + * $array = Spyc::YAMLLoad($file); + * + * or: + * + * $array = spyc_load_file($file); + * + * @package Spyc + */ +class Spyc { + // SETTINGS + const REMPTY = "\0\0\0\0\0"; + /** + * Setting this to true will force YAMLDump to enclose any string value in + * quotes. False by default. + * + * @var bool + */ + public $setting_dump_force_quotes = false; + /** + * Setting this to true will forse YAMLLoad to use syck_load function when + * possible. False by default. + * @var bool + */ + public $setting_use_syck_is_possible = false; + /**#@+ + * @access private + * @var mixed + */ + private $_dumpIndent; + private $_dumpWordWrap; + private $_containsGroupAnchor = false; + private $_containsGroupAlias = false; + private $path; + private $result; + private $LiteralPlaceHolder = '___YAML_Literal_Block___'; + private $SavedGroups = array(); + private $indent; + /** + * Path modifier that should be applied after adding current element. + * @var array + */ + private $delayedPath = array(); + /**#@+ + * @access public + * @var mixed + */ + public $_nodeId; +/** + * Load a valid YAML string to Spyc. + * @param string $input + * @return array + */ + public function load ($input) { + return $this->_loadString($input); + } + /** + * Load a valid YAML file to Spyc. + * @param string $file + * @return array + */ + public function loadFile ($file) { + return $this->_load($file); + } + /** + * Load YAML into a PHP array statically + * + * The load method, when supplied with a YAML stream (string or file), + * will do its best to convert YAML in a file into a PHP array. Pretty + * simple. + * Usage: + * + * $array = Spyc::YAMLLoad('lucky.yaml'); + * print_r($array); + * + * @access public + * @return array + * @param string $input Path of YAML file or string containing YAML + */ + public static function YAMLLoad($input) { + $Spyc = new Spyc; + return $Spyc->_load($input); + } + /** + * Load a string of YAML into a PHP array statically + * + * The load method, when supplied with a YAML string, will do its best + * to convert YAML in a string into a PHP array. Pretty simple. + * + * Note: use this function if you don't want files from the file system + * loaded and processed as YAML. This is of interest to people concerned + * about security whose input is from a string. + * + * Usage: + * + * $array = Spyc::YAMLLoadString("---\n0: hello world\n"); + * print_r($array); + * + * @access public + * @return array + * @param string $input String containing YAML + */ + public static function YAMLLoadString($input) { + $Spyc = new Spyc; + return $Spyc->_loadString($input); + } + /** + * Dump YAML from PHP array statically + * + * The dump method, when supplied with an array, will do its best + * to convert the array into friendly YAML. Pretty simple. Feel free to + * save the returned string as nothing.yaml and pass it around. + * + * Oh, and you can decide how big the indent is and what the wordwrap + * for folding is. Pretty cool -- just pass in 'false' for either if + * you want to use the default. + * + * Indent's default is 2 spaces, wordwrap's default is 40 characters. And + * you can turn off wordwrap by passing in 0. + * + * @access public + * @return string + * @param array|\stdClass $array PHP array + * @param int $indent Pass in false to use the default, which is 2 + * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40) + * @param bool $no_opening_dashes Do not start YAML file with "---\n" + */ + public static function YAMLDump($array, $indent = false, $wordwrap = false, $no_opening_dashes = false) { + $spyc = new Spyc; + return $spyc->dump($array, $indent, $wordwrap, $no_opening_dashes); + } + /** + * Dump PHP array to YAML + * + * The dump method, when supplied with an array, will do its best + * to convert the array into friendly YAML. Pretty simple. Feel free to + * save the returned string as tasteful.yaml and pass it around. + * + * Oh, and you can decide how big the indent is and what the wordwrap + * for folding is. Pretty cool -- just pass in 'false' for either if + * you want to use the default. + * + * Indent's default is 2 spaces, wordwrap's default is 40 characters. And + * you can turn off wordwrap by passing in 0. + * + * @access public + * @return string + * @param array $array PHP array + * @param int $indent Pass in false to use the default, which is 2 + * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40) + */ + public function dump($array,$indent = false,$wordwrap = false, $no_opening_dashes = false) { + // Dumps to some very clean YAML. We'll have to add some more features + // and options soon. And better support for folding. + // New features and options. + if ($indent === false or !is_numeric($indent)) { + $this->_dumpIndent = 2; + } else { + $this->_dumpIndent = $indent; + } + if ($wordwrap === false or !is_numeric($wordwrap)) { + $this->_dumpWordWrap = 40; + } else { + $this->_dumpWordWrap = $wordwrap; + } + // New YAML document + $string = ""; + if (!$no_opening_dashes) $string = "---\n"; + // Start at the base of the array and move through it. + if ($array) { + $array = (array)$array; + $previous_key = -1; + foreach ($array as $key => $value) { + if (!isset($first_key)) $first_key = $key; + $string .= $this->_yamlize($key,$value,0,$previous_key, $first_key, $array); + $previous_key = $key; + } + } + return $string; + } + /** + * Attempts to convert a key / value array item to YAML + * @access private + * @return string + * @param $key The name of the key + * @param $value The value of the item + * @param $indent The indent of the current node + */ + private function _yamlize($key,$value,$indent, $previous_key = -1, $first_key = 0, $source_array = null) { + if(is_object($value)) $value = (array)$value; + if (is_array($value)) { + if (empty ($value)) + return $this->_dumpNode($key, array(), $indent, $previous_key, $first_key, $source_array); + // It has children. What to do? + // Make it the right kind of item + $string = $this->_dumpNode($key, self::REMPTY, $indent, $previous_key, $first_key, $source_array); + // Add the indent + $indent += $this->_dumpIndent; + // Yamlize the array + $string .= $this->_yamlizeArray($value,$indent); + } elseif (!is_array($value)) { + // It doesn't have children. Yip. + $string = $this->_dumpNode($key, $value, $indent, $previous_key, $first_key, $source_array); + } + return $string; + } + /** + * Attempts to convert an array to YAML + * @access private + * @return string + * @param $array The array you want to convert + * @param $indent The indent of the current level + */ + private function _yamlizeArray($array,$indent) { + if (is_array($array)) { + $string = ''; + $previous_key = -1; + foreach ($array as $key => $value) { + if (!isset($first_key)) $first_key = $key; + $string .= $this->_yamlize($key, $value, $indent, $previous_key, $first_key, $array); + $previous_key = $key; + } + return $string; + } else { + return false; + } + } + /** + * Returns YAML from a key and a value + * @access private + * @return string + * @param $key The name of the key + * @param $value The value of the item + * @param $indent The indent of the current node + */ + private function _dumpNode($key, $value, $indent, $previous_key = -1, $first_key = 0, $source_array = null) { + // do some folding here, for blocks + if (is_string ($value) && ((strpos($value,"\n") !== false || strpos($value,": ") !== false || strpos($value,"- ") !== false || + strpos($value,"*") !== false || strpos($value,"#") !== false || strpos($value,"<") !== false || strpos($value,">") !== false || strpos ($value, '%') !== false || strpos ($value, ' ') !== false || + strpos($value,"[") !== false || strpos($value,"]") !== false || strpos($value,"{") !== false || strpos($value,"}") !== false) || strpos($value,"&") !== false || strpos($value, "'") !== false || strpos($value, "!") === 0 || + substr ($value, -1, 1) == ':') + ) { + $value = $this->_doLiteralBlock($value,$indent); + } else { + $value = $this->_doFolding($value,$indent); + } + if ($value === array()) $value = '[ ]'; + if ($value === "") $value = '""'; + if (self::isTranslationWord($value)) { + $value = $this->_doLiteralBlock($value, $indent); + } + if (trim ($value) != $value) + $value = $this->_doLiteralBlock($value,$indent); + if (is_bool($value)) { + $value = $value ? "true" : "false"; + } + if ($value === null) $value = 'null'; + if ($value === "'" . self::REMPTY . "'") $value = null; + $spaces = str_repeat(' ',$indent); + //if (is_int($key) && $key - 1 == $previous_key && $first_key===0) { + if (is_array ($source_array) && array_keys($source_array) === range(0, count($source_array) - 1)) { + // It's a sequence + $string = $spaces.'- '.$value."\n"; + } else { + // if ($first_key===0) throw new Exception('Keys are all screwy. The first one was zero, now it\'s "'. $key .'"'); + // It's mapped + if (strpos($key, ":") !== false || strpos($key, "#") !== false) { $key = '"' . $key . '"'; } + $string = rtrim ($spaces.$key.': '.$value)."\n"; + } + return $string; + } + /** + * Creates a literal block for dumping + * @access private + * @return string + * @param $value + * @param $indent int The value of the indent + */ + private function _doLiteralBlock($value,$indent) { + if ($value === "\n") return '\n'; + if (strpos($value, "\n") === false && strpos($value, "'") === false) { + return sprintf ("'%s'", $value); + } + if (strpos($value, "\n") === false && strpos($value, '"') === false) { + return sprintf ('"%s"', $value); + } + $exploded = explode("\n",$value); + $newValue = '|'; + if (isset($exploded[0]) && ($exploded[0] == "|" || $exploded[0] == "|-" || $exploded[0] == ">")) { + $newValue = $exploded[0]; + unset($exploded[0]); + } + $indent += $this->_dumpIndent; + $spaces = str_repeat(' ',$indent); + foreach ($exploded as $line) { + $line = trim($line); + if (strpos($line, '"') === 0 && strrpos($line, '"') == (strlen($line)-1) || strpos($line, "'") === 0 && strrpos($line, "'") == (strlen($line)-1)) { + $line = substr($line, 1, -1); + } + $newValue .= "\n" . $spaces . ($line); + } + return $newValue; + } + /** + * Folds a string of text, if necessary + * @access private + * @return string + * @param $value The string you wish to fold + */ + private function _doFolding($value,$indent) { + // Don't do anything if wordwrap is set to 0 + if ($this->_dumpWordWrap !== 0 && is_string ($value) && strlen($value) > $this->_dumpWordWrap) { + $indent += $this->_dumpIndent; + $indent = str_repeat(' ',$indent); + $wrapped = wordwrap($value,$this->_dumpWordWrap,"\n$indent"); + $value = ">\n".$indent.$wrapped; + } else { + if ($this->setting_dump_force_quotes && is_string ($value) && $value !== self::REMPTY) + $value = '"' . $value . '"'; + if (is_numeric($value) && is_string($value)) + $value = '"' . $value . '"'; + } + return $value; + } + private function isTrueWord($value) { + $words = self::getTranslations(array('true', 'on', 'yes', 'y')); + return in_array($value, $words, true); + } + private function isFalseWord($value) { + $words = self::getTranslations(array('false', 'off', 'no', 'n')); + return in_array($value, $words, true); + } + private function isNullWord($value) { + $words = self::getTranslations(array('null', '~')); + return in_array($value, $words, true); + } + private function isTranslationWord($value) { + return ( + self::isTrueWord($value) || + self::isFalseWord($value) || + self::isNullWord($value) + ); + } + /** + * Coerce a string into a native type + * Reference: http://yaml.org/type/bool.html + * TODO: Use only words from the YAML spec. + * @access private + * @param $value The value to coerce + */ + private function coerceValue(&$value) { + if (self::isTrueWord($value)) { + $value = true; + } else if (self::isFalseWord($value)) { + $value = false; + } else if (self::isNullWord($value)) { + $value = null; + } + } + /** + * Given a set of words, perform the appropriate translations on them to + * match the YAML 1.1 specification for type coercing. + * @param $words The words to translate + * @access private + */ + private static function getTranslations(array $words) { + $result = array(); + foreach ($words as $i) { + $result = array_merge($result, array(ucfirst($i), strtoupper($i), strtolower($i))); + } + return $result; + } +// LOADING FUNCTIONS + private function _load($input) { + $Source = $this->loadFromSource($input); + return $this->loadWithSource($Source); + } + private function _loadString($input) { + $Source = $this->loadFromString($input); + return $this->loadWithSource($Source); + } + private function loadWithSource($Source) { + if (empty ($Source)) return array(); + if ($this->setting_use_syck_is_possible && function_exists ('syck_load')) { + $array = syck_load (implode ("\n", $Source)); + return is_array($array) ? $array : array(); + } + $this->path = array(); + $this->result = array(); + $cnt = count($Source); + for ($i = 0; $i < $cnt; $i++) { + $line = $Source[$i]; + $this->indent = strlen($line) - strlen(ltrim($line)); + $tempPath = $this->getParentPathByIndent($this->indent); + $line = self::stripIndent($line, $this->indent); + if (self::isComment($line)) continue; + if (self::isEmpty($line)) continue; + $this->path = $tempPath; + $literalBlockStyle = self::startsLiteralBlock($line); + if ($literalBlockStyle) { + $line = rtrim ($line, $literalBlockStyle . " \n"); + $literalBlock = ''; + $line .= ' '.$this->LiteralPlaceHolder; + $literal_block_indent = strlen($Source[$i+1]) - strlen(ltrim($Source[$i+1])); + while (++$i < $cnt && $this->literalBlockContinues($Source[$i], $this->indent)) { + $literalBlock = $this->addLiteralLine($literalBlock, $Source[$i], $literalBlockStyle, $literal_block_indent); + } + $i--; + } + // Strip out comments + if (strpos ($line, '#')) { + $line = preg_replace('/\s*#([^"\']+)$/','',$line); + } + while (++$i < $cnt && self::greedilyNeedNextLine($line)) { + $line = rtrim ($line, " \n\t\r") . ' ' . ltrim ($Source[$i], " \t"); + } + $i--; + $lineArray = $this->_parseLine($line); + if ($literalBlockStyle) + $lineArray = $this->revertLiteralPlaceHolder ($lineArray, $literalBlock); + $this->addArray($lineArray, $this->indent); + foreach ($this->delayedPath as $indent => $delayedPath) + $this->path[$indent] = $delayedPath; + $this->delayedPath = array(); + } + return $this->result; + } + private function loadFromSource ($input) { + if (!empty($input) && strpos($input, "\n") === false && file_exists($input)) + $input = file_get_contents($input); + return $this->loadFromString($input); + } + private function loadFromString ($input) { + $lines = explode("\n",$input); + foreach ($lines as $k => $_) { + $lines[$k] = rtrim ($_, "\r"); + } + return $lines; + } + /** + * Parses YAML code and returns an array for a node + * @access private + * @return array + * @param string $line A line from the YAML file + */ + private function _parseLine($line) { + if (!$line) return array(); + $line = trim($line); + if (!$line) return array(); + $array = array(); + $group = $this->nodeContainsGroup($line); + if ($group) { + $this->addGroup($line, $group); + $line = $this->stripGroup ($line, $group); + } + if ($this->startsMappedSequence($line)) + return $this->returnMappedSequence($line); + if ($this->startsMappedValue($line)) + return $this->returnMappedValue($line); + if ($this->isArrayElement($line)) + return $this->returnArrayElement($line); + if ($this->isPlainArray($line)) + return $this->returnPlainArray($line); + return $this->returnKeyValuePair($line); + } + /** + * Finds the type of the passed value, returns the value as the new type. + * @access private + * @param string $value + * @return mixed + */ + private function _toType($value) { + if ($value === '') return ""; + $first_character = $value[0]; + $last_character = substr($value, -1, 1); + $is_quoted = false; + do { + if (!$value) break; + if ($first_character != '"' && $first_character != "'") break; + if ($last_character != '"' && $last_character != "'") break; + $is_quoted = true; + } while (0); + if ($is_quoted) { + $value = str_replace('\n', "\n", $value); + if ($first_character == "'") + return strtr(substr ($value, 1, -1), array ('\'\'' => '\'', '\\\''=> '\'')); + return strtr(substr ($value, 1, -1), array ('\\"' => '"', '\\\''=> '\'')); + } + if (strpos($value, ' #') !== false && !$is_quoted) + $value = preg_replace('/\s+#(.+)$/','',$value); + if ($first_character == '[' && $last_character == ']') { + // Take out strings sequences and mappings + $innerValue = trim(substr ($value, 1, -1)); + if ($innerValue === '') return array(); + $explode = $this->_inlineEscape($innerValue); + // Propagate value array + $value = array(); + foreach ($explode as $v) { + $value[] = $this->_toType($v); + } + return $value; + } + if (strpos($value,': ')!==false && $first_character != '{') { + $array = explode(': ',$value); + $key = trim($array[0]); + array_shift($array); + $value = trim(implode(': ',$array)); + $value = $this->_toType($value); + return array($key => $value); + } + if ($first_character == '{' && $last_character == '}') { + $innerValue = trim(substr ($value, 1, -1)); + if ($innerValue === '') return array(); + // Inline Mapping + // Take out strings sequences and mappings + $explode = $this->_inlineEscape($innerValue); + // Propagate value array + $array = array(); + foreach ($explode as $v) { + $SubArr = $this->_toType($v); + if (empty($SubArr)) continue; + if (is_array ($SubArr)) { + $array[key($SubArr)] = $SubArr[key($SubArr)]; continue; + } + $array[] = $SubArr; + } + return $array; + } + if ($value == 'null' || $value == 'NULL' || $value == 'Null' || $value == '' || $value == '~') { + return null; + } + if ( is_numeric($value) && preg_match ('/^(-|)[1-9]+[0-9]*$/', $value) ){ + $intvalue = (int)$value; + if ($intvalue != PHP_INT_MAX && $intvalue != ~PHP_INT_MAX) + $value = $intvalue; + return $value; + } + if ( is_string($value) && preg_match('/^0[xX][0-9a-fA-F]+$/', $value)) { + // Hexadecimal value. + return hexdec($value); + } + $this->coerceValue($value); + if (is_numeric($value)) { + if ($value === '0') return 0; + if (rtrim ($value, 0) === $value) + $value = (float)$value; + return $value; + } + return $value; + } + /** + * Used in inlines to check for more inlines or quoted strings + * @access private + * @return array + */ + private function _inlineEscape($inline) { + // There's gotta be a cleaner way to do this... + // While pure sequences seem to be nesting just fine, + // pure mappings and mappings with sequences inside can't go very + // deep. This needs to be fixed. + $seqs = array(); + $maps = array(); + $saved_strings = array(); + $saved_empties = array(); + // Check for empty strings + $regex = '/("")|(\'\')/'; + if (preg_match_all($regex,$inline,$strings)) { + $saved_empties = $strings[0]; + $inline = preg_replace($regex,'YAMLEmpty',$inline); + } + unset($regex); + // Check for strings + $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/'; + if (preg_match_all($regex,$inline,$strings)) { + $saved_strings = $strings[0]; + $inline = preg_replace($regex,'YAMLString',$inline); + } + unset($regex); + // echo $inline; + $i = 0; + do { + // Check for sequences + while (preg_match('/\[([^{}\[\]]+)\]/U',$inline,$matchseqs)) { + $seqs[] = $matchseqs[0]; + $inline = preg_replace('/\[([^{}\[\]]+)\]/U', ('YAMLSeq' . (count($seqs) - 1) . 's'), $inline, 1); + } + // Check for mappings + while (preg_match('/{([^\[\]{}]+)}/U',$inline,$matchmaps)) { + $maps[] = $matchmaps[0]; + $inline = preg_replace('/{([^\[\]{}]+)}/U', ('YAMLMap' . (count($maps) - 1) . 's'), $inline, 1); + } + if ($i++ >= 10) break; + } while (strpos ($inline, '[') !== false || strpos ($inline, '{') !== false); + $explode = explode(',',$inline); + $explode = array_map('trim', $explode); + $stringi = 0; $i = 0; + while (1) { + // Re-add the sequences + if (!empty($seqs)) { + foreach ($explode as $key => $value) { + if (strpos($value,'YAMLSeq') !== false) { + foreach ($seqs as $seqk => $seq) { + $explode[$key] = str_replace(('YAMLSeq'.$seqk.'s'),$seq,$value); + $value = $explode[$key]; + } + } + } + } + // Re-add the mappings + if (!empty($maps)) { + foreach ($explode as $key => $value) { + if (strpos($value,'YAMLMap') !== false) { + foreach ($maps as $mapk => $map) { + $explode[$key] = str_replace(('YAMLMap'.$mapk.'s'), $map, $value); + $value = $explode[$key]; + } + } + } + } + // Re-add the strings + if (!empty($saved_strings)) { + foreach ($explode as $key => $value) { + while (strpos($value,'YAMLString') !== false) { + $explode[$key] = preg_replace('/YAMLString/',$saved_strings[$stringi],$value, 1); + unset($saved_strings[$stringi]); + ++$stringi; + $value = $explode[$key]; + } + } + } + // Re-add the empties + if (!empty($saved_empties)) { + foreach ($explode as $key => $value) { + while (strpos($value,'YAMLEmpty') !== false) { + $explode[$key] = preg_replace('/YAMLEmpty/', '', $value, 1); + $value = $explode[$key]; + } + } + } + $finished = true; + foreach ($explode as $key => $value) { + if (strpos($value,'YAMLSeq') !== false) { + $finished = false; break; + } + if (strpos($value,'YAMLMap') !== false) { + $finished = false; break; + } + if (strpos($value,'YAMLString') !== false) { + $finished = false; break; + } + if (strpos($value,'YAMLEmpty') !== false) { + $finished = false; break; + } + } + if ($finished) break; + $i++; + if ($i > 10) + break; // Prevent infinite loops. + } + return $explode; + } + private function literalBlockContinues ($line, $lineIndent) { + if (!trim($line)) return true; + if (strlen($line) - strlen(ltrim($line)) > $lineIndent) return true; + return false; + } + private function referenceContentsByAlias ($alias) { + do { + if (!isset($this->SavedGroups[$alias])) { echo "Bad group name: $alias."; break; } + $groupPath = $this->SavedGroups[$alias]; + $value = $this->result; + foreach ($groupPath as $k) { + $value = $value[$k]; + } + } while (false); + return $value; + } + private function addArrayInline ($array, $indent) { + $CommonGroupPath = $this->path; + if (empty ($array)) return false; + foreach ($array as $k => $_) { + $this->addArray(array($k => $_), $indent); + $this->path = $CommonGroupPath; + } + return true; + } + private function addArray ($incoming_data, $incoming_indent) { + // print_r ($incoming_data); + if (count ($incoming_data) > 1) + return $this->addArrayInline ($incoming_data, $incoming_indent); + $key = key ($incoming_data); + $value = isset($incoming_data[$key]) ? $incoming_data[$key] : null; + if ($key === '__!YAMLZero') $key = '0'; + if ($incoming_indent == 0 && !$this->_containsGroupAlias && !$this->_containsGroupAnchor) { // Shortcut for root-level values. + if ($key || $key === '' || $key === '0') { + $this->result[$key] = $value; + } else { + $this->result[] = $value; end ($this->result); $key = key ($this->result); + } + $this->path[$incoming_indent] = $key; + return; + } + $history = array(); + // Unfolding inner array tree. + $history[] = $_arr = $this->result; + foreach ($this->path as $k) { + $history[] = $_arr = $_arr[$k]; + } + if ($this->_containsGroupAlias) { + $value = $this->referenceContentsByAlias($this->_containsGroupAlias); + $this->_containsGroupAlias = false; + } + // Adding string or numeric key to the innermost level or $this->arr. + if (is_string($key) && $key == '<<') { + if (!is_array ($_arr)) { $_arr = array (); } + $_arr = array_merge ($_arr, $value); + } else if ($key || $key === '' || $key === '0') { + if (!is_array ($_arr)) + $_arr = array ($key=>$value); + else + $_arr[$key] = $value; + } else { + if (!is_array ($_arr)) { $_arr = array ($value); $key = 0; } + else { $_arr[] = $value; end ($_arr); $key = key ($_arr); } + } + $reverse_path = array_reverse($this->path); + $reverse_history = array_reverse ($history); + $reverse_history[0] = $_arr; + $cnt = count($reverse_history) - 1; + for ($i = 0; $i < $cnt; $i++) { + $reverse_history[$i+1][$reverse_path[$i]] = $reverse_history[$i]; + } + $this->result = $reverse_history[$cnt]; + $this->path[$incoming_indent] = $key; + if ($this->_containsGroupAnchor) { + $this->SavedGroups[$this->_containsGroupAnchor] = $this->path; + if (is_array ($value)) { + $k = key ($value); + if (!is_int ($k)) { + $this->SavedGroups[$this->_containsGroupAnchor][$incoming_indent + 2] = $k; + } + } + $this->_containsGroupAnchor = false; + } + } + private static function startsLiteralBlock ($line) { + $lastChar = substr (trim($line), -1); + if ($lastChar != '>' && $lastChar != '|') return false; + if ($lastChar == '|') return $lastChar; + // HTML tags should not be counted as literal blocks. + if (preg_match ('#<.*?>$#', $line)) return false; + return $lastChar; + } + private static function greedilyNeedNextLine($line) { + $line = trim ($line); + if (!strlen($line)) return false; + if (substr ($line, -1, 1) == ']') return false; + if ($line[0] == '[') return true; + if (preg_match ('#^[^:]+?:\s*\[#', $line)) return true; + return false; + } + private function addLiteralLine ($literalBlock, $line, $literalBlockStyle, $indent = -1) { + $line = self::stripIndent($line, $indent); + if ($literalBlockStyle !== '|') { + $line = self::stripIndent($line); + } + $line = rtrim ($line, "\r\n\t ") . "\n"; + if ($literalBlockStyle == '|') { + return $literalBlock . $line; + } + if (strlen($line) == 0) + return rtrim($literalBlock, ' ') . "\n"; + if ($line == "\n" && $literalBlockStyle == '>') { + return rtrim ($literalBlock, " \t") . "\n"; + } + if ($line != "\n") + $line = trim ($line, "\r\n ") . " "; + return $literalBlock . $line; + } + function revertLiteralPlaceHolder ($lineArray, $literalBlock) { + foreach ($lineArray as $k => $_) { + if (is_array($_)) + $lineArray[$k] = $this->revertLiteralPlaceHolder ($_, $literalBlock); + else if (substr($_, -1 * strlen ($this->LiteralPlaceHolder)) == $this->LiteralPlaceHolder) + $lineArray[$k] = rtrim ($literalBlock, " \r\n"); + } + return $lineArray; + } + private static function stripIndent ($line, $indent = -1) { + if ($indent == -1) $indent = strlen($line) - strlen(ltrim($line)); + return substr ($line, $indent); + } + private function getParentPathByIndent ($indent) { + if ($indent == 0) return array(); + $linePath = $this->path; + do { + end($linePath); $lastIndentInParentPath = key($linePath); + if ($indent <= $lastIndentInParentPath) array_pop ($linePath); + } while ($indent <= $lastIndentInParentPath); + return $linePath; + } + private function clearBiggerPathValues ($indent) { + if ($indent == 0) $this->path = array(); + if (empty ($this->path)) return true; + foreach ($this->path as $k => $_) { + if ($k > $indent) unset ($this->path[$k]); + } + return true; + } + private static function isComment ($line) { + if (!$line) return false; + if ($line[0] == '#') return true; + if (trim($line, " \r\n\t") == '---') return true; + return false; + } + private static function isEmpty ($line) { + return (trim ($line) === ''); + } + private function isArrayElement ($line) { + if (!$line || !is_scalar($line)) return false; + if (substr($line, 0, 2) != '- ') return false; + if (strlen ($line) > 3) + if (substr($line,0,3) == '---') return false; + return true; + } + private function isHashElement ($line) { + return strpos($line, ':'); + } + private function isLiteral ($line) { + if ($this->isArrayElement($line)) return false; + if ($this->isHashElement($line)) return false; + return true; + } + private static function unquote ($value) { + if (!$value) return $value; + if (!is_string($value)) return $value; + if ($value[0] == '\'') return trim ($value, '\''); + if ($value[0] == '"') return trim ($value, '"'); + return $value; + } + private function startsMappedSequence ($line) { + return (substr($line, 0, 2) == '- ' && substr ($line, -1, 1) == ':'); + } + private function returnMappedSequence ($line) { + $array = array(); + $key = self::unquote(trim(substr($line,1,-1))); + $array[$key] = array(); + $this->delayedPath = array(strpos ($line, $key) + $this->indent => $key); + return array($array); + } + private function checkKeysInValue($value) { + if (strchr('[{"\'', $value[0]) === false) { + if (strchr($value, ': ') !== false) { + throw new Exception('Too many keys: '.$value); + } + } + } + private function returnMappedValue ($line) { + $this->checkKeysInValue($line); + $array = array(); + $key = self::unquote (trim(substr($line,0,-1))); + $array[$key] = ''; + return $array; + } + private function startsMappedValue ($line) { + return (substr ($line, -1, 1) == ':'); + } + private function isPlainArray ($line) { + return ($line[0] == '[' && substr ($line, -1, 1) == ']'); + } + private function returnPlainArray ($line) { + return $this->_toType($line); + } + private function returnKeyValuePair ($line) { + $array = array(); + $key = ''; + if (strpos ($line, ': ')) { + // It's a key/value pair most likely + // If the key is in double quotes pull it out + if (($line[0] == '"' || $line[0] == "'") && preg_match('/^(["\'](.*)["\'](\s)*:)/',$line,$matches)) { + $value = trim(str_replace($matches[1],'',$line)); + $key = $matches[2]; + } else { + // Do some guesswork as to the key and the value + $explode = explode(': ', $line); + $key = trim(array_shift($explode)); + $value = trim(implode(': ', $explode)); + $this->checkKeysInValue($value); + } + // Set the type of the value. Int, string, etc + $value = $this->_toType($value); + if ($key === '0') $key = '__!YAMLZero'; + $array[$key] = $value; + } else { + $array = array ($line); + } + return $array; + } + private function returnArrayElement ($line) { + if (strlen($line) <= 1) return array(array()); // Weird %) + $array = array(); + $value = trim(substr($line,1)); + $value = $this->_toType($value); + if ($this->isArrayElement($value)) { + $value = $this->returnArrayElement($value); + } + $array[] = $value; + return $array; + } + private function nodeContainsGroup ($line) { + $symbolsForReference = 'A-z0-9_\-'; + if (strpos($line, '&') === false && strpos($line, '*') === false) return false; // Please die fast ;-) + if ($line[0] == '&' && preg_match('/^(&['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1]; + if ($line[0] == '*' && preg_match('/^(\*['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1]; + if (preg_match('/(&['.$symbolsForReference.']+)$/', $line, $matches)) return $matches[1]; + if (preg_match('/(\*['.$symbolsForReference.']+$)/', $line, $matches)) return $matches[1]; + if (preg_match ('#^\s*<<\s*:\s*(\*[^\s]+).*$#', $line, $matches)) return $matches[1]; + return false; + } + private function addGroup ($line, $group) { + if ($group[0] == '&') $this->_containsGroupAnchor = substr ($group, 1); + if ($group[0] == '*') $this->_containsGroupAlias = substr ($group, 1); + //print_r ($this->path); + } + private function stripGroup ($line, $group) { + $line = trim(str_replace($group, '', $line)); + return $line; + } +} +} +// Enable use of Spyc from command line +// The syntax is the following: php Spyc.php spyc.yaml +do { + if (PHP_SAPI != 'cli') break; + if (empty ($_SERVER['argc']) || $_SERVER['argc'] < 2) break; + if (empty ($_SERVER['PHP_SELF']) || FALSE === strpos ($_SERVER['PHP_SELF'], 'Spyc.php') ) break; + $file = $argv[1]; + echo json_encode (spyc_load_file ($file)); +} while (0); \ No newline at end of file -- 1.9.1