Source for file seo.class.php

Documentation is available at seo.class.php

  1. <?
  2. /**
  3. * Ultimate SEO URLs Contribution - osCommerce MS-2.2
  4. *
  5. * Ultimate SEO URLs offers search engine optimized URLS for osCommerce
  6. * based applications. Other features include optimized performance and
  7. * automatic redirect script.
  8. * @package Ultimate-SEO-URLs
  9. * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  10. * @version 2.1
  11. * @link http://www.oscommerce-freelancers.com/ osCommerce-Freelancers
  12. * @copyright Copyright 2005, Bobby Easland
  13. * @author Bobby Easland
  14. * @filesource
  15. */
  16.  
  17. /**
  18. * SEO_DataBase Class
  19. *
  20. * The SEO_DataBase class provides abstraction so the databaes can be accessed
  21. * without having to use tep API functions. This class has minimal error handling
  22. * so make sure your code is tight!
  23. * @package Ultimate-SEO-URLs
  24. * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  25. * @version 1.1
  26. * @link http://www.oscommerce-freelancers.com/ osCommerce-Freelancers
  27. * @copyright Copyright 2005, Bobby Easland
  28. * @author Bobby Easland
  29. */
  30. class SEO_DataBase{
  31. /**
  32. * Database host (localhost, IP based, etc)
  33. * @var string
  34. */
  35. var $host;
  36. /**
  37. * Database user
  38. * @var string
  39. */
  40. var $user;
  41. /**
  42. * Database name
  43. * @var string
  44. */
  45. var $db;
  46. /**
  47. * Database password
  48. * @var string
  49. */
  50. var $pass;
  51. /**
  52. * Database link
  53. * @var resource
  54. */
  55. var $link_id;
  56.  
  57. /**
  58. * MySQL_DataBase class constructor
  59. * @author Bobby Easland
  60. * @version 1.0
  61. * @param string $host
  62. * @param string $user
  63. * @param string $db
  64. * @param string $pass
  65. */
  66. function SEO_DataBase($host, $user, $db, $pass){
  67. $this->host = $host;
  68. $this->user = $user;
  69. $this->db = $db;
  70. $this->pass = $pass;
  71. $this->ConnectDB();
  72. $this->SelectDB();
  73. } # end function
  74.  
  75.  
  76.  
  77. /**
  78. * Function to connect to MySQL
  79. * @author Bobby Easland
  80. * @version 1.1
  81. */
  82. function ConnectDB(){
  83. $this->link_id = mysql_connect($this->host, $this->user, $this->pass);
  84. } # end function
  85.  
  86. /**
  87. * Function to select the database
  88. * @author Bobby Easland
  89. * @version 1.0
  90. * @return resoource
  91. */
  92. function SelectDB(){
  93. return mysql_select_db($this->db);
  94. } # end function
  95.  
  96. /**
  97. * Function to perform queries
  98. * @author Bobby Easland
  99. * @version 1.0
  100. * @param string $query SQL statement
  101. * @return resource
  102. */
  103. function Query($query){
  104. return @mysql_query($query, $this->link_id);
  105. } # end function
  106.  
  107. /**
  108. * Function to fetch array
  109. * @author Bobby Easland
  110. * @version 1.0
  111. * @param resource $resource_id
  112. * @param string $type MYSQL_BOTH or MYSQL_ASSOC
  113. * @return array
  114. */
  115. function FetchArray($resource_id, $type = MYSQL_BOTH){
  116. return @mysql_fetch_array($resource_id, $type);
  117. } # end function
  118.  
  119. /**
  120. * Function to fetch the number of rows
  121. * @author Bobby Easland
  122. * @version 1.0
  123. * @param resource $resource_id
  124. * @return mixed
  125. */
  126. function NumRows($resource_id){
  127. return @mysql_num_rows($resource_id);
  128. } # end function
  129.  
  130.  
  131.  
  132. /**
  133. * Function to fetch the last insertID
  134. * @author Bobby Easland
  135. * @version 1.0
  136. * @return integer
  137. */
  138. function InsertID() {
  139. return mysql_insert_id();
  140. }
  141. /**
  142. * Function to free the resource
  143. * @author Bobby Easland
  144. * @version 1.0
  145. * @param resource $resource_id
  146. * @return boolean
  147. */
  148. function Free($resource_id){
  149. return @mysql_free_result($resource_id);
  150. } # end function
  151.  
  152.  
  153.  
  154. /**
  155. * Function to add slashes
  156. * @author Bobby Easland
  157. * @version 1.0
  158. * @param string $data
  159. * @return string
  160. */
  161. function Slashes($data){
  162. return addslashes($data);
  163. } # end function
  164.  
  165.  
  166.  
  167. /**
  168. * Function to perform DB inserts and updates - abstracted from osCommerce-MS-2.2 project
  169. * @author Bobby Easland
  170. * @version 1.0
  171. * @param string $table Database table
  172. * @param array $data Associative array of columns / values
  173. * @param string $action insert or update
  174. * @param string $parameters
  175. * @return resource
  176. */
  177. function DBPerform($table, $data, $action = 'insert', $parameters = '') {
  178. reset($data);
  179. if ($action == 'insert') {
  180. $query = 'INSERT INTO `' . $table . '` (';
  181. while (list($columns, ) = each($data)) {
  182. $query .= '`' . $columns . '`, ';
  183. }
  184. $query = substr($query, 0, -2) . ') values (';
  185. reset($data);
  186. while (list(, $value) = each($data)) {
  187. switch ((string)$value) {
  188. case 'now()':
  189. $query .= 'now(), ';
  190. break;
  191. case 'null':
  192. $query .= 'null, ';
  193. break;
  194. default:
  195. $query .= "'" . $this->Slashes($value) . "', ";
  196. break;
  197. }
  198. }
  199. $query = substr($query, 0, -2) . ')';
  200. } elseif ($action == 'update') {
  201. $query = 'UPDATE `' . $table . '` SET ';
  202. while (list($columns, $value) = each($data)) {
  203. switch ((string)$value) {
  204. case 'now()':
  205. $query .= '`' .$columns . '`=now(), ';
  206. break;
  207. case 'null':
  208. $query .= '`' .$columns .= '`=null, ';
  209. break;
  210. default:
  211. $query .= '`' .$columns . "`='" . $this->Slashes($value) . "', ";
  212. break;
  213. }
  214. }
  215. $query = substr($query, 0, -2) . ' WHERE ' . $parameters;
  216. }
  217. return $this->Query($query);
  218. } # end function
  219.  
  220. } # end class
  221.  
  222. /**
  223. * Ultimate SEO URLs Installer and Configuration Class
  224. *
  225. * Ultimate SEO URLs installer and configuration class offers a modular
  226. * and easy to manage method of configuration. The class enables the base
  227. * class to be configured and installed on the fly without the hassle of
  228. * calling additional scripts or executing SQL.
  229. * @package Ultimate-SEO-URLs
  230. * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  231. * @version 1.1
  232. * @link http://www.oscommerce-freelancers.com/ osCommerce-Freelancers
  233. * @copyright Copyright 2005, Bobby Easland
  234. * @author Bobby Easland
  235. */
  236. class SEO_URL_INSTALLER{
  237. /**
  238. * The default_config array has all the default settings which should be all that is needed to make the base class work.
  239. * @var array
  240. */
  241. var $default_config;
  242. /**
  243. * Database object
  244. * @var object
  245. */
  246. var $DB;
  247. /**
  248. * $attributes array holds information about this instance
  249. * @var array
  250. */
  251. var $attributes;
  252. /**
  253. * SEO_URL_INSTALLER class constructor
  254. * @author Bobby Easland
  255. * @version 1.1
  256. */
  257. function SEO_URL_INSTALLER(){
  258. $this->attributes = array();
  259. $x = 0;
  260. $this->default_config = array();
  261. $this->default_config['SEO_ENABLED'] = array('DEFAULT' => 'true',
  262. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Enable SEO URLs?', 'SEO_ENABLED', 'true', 'Enable the SEO URLs? This is a global setting and will turn them off completely.', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), NULL, 'tep_cfg_select_option(array(''true'', ''false''),')"
  263. );
  264. $x++;
  265. $this->default_config['SEO_ADD_CPATH_TO_PRODUCT_URLS'] = array('DEFAULT' => 'false',
  266. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Add cPath to product URLs?', 'SEO_ADD_CPATH_TO_PRODUCT_URLS', 'false', 'This setting will append the cPath to the end of product URLs (i.e. - some-product-p-1.html?cPath=xx).', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), NULL, 'tep_cfg_select_option(array(''true'', ''false''),')"
  267. );
  268. $x++;
  269. $this->default_config['SEO_ADD_CAT_PARENT'] = array('DEFAULT' => 'true',
  270. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Add category parent to begining of URLs?', 'SEO_ADD_CAT_PARENT', 'true', 'This setting will add the category parent name to the beginning of the category URLs (i.e. - parent-category-c-1.html).', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), NULL, 'tep_cfg_select_option(array(''true'', ''false''),')"
  271. );
  272. $x++;
  273. $this->default_config['SEO_URLS_FILTER_SHORT_WORDS'] = array('DEFAULT' => '3',
  274. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Filter Short Words', 'SEO_URLS_FILTER_SHORT_WORDS', '3', 'This setting will filter words less than or equal to the value from the URL.', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), NULL, NULL)"
  275. );
  276. $x++;
  277. $this->default_config['SEO_URLS_USE_W3C_VALID'] = array('DEFAULT' => 'true',
  278. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Output W3C valid URLs (parameter string)?', 'SEO_URLS_USE_W3C_VALID', 'true', 'This setting will output W3C valid URLs.', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), NULL, 'tep_cfg_select_option(array(''true'', ''false''),')"
  279. );
  280. $x++;
  281. $this->default_config['USE_SEO_CACHE_GLOBAL'] = array('DEFAULT' => 'true',
  282. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Enable SEO cache to save queries?', 'USE_SEO_CACHE_GLOBAL', 'true', 'This is a global setting and will turn off caching completely.', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), NULL, 'tep_cfg_select_option(array(''true'', ''false''),')"
  283. );
  284. $x++;
  285. $this->default_config['USE_SEO_CACHE_PRODUCTS'] = array('DEFAULT' => 'true',
  286. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Enable product cache?', 'USE_SEO_CACHE_PRODUCTS', 'true', 'This will turn off caching for the products.', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), NULL, 'tep_cfg_select_option(array(''true'', ''false''),')"
  287. );
  288. $x++;
  289. $this->default_config['USE_SEO_CACHE_CATEGORIES'] = array('DEFAULT' => 'true',
  290. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Enable categories cache?', 'USE_SEO_CACHE_CATEGORIES', 'true', 'This will turn off caching for the categories.', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), NULL, 'tep_cfg_select_option(array(''true'', ''false''),')"
  291. );
  292.  
  293. $x++;
  294. $this->default_config['USE_SEO_CACHE_MANUFACTURERS'] = array('DEFAULT' => 'true',
  295. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Enable manufacturers cache?', 'USE_SEO_CACHE_MANUFACTURERS', 'true', 'This will turn off caching for the manufacturers.', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), NULL, 'tep_cfg_select_option(array(''true'', ''false''),')"
  296. );
  297.  
  298. $x++;
  299. $this->default_config['USE_SEO_CACHE_ARTICLES'] = array('DEFAULT' => 'true',
  300. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Enable articles cache?', 'USE_SEO_CACHE_ARTICLES', 'true', 'This will turn off caching for the articles.', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), NULL, 'tep_cfg_select_option(array(''true'', ''false''),')"
  301. );
  302. $x++;
  303. $this->default_config['USE_SEO_CACHE_TOPICS'] = array('DEFAULT' => 'true',
  304. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Enable topics cache?', 'USE_SEO_CACHE_TOPICS', 'true', 'This will turn off caching for the article topics.', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), NULL, 'tep_cfg_select_option(array(''true'', ''false''),')"
  305. );
  306. $x++;
  307. $this->default_config['USE_SEO_CACHE_INFO_PAGES'] = array('DEFAULT' => 'true',
  308. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Enable information cache?', 'USE_SEO_CACHE_INFO_PAGES', 'true', 'This will turn off caching for the information pages.', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), NULL, 'tep_cfg_select_option(array(''true'', ''false''),')"
  309. );
  310. $x++;
  311. $this->default_config['USE_SEO_REDIRECT'] = array('DEFAULT' => 'true',
  312. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Enable automatic redirects?', 'USE_SEO_REDIRECT', 'true', 'This will activate the automatic redirect code and send 301 headers for old to new URLs.', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), NULL, 'tep_cfg_select_option(array(''true'', ''false''),')"
  313. );
  314. $x++;
  315. $this->default_config['SEO_REWRITE_TYPE'] = array('DEFAULT' => 'Rewrite',
  316. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Choose URL Rewrite Type', 'SEO_REWRITE_TYPE', 'Rewrite', 'Choose which SEO URL format to use.', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), NULL, 'tep_cfg_select_option(array(''Rewrite''),')"
  317. );
  318. $x++;
  319. $this->default_config['SEO_CHAR_CONVERT_SET'] = array('DEFAULT' => '',
  320. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Enter special character conversions', 'SEO_CHAR_CONVERT_SET', '', 'This setting will convert characters.<br><br>The format <b>MUST</b> be in the form: <b>char=>conv,char2=>conv2</b>', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), NULL, NULL)"
  321. );
  322. $x++;
  323. $this->default_config['SEO_REMOVE_ALL_SPEC_CHARS'] = array('DEFAULT' => 'false',
  324. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Remove all non-alphanumeric characters?', 'SEO_REMOVE_ALL_SPEC_CHARS', 'false', 'This will remove all non-letters and non-numbers. This should be handy to remove all special characters with 1 setting.', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), NULL, 'tep_cfg_select_option(array(''true'', ''false''),')"
  325. );
  326. $x++;
  327. $this->default_config['SEO_URLS_CACHE_RESET'] = array('DEFAULT' => 'false',
  328. 'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES ('', 'Reset SEO URLs Cache', 'SEO_URLS_CACHE_RESET', 'false', 'This will reset the cache data for SEO', GROUP_INSERT_ID, ".$x.", NOW(), NOW(), 'tep_reset_cache_data_seo_urls', 'tep_cfg_select_option(array(''reset'', ''false''),')"
  329. );
  330.  
  331. $this->init();
  332. } # end class constructor
  333.  
  334. /**
  335. * Initializer - if there are settings not defined the default config will be used and database settings installed.
  336. * @author Bobby Easland
  337. * @version 1.1
  338. */
  339. function init(){
  340. foreach( $this->default_config as $key => $value ){
  341. $container[] = defined($key) ? 'true' : 'false';
  342. } # end foreach
  343. $this->attributes['IS_DEFINED'] = in_array('false', $container) ? false : true;
  344. switch(true){
  345. case ( !$this->attributes['IS_DEFINED'] ):
  346. $this->eval_defaults();
  347. $this->DB = new SEO_DataBase(DB_SERVER, DB_SERVER_USERNAME, DB_DATABASE, DB_SERVER_PASSWORD);
  348. $sql = "SELECT configuration_key, configuration_value
  349. FROM " . TABLE_CONFIGURATION . "
  350. WHERE configuration_key LIKE '%SEO%'";
  351. $result = $this->DB->Query($sql);
  352. $num_rows = $this->DB->NumRows($result);
  353. $this->DB->Free($result);
  354. $this->attributes['IS_INSTALLED'] = (sizeof($container) == $num_rows) ? true : false;
  355. if ( !$this->attributes['IS_INSTALLED'] ){
  356. $this->install_settings();
  357. }
  358. break;
  359. default:
  360. $this->attributes['IS_INSTALLED'] = true;
  361. break;
  362. } # end switch
  363. } # end function
  364.  
  365. /**
  366. * This function evaluates the default serrings into defined constants
  367. * @author Bobby Easland
  368. * @version 1.0
  369. */
  370. function eval_defaults(){
  371. foreach( $this->default_config as $key => $value ){
  372. define($key, $value['DEFAULT']);
  373. } # end foreach
  374. } # end function
  375.  
  376. /**
  377. * This function removes the database settings (configuration and cache)
  378. * @author Bobby Easland
  379. * @version 1.0
  380. */
  381. function uninstall_settings(){
  382. $this->DB->Query("DELETE FROM `".TABLE_CONFIGURATION_GROUP."` WHERE `configuration_group_title` LIKE '%SEO%'");
  383. $this->DB->Query("DELETE FROM `".TABLE_CONFIGURATION."` WHERE `configuration_key` LIKE '%SEO%'");
  384. $this->DB->Query("DROP TABLE IF EXISTS `cache`");
  385. } # end function
  386.  
  387. /**
  388. * This function installs the database settings
  389. * @author Bobby Easland
  390. * @version 1.0
  391. */
  392. function install_settings(){
  393. $this->uninstall_settings();
  394. $sort_order_query = "SELECT MAX(sort_order) as max_sort FROM `".TABLE_CONFIGURATION_GROUP."`";
  395. $sort = $this->DB->FetchArray( $this->DB->Query($sort_order_query) );
  396. $next_sort = $sort['max_sort'] + 1;
  397. $insert_group = "INSERT INTO `".TABLE_CONFIGURATION_GROUP."` VALUES ('', 'SEO URLs', 'Options for Ultimate SEO URLs by Chemo', '".$next_sort."', '1')";
  398. $this->DB->Query($insert_group);
  399. $group_id = $this->DB->InsertID();
  400.  
  401. foreach ($this->default_config as $key => $value){
  402. $sql = str_replace('GROUP_INSERT_ID', $group_id, $value['QUERY']);
  403. $this->DB->Query($sql);
  404. }
  405.  
  406. $insert_cache_table = "CREATE TABLE `cache` (
  407. `cache_id` varchar(32) NOT NULL default '',
  408. `cache_language_id` tinyint(1) NOT NULL default '0',
  409. `cache_name` varchar(255) NOT NULL default '',
  410. `cache_data` mediumtext NOT NULL,
  411. `cache_global` tinyint(1) NOT NULL default '1',
  412. `cache_gzip` tinyint(1) NOT NULL default '1',
  413. `cache_method` varchar(20) NOT NULL default 'RETURN',
  414. `cache_date` datetime NOT NULL default '0000-00-00 00:00:00',
  415. `cache_expires` datetime NOT NULL default '0000-00-00 00:00:00',
  416. PRIMARY KEY (`cache_id`,`cache_language_id`),
  417. KEY `cache_id` (`cache_id`),
  418. KEY `cache_language_id` (`cache_language_id`),
  419. KEY `cache_global` (`cache_global`)
  420. ) TYPE=MyISAM;";
  421. $this->DB->Query($insert_cache_table);
  422. } # end function
  423.  
  424. } # end class
  425.  
  426. /**
  427. * Ultimate SEO URLs Base Class
  428. *
  429. * Ultimate SEO URLs offers search engine optimized URLS for osCommerce
  430. * based applications. Other features include optimized performance and
  431. * automatic redirect script.
  432. * @package Ultimate-SEO-URLs
  433. * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  434. * @version 2.1
  435. * @link http://www.oscommerce-freelancers.com/ osCommerce-Freelancers
  436. * @copyright Copyright 2005, Bobby Easland
  437. * @author Bobby Easland
  438. */
  439. class SEO_URL{
  440. /**
  441. * $cache is the per page data array that contains all of the previously stripped titles
  442. * @var array
  443. */
  444. var $cache;
  445. /**
  446. * $languages_id contains the language_id for this instance
  447. * @var integer
  448. */
  449. var $languages_id;
  450. /**
  451. * $attributes array contains all the required settings for class
  452. * @var array
  453. */
  454. var $attributes;
  455. /**
  456. * $base_url is the NONSSL URL for site
  457. * @var string
  458. */
  459. var $base_url;
  460. /**
  461. * $base_url_ssl is the secure URL for the site
  462. * @var string
  463. */
  464. var $base_url_ssl;
  465. /**
  466. * $performance array contains evaluation metric data
  467. * @var array
  468. */
  469. var $performance;
  470. /**
  471. * $timestamp simply holds the temp variable for time calculations
  472. * @var float
  473. */
  474. var $timestamp;
  475. /**
  476. * $reg_anchors holds the anchors used by the .htaccess rewrites
  477. * @var array
  478. */
  479. var $reg_anchors;
  480. /**
  481. * $cache_query is the resource_id used for database cache logic
  482. * @var resource
  483. */
  484. var $cache_query;
  485. /**
  486. * $cache_file is the basename of the cache database entry
  487. * @var string
  488. */
  489. var $cache_file;
  490. /**
  491. * $data array contains all records retrieved from database cache
  492. * @var array
  493. */
  494. var $data;
  495. /**
  496. * $need_redirect determines whether the URL needs to be redirected
  497. * @var boolean
  498. */
  499. var $need_redirect;
  500. /**
  501. * $is_seopage holds value as to whether page is in allowed SEO pages
  502. * @var boolean
  503. */
  504. var $is_seopage;
  505. /**
  506. * $uri contains the $_SERVER['REQUEST_URI'] value
  507. * @var string
  508. */
  509. var $uri;
  510. /**
  511. * $real_uri contains the $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING'] value
  512. * @var string
  513. */
  514. var $real_uri;
  515. /**
  516. * $uri_parsed contains the parsed uri value array
  517. * @var array
  518. */
  519. var $uri_parsed;
  520. /**
  521. * $path_info contains the getenv('PATH_INFO') value
  522. * @var string
  523. */
  524. var $path_info;
  525. /**
  526. * $DB is the database object
  527. * @var object
  528. */
  529. var $DB;
  530. /**
  531. * $installer is the installer object
  532. * @var object
  533. */
  534. var $installer;
  535. /**
  536. * SEO_URL class constructor
  537. * @author Bobby Easland
  538. * @version 1.1
  539. * @param integer $languages_id
  540. */
  541. function SEO_URL($languages_id){
  542. global $session_started, $SID;
  543. $this->installer = new SEO_URL_INSTALLER;
  544. $this->DB = new SEO_DataBase(DB_SERVER, DB_SERVER_USERNAME, DB_DATABASE, DB_SERVER_PASSWORD);
  545. $this->languages_id = (int)$languages_id;
  546. $this->data = array();
  547. $seo_pages = array(FILENAME_DEFAULT,
  548. FILENAME_PRODUCT_INFO,
  549. FILENAME_POPUP_IMAGE,
  550. FILENAME_PRODUCT_REVIEWS,
  551. FILENAME_PRODUCT_REVIEWS_INFO);
  552. if ( defined('FILENAME_ARTICLES') ) $seo_pages[] = FILENAME_ARTICLES;
  553. if ( defined('FILENAME_ARTICLE_INFO') ) $seo_pages[] = FILENAME_ARTICLE_INFO;
  554. if ( defined('FILENAME_INFORMATION') ) $seo_pages[] = FILENAME_INFORMATION;
  555. $this->attributes = array('PHP_VERSION' => PHP_VERSION,
  556. 'SESSION_STARTED' => $session_started,
  557. 'SID' => $SID,
  558. 'SEO_ENABLED' => defined('SEO_ENABLED') ? SEO_ENABLED : 'false',
  559. 'SEO_ADD_CPATH_TO_PRODUCT_URLS' => defined('SEO_ADD_CPATH_TO_PRODUCT_URLS') ? SEO_ADD_CPATH_TO_PRODUCT_URLS : 'false',
  560. 'SEO_ADD_CAT_PARENT' => defined('SEO_ADD_CAT_PARENT') ? SEO_ADD_CAT_PARENT : 'true',
  561. 'SEO_URLS_USE_W3C_VALID' => defined('SEO_URLS_USE_W3C_VALID') ? SEO_URLS_USE_W3C_VALID : 'true',
  562. 'USE_SEO_CACHE_GLOBAL' => defined('USE_SEO_CACHE_GLOBAL') ? USE_SEO_CACHE_GLOBAL : 'false',
  563. 'USE_SEO_CACHE_PRODUCTS' => defined('USE_SEO_CACHE_PRODUCTS') ? USE_SEO_CACHE_PRODUCTS : 'false',
  564. 'USE_SEO_CACHE_CATEGORIES' => defined('USE_SEO_CACHE_CATEGORIES') ? USE_SEO_CACHE_CATEGORIES : 'false',
  565. 'USE_SEO_CACHE_MANUFACTURERS' => defined('USE_SEO_CACHE_MANUFACTURERS') ? USE_SEO_CACHE_MANUFACTURERS : 'false',
  566. 'USE_SEO_CACHE_ARTICLES' => defined('USE_SEO_CACHE_ARTICLES') ? USE_SEO_CACHE_ARTICLES : 'false',
  567. 'USE_SEO_CACHE_TOPICS' => defined('USE_SEO_CACHE_TOPICS') ? USE_SEO_CACHE_TOPICS : 'false',
  568. 'USE_SEO_CACHE_INFO_PAGES' => defined('USE_SEO_CACHE_INFO_PAGES') ? USE_SEO_CACHE_INFO_PAGES : 'false',
  569. 'USE_SEO_REDIRECT' => defined('USE_SEO_REDIRECT') ? USE_SEO_REDIRECT : 'false',
  570. 'SEO_REWRITE_TYPE' => defined('SEO_REWRITE_TYPE') ? SEO_REWRITE_TYPE : 'false',
  571. 'SEO_URLS_FILTER_SHORT_WORDS' => defined('SEO_URLS_FILTER_SHORT_WORDS') ? SEO_URLS_FILTER_SHORT_WORDS : 'false',
  572. 'SEO_CHAR_CONVERT_SET' => defined('SEO_CHAR_CONVERT_SET') ? $this->expand(SEO_CHAR_CONVERT_SET) : 'false',
  573. 'SEO_REMOVE_ALL_SPEC_CHARS' => defined('SEO_REMOVE_ALL_SPEC_CHARS') ? SEO_REMOVE_ALL_SPEC_CHARS : 'false',
  574. 'SEO_PAGES' => $seo_pages,
  575. 'SEO_INSTALLER' => $this->installer->attributes
  576. );
  577. $this->base_url = HTTP_SERVER . DIR_WS_HTTP_CATALOG;
  578. $this->base_url_ssl = HTTPS_SERVER . DIR_WS_HTTPS_CATALOG;
  579. $this->cache = array();
  580. $this->timestamp = 0;
  581. $this->reg_anchors = array('products_id' => '-p-',
  582. 'cPath' => '-c-',
  583. 'manufacturers_id' => '-m-',
  584. 'pID' => '-pi-',
  585. 'tPath' => '-t-',
  586. 'articles_id' => '-a-',
  587. 'products_id_review' => '-pr-',
  588. 'products_id_review_info' => '-pri-',
  589. 'info_id' => '-i-'
  590. );
  591. $this->performance = array('NUMBER_URLS_GENERATED' => 0,
  592. 'NUMBER_QUERIES' => 0,
  593. 'CACHE_QUERY_SAVINGS' => 0,
  594. 'NUMBER_STANDARD_URLS_GENERATED' => 0,
  595. 'TOTAL_CACHED_PER_PAGE_RECORDS' => 0,
  596. 'TOTAL_TIME' => 0,
  597. 'TIME_PER_URL' => 0,
  598. 'QUERIES' => array()
  599. );
  600. if ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true'){
  601. $this->cache_file = 'seo_urls_v2_';
  602. $this->cache_gc();
  603. if ( $this->attributes['USE_SEO_CACHE_PRODUCTS'] == 'true' ) $this->generate_products_cache();
  604. if ( $this->attributes['USE_SEO_CACHE_CATEGORIES'] == 'true' ) $this->generate_categories_cache();
  605. if ( $this->attributes['USE_SEO_CACHE_MANUFACTURERS'] == 'true' ) $this->generate_manufacturers_cache();
  606. if ( $this->attributes['USE_SEO_CACHE_ARTICLES'] == 'true' && defined('TABLE_ARTICLES_DESCRIPTION')) $this->generate_articles_cache();
  607. if ( $this->attributes['USE_SEO_CACHE_TOPICS'] == 'true' && defined('TABLE_TOPICS_DESCRIPTION')) $this->generate_topics_cache();
  608. if ( $this->attributes['USE_SEO_CACHE_INFO_PAGES'] == 'true' && defined('TABLE_INFORMATION')) $this->generate_information_cache();
  609. } # end if
  610.  
  611. if ($this->attributes['USE_SEO_REDIRECT'] == 'true'){
  612. $this->check_redirect();
  613. } # end if
  614. } # end constructor
  615.  
  616.  
  617.  
  618. /**
  619. * Function to return SEO URL link SEO'd with stock generattion for error fallback
  620. * @author Bobby Easland
  621. * @version 1.0
  622. * @param string $page Base script for URL
  623. * @param string $parameters URL parameters
  624. * @param string $connection NONSSL/SSL
  625. * @param boolean $add_session_id Switch to add osCsid
  626. * @return string Formed href link
  627. */
  628. function href_link($page = '', $parameters = '', $connection = 'NONSSL', $add_session_id = true){
  629. $this->start($this->timestamp);
  630. $this->performance['NUMBER_URLS_GENERATED']++;
  631. if ( !in_array($page, $this->attributes['SEO_PAGES']) || $this->attributes['SEO_ENABLED'] == 'false' ) {
  632. return $this->stock_href_link($page, $parameters, $connection, $add_session_id);
  633. }
  634. $link = $connection == 'NONSSL' ? $this->base_url : $this->base_url_ssl;
  635. $separator = '?';
  636. if ($this->not_null($parameters)) {
  637. $link .= $this->parse_parameters($page, $parameters, $separator);
  638. } else {
  639. $link .= $page;
  640. }
  641. $link = $this->add_sid($link, $add_session_id, $connection, $separator);
  642. $this->stop($this->timestamp, $time);
  643. $this->performance['TOTAL_TIME'] += $time;
  644. switch($this->attributes['SEO_URLS_USE_W3C_VALID']){
  645. case ('true'):
  646. if (!isset($_SESSION['customer_id']) && defined('ENABLE_PAGE_CACHE') && ENABLE_PAGE_CACHE == 'true' && class_exists('page_cache')){
  647. return $link;
  648. } else {
  649. return htmlspecialchars(utf8_encode($link));
  650. }
  651. break;
  652. case ('false'):
  653. return $link;
  654. break;
  655. }
  656. } # end function
  657.  
  658.  
  659.  
  660. /**
  661. * Stock function, fallback use
  662. */
  663. function stock_href_link($page = '', $parameters = '', $connection = 'NONSSL', $add_session_id = true, $search_engine_safe = true) {
  664. global $request_type, $session_started, $SID;
  665. if (!$this->not_null($page)) {
  666. die('</td></tr></table></td></tr></table><br><br><font color="#ff0000"><b>Error!</b></font><br><br><b>Unable to determine the page link!<br><br>');
  667. }
  668. if ($page == '/') $page = '';
  669. if ($connection == 'NONSSL') {
  670. $link = HTTP_SERVER . DIR_WS_HTTP_CATALOG;
  671. } elseif ($connection == 'SSL') {
  672. if (ENABLE_SSL == true) {
  673. $link = HTTPS_SERVER . DIR_WS_HTTPS_CATALOG;
  674. } else {
  675. $link = HTTP_SERVER . DIR_WS_HTTP_CATALOG;
  676. }
  677. } else {
  678. die('</td></tr></table></td></tr></table><br><br><font color="#ff0000"><b>Error!</b></font><br><br><b>Unable to determine connection method on a link!<br><br>Known methods: NONSSL SSL</b><br><br>');
  679. }
  680. if ($this->not_null($parameters)) {
  681. $link .= $page . '?' . $this->output_string($parameters);
  682. $separator = '&';
  683. } else {
  684. $link .= $page;
  685. $separator = '?';
  686. }
  687. while ( (substr($link, -1) == '&') || (substr($link, -1) == '?') ) $link = substr($link, 0, -1);
  688. if ( ($add_session_id == true) && ($session_started == true) && (SESSION_FORCE_COOKIE_USE == 'False') ) {
  689. if ($this->not_null($SID)) {
  690. $_sid = $SID;
  691. } elseif ( ( ($request_type == 'NONSSL') && ($connection == 'SSL') && (ENABLE_SSL == true) ) || ( ($request_type == 'SSL') && ($connection == 'NONSSL') ) ) {
  692. if (HTTP_COOKIE_DOMAIN != HTTPS_COOKIE_DOMAIN) {
  693. $_sid = $this->SessionName() . '=' . $this->SessionID();
  694. }
  695. }
  696. }
  697. if ( (SEARCH_ENGINE_FRIENDLY_URLS == 'true') && ($search_engine_safe == true) ) {
  698. while (strstr($link, '&&')) $link = str_replace('&&', '&', $link);
  699. $link = str_replace('?', '/', $link);
  700. $link = str_replace('&', '/', $link);
  701. $link = str_replace('=', '/', $link);
  702. $separator = '?';
  703. }
  704. switch(true){
  705. case (!isset($_SESSION['customer_id']) && defined('ENABLE_PAGE_CACHE') && ENABLE_PAGE_CACHE == 'true' && class_exists('page_cache')):
  706. $page_cache = true;
  707. $return = $link . $separator . '<osCsid>';
  708. break;
  709. case (isset($_sid)):
  710. $page_cache = false;
  711. $return = $link . $separator . $_sid;
  712. break;
  713. default:
  714. $page_cache = false;
  715. $return = $link;
  716. break;
  717. } # end switch
  718. $this->performance['NUMBER_STANDARD_URLS_GENERATED']++;
  719. $this->cache['STANDARD_URLS'][] = $link;
  720. $time = 0;
  721. $this->stop($this->timestamp, $time);
  722. $this->performance['TOTAL_TIME'] += $time;
  723. switch(true){
  724. case ($this->attributes['SEO_URLS_USE_W3C_VALID'] == 'true' && !$page_cache):
  725. return htmlspecialchars(utf8_encode($return));
  726. break;
  727. default:
  728. return $return;
  729. break;
  730. }# end swtich
  731. } # end default tep_href function
  732.  
  733.  
  734.  
  735. /**
  736. * Function to append session ID if needed
  737. * @author Bobby Easland
  738. * @version 1.2
  739. * @param string $link
  740. * @param boolean $add_session_id
  741. * @param string $connection
  742. * @param string $separator
  743. * @return string
  744. */
  745. function add_sid( $link, $add_session_id, $connection, $separator ){
  746. global $request_type; // global variable
  747. if ( ($add_session_id) && ($this->attributes['SESSION_STARTED']) && (SESSION_FORCE_COOKIE_USE == 'False') ) {
  748. if ($this->not_null($this->attributes['SID'])) {
  749. $_sid = $this->attributes['SID'];
  750. } elseif ( ( ($request_type == 'NONSSL') && ($connection == 'SSL') && (ENABLE_SSL == true) ) || ( ($request_type == 'SSL') && ($connection == 'NONSSL') ) ) {
  751. if (HTTP_COOKIE_DOMAIN != HTTPS_COOKIE_DOMAIN) {
  752. $_sid = $this->SessionName() . '=' . $this->SessionID();
  753. }
  754. }
  755. }
  756. switch(true){
  757. case (!isset($_SESSION['customer_id']) && defined('ENABLE_PAGE_CACHE') && ENABLE_PAGE_CACHE == 'true' && class_exists('page_cache')):
  758. $return = $link . $separator . '<osCsid>';
  759. break;
  760. case ($this->not_null($_sid)):
  761. $return = $link . $separator . $_sid;
  762. break;
  763. default:
  764. $return = $link;
  765. break;
  766. } # end switch
  767. return $return;
  768. } # end function
  769.  
  770. /**
  771. * SFunction to parse the parameters into an SEO URL
  772. * @author Bobby Easland
  773. * @version 1.2
  774. * @param string $page
  775. * @param string $params
  776. * @param string $separator NOTE: passed by reference
  777. * @return string
  778. */
  779. function parse_parameters($page, $params, &$separator){
  780. $p = @explode('&', $params);
  781. krsort($p);
  782. $container = array();
  783. foreach ($p as $index => $valuepair){
  784. $p2 = @explode('=', $valuepair);
  785. switch ($p2[0]){
  786. case 'products_id':
  787. switch(true){
  788. case ( $page == FILENAME_PRODUCT_INFO && !$this->is_attribute_string($p2[1]) ):
  789. $url = $this->make_url($page, $this->get_product_name($p2[1]), $p2[0], $p2[1], '.html', $separator);
  790. break;
  791. case ( $page == FILENAME_PRODUCT_REVIEWS ):
  792. $url = $this->make_url($page, $this->get_product_name($p2[1]), 'products_id_review', $p2[1], '.html', $separator);
  793. break;
  794. case ( $page == FILENAME_PRODUCT_REVIEWS_INFO ):
  795. $url = $this->make_url($page, $this->get_product_name($p2[1]), 'products_id_review_info', $p2[1], '.html', $separator);
  796. break;
  797. default:
  798. $container[$p2[0]] = $p2[1];
  799. break;
  800. } # end switch
  801. break;
  802. case 'cPath':
  803. switch(true){
  804. case ($page == FILENAME_DEFAULT):
  805. $url = $this->make_url($page, $this->get_category_name($p2[1]), $p2[0], $p2[1], '.html', $separator);
  806. break;
  807. case ( !$this->is_product_string($params) ):
  808. if ( $this->attributes['SEO_ADD_CPATH_TO_PRODUCT_URLS'] == 'true' ){
  809. $container[$p2[0]] = $p2[1];
  810. }
  811. break;
  812. default:
  813. $container[$p2[0]] = $p2[1];
  814. break;
  815. } # end switch
  816. break;
  817. case 'manufacturers_id':
  818. switch(true){
  819. case ($page == FILENAME_DEFAULT && !$this->is_cPath_string($params) && !$this->is_product_string($params) ):
  820. $url = $this->make_url($page, $this->get_manufacturer_name($p2[1]), $p2[0], $p2[1], '.html', $separator);
  821. break;
  822. case ($page == FILENAME_PRODUCT_INFO):
  823. break;
  824. default:
  825. $container[$p2[0]] = $p2[1];
  826. break;
  827. } # end switch
  828. break;
  829. case 'pID':
  830. switch(true){
  831. case ($page == FILENAME_POPUP_IMAGE):
  832. $url = $this->make_url($page, $this->get_product_name($p2[1]), $p2[0], $p2[1], '.html', $separator);
  833. break;
  834. default:
  835. $container[$p2[0]] = $p2[1];
  836. break;
  837. } # end switch
  838. break;
  839. case 'tPath':
  840. switch(true){
  841. case ($page == FILENAME_ARTICLES):
  842. $url = $this->make_url($page, $this->get_topic_name($p2[1]), $p2[0], $p2[1], '.html', $separator);
  843. break;
  844. default:
  845. $container[$p2[0]] = $p2[1];
  846. break;
  847. } # end switch
  848. break;
  849. case 'articles_id':
  850. switch(true){
  851. case ($page == FILENAME_ARTICLE_INFO):
  852. $url = $this->make_url($page, $this->get_article_name($p2[1]), $p2[0], $p2[1], '.html', $separator);
  853. break;
  854. default:
  855. $container[$p2[0]] = $p2[1];
  856. break;
  857. } # end switch
  858. break;
  859. case 'info_id':
  860. switch(true){
  861. case ($page == FILENAME_INFORMATION):
  862. $url = $this->make_url($page, $this->get_information_name($p2[1]), $p2[0], $p2[1], '.html', $separator);
  863. break;
  864. default:
  865. $container[$p2[0]] = $p2[1];
  866. break;
  867. } # end switch
  868. break;
  869. default:
  870. $container[$p2[0]] = $p2[1];
  871. break;
  872. } # end switch
  873. } # end foreach $p
  874. $url = isset($url) ? $url : $page;
  875. if ( sizeof($container) > 0 ){
  876. if ( $imploded_params = $this->implode_assoc($container) ){
  877. $url .= $separator . $this->output_string( $imploded_params );
  878. $separator = '&';
  879. }
  880. }
  881. return $url;
  882. } # end function
  883.  
  884.  
  885.  
  886. /**
  887. * Function to return the generated SEO URL
  888. * @author Bobby Easland
  889. * @version 1.0
  890. * @param string $page
  891. * @param string $string Stripped, formed anchor
  892. * @param string $anchor_type Parameter type (products_id, cPath, etc.)
  893. * @param integer $id
  894. * @param string $extension Default = .html
  895. * @param string $separator NOTE: passed by reference
  896. * @return string
  897. */
  898. function make_url($page, $string, $anchor_type, $id, $extension = '.html', &$separator){
  899. // Right now there is but one rewrite method since cName was dropped
  900. // In the future there will be additional methods here in the switch
  901. switch ( $this->attributes['SEO_REWRITE_TYPE'] ){
  902. case 'Rewrite':
  903. return $string . $this->reg_anchors[$anchor_type] . $id . $extension;
  904. break;
  905. default:
  906. break;
  907. } # end switch
  908. } # end function
  909.  
  910.  
  911.  
  912. /**
  913. * Function to get the product name. Use evaluated cache, per page cache, or database query in that order of precedent
  914. * @author Bobby Easland
  915. * @version 1.1
  916. * @param integer $pID
  917. * @return string Stripped anchor text
  918. */
  919. function get_product_name($pID){
  920. switch(true){
  921. case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && defined('PRODUCT_NAME_' . $pID)):
  922. $this->performance['CACHE_QUERY_SAVINGS']++;
  923. $return = constant('PRODUCT_NAME_' . $pID);
  924. $this->cache['PRODUCTS'][$pID] = $return;
  925. break;
  926. case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && isset($this->cache['PRODUCTS'][$pID])):
  927. $this->performance['CACHE_QUERY_SAVINGS']++;
  928. $return = $this->cache['PRODUCTS'][$pID];
  929. break;
  930. default:
  931. $this->performance['NUMBER_QUERIES']++;
  932. $sql = "SELECT products_name as pName
  933. FROM ".TABLE_PRODUCTS_DESCRIPTION."
  934. WHERE products_id='".(int)$pID."'
  935. AND language_id='".(int)$this->languages_id."'
  936. LIMIT 1";
  937. $result = $this->DB->FetchArray( $this->DB->Query( $sql ) );
  938. $pName = $this->strip( $result['pName'] );
  939. $this->cache['PRODUCTS'][$pID] = $pName;
  940. $this->performance['QUERIES']['PRODUCTS'][] = $sql;
  941. $return = $pName;
  942. break;
  943. } # end switch
  944. return $return;
  945. } # end function
  946.  
  947. /**
  948. * Function to get the category name. Use evaluated cache, per page cache, or database query in that order of precedent
  949. * @author Bobby Easland
  950. * @version 1.1
  951. * @param integer $cID NOTE: passed by reference
  952. * @return string Stripped anchor text
  953. */
  954. function get_category_name(&$cID){
  955. $full_cPath = $this->get_full_cPath($cID, $single_cID); // full cPath needed for uniformity
  956. switch(true){
  957. case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && defined('CATEGORY_NAME_' . $full_cPath)):
  958. $this->performance['CACHE_QUERY_SAVINGS']++;
  959. $return = constant('CATEGORY_NAME_' . $full_cPath);
  960. $this->cache['CATEGORIES'][$full_cPath] = $return;
  961. break;
  962. case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && isset($this->cache['CATEGORIES'][$full_cPath])):
  963. $this->performance['CACHE_QUERY_SAVINGS']++;
  964. $return = $this->cache['CATEGORIES'][$full_cPath];
  965. break;
  966. default:
  967. $this->performance['NUMBER_QUERIES']++;
  968. switch(true){
  969. case ($this->attributes['SEO_ADD_CAT_PARENT'] == 'true'):
  970. $sql = "SELECT c.categories_id, c.parent_id, cd.categories_name as cName, cd2.categories_name as pName
  971. FROM ".TABLE_CATEGORIES." c,
  972. ".TABLE_CATEGORIES_DESCRIPTION." cd
  973. LEFT JOIN ".TABLE_CATEGORIES_DESCRIPTION." cd2
  974. ON c.parent_id=cd2.categories_id AND cd2.language_id='".(int)$this->languages_id."'
  975. WHERE c.categories_id='".(int)$single_cID."'
  976. AND cd.categories_id='".(int)$single_cID."'
  977. AND cd.language_id='".(int)$this->languages_id."'
  978. LIMIT 1";
  979. $result = $this->DB->FetchArray( $this->DB->Query( $sql ) );
  980. $cName = $this->not_null($result['pName']) ? $result['pName'] . ' ' . $result['cName'] : $result['cName'];
  981. break;
  982. default:
  983. $sql = "SELECT categories_name as cName
  984. FROM ".TABLE_CATEGORIES_DESCRIPTION."
  985. WHERE categories_id='".(int)$single_cID."'
  986. AND language_id='".(int)$this->languages_id."'
  987. LIMIT 1";
  988. $result = $this->DB->FetchArray( $this->DB->Query( $sql ) );
  989. $cName = $result['cName'];
  990. break;
  991. }
  992. $cName = $this->strip($cName);
  993. $this->cache['CATEGORIES'][$full_cPath] = $cName;
  994. $this->performance['QUERIES']['CATEGORIES'][] = $sql;
  995. $return = $cName;
  996. break;
  997. } # end switch
  998. $cID = $full_cPath;
  999. return $return;
  1000. } # end function
  1001.  
  1002.  
  1003.  
  1004. /**
  1005. * Function to get the manufacturer name. Use evaluated cache, per page cache, or database query in that order of precedent.
  1006. * @author Bobby Easland
  1007. * @version 1.1
  1008. * @param integer $mID
  1009. * @return string
  1010. */
  1011. function get_manufacturer_name($mID){
  1012. switch(true){
  1013. case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && defined('MANUFACTURER_NAME_' . $mID)):
  1014. $this->performance['CACHE_QUERY_SAVINGS']++;
  1015. $return = constant('MANUFACTURER_NAME_' . $mID);
  1016. $this->cache['MANUFACTURERS'][$mID] = $return;
  1017. break;
  1018. case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && isset($this->cache['MANUFACTURERS'][$mID])):
  1019. $this->performance['CACHE_QUERY_SAVINGS']++;
  1020. $return = $this->cache['MANUFACTURERS'][$mID];
  1021. break;
  1022. default:
  1023. $this->performance['NUMBER_QUERIES']++;
  1024. $sql = "SELECT manufacturers_name as mName
  1025. FROM ".TABLE_MANUFACTURERS."
  1026. WHERE manufacturers_id='".(int)$mID."'
  1027. LIMIT 1";
  1028. $result = $this->DB->FetchArray( $this->DB->Query( $sql ) );
  1029. $mName = $this->strip( $result['mName'] );
  1030. $this->cache['MANUFACTURERS'][$mID] = $mName;
  1031. $this->performance['QUERIES']['MANUFACTURERS'][] = $sql;
  1032. $return = $mName;
  1033. break;
  1034. } # end switch
  1035. return $return;
  1036. } # end function
  1037.  
  1038.  
  1039.  
  1040. /**
  1041. * Function to get the article name. Use evaluated cache, per page cache, or database query in that order of precedent.
  1042. * @author Bobby Easland
  1043. * @version 1.0
  1044. * @param integer $aID
  1045. * @return string
  1046. */
  1047. function get_article_name($aID){
  1048. switch(true){
  1049. case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && defined('ARTICLE_NAME_' . $mID)):
  1050. $this->performance['CACHE_QUERY_SAVINGS']++;
  1051. $return = constant('ARTICLE_NAME_' . $aID);
  1052. $this->cache['ARTICLES'][$aID] = $return;
  1053. break;
  1054. case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && isset($this->cache['ARTICLES'][$aID])):
  1055. $this->performance['CACHE_QUERY_SAVINGS']++;
  1056. $return = $this->cache['ARTICLES'][$aID];
  1057. break;
  1058. default:
  1059. $this->performance['NUMBER_QUERIES']++;
  1060. $sql = "SELECT articles_name as aName
  1061. FROM ".TABLE_ARTICLES_DESCRIPTION."
  1062. WHERE articles_id='".(int)$aID."'
  1063. AND language_id='".(int)$this->languages_id."'
  1064. LIMIT 1";
  1065. $result = $this->DB->FetchArray( $this->DB->Query( $sql ) );
  1066. $aName = $this->strip( $result['aName'] );
  1067. $this->cache['ARTICLES'][$aID] = $aName;
  1068. $this->performance['QUERIES']['ARTICLES'][] = $sql;
  1069. $return = $aName;
  1070. break;
  1071. } # end switch
  1072. return $return;
  1073. } # end function
  1074.  
  1075.  
  1076.  
  1077. /**
  1078. * Function to get the topic name. Use evaluated cache, per page cache, or database query in that order of precedent.
  1079. * @author Bobby Easland
  1080. * @version 1.1
  1081. * @param integer $tID
  1082. * @return string
  1083. */
  1084. function get_topic_name($tID){
  1085. switch(true){
  1086. case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && defined('TOPIC_NAME_' . $tID)):
  1087. $this->performance['CACHE_QUERY_SAVINGS']++;
  1088. $return = constant('TOPIC_NAME_' . $tID);
  1089. $this->cache['TOPICS'][$tID] = $return;
  1090. break;
  1091. case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && isset($this->cache['TOPICS'][$tID])):
  1092. $this->performance['CACHE_QUERY_SAVINGS']++;
  1093. $return = $this->cache['TOPICS'][$tID];
  1094. break;
  1095. default:
  1096. $this->performance['NUMBER_QUERIES']++;
  1097. $sql = "SELECT topics_name as tName
  1098. FROM ".TABLE_TOPICS_DESCRIPTION."
  1099. WHERE topics_id='".(int)$tID."'
  1100. AND language_id='".(int)$this->languages_id."'
  1101. LIMIT 1";
  1102. $result = $this->DB->FetchArray( $this->DB->Query( $sql ) );
  1103. $tName = $this->strip( $result['tName'] );
  1104. $this->cache['ARTICLES'][$aID] = $tName;
  1105. $this->performance['QUERIES']['TOPICS'][] = $sql;
  1106. $return = $tName;
  1107. break;
  1108. } # end switch
  1109. return $return;
  1110. } # end function
  1111.  
  1112.  
  1113.  
  1114. /**
  1115. * Function to get the informatin name. Use evaluated cache, per page cache, or database query in that order of precedent.
  1116. * @author Bobby Easland
  1117. * @version 1.1
  1118. * @param integer $iID
  1119. * @return string
  1120. */
  1121. function get_information_name($iID){
  1122. switch(true){
  1123. case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && defined('INFO_NAME_' . $iID)):
  1124. $this->performance['CACHE_QUERY_SAVINGS']++;
  1125. $return = constant('INFO_NAME_' . $iID);
  1126. $this->cache['INFO'][$iID] = $return;
  1127. break;
  1128. case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && isset($this->cache['INFO'][$iID])):
  1129. $this->performance['CACHE_QUERY_SAVINGS']++;
  1130. $return = $this->cache['INFO'][$iID];
  1131. break;
  1132. default:
  1133. $this->performance['NUMBER_QUERIES']++;
  1134. $sql = "SELECT info_title as iName
  1135. FROM ".TABLE_INFORMATION."
  1136. WHERE information_id='".(int)$iID."'
  1137. AND languages_id='".(int)$this->languages_id."'
  1138. LIMIT 1";
  1139. $result = $this->DB->FetchArray( $this->DB->Query( $sql ) );
  1140. $iName = $this->strip( $result['iName'] );
  1141. $this->cache['INFO'][$iID] = $iName;
  1142. $this->performance['QUERIES']['INFO'][] = $sql;
  1143. $return = $iName;
  1144. break;
  1145. } # end switch
  1146. return $return;
  1147. } # end function
  1148.  
  1149.  
  1150.  
  1151. /**
  1152. * Function to retrieve full cPath from category ID
  1153. * @author Bobby Easland
  1154. * @version 1.1
  1155. * @param mixed $cID Could contain cPath or single category_id
  1156. * @param integer $original Single category_id passed back by reference
  1157. * @return string Full cPath string
  1158. */
  1159. function get_full_cPath($cID, &$original){
  1160. if ( is_numeric(strpos($cID, '_')) ){
  1161. $temp = @explode('_', $cID);
  1162. $original = $temp[sizeof($temp)-1];
  1163. return $cID;
  1164. } else {
  1165. $c = array();
  1166. $this->GetParentCategories($c, $cID);
  1167. $c = array_reverse($c);
  1168. $c[] = $cID;
  1169. $original = $cID;
  1170. $cID = sizeof($c) > 1 ? implode('_', $c) : $cID;
  1171. return $cID;
  1172. }
  1173. } # end function
  1174.  
  1175.  
  1176.  
  1177. /**
  1178. * Recursion function to retrieve parent categories from category ID
  1179. * @author Bobby Easland
  1180. * @version 1.0
  1181. * @param mixed $categories Passed by reference
  1182. * @param integer $categories_id
  1183. */
  1184. function GetParentCategories(&$categories, $categories_id) {
  1185. $sql = "SELECT parent_id
  1186. FROM " . TABLE_CATEGORIES . "
  1187. WHERE categories_id='" . (int)$categories_id . "'";
  1188. $parent_categories_query = $this->DB->Query($sql);
  1189. while ($parent_categories = $this->DB->FetchArray($parent_categories_query)) {
  1190. if ($parent_categories['parent_id'] == 0) return true;
  1191. $categories[sizeof($categories)] = $parent_categories['parent_id'];
  1192. if ($parent_categories['parent_id'] != $categories_id) {
  1193. $this->GetParentCategories($categories, $parent_categories['parent_id']);
  1194. }
  1195. }
  1196. } # end function
  1197.  
  1198.  
  1199.  
  1200. /**
  1201. * Function to check if a value is NULL
  1202. * @author Bobby Easland as abstracted from osCommerce-MS2.2
  1203. * @version 1.0
  1204. * @param mixed $value
  1205. * @return boolean
  1206. */
  1207. function not_null($value) {
  1208. if (is_array($value)) {
  1209. if (sizeof($value) > 0) {
  1210. return true;
  1211. } else {
  1212. return false;
  1213. }
  1214. } else {
  1215. if (($value != '') && (strtolower($value) != 'null') && (strlen(trim($value)) > 0)) {
  1216. return true;
  1217. } else {
  1218. return false;
  1219. }
  1220. }
  1221. } # end function
  1222.  
  1223.  
  1224.  
  1225. /**
  1226. * Function to check if the products_id contains an attribute
  1227. * @author Bobby Easland
  1228. * @version 1.1
  1229. * @param integer $pID
  1230. * @return boolean
  1231. */
  1232. function is_attribute_string($pID){
  1233. if ( is_numeric(strpos($pID, '{')) ){
  1234. return true;
  1235. } else {
  1236. return false;
  1237. }
  1238. } # end function
  1239.  
  1240.  
  1241.  
  1242. /**
  1243. * Function to check if the params contains a products_id
  1244. * @author Bobby Easland
  1245. * @version 1.1
  1246. * @param string $params
  1247. * @return boolean
  1248. */
  1249. function is_product_string($params){
  1250. if ( is_numeric(strpos('products_id', $params)) ){
  1251. return true;
  1252. } else {
  1253. return false;
  1254. }
  1255. } # end function
  1256.  
  1257.  
  1258.  
  1259. /**
  1260. * Function to check if cPath is in the parameter string
  1261. * @author Bobby Easland
  1262. * @version 1.0
  1263. * @param string $params
  1264. * @return boolean
  1265. */
  1266. function is_cPath_string($params){
  1267. if ( eregi('cPath', $params) ){
  1268. return true;
  1269. } else {
  1270. return false;
  1271. }
  1272. } # end function
  1273.  
  1274.  
  1275.  
  1276. /**
  1277. * Function used to output class profile
  1278. * @author Bobby Easland
  1279. * @version 1.0
  1280. */
  1281. function profile(){
  1282. $this->calculate_performance();
  1283. $this->PrintArray($this->attributes, 'Class Attributes');
  1284. $this->PrintArray($this->cache, 'Cached Data');
  1285. } # end function
  1286.  
  1287.  
  1288.  
  1289. /**
  1290. * Function used to calculate and output the performance metrics of the class
  1291. * @author Bobby Easland
  1292. * @version 1.0
  1293. * @return mixed Output of performance data wrapped in HTML pre tags
  1294. */
  1295. function calculate_performance(){
  1296. foreach ($this->cache as $type){
  1297. $this->performance['TOTAL_CACHED_PER_PAGE_RECORDS'] += sizeof($type);
  1298. }
  1299. $this->performance['TIME_PER_URL'] = $this->performance['TOTAL_TIME'] / $this->performance['NUMBER_URLS_GENERATED'];
  1300. return $this->PrintArray($this->performance, 'Performance Data');
  1301. } # end function
  1302.  
  1303. /**
  1304. * Function to strip the string of punctuation and white space
  1305. * @author Bobby Easland
  1306. * @version 1.1
  1307. * @param string $string
  1308. * @return string Stripped text. Removes all non-alphanumeric characters.
  1309. */
  1310. function strip($string){
  1311. if ( is_array($this->attributes['SEO_CHAR_CONVERT_SET']) ) $string = strtr($string, $this->attributes['SEO_CHAR_CONVERT_SET']);
  1312. $pattern = $this->attributes['SEO_REMOVE_ALL_SPEC_CHARS'] == 'true'
  1313. ? "([^[:alnum:]])+"
  1314. : "([[:punct:]])+";
  1315. $anchor = ereg_replace($pattern, '', strtolower($string));
  1316. $pattern = "([[:space:]]|[[:blank:]])+";
  1317. $anchor = ereg_replace($pattern, '-', $anchor);
  1318. return $this->short_name($anchor); // return the short filtered name
  1319. } # end function
  1320.  
  1321.  
  1322.  
  1323. /**
  1324. * Function to expand the SEO_CONVERT_SET group
  1325. * @author Bobby Easland
  1326. * @version 1.0
  1327. * @param string $set
  1328. * @return mixed
  1329. */
  1330. function expand($set){
  1331. if ( $this->not_null($set) ){
  1332. if ( $data = @explode(',', $set) ){
  1333. foreach ( $data as $index => $valuepair){
  1334. $p = @explode('=>', $valuepair);
  1335. $container[trim($p[0])] = trim($p[1]);
  1336. }
  1337. return $container;
  1338. } else {
  1339. return 'false';
  1340. }
  1341. } else {
  1342. return 'false';
  1343. }
  1344. } # end function
  1345.  
  1346. /**
  1347. * Function to return the short word filtered string
  1348. * @author Bobby Easland
  1349. * @version 1.0
  1350. * @param string $str
  1351. * @param integer $limit
  1352. * @return string Short word filtered
  1353. */
  1354. function short_name($str, $limit=3){
  1355. if ( $this->attributes['SEO_URLS_FILTER_SHORT_WORDS'] != 'false' ) $limit = (int)$this->attributes['SEO_URLS_FILTER_SHORT_WORDS'];
  1356. $foo = @explode('-', $str);
  1357. foreach($foo as $index => $value){
  1358. switch (true){
  1359. case ( strlen($value) <= $limit ):
  1360. continue;
  1361. default:
  1362. $container[] = $value;
  1363. break;
  1364. }
  1365. } # end foreach
  1366. $container = ( sizeof($container) > 1 ? implode('-', $container) : $str );
  1367. return $container;
  1368. }
  1369. /**
  1370. * Function to implode an associative array
  1371. * @author Bobby Easland
  1372. * @version 1.0
  1373. * @param array $array Associative data array
  1374. * @param string $inner_glue
  1375. * @param string $outer_glue
  1376. * @return string
  1377. */
  1378. function implode_assoc($array, $inner_glue='=', $outer_glue='&') {
  1379. $output = array();
  1380. foreach( $array as $key => $item ){
  1381. if ( $this->not_null($key) && $this->not_null($item) ){
  1382. $output[] = $key . $inner_glue . $item;
  1383. }
  1384. } # end foreach
  1385. return @implode($outer_glue, $output);
  1386. }
  1387.  
  1388. /**
  1389. * Function to print an array within pre tags, debug use
  1390. * @author Bobby Easland
  1391. * @version 1.0
  1392. * @param mixed $array
  1393. */
  1394. function PrintArray($array, $heading = ''){
  1395. echo '<fieldset style="border-style:solid; border-width:1px;">' . "\n";
  1396. echo '<legend style="background-color:#FFFFCC; border-style:solid; border-width:1px;">' . $heading . '</legend>' . "\n";
  1397. echo '<pre style="text-align:left;">' . "\n";
  1398. print_r($array);
  1399. echo '</pre>' . "\n";
  1400. echo '</fieldset><br/>' . "\n";
  1401. } # end function
  1402.  
  1403.  
  1404.  
  1405. /**
  1406. * Function to start time for performance metric
  1407. * @author Bobby Easland
  1408. * @version 1.0
  1409. * @param float $start_time
  1410. */
  1411. function start(&$start_time){
  1412. $start_time = explode(' ', microtime());
  1413. }
  1414. /**
  1415. * Function to stop time for performance metric
  1416. * @author Bobby Easland
  1417. * @version 1.0
  1418. * @param float $start
  1419. * @param float $time NOTE: passed by reference
  1420. */
  1421. function stop($start, &$time){
  1422. $end = explode(' ', microtime());
  1423. $time = number_format( array_sum($end) - array_sum($start), 8, '.', '' );
  1424. }
  1425.  
  1426. /**
  1427. * Function to translate a string
  1428. * @author Bobby Easland
  1429. * @version 1.0
  1430. * @param string $data String to be translated
  1431. * @param array $parse Array of tarnslation variables
  1432. * @return string
  1433. */
  1434. function parse_input_field_data($data, $parse) {
  1435. return strtr(trim($data), $parse);
  1436. }
  1437. /**
  1438. * Function to output a translated or sanitized string
  1439. * @author Bobby Easland
  1440. * @version 1.0
  1441. * @param string $sting String to be output
  1442. * @param mixed $translate Array of translation characters
  1443. * @param boolean $protected Switch for htemlspecialchars processing
  1444. * @return string
  1445. */
  1446. function output_string($string, $translate = false, $protected = false) {
  1447. if ($protected == true) {
  1448. return htmlspecialchars($string);
  1449. } else {
  1450. if ($translate == false) {
  1451. return $this->parse_input_field_data($string, array('"' => '&quot;'));
  1452. } else {
  1453. return $this->parse_input_field_data($string, $translate);
  1454. }
  1455. }
  1456. }
  1457.  
  1458. /**
  1459. * Function to return the session ID
  1460. * @author Bobby Easland
  1461. * @version 1.0
  1462. * @param string $sessid
  1463. * @return string
  1464. */
  1465. function SessionID($sessid = '') {
  1466. if (!empty($sessid)) {
  1467. return session_id($sessid);
  1468. } else {
  1469. return session_id();
  1470. }
  1471. }
  1472. /**
  1473. * Function to return the session name
  1474. * @author Bobby Easland
  1475. * @version 1.0
  1476. * @param string $name
  1477. * @return string
  1478. */
  1479. function SessionName($name = '') {
  1480. if (!empty($name)) {
  1481. return session_name($name);
  1482. } else {
  1483. return session_name();
  1484. }
  1485. }
  1486.  
  1487. /**
  1488. * Function to generate products cache entries
  1489. * @author Bobby Easland
  1490. * @version 1.0
  1491. */
  1492. function generate_products_cache(){
  1493. $this->is_cached($this->cache_file . 'products', $is_cached, $is_expired);
  1494. if ( !$is_cached || $is_expired ) {
  1495. $sql = "SELECT p.products_id as id, pd.products_name as name
  1496. FROM ".TABLE_PRODUCTS." p
  1497. LEFT JOIN ".TABLE_PRODUCTS_DESCRIPTION." pd
  1498. ON p.products_id=pd.products_id
  1499. AND pd.language_id='".(int)$this->languages_id."'
  1500. WHERE p.products_status='1'";
  1501. $product_query = $this->DB->Query( $sql );
  1502. $prod_cache = '';
  1503. while ($product = $this->DB->FetchArray($product_query)) {
  1504. $define = 'define(\'PRODUCT_NAME_' . $product['id'] . '\', \'' . $this->strip($product['name']) . '\');';
  1505. $prod_cache .= $define . "\n";
  1506. eval("$define");
  1507. }
  1508. $this->DB->Free($product_query);
  1509. $this->save_cache($this->cache_file . 'products', $prod_cache, 'EVAL', 1 , 1);
  1510. unset($prod_cache);
  1511. } else {
  1512. $this->get_cache($this->cache_file . 'products');
  1513. }
  1514. } # end function
  1515.  
  1516. /**
  1517. * Function to generate manufacturers cache entries
  1518. * @author Bobby Easland
  1519. * @version 1.0
  1520. */
  1521. function generate_manufacturers_cache(){
  1522. $this->is_cached($this->cache_file . 'manufacturers', $is_cached, $is_expired);
  1523. if ( !$is_cached || $is_expired ) { // it's not cached so create it
  1524. $sql = "SELECT m.manufacturers_id as id, m.manufacturers_name as name
  1525. FROM ".TABLE_MANUFACTURERS." m
  1526. LEFT JOIN ".TABLE_MANUFACTURERS_INFO." md
  1527. ON m.manufacturers_id=md.manufacturers_id
  1528. AND md.languages_id='".(int)$this->languages_id."'";
  1529. $manufacturers_query = $this->DB->Query( $sql );
  1530. $man_cache = '';
  1531. while ($manufacturer = $this->DB->FetchArray($manufacturers_query)) {
  1532. $define = 'define(\'MANUFACTURER_NAME_' . $manufacturer['id'] . '\', \'' . $this->strip($manufacturer['name']) . '\');';
  1533. $man_cache .= $define . "\n";
  1534. eval("$define");
  1535. }
  1536. $this->DB->Free($manufacturers_query);
  1537. $this->save_cache($this->cache_file . 'manufacturers', $man_cache, 'EVAL', 1 , 1);
  1538. unset($man_cache);
  1539. } else {
  1540. $this->get_cache($this->cache_file . 'manufacturers');
  1541. }
  1542. } # end function
  1543.  
  1544.  
  1545.  
  1546. /**
  1547. * Function to generate categories cache entries
  1548. * @author Bobby Easland
  1549. * @version 1.1
  1550. */
  1551. function generate_categories_cache(){
  1552. $this->is_cached($this->cache_file . 'categories', $is_cached, $is_expired);
  1553. if ( !$is_cached || $is_expired ) { // it's not cached so create it
  1554. switch(true){
  1555. case ($this->attributes['SEO_ADD_CAT_PARENT'] == 'true'):
  1556. $sql = "SELECT c.categories_id as id, c.parent_id, cd.categories_name as cName, cd2.categories_name as pName
  1557. FROM ".TABLE_CATEGORIES." c,
  1558. ".TABLE_CATEGORIES_DESCRIPTION." cd
  1559. LEFT JOIN ".TABLE_CATEGORIES_DESCRIPTION." cd2
  1560. ON c.parent_id=cd2.categories_id AND cd2.language_id='".(int)$this->languages_id."'
  1561. WHERE c.categories_id=cd.categories_id
  1562. AND cd.language_id='".(int)$this->languages_id."'";
  1563. break;
  1564. default:
  1565. $sql = "SELECT categories_id as id, categories_name as cName
  1566. FROM ".TABLE_CATEGORIES_DESCRIPTION."
  1567. WHERE language_id='".(int)$this->languages_id."'";
  1568. break;
  1569. } # end switch
  1570. $category_query = $this->DB->Query( $sql );
  1571. $cat_cache = '';
  1572. while ($category = $this->DB->FetchArray($category_query)) {
  1573. $id = $this->get_full_cPath($category['id'], $single_cID);
  1574. $name = $this->not_null($category['pName']) ? $category['pName'] . ' ' . $category['cName'] : $category['cName'];
  1575. $define = 'define(\'CATEGORY_NAME_' . $id . '\', \'' . $this->strip($name) . '\');';
  1576. $cat_cache .= $define . "\n";
  1577. eval("$define");
  1578. }
  1579. $this->DB->Free($category_query);
  1580. $this->save_cache($this->cache_file . 'categories', $cat_cache, 'EVAL', 1 , 1);
  1581. unset($cat_cache);
  1582. } else {
  1583. $this->get_cache($this->cache_file . 'categories');
  1584. }
  1585. } # end function
  1586.  
  1587.  
  1588.  
  1589. /**
  1590. * Function to generate articles cache entries
  1591. * @author Bobby Easland
  1592. * @version 1.0
  1593. */
  1594. function generate_articles_cache(){
  1595. $this->is_cached($this->cache_file . 'articles', $is_cached, $is_expired);
  1596. if ( !$is_cached || $is_expired ) { // it's not cached so create it
  1597. $sql = "SELECT articles_id as id, articles_name as name
  1598. FROM ".TABLE_ARTICLES_DESCRIPTION."
  1599. WHERE language_id = '".(int)$this->languages_id."'";
  1600. $article_query = $this->DB->Query( $sql );
  1601. $article_cache = '';
  1602. while ($article = $this->DB->FetchArray($article_query)) {
  1603. $define = 'define(\'ARTICLE_NAME_' . $article['id'] . '\', \'' . $this->strip($article['name']) . '\');';
  1604. $article_cache .= $define . "\n";
  1605. eval("$define");
  1606. }
  1607. $this->DB->Free($article_query);
  1608. $this->save_cache($this->cache_file . 'articles', $article_cache, 'EVAL', 1 , 1);
  1609. unset($article_cache);
  1610. } else {
  1611. $this->get_cache($this->cache_file . 'articles');
  1612. }
  1613. } # end function
  1614.  
  1615.  
  1616.  
  1617. /**
  1618. * Function to generate topics cache entries
  1619. * @author Bobby Easland
  1620. * @version 1.0
  1621. */
  1622. function generate_topics_cache(){
  1623. $this->is_cached($this->cache_file . 'topics', $is_cached, $is_expired);
  1624. if ( !$is_cached || $is_expired ) { // it's not cached so create it
  1625. $sql = "SELECT topics_id as id, topics_name as name
  1626. FROM ".TABLE_TOPICS_DESCRIPTION."
  1627. WHERE language_id='".(int)$this->languages_id."'";
  1628. $topic_query = $this->DB->Query( $sql );
  1629. $topic_cache = '';
  1630. while ($topic = $this->DB->FetchArray($topic_query)) {
  1631. $define = 'define(\'TOPIC_NAME_' . $topic['id'] . '\', \'' . $this->strip($topic['name']) . '\');';
  1632. $topic_cache .= $define . "\n";
  1633. eval("$define");
  1634. }
  1635. $this->DB->Free($topic_query);
  1636. $this->save_cache($this->cache_file . 'topics', $topic_cache, 'EVAL', 1 , 1);
  1637. unset($topic_cache);
  1638. } else {
  1639. $this->get_cache($this->cache_file . 'topics');
  1640. }
  1641. } # end function
  1642.  
  1643.  
  1644.  
  1645. /**
  1646. * Function to generate information cache entries
  1647. * @author Bobby Easland
  1648. * @version 1.0
  1649. */
  1650. function generate_information_cache(){
  1651. $this->is_cached($this->cache_file . 'information', $is_cached, $is_expired);
  1652. if ( !$is_cached || $is_expired ) { // it's not cached so create it
  1653. $sql = "SELECT information_id as id, info_title as name
  1654. FROM ".TABLE_INFORMATION."
  1655. WHERE languages_id='".(int)$this->languages_id."'";
  1656. $information_query = $this->DB->Query( $sql );
  1657. $information_cache = '';
  1658. while ($information = $this->DB->FetchArray($information_query)) {
  1659. $define = 'define(\'INFO_NAME_' . $information['id'] . '\', \'' . $this->strip($information['name']) . '\');';
  1660. $information_cache .= $define . "\n";
  1661. eval("$define");
  1662. }
  1663. $this->DB->Free($information_query);
  1664. $this->save_cache($this->cache_file . 'information', $information_cache, 'EVAL', 1 , 1);
  1665. unset($information_cache);
  1666. } else {
  1667. $this->get_cache($this->cache_file . 'information');
  1668. }
  1669. } # end function
  1670.  
  1671.  
  1672.  
  1673. /**
  1674. * Function to save the cache to database
  1675. * @author Bobby Easland
  1676. * @version 1.0
  1677. * @param string $name Cache name
  1678. * @param mixed $value Can be array, string, PHP code, or just about anything
  1679. * @param string $method RETURN, ARRAY, EVAL
  1680. * @param integer $gzip Enables compression
  1681. * @param integer $global Sets whether cache record is global is scope
  1682. * @param string $expires Sets the expiration
  1683. */
  1684. function save_cache($name, $value, $method='RETURN', $gzip=1, $global=0, $expires = '30/days'){
  1685. $expires = $this->convert_time($expires);
  1686. if ($method == 'ARRAY' ) $value = serialize($value);
  1687. $value = ( $gzip === 1 ? base64_encode(gzdeflate($value, 1)) : addslashes($value) );
  1688. $sql_data_array = array('cache_id' => md5($name),
  1689. 'cache_language_id' => (int)$this->languages_id,
  1690. 'cache_name' => $name,
  1691. 'cache_data' => $value,
  1692. 'cache_global' => (int)$global,
  1693. 'cache_gzip' => (int)$gzip,
  1694. 'cache_method' => $method,
  1695. 'cache_date' => date("Y-m-d H:i:s"),
  1696. 'cache_expires' => $expires
  1697. );
  1698. $this->is_cached($name, $is_cached, $is_expired);
  1699. $cache_check = ( $is_cached ? 'true' : 'false' );
  1700. switch ( $cache_check ) {
  1701. case 'true':
  1702. $this->DB->DBPerform('cache', $sql_data_array, 'update', "cache_id='".md5($name)."'");
  1703. break;
  1704. case 'false':
  1705. $this->DB->DBPerform('cache', $sql_data_array, 'insert');
  1706. break;
  1707. default:
  1708. break;
  1709. } # end switch ($cache check)
  1710. # unset the variables...clean as we go
  1711. unset($value, $expires, $sql_data_array);
  1712. }# end function save_cache()
  1713.  
  1714. /**
  1715. * Function to get cache entry
  1716. * @author Bobby Easland
  1717. * @version 1.0
  1718. * @param string $name
  1719. * @param boolean $local_memory
  1720. * @return mixed
  1721. */
  1722. function get_cache($name = 'GLOBAL', $local_memory = false){
  1723. $select_list = 'cache_id, cache_language_id, cache_name, cache_data, cache_global, cache_gzip, cache_method, cache_date, cache_expires';
  1724. $global = ( $name == 'GLOBAL' ? true : false ); // was GLOBAL passed or is using the default?
  1725. switch($name){
  1726. case 'GLOBAL':
  1727. $this->cache_query = $this->DB->Query("SELECT ".$select_list." FROM cache WHERE cache_language_id='".(int)$this->languages_id."' AND cache_global='1'");
  1728. break;
  1729. default:
  1730. $this->cache_query = $this->DB->Query("SELECT ".$select_list." FROM cache WHERE cache_id='".md5($name)."' AND cache_language_id='".(int)$this->languages_id."'");
  1731. break;
  1732. } # end switch ($name)
  1733. $num_rows = $this->DB->NumRows($this->cache_query);
  1734. if ( $num_rows ){
  1735. $container = array();
  1736. while($cache = $this->DB->FetchArray($this->cache_query)){
  1737. $cache_name = $cache['cache_name'];
  1738. if ( $cache['cache_expires'] > date("Y-m-d H:i:s") ) {
  1739. $cache_data = ( $cache['cache_gzip'] == 1 ? gzinflate(base64_decode($cache['cache_data'])) : stripslashes($cache['cache_data']) );
  1740. switch($cache['cache_method']){
  1741. case 'EVAL': // must be PHP code
  1742. eval("$cache_data");
  1743. break;
  1744. case 'ARRAY':
  1745. $cache_data = unserialize($cache_data);
  1746. case 'RETURN':
  1747. default:
  1748. break;
  1749. } # end switch ($cache['cache_method'])
  1750. if ($global) $container['GLOBAL'][$cache_name] = $cache_data;
  1751. else $container[$cache_name] = $cache_data; // not global
  1752. } else { // cache is expired
  1753. if ($global) $container['GLOBAL'][$cache_name] = false;
  1754. else $container[$cache_name] = false;
  1755. }# end if ( $cache['cache_expires'] > date("Y-m-d H:i:s") )
  1756. if ( $this->keep_in_memory || $local_memory ) {
  1757. if ($global) $this->data['GLOBAL'][$cache_name] = $container['GLOBAL'][$cache_name];
  1758. else $this->data[$cache_name] = $container[$cache_name];
  1759. }
  1760. } # end while ($cache = $this->DB->FetchArray($this->cache_query))
  1761. unset($cache_data);
  1762. $this->DB->Free($this->cache_query);
  1763. switch (true) {
  1764. case ($num_rows == 1):
  1765. if ($global){
  1766. if ($container['GLOBAL'][$cache_name] == false || !isset($container['GLOBAL'][$cache_name])) return false;
  1767. else return $container['GLOBAL'][$cache_name];
  1768. } else { // not global
  1769. if ($container[$cache_name] == false || !isset($container[$cache_name])) return false;
  1770. else return $container[$cache_name];
  1771. } # end if ($global)
  1772. case ($num_rows > 1):
  1773. default:
  1774. return $container;
  1775. break;
  1776. }# end switch (true)
  1777. } else {
  1778. return false;
  1779. }# end if ( $num_rows )
  1780. } # end function get_cache()
  1781.  
  1782.  
  1783.  
  1784. /**
  1785. * Function to get cache from memory
  1786. * @author Bobby Easland
  1787. * @version 1.0
  1788. * @param string $name
  1789. * @param string $method
  1790. * @return mixed
  1791. */
  1792. function get_cache_memory($name, $method = 'RETURN'){
  1793. $data = ( isset($this->data['GLOBAL'][$name]) ? $this->data['GLOBAL'][$name] : $this->data[$name] );
  1794. if ( isset($data) && !empty($data) && $data != false ){
  1795. switch($method){
  1796. case 'EVAL': // data must be PHP
  1797. eval("$data");
  1798. return true;
  1799. break;
  1800. case 'ARRAY':
  1801. case 'RETURN':
  1802. default:
  1803. return $data;
  1804. break;
  1805. } # end switch ($method)
  1806. } else {
  1807. return false;
  1808. } # end if (isset($data) && !empty($data) && $data != false)
  1809. } # end function get_cache_memory()
  1810.  
  1811.  
  1812.  
  1813. /**
  1814. * Function to perform basic garbage collection for database cache system
  1815. * @author Bobby Easland
  1816. * @version 1.0
  1817. */
  1818. function cache_gc(){
  1819. $this->DB->Query("DELETE FROM cache WHERE cache_expires <= '" . date("Y-m-d H:i:s") . "'" );
  1820. }
  1821.  
  1822. /**
  1823. * Function to convert time for cache methods
  1824. * @author Bobby Easland
  1825. * @version 1.0
  1826. * @param string $expires
  1827. * @return string
  1828. */
  1829. function convert_time($expires){ //expires date interval must be spelled out and NOT abbreviated !!
  1830. $expires = explode('/', $expires);
  1831. switch( strtolower($expires[1]) ){
  1832. case 'seconds':
  1833. $expires = mktime( date("H"), date("i"), date("s")+(int)$expires[0], date("m"), date("d"), date("Y") );
  1834. break;
  1835. case 'minutes':
  1836. $expires = mktime( date("H"), date("i")+(int)$expires[0], date("s"), date("m"), date("d"), date("Y") );
  1837. break;
  1838. case 'hours':
  1839. $expires = mktime( date("H")+(int)$expires[0], date("i"), date("s"), date("m"), date("d"), date("Y") );
  1840. break;
  1841. case 'days':
  1842. $expires = mktime( date("H"), date("i"), date("s"), date("m"), date("d")+(int)$expires[0], date("Y") );
  1843. break;
  1844. case 'months':
  1845. $expires = mktime( date("H"), date("i"), date("s"), date("m")+(int)$expires[0], date("d"), date("Y") );
  1846. break;
  1847. case 'years':
  1848. $expires = mktime( date("H"), date("i"), date("s"), date("m"), date("d"), date("Y")+(int)$expires[0] );
  1849. break;
  1850. default: // if something fudged up then default to 1 month
  1851. $expires = mktime( date("H"), date("i"), date("s"), date("m")+1, date("d"), date("Y") );
  1852. break;
  1853. } # end switch( strtolower($expires[1]) )
  1854. return date("Y-m-d H:i:s", $expires);
  1855. } # end function convert_time()
  1856.  
  1857.  
  1858.  
  1859. /**
  1860. * Function to check if the cache is in the database and expired
  1861. * @author Bobby Easland
  1862. * @version 1.0
  1863. * @param string $name
  1864. * @param boolean $is_cached NOTE: passed by reference
  1865. * @param boolean $is_expired NOTE: passed by reference
  1866. */
  1867. function is_cached($name, &$is_cached, &$is_expired){ // NOTE: $is_cached and $is_expired is passed by reference !!
  1868. $this->cache_query = $this->DB->Query("SELECT cache_expires FROM cache WHERE cache_id='".md5($name)."' AND cache_language_id='".(int)$this->languages_id."' LIMIT 1");
  1869. $is_cached = ( $this->DB->NumRows($this->cache_query ) > 0 ? true : false );
  1870. if ($is_cached){
  1871. $check = $this->DB->FetchArray($this->cache_query);
  1872. $is_expired = ( $check['cache_expires'] <= date("Y-m-d H:i:s") ? true : false );
  1873. unset($check);
  1874. }
  1875. $this->DB->Free($this->cache_query);
  1876. }# end function is_cached()
  1877.  
  1878.  
  1879.  
  1880. /**
  1881. * Function to initialize the redirect logic
  1882. * @author Bobby Easland
  1883. * @version 1.1
  1884. */
  1885. function check_redirect(){
  1886. $this->need_redirect = false;
  1887. $this->path_info = is_numeric(strpos(ltrim(getenv('PATH_INFO'), '/') , '/')) ? ltrim(getenv('PATH_INFO'), '/') : NULL;
  1888. $this->uri = ltrim( basename($_SERVER['REQUEST_URI']), '/' );
  1889. $this->real_uri = ltrim( basename($_SERVER['SCRIPT_NAME']) . '?' . $_SERVER['QUERY_STRING'], '/' );
  1890. $this->uri_parsed = $this->not_null( $this->path_info )
  1891. ? parse_url(basename($_SERVER['SCRIPT_NAME']) . '?' . $this->parse_path($this->path_info) )
  1892. : parse_url(basename($_SERVER['REQUEST_URI']));
  1893. $this->attributes['SEO_REDIRECT']['PATH_INFO'] = $this->path_info;
  1894. $this->attributes['SEO_REDIRECT']['URI'] = $this->uri;
  1895. $this->attributes['SEO_REDIRECT']['REAL_URI'] = $this->real_uri;
  1896. $this->attributes['SEO_REDIRECT']['URI_PARSED'] = $this->uri_parsed;
  1897. $this->need_redirect();
  1898. $this->check_seo_page();
  1899. if ( $this->need_redirect && $this->is_seopage && $this->attributes['USE_SEO_REDIRECT'] == 'true') $this->do_redirect();
  1900. } # end function
  1901.  
  1902. /**
  1903. * Function to check if the URL needs to be redirected
  1904. * @author Bobby Easland
  1905. * @version 1.2
  1906. */
  1907. function need_redirect(){
  1908. foreach( $this->reg_anchors as $param => $value){
  1909. $pattern[] = $param;
  1910. }
  1911. switch(true){
  1912. case ($this->is_attribute_string($this->uri)):
  1913. $this->need_redirect = false;
  1914. break;
  1915. case ($this->uri != $this->real_uri && !$this->not_null($this->path_info)):
  1916. $this->need_redirect = false;
  1917. break;
  1918. case (is_numeric(strpos($this->uri, '.htm'))):
  1919. $this->need_redirect = false;
  1920. break;
  1921. case (@eregi("(".@implode('|', $pattern).")", $this->uri)):
  1922. $this->need_redirect = true;
  1923. break;
  1924. case (@eregi("(".@implode('|', $pattern).")", $this->path_info)):
  1925. $this->need_redirect = true;
  1926. break;
  1927. default:
  1928. break;
  1929. } # end switch
  1930. $this->attributes['SEO_REDIRECT']['NEED_REDIRECT'] = $this->need_redirect ? 'true' : 'false';
  1931. } # end function set_seopage
  1932.  
  1933. /**
  1934. * Function to check if it's a valid redirect page
  1935. * @author Bobby Easland
  1936. * @version 1.1
  1937. */
  1938. function check_seo_page(){
  1939. switch (true){
  1940. case (in_array($this->uri_parsed['path'], $this->attributes['SEO_PAGES'])):
  1941. $this->is_seopage = true;
  1942. break;
  1943. case ($this->attributes['SEO_ENABLED'] == 'false'):
  1944. default:
  1945. $this->is_seopage = false;
  1946. break;
  1947. } # end switch
  1948. $this->attributes['SEO_REDIRECT']['IS_SEOPAGE'] = $this->is_seopage ? 'true' : 'false';
  1949. } # end function check_seo_page
  1950.  
  1951. /**
  1952. * Function to parse the path for old SEF URLs
  1953. * @author Bobby Easland
  1954. * @version 1.0
  1955. * @param string $path_info
  1956. * @return array
  1957. */
  1958. function parse_path($path_info){
  1959. $tmp = @explode('/', $path_info);
  1960. if ( sizeof($tmp) > 2 ){
  1961. $container = array();
  1962. for ($i=0, $n=sizeof($tmp); $i<$n; $i++) {
  1963. $container[] = $tmp[$i] . '=' . $tmp[$i+1];
  1964. $i++;
  1965. }
  1966. return @implode('&', $container);
  1967. } else {
  1968. return @implode('=', $tmp);
  1969. }
  1970. } # end function parse_path
  1971.  
  1972. /**
  1973. * Function to perform redirect
  1974. * @author Bobby Easland
  1975. * @version 1.0
  1976. */
  1977. function do_redirect(){
  1978. $p = @explode('&', $this->uri_parsed['query']);
  1979. foreach( $p as $index => $value ){
  1980. $tmp = @explode('=', $value);
  1981. switch($tmp[0]){
  1982. case 'products_id':
  1983. if ( $this->is_attribute_string($tmp[1]) ){
  1984. $pieces = @explode('{', $tmp[1]);
  1985. $params[] = $tmp[0] . '=' . $pieces[0];
  1986. } else {
  1987. $params[] = $tmp[0] . '=' . $tmp[1];
  1988. }
  1989. break;
  1990. default:
  1991. $params[] = $tmp[0].'='.$tmp[1];
  1992. break;
  1993. }
  1994. } # end foreach( $params as $var => $value )
  1995. $params = ( sizeof($params) > 1 ? implode('&', $params) : $params[0] );
  1996. $url = $this->href_link($this->uri_parsed['path'], $params, 'NONSSL', false);
  1997. switch(true){
  1998. case (defined('USE_SEO_REDIRECT_DEBUG') && USE_SEO_REDIRECT_DEBUG == 'true'):
  1999. $this->attributes['SEO_REDIRECT']['REDIRECT_URL'] = $url;
  2000. break;
  2001. case ($this->attributes['USE_SEO_REDIRECT'] == 'true'):
  2002. header("HTTP/1.0 301 Moved Permanently");
  2003. header("Location: $url"); // redirect...bye bye
  2004. break;
  2005. default:
  2006. $this->attributes['SEO_REDIRECT']['REDIRECT_URL'] = $url;
  2007. break;
  2008. } # end switch
  2009. } # end function do_redirect
  2010.  
  2011. } # end class
  2012. ?>

Documentation generated on Sun, 12 Jun 2005 14:35:29 -0400 by phpDocumentor 1.3.0RC3