Advertisement
Guest User

seo_url.php

a guest
Apr 14th, 2016
236
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.42 KB | None | 0 0
  1. <?php
  2. class ControllerCommonSeoPro extends Controller {
  3. private $cache_data = null;
  4. private $languages = array();
  5. private $config_language;
  6.  
  7. public function __construct($registry) {
  8. parent::__construct($registry);
  9. $this->cache_data = $this->cache->get('seo_pro');
  10. if (!$this->cache_data) {
  11. $query = $this->db->query("SELECT LOWER(`keyword`) as 'keyword', `query` FROM " . DB_PREFIX . "url_alias");
  12. $this->cache_data = array();
  13. foreach ($query->rows as $row) {
  14. $this->cache_data['keywords'][$row['keyword']] = $row['query'];
  15. $this->cache_data['queries'][$row['query']] = $row['keyword'];
  16. }
  17. $this->cache->set('seo_pro', $this->cache_data);
  18. }
  19.  
  20. $query = $this->db->query("SELECT `value` FROM `" . DB_PREFIX . "setting` WHERE `key` = 'config_language'");
  21. $this->config_language = $query->row['value'];
  22.  
  23. $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "language WHERE status = '1'");
  24.  
  25. foreach ($query->rows as $result) {
  26. $this->languages[$result['code']] = $result;
  27. }
  28.  
  29. }
  30.  
  31. public function index() {
  32.  
  33. $code = null;
  34.  
  35. // If language specified in URI - switch to code from URI
  36. if(isset($this->request->get['_route_'])) {
  37. $route_ = $this->request->get['_route_'];
  38. $tokens = explode('/', $this->request->get['_route_']);
  39.  
  40. if(array_key_exists($tokens[0], $this->languages)) {
  41. $code = $tokens[0];
  42. $this->request->get['_route_'] = substr($this->request->get['_route_'], strlen($code) + 1);
  43. }
  44.  
  45. if(trim($this->request->get['_route_']) == '' || trim($this->request->get['_route_']) == 'index.php') {
  46. unset($this->request->get['_route_']);
  47. }
  48. }
  49.  
  50. // Pavillion Theme fix for "original_route" param.
  51. // Theme: <http://themeforest.net/item/pavilion-premium-responsive-opencart-theme/9219645>
  52. if(isset($this->request->get['original_route'])) {
  53. unset($this->request->get['original_route']);
  54. }
  55.  
  56. // Detect language code
  57. if(!isset($code)) {
  58. if (isset($this->session->data['language'])) {
  59. $code = $this->session->data['language'];
  60. } elseif (isset($this->request->cookie['language'])) {
  61. $code = $this->request->cookie['language'];
  62. } else {
  63. $code = $this->config_language;
  64. }
  65. }
  66.  
  67. if(!isset($this->session->data['language']) || $this->session->data['language'] != $code) {
  68. $this->session->data['language'] = $code;
  69. }
  70.  
  71.  
  72. $xhttprequested =
  73. isset($this->request->server['HTTP_X_REQUESTED_WITH'])
  74. && (strtolower($this->request->server['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
  75.  
  76. $captcha = isset($this->request->get['route']) && $this->request->get['route']=='tool/captcha';
  77.  
  78. if(!$xhttprequested && !$captcha) {
  79. setcookie('language', $code, time() + 60 * 60 * 24 * 30, '/',
  80. ($this->request->server['HTTP_HOST'] != 'localhost') ? $this->request->server['HTTP_HOST'] : false);
  81. }
  82.  
  83.  
  84. $this->config->set('config_language_id', $this->languages[$code]['language_id']);
  85. $this->config->set('config_language', $this->languages[$code]['code']);
  86.  
  87. $language = new Language($this->languages[$code]['directory']);
  88. $language->load('default');
  89. $language->load($this->languages[$code]['directory']);
  90. $this->registry->set('language', $language);
  91.  
  92.  
  93. // Add rewrite to url class
  94. if ($this->config->get('config_seo_url')) {
  95. $this->url->addRewrite($this);
  96. } else {
  97. return;
  98. }
  99.  
  100. // Decode URL
  101. if (!isset($this->request->get['_route_'])) {
  102. $this->validate();
  103. } else {
  104. $route = $this->request->get['_route_'];
  105. unset($this->request->get['_route_']);
  106. $parts = explode('/', trim(utf8_strtolower($route), '/'));
  107. list($last_part) = explode('.', array_pop($parts));
  108. array_push($parts, $last_part);
  109.  
  110. $rows = array();
  111.  
  112. // OCFilter start
  113. foreach ($parts as $key => $keyword) {
  114. if (false !== strpos($keyword, ':')) {
  115. unset($parts[$key]);
  116.  
  117. continue;
  118. }
  119. // OCFilter end
  120.  
  121. if (isset($this->cache_data['keywords'][$keyword])) {
  122. $rows[] = array('keyword' => $keyword, 'query' => $this->cache_data['keywords'][$keyword]);
  123. }
  124. }
  125.  
  126. if (count($rows) == sizeof($parts)) {
  127. $queries = array();
  128. foreach ($rows as $row) {
  129. $queries[utf8_strtolower($row['keyword'])] = $row['query'];
  130. }
  131.  
  132. reset($parts);
  133.  
  134. // OCFilter start
  135. foreach ($parts as $key => $part) {
  136. if (false !== strpos($part, ':')) {
  137. unset($parts[$key]);
  138.  
  139. continue;
  140. }
  141. // OCFilter end
  142.  
  143.  
  144. // fix "undefined index" exception,
  145. // https://github.com/myopencart/ocStore/commit/51bd518ca3ee3330ae87314472f63def17dcf746
  146. if(!isset($queries[$part])) return false;
  147.  
  148. $url = explode('=', $queries[$part], 2);
  149.  
  150. if ($url[0] == 'category_id') {
  151. if (!isset($this->request->get['path'])) {
  152. $this->request->get['path'] = $url[1];
  153. } else {
  154. $this->request->get['path'] .= '_' . $url[1];
  155. }
  156. } elseif (count($url) > 1) {
  157. $this->request->get[$url[0]] = $url[1];
  158. }
  159. }
  160. } else {
  161. $this->request->get['route'] = 'error/not_found';
  162. }
  163.  
  164. if (isset($this->request->get['product_id'])) {
  165. $this->request->get['route'] = 'product/product';
  166. if (!isset($this->request->get['path'])) {
  167. $path = $this->getPathByProduct($this->request->get['product_id']);
  168. if ($path) $this->request->get['path'] = $path;
  169. }
  170. } elseif (isset($this->request->get['path'])) {
  171. $this->request->get['route'] = 'product/category';
  172. } elseif (isset($this->request->get['manufacturer_id'])) {
  173. $this->request->get['route'] = 'product/manufacturer/info';
  174. } elseif (isset($this->request->get['information_id'])) {
  175. $this->request->get['route'] = 'information/information';
  176.  
  177. // Compatibility with Shopencart News/Blog:
  178. } elseif (isset($this->request->get['news_id'])) {
  179. $this->request->get['route'] = 'news/article';
  180. } elseif (isset($this->request->get['author'])) {
  181. $this->request->get['route'] = 'news/ncategory';
  182. } elseif (isset($this->request->get['ncat'])) {
  183. $this->request->get['route'] = 'news/ncategory';
  184. } elseif (isset($this->request->get['author'])) {
  185. $this->request->get['route'] = 'news/ncategory';
  186.  
  187. } elseif(isset($this->cache_data['queries'][$route_])) {
  188. header($this->request->server['SERVER_PROTOCOL'] . ' 301 Moved Permanently');
  189. $this->response->redirect($this->cache_data['queries'][$route_]);
  190. } else {
  191. if (isset($queries[$parts[0]])) {
  192. $this->request->get['route'] = $queries[$parts[0]];
  193. }
  194. }
  195.  
  196.  
  197. $this->validate();
  198.  
  199. if (isset($this->request->get['route'])) {
  200. return new Action($this->request->get['route']);
  201. }
  202. }
  203. }
  204.  
  205. public function rewrite($link, $code = '') {
  206. if(!$code) {
  207. $code = $this->session->data['language'];
  208. }
  209. if($this->config->get('ocjazz_seopro_hide_default') && $code == $this->config_language) {
  210. $code='';
  211. }
  212. else {
  213. $code .='/';
  214. }
  215. if (!$this->config->get('config_seo_url')) return $link;
  216.  
  217. $seo_url = '';
  218.  
  219. $component = parse_url(str_replace('&amp;', '&', $link));
  220.  
  221. $data = array();
  222. parse_str($component['query'], $data);
  223.  
  224. $route = $data['route'];
  225. unset($data['route']);
  226.  
  227. switch ($route) {
  228. case 'common/home':
  229. if ($component['scheme'] == 'https') {
  230. $link = $this->config->get('config_ssl');
  231. } else {
  232. $link = $this->config->get('config_url');
  233. }
  234. if($code != $this->config_language.'/') {
  235. $link .= $code;
  236. }
  237. if(isset($this->cache_data['queries']['common/home'])) {
  238. $link .= $this->cache_data['queries']['common/home'];
  239. }
  240. // Return clean shop link with any GET-parameters stripped off
  241. return $link;
  242. // (if you want to pass all parameters on homepage as is, comment the line above: `// return $link;`)
  243. break;
  244. case 'product/product':
  245. if (isset($data['product_id'])) {
  246. // Whitelist GET parameters
  247. $tmp = $data;
  248. $data = array();
  249. if ($this->config->get('config_seo_url_include_path')) {
  250. $data['path'] = $this->getPathByProduct($tmp['product_id']);
  251. if (!$data['path']) return $link;
  252. }
  253.  
  254. $allowed_parameters = array(
  255. 'product_id', 'tracking',
  256. // Compatibility with "OCJ Merchandising Reports" module.
  257. // Save and pass-thru module specific GET parameters.
  258. 'uri', 'list_type',
  259. // Compatibility with Google Analytics
  260. 'gclid', 'utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',
  261. 'type', 'source', 'block', 'position', 'keyword',
  262. // Compatibility with Yandex Metrics, Yandex Market
  263. 'yclid', 'ymclid', 'openstat', 'frommarket',
  264. 'openstat_service', 'openstat_campaign', 'openstat_ad', 'openstat_source'
  265. );
  266. foreach($allowed_parameters as $ap) {
  267. if (isset($tmp[$ap])) {
  268. $data[$ap] = $tmp[$ap];
  269. }
  270. }
  271.  
  272. }
  273. break;
  274.  
  275. case 'product/category':
  276. if (isset($data['path'])) {
  277. $category = explode('_', $data['path']);
  278. $category = end($category);
  279. $data['path'] = $this->getPathByCategory($category);
  280. if (!$data['path']) return $link;
  281. }
  282. break;
  283.  
  284. // pages retreived by AJAX requests
  285. case 'product/product/review':
  286. case 'information/information/info':
  287. case 'information/information/agree':
  288. return $link;
  289. break;
  290.  
  291. default:
  292. break;
  293. }
  294.  
  295. if ($component['scheme'] == 'https') {
  296. $link = $this->config->get('config_ssl');
  297. } else {
  298. $link = $this->config->get('config_url');
  299. }
  300.  
  301. $link .= $code . 'index.php?route=' . $route;
  302.  
  303. if (count($data)) {
  304. $link .= '&amp;' . urldecode(http_build_query($data, '', '&amp;'));
  305. }
  306.  
  307. $queries = array();
  308. foreach ($data as $key => $value) {
  309. switch ($key) {
  310. case 'product_id':
  311. case 'manufacturer_id':
  312. case 'category_id':
  313. case 'information_id':
  314. case 'order_id':
  315.  
  316. case 'search':
  317. case 'sub_category':
  318. case 'description':
  319.  
  320. // Compatibility with Shopencart News/Blog:
  321. case 'news_id':
  322. case 'author':
  323. case 'ncat':
  324. case 'page':
  325.  
  326. $queries[] = $key . '=' . $value;
  327. unset($data[$key]);
  328. $postfix = 1;
  329. break;
  330.  
  331. case 'path':
  332. // ATTN: user can set any path: path=2_4_1_2_3
  333. $category_path = explode('_', $value);
  334.  
  335. // find real category path:
  336. $category_id = end($category_path);
  337. $categories = $this->getPathByCategory($category_id);
  338.  
  339. // save all categories queries to find later their aliases
  340. $categories = explode('_', $categories);
  341. foreach ($categories as $category) {
  342. $queries[] = 'category_id=' . $category;
  343. }
  344. unset($data[$key]);
  345. break;
  346.  
  347. default:
  348. break;
  349. }
  350. }
  351.  
  352. if(empty($queries)) {
  353. $queries[] = $route;
  354. }
  355.  
  356. $rows = array();
  357. foreach($queries as $query) {
  358. if(isset($this->cache_data['queries'][$query])) {
  359. $rows[] = array('query' => $query, 'keyword' => $this->cache_data['queries'][$query]);
  360. }
  361. }
  362.  
  363. if(count($rows) == count($queries)) {
  364. $aliases = array();
  365. foreach($rows as $row) {
  366. $aliases[$row['query']] = $row['keyword'];
  367. }
  368. foreach($queries as $query) {
  369. $seo_url .= '/' . rawurlencode($aliases[$query]);
  370. }
  371. }
  372.  
  373. if ($seo_url == '') return $link;
  374.  
  375. $seo_url = $code . trim($seo_url, '/');
  376.  
  377. if ($component['scheme'] == 'https') {
  378. $seo_url = $this->config->get('config_ssl') . $seo_url;
  379. } else {
  380. $seo_url = $this->config->get('config_url') . $seo_url;
  381. }
  382.  
  383. if (isset($postfix)) {
  384. $seo_url .= trim($this->config->get('config_seo_url_postfix'));
  385. } else {
  386. $seo_url .= '/';
  387. }
  388.  
  389. if(substr($seo_url, -2) == '//') {
  390. $seo_url = substr($seo_url, 0, -1);
  391. }
  392.  
  393.  
  394. if (count($data)) {
  395. $seo_url .= '?' . urldecode(http_build_query($data, '', '&amp;'));
  396. }
  397.  
  398. return $seo_url;
  399. }
  400.  
  401. private function getPathByProduct($product_id) {
  402. $product_id = (int)$product_id;
  403. if ($product_id < 1) return false;
  404.  
  405. static $path = null;
  406. if (!is_array($path)) {
  407. $path = $this->cache->get('product.seopath');
  408. if (!is_array($path)) $path = array();
  409. }
  410.  
  411. if (!isset($path[$product_id])) {
  412. $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");
  413.  
  414. $path[$product_id] = $this->getPathByCategory($query->num_rows ? (int)$query->row['category_id'] : 0);
  415.  
  416. $this->cache->set('product.seopath', $path);
  417. }
  418.  
  419. return $path[$product_id];
  420. }
  421.  
  422. private function getPathByCategory($category_id) {
  423. $category_id = (int)$category_id;
  424. if ($category_id < 1) return false;
  425.  
  426. static $path = null;
  427. if (!is_array($path)) {
  428. $path = $this->cache->get('category.seopath');
  429. if (!is_array($path)) $path = array();
  430. }
  431.  
  432. if (!isset($path[$category_id])) {
  433. $max_level = 10;
  434.  
  435. $sql = "SELECT CONCAT_WS('_'";
  436. for ($i = $max_level-1; $i >= 0; --$i) {
  437. $sql .= ",t$i.category_id";
  438. }
  439. $sql .= ") AS path FROM " . DB_PREFIX . "category t0";
  440. for ($i = 1; $i < $max_level; ++$i) {
  441. $sql .= " LEFT JOIN " . DB_PREFIX . "category t$i ON (t$i.category_id = t" . ($i-1) . ".parent_id)";
  442. }
  443. $sql .= " WHERE t0.category_id = '" . $category_id . "'";
  444.  
  445. $query = $this->db->query($sql);
  446.  
  447. $path[$category_id] = $query->num_rows ? $query->row['path'] : false;
  448.  
  449. $this->cache->set('category.seopath', $path);
  450. }
  451.  
  452. return $path[$category_id];
  453. }
  454.  
  455. private function validate() {
  456. if (isset($this->request->get['route']) && ($this->request->get['route'] == 'error/not_found'
  457. || preg_match('~^api/~',$this->request->get['route']) // Masks all api requests
  458. )) {
  459. return;
  460. }
  461. if (ltrim($this->request->server['REQUEST_URI'], '/') == 'sitemap.xml') {
  462. $this->request->get['route'] = 'feed/google_sitemap';
  463. return;
  464. }
  465.  
  466. if(empty($this->request->get['route'])) {
  467. $this->request->get['route'] = 'common/home';
  468. }
  469.  
  470. if (isset($this->request->server['HTTP_X_REQUESTED_WITH']) && strtolower($this->request->server['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
  471. return;
  472. }
  473.  
  474. if (isset($this->request->server['HTTPS']) && (($this->request->server['HTTPS'] == 'on') || ($this->request->server['HTTPS'] == '1'))) {
  475. $url = str_replace('&amp;', '&', $this->config->get('config_ssl') . ltrim($this->request->server['REQUEST_URI'], '/'));
  476. $seo = str_replace('&amp;', '&', $this->url->link($this->request->get['route'], $this->getQueryString(array('route')), 'SSL'));
  477. } else {
  478. $url = str_replace('&amp;', '&',
  479. substr($this->config->get('config_url'), 0, strpos($this->config->get('config_url'), '/', 10)) // leave only domain
  480. . $this->request->server['REQUEST_URI']);
  481. $seo = str_replace('&amp;', '&', $this->url->link($this->request->get['route'], $this->getQueryString(array('route')), 'NONSSL'));
  482. }
  483.  
  484.  
  485. // OCFilter start
  486. if (isset($this->request->get['route']) && $this->request->get['route'] == 'product/category') {
  487. return;
  488. }
  489. // OCFilter end
  490.  
  491. if (rawurldecode($url) != rawurldecode($seo)) {
  492. // header($this->request->server['SERVER_PROTOCOL'] . ' 303 See Other');
  493. // $this->response->redirect($seo,303);
  494. header($this->request->server['SERVER_PROTOCOL'] . ' 301 Moved Permanently');
  495. $this->response->redirect($seo,301);
  496. }
  497. }
  498.  
  499. private function getQueryString($exclude = array()) {
  500. if (!is_array($exclude)) {
  501. $exclude = array();
  502. }
  503.  
  504. return urldecode(
  505. http_build_query(
  506. array_diff_key($this->request->get, array_flip($exclude))
  507. )
  508. );
  509. }
  510. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement