PageRenderTime 277ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/catalog/controller/common/seo_pro.php

https://gitlab.com/AndreyLes/top-tap
PHP | 434 lines | 356 code | 76 blank | 2 comment | 103 complexity | bda2ed58828fe0578896eb37b1c9c111 MD5 | raw file
  1. <?php
  2. class ControllerCommonSeoPro extends Controller {
  3. private $cache_data = null;
  4. public function __construct($registry) {
  5. parent::__construct($registry);
  6. $this->cache_data = $this->cache->get('seo_pro');
  7. if (!$this->cache_data) {
  8. $query = $this->db->query("SELECT LOWER(`keyword`) as 'keyword', `query` FROM " . DB_PREFIX . "url_alias");
  9. $this->cache_data = array();
  10. foreach ($query->rows as $row) {
  11. $this->cache_data['keywords'][$row['keyword']] = $row['query'];
  12. $this->cache_data['queries'][$row['query']] = $row['keyword'];
  13. }
  14. $this->cache->set('seo_pro', $this->cache_data);
  15. }
  16. }
  17. public function index() {
  18. // Add rewrite to url class
  19. if ($this->config->get('config_seo_url')) {
  20. $this->url->addRewrite($this);
  21. } else {
  22. return;
  23. }
  24. // Decode URL
  25. if (!isset($this->request->get['_route_'])) {
  26. $this->validate();
  27. } else {
  28. $route = $this->request->get['_route_'];
  29. unset($this->request->get['_route_']);
  30. $parts = explode('/', trim(utf8_strtolower($route), '/'));
  31. list($last_part) = explode('.', array_pop($parts));
  32. array_push($parts, $last_part);
  33. $rows = array();
  34. foreach ($parts as $keyword) {
  35. if (isset($this->cache_data['keywords'][$keyword])) {
  36. $rows[] = array('keyword' => $keyword, 'query' => $this->cache_data['keywords'][$keyword]);
  37. }
  38. }
  39. if (count($rows) == sizeof($parts)) {
  40. $queries = array();
  41. foreach ($rows as $row) {
  42. $queries[utf8_strtolower($row['keyword'])] = $row['query'];
  43. }
  44. reset($parts);
  45. foreach ($parts as $part) {
  46. $url = explode('=', $queries[$part], 2);
  47. if ($url[0] == 'product_id') {
  48. $this->request->get['product_id'] = $url[1];
  49. }
  50. if ($url[0] == 'category_id') {
  51. if (!isset($this->request->get['path'])) {
  52. $this->request->get['path'] = $url[1];
  53. } else {
  54. $this->request->get['path'] .= '_' . $url[1];
  55. }
  56. }
  57. if ($url[0] == 'news_id') {
  58. $this->request->get['news_id'] = $url[1];
  59. }
  60. if ($url[0] == 'news_category_id') {
  61. if (!isset($this->request->get['ncat'])) {
  62. $this->request->get['ncat'] = $url[1];
  63. } else {
  64. $this->request->get['ncat'] .= '_' . $url[1];
  65. }
  66. }
  67. if ($url[0] == 'manufacturer_id') {
  68. $this->request->get['manufacturer_id'] = $url[1];
  69. }
  70. if ($url[0] == 'information_id') {
  71. $this->request->get['information_id'] = $url[1];
  72. } else{
  73. $route = $url[0];
  74. }
  75. }
  76. } else {
  77. $this->request->get['route'] = 'error/not_found';
  78. }
  79. if (isset($this->request->get['product_id'])) {
  80. $this->request->get['route'] = 'product/product';
  81. if (!isset($this->request->get['path'])) {
  82. $path = $this->getPathByProduct($this->request->get['product_id']);
  83. if ($path) $this->request->get['path'] = $path;
  84. }
  85. } elseif (isset($this->request->get['news_id'])) {
  86. $this->request->get['route'] = 'news/news';
  87. if (!isset($this->request->get['ncat'])) {
  88. $ncat = $this->getNcatByNews($this->request->get['news_id']);
  89. if ($ncat) $this->request->get['ncat'] = $ncat;
  90. }
  91. } elseif (isset($this->request->get['path'])) {
  92. $this->request->get['route'] = 'product/category';
  93. } elseif (isset($this->request->get['ncat'])) {
  94. $this->request->get['route'] = 'news/news_category';
  95. } elseif (isset($this->request->get['manufacturer_id'])) {
  96. $this->request->get['route'] = 'product/manufacturer/info';
  97. } elseif (isset($this->request->get['information_id'])) {
  98. $this->request->get['route'] = 'information/information';
  99. } else {
  100. if (isset($queries[$parts[0]])) {
  101. $this->request->get['route'] = $queries[$parts[0]];
  102. }
  103. }
  104. $this->validate();
  105. if (isset($this->request->get['route'])) {
  106. return $this->forward($this->request->get['route']);
  107. }
  108. }
  109. }
  110. public function rewrite($link) {
  111. if (!$this->config->get('config_seo_url')) return $link;
  112. $seo_url = '';
  113. $component = parse_url(str_replace('&amp;', '&', $link));
  114. $data = array();
  115. parse_str($component['query'], $data);
  116. $route = $data['route'];
  117. unset($data['route']);
  118. switch ($route) {
  119. case 'product/product':
  120. if (isset($data['product_id'])) {
  121. $tmp = $data;
  122. $data = array();
  123. if ($this->config->get('config_seo_url_include_path')) {
  124. $data['path'] = $this->getPathByProduct($tmp['product_id']);
  125. if (!$data['path']) return $link;
  126. }
  127. $data['product_id'] = $tmp['product_id'];
  128. if (isset($tmp['tracking'])) {
  129. $data['tracking'] = $tmp['tracking'];
  130. }
  131. }
  132. break;
  133. case 'product/category':
  134. if (isset($data['path'])) {
  135. $category = explode('_', $data['path']);
  136. $category = end($category);
  137. $data['path'] = $this->getPathByCategory($category);
  138. if (!$data['path']) return $link;
  139. }
  140. break;
  141. case 'news/news':
  142. if (isset($data['news_id'])) {
  143. $tmp = $data;
  144. $data = array();
  145. if ($this->config->get('config_seo_url_include_path')) {
  146. $data['ncat'] = $this->getNcatByNews($tmp['news_id']);
  147. if (!$data['ncat']) return $link;
  148. }
  149. $data['news_id'] = $tmp['news_id'];
  150. if (isset($tmp['tracking'])) {
  151. $data['tracking'] = $tmp['tracking'];
  152. }
  153. }
  154. break;
  155. case 'news/news_category':
  156. if (isset($data['ncat'])) {
  157. $news_category = explode('_', $data['ncat']);
  158. $news_category = end($news_category);
  159. $data['ncat'] = $this->getNcatByNcategory($news_category);
  160. if (!$data['ncat']) return $link;
  161. }
  162. break;
  163. case 'product/product/review':
  164. case 'information/information/info':
  165. case 'account/return/insert':
  166. return $link;
  167. break;
  168. default:
  169. break;
  170. }
  171. if ($component['scheme'] == 'https') {
  172. $link = $this->config->get('config_ssl');
  173. } else {
  174. $link = $this->config->get('config_url');
  175. }
  176. $link .= 'index.php?route=' . $route;
  177. if (count($data)) {
  178. $link .= '&amp;' . urldecode(http_build_query($data, '', '&amp;'));
  179. }
  180. $queries = array();
  181. foreach ($data as $key => $value) {
  182. switch ($key) {
  183. case 'product_id':
  184. case 'news_id':
  185. case 'manufacturer_id':
  186. case 'category_id':
  187. case 'news_category_id':
  188. case 'information_id':
  189. $queries[] = $key . '=' . $value;
  190. unset($data[$key]);
  191. $postfix = 1;
  192. break;
  193. case 'path':
  194. $categories = explode('_', $value);
  195. foreach ($categories as $category) {
  196. $queries[] = 'category_id=' . $category;
  197. }
  198. unset($data[$key]);
  199. break;
  200. default:
  201. break;
  202. case 'ncat':
  203. $news_categories = explode('_', $value);
  204. foreach ($news_categories as $news_category) {
  205. $queries[] = 'news_category_id=' . $news_category;
  206. }
  207. unset($data[$key]);
  208. break;
  209. default:
  210. break;
  211. }
  212. }
  213. if(empty($queries)) {
  214. $queries[] = $route;
  215. if ($route != 'common/home') {$postfix = 1;}
  216. }
  217. $rows = array();
  218. foreach($queries as $query) {
  219. if(isset($this->cache_data['queries'][$query])) {
  220. $rows[] = array('query' => $query, 'keyword' => $this->cache_data['queries'][$query]);
  221. }
  222. }
  223. if(count($rows) == count($queries)) {
  224. $aliases = array();
  225. foreach($rows as $row) {
  226. $aliases[$row['query']] = $row['keyword'];
  227. }
  228. foreach($queries as $query) {
  229. $seo_url .= '/' . rawurlencode($aliases[$query]);
  230. }
  231. }
  232. if ($seo_url == '') return $link;
  233. $seo_url = trim($seo_url, '/');
  234. if ($component['scheme'] == 'https') {
  235. $seo_url = $this->config->get('config_ssl') . $seo_url;
  236. } else {
  237. $seo_url = $this->config->get('config_url') . $seo_url;
  238. }
  239. if (isset($postfix)) {
  240. $seo_url .= trim($this->config->get('config_seo_url_postfix'));
  241. } else {
  242. $seo_url .= '/';
  243. }
  244. if(substr($seo_url, -2) == '//') {
  245. $seo_url = substr($seo_url, 0, -1);
  246. }
  247. if (count($data)) {
  248. $seo_url .= '?' . urldecode(http_build_query($data, '', '&amp;'));
  249. }
  250. return $seo_url;
  251. }
  252. private function getPathByProduct($product_id) {
  253. $product_id = (int)$product_id;
  254. if ($product_id < 1) return false;
  255. static $path = null;
  256. if (!is_array($path)) {
  257. $path = $this->cache->get('product.seopath');
  258. if (!is_array($path)) $path = array();
  259. }
  260. if (!isset($path[$product_id])) {
  261. $query = $this->db->query("SELECT category_id FROM " . DB_PREFIX . "product_to_category WHERE product_id = '" . $product_id . "' ORDER BY main_category DESC LIMIT 1");
  262. $path[$product_id] = $this->getPathByCategory($query->num_rows ? (int)$query->row['category_id'] : 0);
  263. $this->cache->set('product.seopath', $path);
  264. }
  265. return $path[$product_id];
  266. }
  267. private function getNcatByNews($news_id) {
  268. $news_id = (int)$news_id;
  269. if ($news_id < 1) return false;
  270. static $ncat = null;
  271. if (!is_array($ncat)) {
  272. $ncat = $this->cache->get('news.seoncat');
  273. if (!is_array($ncat)) $ncat = array();
  274. }
  275. if (!isset($ncat[$news_id])) {
  276. $query = $this->db->query("SELECT news_category_id FROM " . DB_PREFIX . "news_to_news_category WHERE news_id = '" . $news_id . "' ORDER BY main_category DESC LIMIT 1");
  277. $ncat[$news_id] = $this->getNcatByNcategory($query->num_rows ? (int)$query->row['news_category_id'] : 0);
  278. $this->cache->set('news.seoncat', $ncat);
  279. }
  280. return $ncat[$news_id];
  281. }
  282. private function getPathByCategory($category_id) {
  283. $category_id = (int)$category_id;
  284. if ($category_id < 1) return false;
  285. static $path = null;
  286. if (!is_array($path)) {
  287. $path = $this->cache->get('category.seopath');
  288. if (!is_array($path)) $path = array();
  289. }
  290. if (!isset($path[$category_id])) {
  291. $max_level = 10;
  292. $sql = "SELECT CONCAT_WS('_'";
  293. for ($i = $max_level-1; $i >= 0; --$i) {
  294. $sql .= ",t$i.category_id";
  295. }
  296. $sql .= ") AS path FROM " . DB_PREFIX . "category t0";
  297. for ($i = 1; $i < $max_level; ++$i) {
  298. $sql .= " LEFT JOIN " . DB_PREFIX . "category t$i ON (t$i.category_id = t" . ($i-1) . ".parent_id)";
  299. }
  300. $sql .= " WHERE t0.category_id = '" . $category_id . "'";
  301. $query = $this->db->query($sql);
  302. $path[$category_id] = $query->num_rows ? $query->row['path'] : false;
  303. $this->cache->set('category.seopath', $path);
  304. }
  305. return $path[$category_id];
  306. }
  307. private function getNcatByNcategory($news_category_id) {
  308. $news_category_id = (int)$news_category_id;
  309. if ($news_category_id < 1) return false;
  310. static $ncat = null;
  311. if (!is_array($ncat)) {
  312. $ncat = $this->cache->get('news_category.seoncat');
  313. if (!is_array($ncat)) $ncat = array();
  314. }
  315. if (!isset($ncat[$news_category_id])) {
  316. $max_level = 10;
  317. $sql = "SELECT CONCAT_WS('_'";
  318. for ($i = $max_level-1; $i >= 0; --$i) {
  319. $sql .= ",t$i.news_category_id";
  320. }
  321. $sql .= ") AS ncat FROM " . DB_PREFIX . "news_category t0";
  322. for ($i = 1; $i < $max_level; ++$i) {
  323. $sql .= " LEFT JOIN " . DB_PREFIX . "news_category t$i ON (t$i.news_category_id = t" . ($i-1) . ".parent_id)";
  324. }
  325. $sql .= " WHERE t0.news_category_id = '" . $news_category_id . "'";
  326. $query = $this->db->query($sql);
  327. $ncat[$news_category_id] = $query->num_rows ? $query->row['ncat'] : false;
  328. $this->cache->set('news_category.seoncat', $ncat);
  329. }
  330. return $ncat[$news_category_id];
  331. }
  332. private function validate() {
  333. if (empty($this->request->get['route']) || $this->request->get['route'] == 'error/not_found') {
  334. return;
  335. }
  336. if (isset($this->request->server['HTTP_X_REQUESTED_WITH']) && strtolower($this->request->server['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
  337. return;
  338. }
  339. if (isset($this->request->server['HTTPS']) && (($this->request->server['HTTPS'] == 'on') || ($this->request->server['HTTPS'] == '1'))) {
  340. $url = str_replace('&amp;', '&', $this->config->get('config_ssl') . ltrim($this->request->server['REQUEST_URI'], '/'));
  341. $seo = str_replace('&amp;', '&', $this->url->link($this->request->get['route'], $this->getQueryString(array('route')), 'SSL'));
  342. } else {
  343. $url = str_replace('&amp;', '&', $this->config->get('config_url') . ltrim($this->request->server['REQUEST_URI'], '/'));
  344. $seo = str_replace('&amp;', '&', $this->url->link($this->request->get['route'], $this->getQueryString(array('route')), 'NONSSL'));
  345. }
  346. if (rawurldecode($url) != rawurldecode($seo)) {
  347. header($this->request->server['SERVER_PROTOCOL'] . ' 301 Moved Permanently');
  348. $this->response->redirect($seo);
  349. }
  350. }
  351. private function getQueryString($exclude = array()) {
  352. if (!is_array($exclude)) {
  353. $exclude = array();
  354. }
  355. return urldecode(http_build_query(array_diff_key($this->request->get, array_flip($exclude))));
  356. }
  357. }
  358. ?>