Store.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. <?php
  2. /*
  3. * FecShop file.
  4. *
  5. * @link http://www.fecshop.com/
  6. * @copyright Copyright (c) 2016 FecShop Software LLC
  7. * @license http://www.fecshop.com/license/
  8. */
  9. namespace fecshop\services;
  10. use Yii;
  11. use yii\base\InvalidValueException;
  12. /**
  13. * store service
  14. * @author Terry Zhao <2358269014@qq.com>
  15. * @since 1.0
  16. */
  17. class Store extends Service
  18. {
  19. /**
  20. * init by config file.
  21. * all stores config . include : domain,language,theme,themePackage.
  22. */
  23. public $stores;
  24. public $store;
  25. /**
  26. * current store language,for example: en_US,fr_FR.
  27. */
  28. public $currentLang;
  29. /**
  30. * current store language name.
  31. */
  32. public $currentLangName;
  33. /**
  34. * current store theme package.
  35. */
  36. //public $currentThemePackage = 'default';
  37. /**
  38. * current store theme.
  39. */
  40. //public $currentTheme = 'default';
  41. /**
  42. * 当前store的key,也就是当前的store.
  43. */
  44. public $currentStore;
  45. /**
  46. * current language code example : fr es cn ru.
  47. */
  48. public $currentLangCode;
  49. public $thirdLogin;
  50. //public $https;
  51. public $serverLangs;
  52. public $apiAppNameArr = ['appserver','appapi'];
  53. // 是否是api入口
  54. public function isApiStore()
  55. {
  56. $appName = Yii::$app->params['appName'];
  57. if ($appName && in_array($appName, $this->apiAppNameArr)) {
  58. return true;
  59. } else {
  60. return false;
  61. }
  62. }
  63. /**
  64. * 得到当前入口的名字
  65. * @return mixed
  66. */
  67. public function getCurrentAppName()
  68. {
  69. return Yii::$app->params['appName'];
  70. }
  71. /**
  72. * Bootstrap:init website, class property $currentLang ,$currentTheme and $currentStore.
  73. * if you not config this ,default class property will be set.
  74. * if current store_code is not config , InvalidValueException will be throw.
  75. * class property $currentStore will be set value $store_code.
  76. * @param $app
  77. */
  78. protected function actionBootstrap($app)
  79. {
  80. $host = explode('//', $app->getHomeUrl());
  81. $stores = $this->stores;
  82. $init_complete = 0;
  83. if (is_array($stores) && !empty($stores)) {
  84. foreach ($stores as $store_code => $store) {
  85. if ($host[1] == $store_code) {
  86. $this->html5DeviceCheckAndRedirect($store_code, $store);
  87. Yii::$service->store->currentStore = $store_code;
  88. $this->store = $store;
  89. if (isset($store['language']) && !empty($store['language'])) {
  90. Yii::$service->store->currentLang = $store['language'];
  91. Yii::$service->store->currentLangCode = Yii::$service->fecshoplang->getLangCodeByLanguage($store['language']);
  92. Yii::$service->store->currentLangName = $store['languageName'];
  93. Yii::$service->page->translate->setLanguage($store['language']);
  94. }
  95. if (isset($store['theme']) && !empty($store['theme'])) {
  96. Yii::$service->store->currentTheme = $store['theme'];
  97. }
  98. // set local theme dir.
  99. if (isset($store['localThemeDir']) && $store['localThemeDir']) {
  100. //Yii::$service->page->theme->localThemeDir = $store['localThemeDir'];
  101. Yii::$service->page->theme->setLocalThemeDir($store['localThemeDir']);
  102. }
  103. // set third theme dir.
  104. if (isset($store['thirdThemeDir']) && $store['thirdThemeDir']) {
  105. //Yii::$service->page->theme->thirdThemeDir = $store['thirdThemeDir'];
  106. Yii::$service->page->theme->setThirdThemeDir($store['thirdThemeDir']);
  107. }
  108. // init store currency.
  109. if (isset($store['currency']) && !empty($store['currency'])) {
  110. $currency = $store['currency'];
  111. } else {
  112. $currency = '';
  113. }
  114. Yii::$service->page->currency->initCurrency($currency);
  115. /**
  116. * current domain is config is store config.
  117. */
  118. $init_complete = 1;
  119. $this->thirdLogin = $store['thirdLogin'];
  120. /**
  121. * appserver 部分
  122. */
  123. if (isset($store['serverLangs']) && !empty($store['serverLangs'])) {
  124. $this->serverLangs = $store['serverLangs'];
  125. }
  126. $headers = Yii::$app->request->getHeaders();
  127. if (isset($headers['fecshop-lang']) && $headers['fecshop-lang']) {
  128. $h_lang = $headers['fecshop-lang'];
  129. if (is_array($this->serverLangs)) {
  130. foreach ($this->serverLangs as $one) {
  131. if ($one['code'] == $h_lang) {
  132. Yii::$service->store->currentLangCode = $h_lang;
  133. Yii::$service->store->currentLang = $one['language'];
  134. Yii::$service->store->currentLangName = $one['languageName'];
  135. Yii::$service->page->translate->setLanguage($one['language']);
  136. }
  137. }
  138. }
  139. }
  140. if (isset($headers['fecshop-currency']) && $headers['fecshop-currency']) {
  141. $currentC = Yii::$service->page->currency->getCurrentCurrency();
  142. if ($currentC != $headers['fecshop-currency']) {
  143. Yii::$service->page->currency->setCurrentCurrency($headers['fecshop-currency']);
  144. }
  145. }
  146. break;
  147. }
  148. }
  149. }
  150. if (!$init_complete) {
  151. throw new InvalidValueException('this domain is not config in store component');
  152. }
  153. }
  154. /**
  155. * @param $store_code | String
  156. * @param $store | Array
  157. * mobile device url redirect.
  158. * pc端自动跳转到html5端的检测
  159. */
  160. protected function html5DeviceCheckAndRedirect($store_code, $store)
  161. {
  162. if (!isset($store['mobile'])) {
  163. return;
  164. }
  165. $enable = isset($store['mobile']['enable']) ? $store['mobile']['enable'] : false;
  166. if (!$enable) {
  167. return;
  168. }
  169. $condition = isset($store['mobile']['condition']) ? $store['mobile']['condition'] : false;
  170. $redirectDomain = isset($store['mobile']['redirectDomain']) ? $store['mobile']['redirectDomain'] : false;
  171. $redirectType = isset($store['mobile']['type']) ? $store['mobile']['type'] : false;
  172. if (is_array($condition) && !empty($condition) && !empty($redirectDomain) && $redirectType === 'apphtml5') {
  173. $mobileDetect = Yii::$service->helper->mobileDetect;
  174. $mobile_https = (isset($store['mobile']['https']) && $store['mobile']['https']) ? true : false;
  175. if (in_array('phone', $condition) && in_array('tablet', $condition)) {
  176. if ($mobileDetect->isMobile()) {
  177. $this->redirectAppHtml5Mobile($store_code, $redirectDomain, $mobile_https);
  178. }
  179. } elseif (in_array('phone', $condition)) {
  180. if ($mobileDetect->isMobile() && !$mobileDetect->isTablet()) {
  181. $this->redirectAppHtml5Mobile($store_code, $redirectDomain, $mobile_https);
  182. }
  183. } elseif (in_array('tablet', $condition)) {
  184. if ($mobileDetect->isTablet()) {
  185. $this->redirectAppHtml5Mobile($store_code, $redirectDomain, $mobile_https);
  186. }
  187. }
  188. }
  189. }
  190. /**
  191. * @param $store_code | String
  192. * @param $redirectDomain | String
  193. * 检测,html5端跳转检测
  194. */
  195. protected function redirectAppHtml5Mobile($store_code, $redirectDomain, $mobile_https)
  196. {
  197. $currentUrl = Yii::$service->url->getCurrentUrl();
  198. $redirectUrl = str_replace($store_code, $redirectDomain, $currentUrl);
  199. // pc端跳转到html5,可能一个是https,一个是http,因此需要下面的代码进行转换。
  200. if ($mobile_https) {
  201. if (strstr($redirectUrl, 'https://') || strstr($redirectUrl, 'http://')) {
  202. $redirectUrl = str_replace('http://', 'https://', $redirectUrl);
  203. } else {
  204. $redirectUrl = 'https:'.$redirectUrl;
  205. }
  206. } else {
  207. if (strstr($redirectUrl, 'https://') || strstr($redirectUrl, 'http://')) {
  208. $redirectUrl = str_replace('https://', 'http://', $redirectUrl);
  209. } else {
  210. $redirectUrl = 'http:'.$redirectUrl;
  211. }
  212. }
  213. header('Location:'.$redirectUrl);
  214. exit;
  215. }
  216. /**
  217. * @return boolean, 检测是否属于满足跳转到appserver的条件
  218. */
  219. public function isAppServerMobile()
  220. {
  221. $store = $this->store;
  222. $condition = isset($store['mobile']['condition']) ? $store['mobile']['condition'] : false;
  223. $redirectDomain = isset($store['mobile']['redirectDomain']) ? $store['mobile']['redirectDomain'] : false;
  224. $redirectType = isset($store['mobile']['type']) ? $store['mobile']['type'] : false;
  225. if (is_array($condition) && !empty($condition) && !empty($redirectDomain) && $redirectType === 'appserver') {
  226. $mobileDetect = Yii::$service->helper->mobileDetect;
  227. if (in_array('phone', $condition) && in_array('tablet', $condition)) {
  228. if ($mobileDetect->isMobile()) {
  229. return true;
  230. }
  231. } elseif (in_array('phone', $condition)) {
  232. if ($mobileDetect->isMobile() && !$mobileDetect->isTablet()) {
  233. return true;
  234. }
  235. } elseif (in_array('tablet', $condition)) {
  236. if ($mobileDetect->isTablet()) {
  237. return true;
  238. }
  239. }
  240. }
  241. return false;
  242. }
  243. /**
  244. * @param $urlPath | String,跳转到vue端的url Path
  245. * @return boolean, 生成vue端的url,然后进行跳转。
  246. */
  247. public function redirectAppServerMobile($urlPath)
  248. {
  249. $store = $this->store;
  250. $redirectDomain = isset($store['mobile']['redirectDomain']) ? $store['mobile']['redirectDomain'] : false;
  251. $mobile_https = (isset($store['mobile']['https']) && $store['mobile']['https']) ? 'https://' : 'http://';
  252. $host = $mobile_https.$redirectDomain.'/#/';
  253. $urlParam = $_SERVER["QUERY_STRING"];
  254. // 得到当前的语言
  255. if ($urlParam) {
  256. $urlParam .= '&lang='.$this->currentLangCode;
  257. } else {
  258. $urlParam .= 'lang='.$this->currentLangCode;
  259. }
  260. $redirectUrl = $host.$urlPath.'?'.$urlParam;
  261. header('Location:'.$redirectUrl);
  262. exit;
  263. }
  264. /**
  265. * @param $attrVal|array , language attr array , like ['title_en' => 'xxxx','title_fr' => 'yyyy']
  266. * @param $attrName|String, attribute name ,like: title ,description.
  267. * if object or array attribute is a language attribute, you can get current
  268. * language value by this function.
  269. * if lang attribute in current store language is empty , default language attribute will be return.
  270. * if attribute in default language value is empty, $attrVal will be return.
  271. */
  272. protected function actionGetStoreAttrVal($attrVal, $attrName)
  273. {
  274. $lang = $this->currentLangCode;
  275. return Yii::$service->fecshoplang->getLangAttrVal($attrVal, $attrName, $lang);
  276. }
  277. /**
  278. * @return array
  279. * get all store info, one item in array format is: ['storeCode' => 'store language'].
  280. */
  281. protected function actionGetStoresLang()
  282. {
  283. $stores = $this->stores;
  284. $topLang = [];
  285. foreach ($stores as $storeCode=> $store) {
  286. $languageName = $store['languageName'];
  287. $topLang[$storeCode] = $languageName;
  288. }
  289. return $topLang;
  290. }
  291. }