[ Index ]

PHP Cross Reference of osCMax 2.0.4

title

Body

[close]

/includes/classes/ -> seo.class.php (source)

   1  <?php
   2  define('USE_SEO_REDIRECT_DEBUG', 'false');
   3  /**

   4   * Ultimate SEO URLs Contribution - osCommerce MS-2.2

   5   *

   6   * Ultimate SEO URLs offers search engine optimized URLS for osCommerce

   7   * based applications. Other features include optimized performance and 

   8   * automatic redirect script.

   9   * @package Ultimate-SEO-URLs

  10   * @link http://www.oscommerce-freelancers.com/ osCommerce-Freelancers

  11   * @copyright Copyright 2005, Bobby Easland 

  12   * @author Bobby Easland 

  13   * @filesource

  14   */
  15  
  16  /**

  17   * SEO_DataBase Class

  18   *

  19   * The SEO_DataBase class provides abstraction so the databaes can be accessed

  20   * without having to use tep API functions. This class has minimal error handling

  21   * so make sure your code is tight!

  22   * @package Ultimate-SEO-URLs

  23   * @link http://www.oscommerce-freelancers.com/ osCommerce-Freelancers

  24   * @copyright Copyright 2005, Bobby Easland 

  25   * @author Bobby Easland 

  26   */
  27  /**

  28  * Modified for MySQL5 in STRICT mode

  29  * by FWR Media

  30  * www.fwrmedia.co.uk

  31  */
  32  class SEO_DataBase{
  33          /**

  34           * Database host (localhost, IP based, etc)

  35          * @var string

  36           */
  37          var $host;
  38          /**

  39           * Database user

  40          * @var string

  41           */
  42          var $user;
  43          /**

  44           * Database name

  45          * @var string

  46           */
  47          var $db;
  48          /**

  49           * Database password

  50          * @var string

  51           */
  52          var $pass;
  53          /**

  54           * Database link

  55          * @var resource

  56           */
  57          var $link_id;
  58  
  59  /**

  60   * MySQL_DataBase class constructor 

  61   * @author Bobby Easland 

  62   * @version 1.0

  63   * @param string $host

  64   * @param string $user

  65   * @param string $db

  66   * @param string $pass  

  67   */        
  68          function SEO_DataBase($host, $user, $db, $pass){
  69                  $this->host = $host;
  70                  $this->user = $user;
  71                  $this->db = $db;
  72                  $this->pass = $pass;                
  73                  $this->ConnectDB();
  74                  $this->SelectDB();
  75          } # end function

  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   * Function to fetch the last insertID

 132   * @author Bobby Easland 

 133   * @version 1.0

 134   * @return integer  

 135   */        
 136          function InsertID() {
 137                  return mysql_insert_id();
 138          }
 139          
 140  /**

 141   * Function to free the resource

 142   * @author Bobby Easland 

 143   * @version 1.0

 144   * @param resource $resource_id

 145   * @return boolean

 146   */        
 147          function Free($resource_id){
 148                  return @mysql_free_result($resource_id);
 149          } # end function

 150  
 151  /**

 152   * Function to add slashes

 153   * @author Bobby Easland 

 154   * @version 1.0

 155   * @param string $data

 156   * @return string 

 157   */        
 158          function Slashes($data){
 159                  return addslashes($data);
 160          } # end function

 161  
 162  /**

 163   * Function to perform DB inserts and updates - abstracted from osCommerce-MS-2.2 project

 164   * @author Bobby Easland 

 165   * @version 1.0

 166   * @param string $table Database table

 167   * @param array $data Associative array of columns / values

 168   * @param string $action insert or update

 169   * @param string $parameters

 170   * @return resource

 171   */        
 172          function DBPerform($table, $data, $action = 'insert', $parameters = '') {
 173                  reset($data);
 174                  if ($action == 'insert') {
 175                    $query = 'INSERT INTO `' . $table . '` (';
 176                    while (list($columns, ) = each($data)) {
 177                          $query .= '`' . $columns . '`, ';
 178                    }
 179                    $query = substr($query, 0, -2) . ') values (';
 180                    reset($data);
 181                    while (list(, $value) = each($data)) {
 182                          switch ((string)$value) {
 183                            case 'now()':
 184                                  $query .= 'now(), ';
 185                                  break;
 186                            case 'null':
 187                                  $query .= 'null, ';
 188                                  break;
 189                            default:
 190                                  $query .= "'" . $this->Slashes($value) . "', ";
 191                                  break;
 192                          }
 193                    }
 194                    $query = substr($query, 0, -2) . ')';
 195                  } elseif ($action == 'update') {
 196                    $query = 'UPDATE `' . $table . '` SET ';
 197                    while (list($columns, $value) = each($data)) {
 198                          switch ((string)$value) {
 199                            case 'now()':
 200                                  $query .= '`' .$columns . '`=now(), ';
 201                                  break;
 202                            case 'null':
 203                                  $query .= '`' .$columns .= '`=null, ';
 204                                  break;
 205                            default:
 206                                  $query .= '`' .$columns . "`='" . $this->Slashes($value) . "', ";
 207                                  break;
 208                          }
 209                    }
 210                    $query = substr($query, 0, -2) . ' WHERE ' . $parameters;
 211                  }
 212                  return $this->Query($query);
 213          } # end function        

 214  } # end class

 215  
 216  /**

 217   * Ultimate SEO URLs Installer and Configuration Class

 218   *

 219   * Ultimate SEO URLs installer and configuration class offers a modular 

 220   * and easy to manage method of configuration.  The class enables the base

 221   * class to be configured and installed on the fly without the hassle of 

 222   * calling additional scripts or executing SQL.

 223   * @package Ultimate-SEO-URLs

 224   * @license http://opensource.org/licenses/gpl-license.php GNU Public License

 225   * @version 1.1

 226   * @link http://www.oscommerce-freelancers.com/ osCommerce-Freelancers

 227   * @copyright Copyright 2005, Bobby Easland 

 228   * @author Bobby Easland 

 229   */
 230  class SEO_URL_INSTALLER{        
 231          /**

 232           * The default_config array has all the default settings which should be all that is needed to make the base class work.

 233          * @var array

 234           */
 235          var $default_config;
 236          /**

 237           * Database object

 238          * @var object

 239           */
 240          var $DB;
 241          /**

 242           * $attributes array holds information about this instance

 243          * @var array

 244           */
 245          var $attributes;
 246          
 247  /**

 248   * SEO_URL_INSTALLER class constructor 

 249   * @author Bobby Easland 

 250   * @version 1.1

 251   */        
 252          function SEO_URL_INSTALLER(){
 253                  
 254                  $this->attributes = array();
 255                  
 256                  $x = 0;
 257                  $this->default_config = array();
 258                  $this->default_config['SEO_ENABLED'] = array('DEFAULT' => 'false',
 259                                                                                                       'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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''),')"
 260                                                                                                       );
 261                  $x++;
 262                  $this->default_config['SEO_ADD_CPATH_TO_PRODUCT_URLS'] = array('DEFAULT' => 'false',
 263                                                                                                                                                'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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''),')"
 264                                                                                                                                                  );
 265                  $x++;
 266                  $this->default_config['SEO_ADD_CAT_PARENT'] = array('DEFAULT' => 'false',
 267                                                                                                                             'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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''),')"
 268                                                                                                                          );
 269                  $x++;
 270                  $this->default_config['SEO_URLS_FILTER_SHORT_WORDS'] = array('DEFAULT' => '3',
 271                                                                                                                                              'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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)"
 272                                                                                                                                          );
 273                  $x++;
 274                  $this->default_config['SEO_URLS_USE_W3C_VALID'] = array('DEFAULT' => 'true',
 275                                                                                                                                              'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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''),')"
 276                                                                                                                                                   );
 277                  $x++;
 278                  $this->default_config['USE_SEO_CACHE_GLOBAL'] = array('DEFAULT' => 'true',
 279                                                                                                                               'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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''),')"
 280                                                                                                                            );
 281                  $x++;
 282                  $this->default_config['USE_SEO_CACHE_PRODUCTS'] = array('DEFAULT' => 'true',
 283                                                                                                                                  'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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''),')"
 284                                                                                                                                  );
 285                  $x++;
 286                  $this->default_config['USE_SEO_CACHE_CATEGORIES'] = array('DEFAULT' => 'true',
 287                                                                                                                                       'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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''),')"
 288                                                                                                                                    );
 289  
 290                  $x++;
 291                  $this->default_config['USE_SEO_CACHE_MANUFACTURERS'] = array('DEFAULT' => 'true',
 292                                                                                                                                              'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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''),')"
 293                                                                                                                                           );
 294  
 295                  $x++;
 296                  $this->default_config['USE_SEO_CACHE_ARTICLES'] = array('DEFAULT' => 'true',
 297                                                                                                                                     'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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''),')"
 298                                                                                                                                  );
 299                  $x++;
 300                  $this->default_config['USE_SEO_CACHE_TOPICS'] = array('DEFAULT' => 'true',
 301                                                                                                                               'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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''),')"
 302                                                                                                                            );
 303                  $x++;
 304                  $this->default_config['USE_SEO_CACHE_INFO_PAGES'] = array('DEFAULT' => 'true',
 305                                                                                                                                       'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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''),')"
 306                                                                                                                                    );
 307                  $x++;
 308                  $this->default_config['USE_SEO_REDIRECT'] = array('DEFAULT' => 'true',
 309                                                                                                                       'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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''),')"
 310                                                                                                                    );
 311                  $x++;
 312                  $this->default_config['SEO_REWRITE_TYPE'] = array('DEFAULT' => 'Rewrite',
 313                                                                                                                       'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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''),')"
 314                                                                                                                    );
 315                  $x++;
 316                  $this->default_config['SEO_CHAR_CONVERT_SET'] = array('DEFAULT' => '',
 317                                                                                                                               'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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)"
 318                                                                                                                            );
 319                  $x++;
 320                  $this->default_config['SEO_REMOVE_ALL_SPEC_CHARS'] = array('DEFAULT' => 'false',
 321                                                                                                                                        'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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''),')"
 322                                                                                                                                          );
 323                  $x++;
 324                  $this->default_config['SEO_URLS_CACHE_RESET'] = array('DEFAULT' => 'false',
 325                                                                                                                               'QUERY' => "INSERT INTO `".TABLE_CONFIGURATION."` VALUES (NULL, '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''),')"
 326                                                                                                                            );
 327  
 328                  $this->init();
 329          } # end class constructor

 330          
 331  /**

 332   * Initializer - if there are settings not defined the default config will be used and database settings installed. 

 333   * @author Bobby Easland 

 334   * @version 1.1

 335   */        
 336          function init(){
 337                  foreach( $this->default_config as $key => $value ){
 338                          $container[] = defined($key) ? 'true' : 'false';
 339                  } # end foreach

 340                  $this->attributes['IS_DEFINED'] = in_array('false', $container) ? false : true;
 341                  switch(true){
 342                          case ( !$this->attributes['IS_DEFINED'] ):
 343                                  $this->eval_defaults();
 344                                  $this->DB = new SEO_DataBase(DB_SERVER, DB_SERVER_USERNAME, DB_DATABASE, DB_SERVER_PASSWORD);
 345                                  $sql = "SELECT configuration_key, configuration_value  
 346                                                  FROM " . TABLE_CONFIGURATION . " 
 347                                                  WHERE configuration_key LIKE '%SEO%'";
 348                                  $result = $this->DB->Query($sql);
 349                                  $num_rows = $this->DB->NumRows($result);
 350                                  $this->DB->Free($result);                
 351                                  $this->attributes['IS_INSTALLED'] = (sizeof($container) == $num_rows) ? true : false;
 352                                  if ( !$this->attributes['IS_INSTALLED'] ){
 353                                          $this->install_settings(); 
 354                                  }
 355                                  break;
 356                          default:
 357                                  $this->attributes['IS_INSTALLED'] = true;
 358                                  break;
 359                  } # end switch

 360          } # end function

 361          
 362  /**

 363   * This function evaluates the default serrings into defined constants 

 364   * @author Bobby Easland 

 365   * @version 1.0

 366   */        
 367          function eval_defaults(){
 368                  foreach( $this->default_config as $key => $value ){
 369                          define($key, $value['DEFAULT']);
 370                  } # end foreach

 371          } # end function

 372          
 373  /**

 374   * This function removes the database settings (configuration and cache)

 375   * @author Bobby Easland 

 376   * @version 1.0

 377   */        
 378          function uninstall_settings(){
 379                  $this->DB->Query("DELETE FROM `".TABLE_CONFIGURATION_GROUP."` WHERE `configuration_group_title` LIKE '%SEO%'");
 380                  $this->DB->Query("DELETE FROM `".TABLE_CONFIGURATION."` WHERE `configuration_key` LIKE '%SEO%'");
 381              $this->DB->Query("DROP TABLE IF EXISTS `cache`");
 382          } # end function

 383          
 384  /**

 385   * This function installs the database settings

 386   * @author Bobby Easland 

 387   * @version 1.0

 388   */        
 389          function install_settings(){
 390                  $this->uninstall_settings();
 391                  $sort_order_query = "SELECT MAX(sort_order) as max_sort FROM `".TABLE_CONFIGURATION_GROUP."`";
 392                  $sort = $this->DB->FetchArray( $this->DB->Query($sort_order_query) );
 393                  $next_sort = $sort['max_sort'] + 1;
 394                  $insert_group = "INSERT INTO `".TABLE_CONFIGURATION_GROUP."` VALUES (NULL, 'SEO URLs', 'Options for Ultimate SEO URLs by Chemo', '".$next_sort."', '1')";
 395                  $this->DB->Query($insert_group);
 396                  $group_id = $this->DB->InsertID();
 397  
 398                  foreach ($this->default_config as $key => $value){
 399                          $sql = str_replace('GROUP_INSERT_ID', $group_id, $value['QUERY']);
 400                          $this->DB->Query($sql);
 401                  }
 402  
 403                  $insert_cache_table = "CREATE TABLE `cache` (
 404                    `cache_id` varchar(32) NOT NULL default '',
 405                    `cache_language_id` tinyint(1) NOT NULL default '0',
 406                    `cache_name` varchar(255) NOT NULL default '',
 407                    `cache_data` mediumtext NOT NULL,
 408                    `cache_global` tinyint(1) NOT NULL default '1',
 409                    `cache_gzip` tinyint(1) NOT NULL default '1',
 410                    `cache_method` varchar(20) NOT NULL default 'RETURN',
 411                    `cache_date` datetime NOT NULL,
 412                    `cache_expires` datetime NOT NULL,
 413                    PRIMARY KEY  (`cache_id`,`cache_language_id`),
 414                    KEY `cache_id` (`cache_id`),
 415                    KEY `cache_language_id` (`cache_language_id`),
 416                    KEY `cache_global` (`cache_global`)
 417                  ) TYPE=MyISAM;";
 418                  $this->DB->Query($insert_cache_table);
 419          } # end function        

 420  } # end class

 421  
 422  /**

 423   * Ultimate SEO URLs Base Class

 424   *

 425   * Ultimate SEO URLs offers search engine optimized URLS for osCommerce

 426   * based applications. Other features include optimized performance and 

 427   * automatic redirect script.

 428   * @package Ultimate-SEO-URLs

 429   * @license http://opensource.org/licenses/gpl-license.php GNU Public License

 430   * @version 2.1

 431   * @link http://www.oscommerce-freelancers.com/ osCommerce-Freelancers

 432   * @copyright Copyright 2005, Bobby Easland 

 433   * @author Bobby Easland 

 434   */
 435  class SEO_URL{
 436          /**

 437           * $cache is the per page data array that contains all of the previously stripped titles

 438          * @var array

 439           */
 440          var $cache;
 441          /**

 442           * $languages_id contains the language_id for this instance

 443          * @var integer

 444           */
 445          var $languages_id;
 446          /**

 447           * $attributes array contains all the required settings for class

 448          * @var array

 449           */
 450          var $attributes;
 451          /**

 452           * $base_url is the NONSSL URL for site

 453          * @var string

 454           */
 455          var $base_url;
 456          /**

 457           * $base_url_ssl is the secure URL for the site

 458          * @var string

 459           */
 460          var $base_url_ssl;
 461          /**

 462           * $performance array contains evaluation metric data

 463          * @var array

 464           */
 465          var $performance;
 466          /**

 467           * $timestamp simply holds the temp variable for time calculations

 468          * @var float

 469           */
 470          var $timestamp;
 471          /**

 472           * $reg_anchors holds the anchors used by the .htaccess rewrites

 473          * @var array

 474           */
 475          var $reg_anchors;
 476          /**

 477           * $cache_query is the resource_id used for database cache logic

 478          * @var resource

 479           */
 480          var $cache_query;
 481          /**

 482           * $cache_file is the basename of the cache database entry

 483          * @var string

 484           */
 485          var $cache_file;
 486          /**

 487           * $data array contains all records retrieved from database cache

 488          * @var array

 489           */
 490          var $data;
 491          /**

 492           * $need_redirect determines whether the URL needs to be redirected

 493          * @var boolean

 494           */
 495          var $need_redirect;
 496          /**

 497           * $is_seopage holds value as to whether page is in allowed SEO pages

 498          * @var boolean

 499           */
 500          var $is_seopage;
 501          /**

 502           * $uri contains the $_SERVER['REQUEST_URI'] value

 503          * @var string

 504           */
 505          var $uri;
 506          /**

 507           * $real_uri contains the $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING'] value

 508          * @var string

 509           */
 510          var $real_uri;
 511          /**

 512           * $uri_parsed contains the parsed uri value array

 513          * @var array

 514           */
 515          var $uri_parsed;
 516          /**

 517           * $path_info contains the getenv('PATH_INFO') value

 518          * @var string

 519           */
 520          var $path_info;
 521          /**

 522           * $DB is the database object

 523          * @var object

 524           */
 525          var $DB;
 526          /**

 527           * $installer is the installer object

 528          * @var object

 529           */
 530          var $installer;
 531          
 532  /**

 533   * SEO_URL class constructor 

 534   * @author Bobby Easland 

 535   * @version 1.1

 536   * @param integer $languages_id

 537   */        
 538          function SEO_URL($languages_id){
 539              global $session_started, $SID;
 540                                  
 541                  $this->installer = new SEO_URL_INSTALLER;
 542                  
 543                  $this->DB = new SEO_DataBase(DB_SERVER, DB_SERVER_USERNAME, DB_DATABASE, DB_SERVER_PASSWORD);
 544                  
 545                  $this->languages_id = (int)$languages_id; 
 546                  
 547                  $this->data = array(); 
 548                  
 549                  $seo_pages = array(FILENAME_DEFAULT, 
 550                                     FILENAME_PRODUCT_INFO, 
 551                                                     FILENAME_POPUP_IMAGE,
 552                                                     FILENAME_PRODUCT_REVIEWS,
 553                                                     FILENAME_PRODUCT_REVIEWS_INFO);
 554                  if ( defined('FILENAME_ARTICLES') ) $seo_pages[] = FILENAME_ARTICLES;
 555                  if ( defined('FILENAME_ARTICLE_INFO') ) $seo_pages[] = FILENAME_ARTICLE_INFO;
 556                  if ( defined('FILENAME_INFORMATION') ) $seo_pages[] = FILENAME_INFORMATION;                
 557                  
 558                  $this->attributes = array('PHP_VERSION' => PHP_VERSION,
 559                                            'SESSION_STARTED' => $session_started,
 560                                                                    'SID' => $SID,
 561                                                                    'SEO_ENABLED' => defined('SEO_ENABLED') ? SEO_ENABLED : 'false',
 562                                                                    'SEO_ADD_CPATH_TO_PRODUCT_URLS' => defined('SEO_ADD_CPATH_TO_PRODUCT_URLS') ? SEO_ADD_CPATH_TO_PRODUCT_URLS : 'false',
 563                                                                    'SEO_ADD_CAT_PARENT' => defined('SEO_ADD_CAT_PARENT') ? SEO_ADD_CAT_PARENT : 'true',
 564                                                                    'SEO_URLS_USE_W3C_VALID' => defined('SEO_URLS_USE_W3C_VALID') ? SEO_URLS_USE_W3C_VALID : 'true',
 565                                                                    'USE_SEO_CACHE_GLOBAL' => defined('USE_SEO_CACHE_GLOBAL') ? USE_SEO_CACHE_GLOBAL : 'false',
 566                                                                    'USE_SEO_CACHE_PRODUCTS' => defined('USE_SEO_CACHE_PRODUCTS') ? USE_SEO_CACHE_PRODUCTS : 'false',
 567                                                                    'USE_SEO_CACHE_CATEGORIES' => defined('USE_SEO_CACHE_CATEGORIES') ? USE_SEO_CACHE_CATEGORIES : 'false',
 568                                                                    'USE_SEO_CACHE_MANUFACTURERS' => defined('USE_SEO_CACHE_MANUFACTURERS') ? USE_SEO_CACHE_MANUFACTURERS : 'false',
 569                                                                    'USE_SEO_CACHE_ARTICLES' => defined('USE_SEO_CACHE_ARTICLES') ? USE_SEO_CACHE_ARTICLES : 'false',
 570                                                                    'USE_SEO_CACHE_TOPICS' => defined('USE_SEO_CACHE_TOPICS') ? USE_SEO_CACHE_TOPICS : 'false',
 571                                                                    'USE_SEO_CACHE_INFO_PAGES' => defined('USE_SEO_CACHE_INFO_PAGES') ? USE_SEO_CACHE_INFO_PAGES : 'false',
 572                                                                    'USE_SEO_REDIRECT' => defined('USE_SEO_REDIRECT') ? USE_SEO_REDIRECT : 'false',
 573                                                                    'SEO_REWRITE_TYPE' => defined('SEO_REWRITE_TYPE') ? SEO_REWRITE_TYPE : 'false',
 574                                                                    'SEO_URLS_FILTER_SHORT_WORDS' => defined('SEO_URLS_FILTER_SHORT_WORDS') ? SEO_URLS_FILTER_SHORT_WORDS : 'false',
 575                                                                    'SEO_CHAR_CONVERT_SET' => defined('SEO_CHAR_CONVERT_SET') ? $this->expand(SEO_CHAR_CONVERT_SET) : 'false',
 576                                                                    'SEO_REMOVE_ALL_SPEC_CHARS' => defined('SEO_REMOVE_ALL_SPEC_CHARS') ? SEO_REMOVE_ALL_SPEC_CHARS : 'false',
 577                                                                    'SEO_PAGES' => $seo_pages,
 578                                                                    'SEO_INSTALLER' => $this->installer->attributes
 579                                                                    );                
 580                  
 581                  $this->base_url = HTTP_SERVER . DIR_WS_HTTP_CATALOG;
 582                  $this->base_url_ssl = HTTPS_SERVER . DIR_WS_HTTPS_CATALOG;                
 583                  $this->cache = array();
 584                  $this->timestamp = 0;
 585                  
 586                  $this->reg_anchors = array('products_id' => '-p-',
 587                                                                     'cPath' => '-c-',
 588                                                                     'manufacturers_id' => '-m-',
 589                                                                     'pID' => '-pi-',
 590                                                                     'tPath' => '-t-',
 591                                                                     'articles_id' => '-a-',
 592                                                                     'products_id_review' => '-pr-',
 593                                                                     'products_id_review_info' => '-pri-',
 594                                                                     'info_id' => '-i-'
 595                                                                     );
 596                  
 597                  $this->performance = array('NUMBER_URLS_GENERATED' => 0,
 598                                                                     'NUMBER_QUERIES' => 0,                                                                   
 599                                                                     'CACHE_QUERY_SAVINGS' => 0,
 600                                                                     'NUMBER_STANDARD_URLS_GENERATED' => 0,
 601                                                                     'TOTAL_CACHED_PER_PAGE_RECORDS' => 0,
 602                                                                     'TOTAL_TIME' => 0,
 603                                                                     'TIME_PER_URL' => 0,
 604                                                                     'QUERIES' => array()
 605                                                                     );
 606                  
 607                  if ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true'){
 608                          $this->cache_file = 'seo_urls_v2_';
 609                          $this->cache_gc();
 610                          if ( $this->attributes['USE_SEO_CACHE_PRODUCTS'] == 'true' ) $this->generate_products_cache();
 611                          if ( $this->attributes['USE_SEO_CACHE_CATEGORIES'] == 'true' ) $this->generate_categories_cache();
 612                          if ( $this->attributes['USE_SEO_CACHE_MANUFACTURERS'] == 'true' ) $this->generate_manufacturers_cache();
 613                          if ( $this->attributes['USE_SEO_CACHE_ARTICLES'] == 'true' && defined('TABLE_ARTICLES_DESCRIPTION')) $this->generate_articles_cache();
 614                          if ( $this->attributes['USE_SEO_CACHE_TOPICS'] == 'true' && defined('TABLE_TOPICS_DESCRIPTION')) $this->generate_topics_cache();
 615                          if ( $this->attributes['USE_SEO_CACHE_INFO_PAGES'] == 'true' && defined('TABLE_INFORMATION')) $this->generate_information_cache();
 616                  } # end if

 617  
 618                  if ($this->attributes['USE_SEO_REDIRECT'] == 'true'){
 619                          $this->check_redirect();
 620                  } # end if

 621          } # end constructor

 622  
 623  /**

 624   * Function to return SEO URL link SEO'd with stock generattion for error fallback

 625   * @author Bobby Easland 

 626   * @version 1.0

 627   * @param string $page Base script for URL 

 628   * @param string $parameters URL parameters

 629   * @param string $connection NONSSL/SSL

 630   * @param boolean $add_session_id Switch to add osCsid

 631   * @return string Formed href link 

 632   */        
 633          function href_link($page = '', $parameters = '', $connection = 'NONSSL', $add_session_id = true){
 634                  $this->start($this->timestamp);
 635                  $this->performance['NUMBER_URLS_GENERATED']++;
 636                  if ( !in_array($page, $this->attributes['SEO_PAGES']) || $this->attributes['SEO_ENABLED'] == 'false' ) {
 637                          return $this->stock_href_link($page, $parameters, $connection, $add_session_id);
 638                  }
 639                  $link = $connection == 'NONSSL' ? $this->base_url : $this->base_url_ssl;
 640                  $separator = '?';
 641                  if ($this->not_null($parameters)) { 
 642                          $link .= $this->parse_parameters($page, $parameters, $separator);        
 643                  } else {
 644                    $link .= $page;
 645                  }
 646                  $link = $this->add_sid($link, $add_session_id, $connection, $separator); 
 647                  $this->stop($this->timestamp, $time);
 648                  $this->performance['TOTAL_TIME'] += $time;
 649                  switch($this->attributes['SEO_URLS_USE_W3C_VALID']){
 650                          case ('true'):
 651                                  if (!isset($_SESSION['customer_id']) && defined('ENABLE_PAGE_CACHE') && ENABLE_PAGE_CACHE == 'true' && class_exists('page_cache')){
 652                                          return $link;
 653                                  } else {
 654                                           return htmlspecialchars(utf8_encode($link));
 655                                  }
 656                                  break;
 657                          case ('false'):
 658                                  return $link;
 659                                  break;
 660                  }
 661          } # end function

 662  
 663  /**

 664   * Stock function, fallback use 

 665   */        
 666    function stock_href_link($page = '', $parameters = '', $connection = 'NONSSL', $add_session_id = true, $search_engine_safe = true) {
 667      global $request_type, $session_started, $SID;
 668      if (!$this->not_null($page)) {
 669        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>');
 670      }
 671          if ($page == '/') $page = '';
 672      if ($connection == 'NONSSL') {
 673        $link = HTTP_SERVER . DIR_WS_HTTP_CATALOG;
 674      } elseif ($connection == 'SSL') {
 675        if (ENABLE_SSL == true) {
 676          $link = HTTPS_SERVER . DIR_WS_HTTPS_CATALOG;
 677        } else {
 678          $link = HTTP_SERVER . DIR_WS_HTTP_CATALOG;
 679        }
 680      } else {
 681        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>');
 682      }
 683      if ($this->not_null($parameters)) {
 684        $link .= $page . '?' . $this->output_string($parameters);
 685        $separator = '&';
 686      } else {
 687        $link .= $page;
 688        $separator = '?';
 689      }
 690      while ( (substr($link, -1) == '&') || (substr($link, -1) == '?') ) $link = substr($link, 0, -1);
 691      if ( ($add_session_id == true) && ($session_started == true) && (SESSION_FORCE_COOKIE_USE == 'False') ) {
 692        if ($this->not_null($SID)) {
 693          $_sid = $SID;
 694        } elseif ( ( ($request_type == 'NONSSL') && ($connection == 'SSL') && (ENABLE_SSL == true) ) || ( ($request_type == 'SSL') && ($connection == 'NONSSL') ) ) {
 695          if (HTTP_COOKIE_DOMAIN != HTTPS_COOKIE_DOMAIN) {
 696            $_sid = $this->SessionName() . '=' . $this->SessionID();
 697          }
 698        }
 699      }
 700      if ( (SEARCH_ENGINE_FRIENDLY_URLS == 'true') && ($search_engine_safe == true) ) {
 701        while (strstr($link, '&&')) $link = str_replace('&&', '&', $link);
 702        $link = str_replace('?', '/', $link);
 703        $link = str_replace('&', '/', $link);
 704        $link = str_replace('=', '/', $link);
 705        $separator = '?';
 706      }
 707          switch(true){
 708                  case (!isset($_SESSION['customer_id']) && defined('ENABLE_PAGE_CACHE') && ENABLE_PAGE_CACHE == 'true' && class_exists('page_cache')):
 709                          $page_cache = true;
 710                          $return = $link . $separator . '<osCsid>';
 711                          break;
 712                  case (isset($_sid)):
 713                          $page_cache = false;
 714                          $return = $link . $separator . tep_output_string($_sid);
 715                          break;
 716                  default:
 717                          $page_cache = false;
 718                          $return = $link;
 719                          break;
 720          } # end switch

 721          $this->performance['NUMBER_STANDARD_URLS_GENERATED']++;
 722          $this->cache['STANDARD_URLS'][] = $link;
 723          $time = 0;
 724          $this->stop($this->timestamp, $time);
 725          $this->performance['TOTAL_TIME'] += $time;
 726          switch(true){
 727                  case ($this->attributes['SEO_URLS_USE_W3C_VALID'] == 'true' && !$page_cache):
 728                          return htmlspecialchars(utf8_encode($return));
 729                          break;
 730                  default:
 731                          return $return;
 732                          break;
 733          }# end swtich

 734    } # end default tep_href function

 735  
 736  /**

 737   * Function to append session ID if needed 

 738   * @author Bobby Easland 

 739   * @version 1.2

 740   * @param string $link 

 741   * @param boolean $add_session_id

 742   * @param string $connection

 743   * @param string $separator

 744   * @return string

 745   */        
 746          function add_sid( $link, $add_session_id, $connection, $separator ){
 747                  global $request_type; // global variable

 748                  if ( ($add_session_id) && ($this->attributes['SESSION_STARTED']) && (SESSION_FORCE_COOKIE_USE == 'False') ) {
 749                    if ($this->not_null($this->attributes['SID'])) {
 750                          $_sid = $this->attributes['SID'];
 751                    } elseif ( ( ($request_type == 'NONSSL') && ($connection == 'SSL') && (ENABLE_SSL == true) ) || ( ($request_type == 'SSL') && ($connection == 'NONSSL') ) ) {
 752                          if (HTTP_COOKIE_DOMAIN != HTTPS_COOKIE_DOMAIN) {
 753                            $_sid = $this->SessionName() . '=' . $this->SessionID();
 754                          }
 755                    }
 756                  } 
 757                  switch(true){
 758                          case (!isset($_SESSION['customer_id']) && defined('ENABLE_PAGE_CACHE') && ENABLE_PAGE_CACHE == 'true' && class_exists('page_cache')):
 759                                  $return = $link . $separator . '<osCsid>';
 760                                  break;
 761                          case ($this->not_null($_sid)):
 762                                  $return = $link . $separator . tep_output_string($_sid);
 763                                  break;
 764                          default:
 765                                  $return = $link;
 766                                  break;
 767                  } # end switch

 768                  return $return;
 769          } # end function

 770          
 771  /**

 772   * SFunction to parse the parameters into an SEO URL 

 773   * @author Bobby Easland 

 774   * @version 1.2

 775   * @param string $page

 776   * @param string $params

 777   * @param string $separator NOTE: passed by reference

 778   * @return string 

 779   */        
 780          function parse_parameters($page, $params, &$separator){
 781                  $p = @explode('&', $params);
 782                  krsort($p);
 783                  $container = array();
 784                  foreach ($p as $index => $valuepair){
 785                          $p2 = @explode('=', $valuepair); 
 786                          switch ($p2[0]){ 
 787                                  case 'products_id':
 788                                          switch(true){
 789                                                  case ( $page == FILENAME_PRODUCT_INFO && !$this->is_attribute_string($p2[1]) ):
 790                                                          $url = $this->make_url($page, $this->get_product_name($p2[1]), $p2[0], $p2[1], '.html', $separator);
 791                                                          break;
 792                                                  case ( $page == FILENAME_PRODUCT_REVIEWS ):
 793                                                          $url = $this->make_url($page, $this->get_product_name($p2[1]), 'products_id_review', $p2[1], '.html', $separator);
 794                                                          break;
 795                                                  case ( $page == FILENAME_PRODUCT_REVIEWS_INFO ):                                                        
 796                                                          $url = $this->make_url($page, $this->get_product_name($p2[1]), 'products_id_review_info', $p2[1], '.html', $separator);
 797                                                          break;
 798                                                  default:
 799                                                          $container[$p2[0]] = $p2[1];
 800                                                          break;
 801                                          } # end switch

 802                                          break;
 803                                  case 'cPath':
 804                                          switch(true){
 805                                                  case ($page == FILENAME_DEFAULT):
 806                                                          $url = $this->make_url($page, $this->get_category_name($p2[1]), $p2[0], $p2[1], '.html', $separator);
 807                                                          break;
 808                                                  case ( !$this->is_product_string($params) ):
 809                                                          if ( $this->attributes['SEO_ADD_CPATH_TO_PRODUCT_URLS'] == 'true' ){
 810                                                                  $container[$p2[0]] = $p2[1];
 811                                                          }
 812                                                          break;
 813                                                  default:
 814                                                          $container[$p2[0]] = $p2[1];
 815                                                          break;
 816                                                  } # end switch

 817                                          break;
 818                                  case 'manufacturers_id':
 819                                          switch(true){
 820                                                  case ($page == FILENAME_DEFAULT && !$this->is_cPath_string($params) && !$this->is_product_string($params) ):
 821                                                          $url = $this->make_url($page, $this->get_manufacturer_name($p2[1]), $p2[0], $p2[1], '.html', $separator);
 822                                                          break;
 823                                                  case ($page == FILENAME_PRODUCT_INFO):
 824                                                          break;
 825                                                  default:
 826                                                          $container[$p2[0]] = $p2[1];
 827                                                          break;                                        
 828                                                  } # end switch

 829                                          break;
 830                                  case 'pID':
 831                                          switch(true){
 832                                                  case ($page == FILENAME_POPUP_IMAGE):
 833                                                  $url = $this->make_url($page, $this->get_product_name($p2[1]), $p2[0], $p2[1], '.html', $separator);
 834                                                  break;
 835                                          default:
 836                                                  $container[$p2[0]] = $p2[1];
 837                                                  break;
 838                                          } # end switch

 839                                          break;
 840                                  case 'tPath':
 841                                          switch(true){
 842                                                  case ($page == FILENAME_ARTICLES):
 843                                                          $url = $this->make_url($page, $this->get_topic_name($p2[1]), $p2[0], $p2[1], '.html', $separator);
 844                                                          break;
 845                                                  default:
 846                                                          $container[$p2[0]] = $p2[1];
 847                                                          break;
 848                                          } # end switch

 849                                          break;
 850                                  case 'articles_id':
 851                                          switch(true){
 852                                                  case ($page == FILENAME_ARTICLE_INFO):
 853                                                          $url = $this->make_url($page, $this->get_article_name($p2[1]), $p2[0], $p2[1], '.html', $separator);
 854                                                          break;
 855                                                  default: 
 856                                                          $container[$p2[0]] = $p2[1];
 857                                                          break;
 858                                          } # end switch

 859                                          break;
 860                                  case 'info_id':
 861                                          switch(true){
 862                                                  case ($page == FILENAME_INFORMATION):
 863                                                          $url = $this->make_url($page, $this->get_information_name($p2[1]), $p2[0], $p2[1], '.html', $separator);
 864                                                          break;
 865                                                  default: 
 866                                                          $container[$p2[0]] = $p2[1];
 867                                                          break;
 868                                          } # end switch

 869                                          break;
 870                                  default:
 871                                          $container[$p2[0]] = $p2[1]; 
 872                                          break;
 873                          } # end switch

 874                  } # end foreach $p

 875                  $url = isset($url) ? $url : $page;
 876                  if ( sizeof($container) > 0 ){
 877                          if ( $imploded_params = $this->implode_assoc($container) ){
 878                                  $url .= $separator . $this->output_string( $imploded_params );
 879                                  $separator = '&';
 880                          }
 881                  }
 882                  return $url;
 883          } # end function

 884  
 885  /**

 886   * Function to return the generated SEO URL         

 887   * @author Bobby Easland 

 888   * @version 1.0

 889   * @param string $page

 890   * @param string $string Stripped, formed anchor

 891   * @param string $anchor_type Parameter type (products_id, cPath, etc.)

 892   * @param integer $id

 893   * @param string $extension Default = .html

 894   * @param string $separator NOTE: passed by reference

 895   * @return string

 896   */        
 897          function make_url($page, $string, $anchor_type, $id, $extension = '.html', &$separator){
 898                  // Right now there is but one rewrite method since cName was dropped

 899                  // In the future there will be additional methods here in the switch

 900                  switch ( $this->attributes['SEO_REWRITE_TYPE'] ){
 901                          case 'Rewrite':
 902                                  return $string . $this->reg_anchors[$anchor_type] . $id . $extension;
 903                                  break;
 904                          default:
 905                                  break;
 906                  } # end switch

 907          } # end function

 908  
 909  /**

 910   * Function to get the product name. Use evaluated cache, per page cache, or database query in that order of precedent        

 911   * @author Bobby Easland 

 912   * @version 1.1

 913   * @param integer $pID

 914   * @return string Stripped anchor text

 915   */        
 916          function get_product_name($pID){
 917                  switch(true){
 918                          case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && defined('PRODUCT_NAME_' . $pID)):
 919                                  $this->performance['CACHE_QUERY_SAVINGS']++;
 920                                  $return = constant('PRODUCT_NAME_' . $pID);
 921                                  $this->cache['PRODUCTS'][$pID] = $return;
 922                                  break;
 923                          case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && isset($this->cache['PRODUCTS'][$pID])):
 924                                  $this->performance['CACHE_QUERY_SAVINGS']++;
 925                                  $return = $this->cache['PRODUCTS'][$pID];
 926                                  break;
 927                          default:
 928                                  $this->performance['NUMBER_QUERIES']++;
 929                                  $sql = "SELECT products_name as pName 
 930                                                  FROM ".TABLE_PRODUCTS_DESCRIPTION." 
 931                                                  WHERE products_id='".(int)$pID."' 
 932                                                  AND language_id='".(int)$this->languages_id."' 
 933                                                  LIMIT 1";
 934                                  $result = $this->DB->FetchArray( $this->DB->Query( $sql ) );
 935                                  $pName = $this->strip( $result['pName'] );
 936                                  $this->cache['PRODUCTS'][$pID] = $pName;
 937                                  $this->performance['QUERIES']['PRODUCTS'][] = $sql;
 938                                  $return = $pName;
 939                                  break;                                                                
 940                  } # end switch                

 941                  return $return;
 942          } # end function

 943          
 944  /**

 945   * Function to get the category name. Use evaluated cache, per page cache, or database query in that order of precedent 

 946   * @author Bobby Easland 

 947   * @version 1.1

 948   * @param integer $cID NOTE: passed by reference

 949   * @return string Stripped anchor text

 950   */        
 951          function get_category_name(&$cID){
 952                  $full_cPath = $this->get_full_cPath($cID, $single_cID); // full cPath needed for uniformity

 953                  switch(true){
 954                          case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && defined('CATEGORY_NAME_' . $full_cPath)):
 955                                  $this->performance['CACHE_QUERY_SAVINGS']++;
 956                                  $return = constant('CATEGORY_NAME_' . $full_cPath);
 957                                  $this->cache['CATEGORIES'][$full_cPath] = $return;
 958                                  break;
 959                          case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && isset($this->cache['CATEGORIES'][$full_cPath])):
 960                                  $this->performance['CACHE_QUERY_SAVINGS']++;
 961                                  $return = $this->cache['CATEGORIES'][$full_cPath];
 962                                  break;
 963                          default:
 964                                  $this->performance['NUMBER_QUERIES']++;
 965                                  switch(true){
 966                                          case ($this->attributes['SEO_ADD_CAT_PARENT'] == 'true'):
 967                                                  $sql = "SELECT c.categories_id, c.parent_id, cd.categories_name AS cName, cd2.categories_name AS pName
 968                                                  FROM ".TABLE_CATEGORIES." c
 969                                                  INNER JOIN ".TABLE_CATEGORIES_DESCRIPTION." cd ON cd.categories_id = '".(int)$single_cID."'
 970                                                  AND cd.language_id='".(int)$this->languages_id."'
 971                                                  LEFT JOIN ".TABLE_CATEGORIES_DESCRIPTION." cd2 ON c.parent_id = cd2.categories_id
 972                                                  AND cd2.language_id = '".(int)$this->languages_id."'
 973                                                  WHERE c.categories_id = '".(int)$single_cID."'
 974                                                  LIMIT 1";
 975                                                  $result = $this->DB->FetchArray( $this->DB->Query( $sql ) );
 976                                                  $cName = $this->not_null($result['pName']) ? $result['pName'] . ' ' . $result['cName'] : $result['cName'];
 977                                                  break;
 978                                          default:
 979                                                  $sql = "SELECT categories_name as cName 
 980                                                                  FROM ".TABLE_CATEGORIES_DESCRIPTION." 
 981                                                                  WHERE categories_id='".(int)$single_cID."' 
 982                                                                  AND language_id='".(int)$this->languages_id."' 
 983                                                                  LIMIT 1";
 984                                                  $result = $this->DB->FetchArray( $this->DB->Query( $sql ) );
 985                                                  $cName = $result['cName'];
 986                                                  break;
 987                                  }                                                                                
 988                                  $cName = $this->strip($cName);
 989                                  $this->cache['CATEGORIES'][$full_cPath] = $cName;
 990                                  $this->performance['QUERIES']['CATEGORIES'][] = $sql;
 991                                  $return = $cName;
 992                                  break;                                                                
 993                  } # end switch                

 994                  $cID = $full_cPath;
 995                  return $return;
 996          } # end function

 997  
 998  /**

 999   * Function to get the manufacturer name. Use evaluated cache, per page cache, or database query in that order of precedent.

1000   * @author Bobby Easland 

1001   * @version 1.1

1002   * @param integer $mID

1003   * @return string

1004   */        
1005          function get_manufacturer_name($mID){
1006                  switch(true){
1007                          case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && defined('MANUFACTURER_NAME_' . $mID)):
1008                                  $this->performance['CACHE_QUERY_SAVINGS']++;
1009                                  $return = constant('MANUFACTURER_NAME_' . $mID);
1010                                  $this->cache['MANUFACTURERS'][$mID] = $return;
1011                                  break;
1012                          case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && isset($this->cache['MANUFACTURERS'][$mID])):
1013                                  $this->performance['CACHE_QUERY_SAVINGS']++;
1014                                  $return = $this->cache['MANUFACTURERS'][$mID];
1015                                  break;
1016                          default:
1017                                  $this->performance['NUMBER_QUERIES']++;
1018                                  $sql = "SELECT manufacturers_name as mName 
1019                                                  FROM ".TABLE_MANUFACTURERS." 
1020                                                  WHERE manufacturers_id='".(int)$mID."' 
1021                                                  LIMIT 1";
1022                                  $result = $this->DB->FetchArray( $this->DB->Query( $sql ) );
1023                                  $mName = $this->strip( $result['mName'] );
1024                                  $this->cache['MANUFACTURERS'][$mID] = $mName;
1025                                  $this->performance['QUERIES']['MANUFACTURERS'][] = $sql;
1026                                  $return = $mName;
1027                                  break;                                                                
1028                  } # end switch                

1029                  return $return;
1030          } # end function

1031  
1032  /**

1033   * Function to get the article name. Use evaluated cache, per page cache, or database query in that order of precedent.

1034   * @author Bobby Easland 

1035   * @version 1.0

1036   * @param integer $aID

1037   * @return string

1038   */        
1039          function get_article_name($aID){
1040                  switch(true){
1041                          case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && defined('ARTICLE_NAME_' . $aID)):
1042                                  $this->performance['CACHE_QUERY_SAVINGS']++;
1043                                  $return = constant('ARTICLE_NAME_' . $aID);
1044                                  $this->cache['ARTICLES'][$aID] = $return;
1045                                  break;
1046                          case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && isset($this->cache['ARTICLES'][$aID])):
1047                                  $this->performance['CACHE_QUERY_SAVINGS']++;
1048                                  $return = $this->cache['ARTICLES'][$aID];
1049                                  break;
1050                          default:
1051                                  $this->performance['NUMBER_QUERIES']++;
1052                                  $sql = "SELECT articles_name as aName 
1053                                                  FROM ".TABLE_ARTICLES_DESCRIPTION." 
1054                                                  WHERE articles_id='".(int)$aID."' 
1055                                                  AND language_id='".(int)$this->languages_id."' 
1056                                                  LIMIT 1";
1057                                  $result = $this->DB->FetchArray( $this->DB->Query( $sql ) );
1058                                  $aName = $this->strip( $result['aName'] );
1059                                  $this->cache['ARTICLES'][$aID] = $aName;
1060                                  $this->performance['QUERIES']['ARTICLES'][] = $sql;
1061                                  $return = $aName;
1062                                  break;                                                                
1063                  } # end switch                

1064                  return $return;
1065          } # end function

1066  
1067  /**

1068   * Function to get the topic name. Use evaluated cache, per page cache, or database query in that order of precedent.

1069   * @author Bobby Easland 

1070   * @version 1.1

1071   * @param integer $tID

1072   * @return string

1073   */        
1074          function get_topic_name($tID){
1075                  switch(true){
1076                          case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && defined('TOPIC_NAME_' . $tID)):
1077                                  $this->performance['CACHE_QUERY_SAVINGS']++;
1078                                  $return = constant('TOPIC_NAME_' . $tID);
1079                                  $this->cache['TOPICS'][$tID] = $return;
1080                                  break;
1081                          case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && isset($this->cache['TOPICS'][$tID])):
1082                                  $this->performance['CACHE_QUERY_SAVINGS']++;
1083                                  $return = $this->cache['TOPICS'][$tID];
1084                                  break;
1085                          default:
1086                                  $this->performance['NUMBER_QUERIES']++;
1087                                  $sql = "SELECT topics_name as tName 
1088                                                  FROM ".TABLE_TOPICS_DESCRIPTION." 
1089                                                  WHERE topics_id='".(int)$tID."' 
1090                                                  AND language_id='".(int)$this->languages_id."' 
1091                                                  LIMIT 1";
1092                                  $result = $this->DB->FetchArray( $this->DB->Query( $sql ) );
1093                                  $tName = $this->strip( $result['tName'] );
1094                                  $this->cache['ARTICLES'][$aID] = $tName;
1095                                  $this->performance['QUERIES']['TOPICS'][] = $sql;
1096                                  $return = $tName;
1097                                  break;                                                                
1098                  } # end switch                

1099                  return $return;
1100          } # end function

1101  
1102  /**

1103   * Function to get the informatin name. Use evaluated cache, per page cache, or database query in that order of precedent.

1104   * @author Bobby Easland 

1105   * @version 1.1

1106   * @param integer $iID

1107   * @return string

1108   */        
1109          function get_information_name($iID){
1110                  switch(true){
1111                          case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && defined('INFO_NAME_' . $iID)):
1112                                  $this->performance['CACHE_QUERY_SAVINGS']++;
1113                                  $return = constant('INFO_NAME_' . $iID);
1114                                  $this->cache['INFO'][$iID] = $return;
1115                                  break;
1116                          case ($this->attributes['USE_SEO_CACHE_GLOBAL'] == 'true' && isset($this->cache['INFO'][$iID])):
1117                                  $this->performance['CACHE_QUERY_SAVINGS']++;
1118                                  $return = $this->cache['INFO'][$iID];
1119                                  break;
1120                          default:
1121                                  $this->performance['NUMBER_QUERIES']++;
1122                                  $sql = "SELECT info_title as iName 
1123                                                  FROM ".TABLE_INFORMATION." 
1124                                                  WHERE information_id='".(int)$iID."' 
1125                                                  AND languages_id='".(int)$this->languages_id."' 
1126                                                  LIMIT 1";
1127                                  $result = $this->DB->FetchArray( $this->DB->Query( $sql ) );
1128                                  $iName = $this->strip( $result['iName'] );
1129                                  $this->cache['INFO'][$iID] = $iName;
1130                                  $this->performance['QUERIES']['INFO'][] = $sql;
1131                                  $return = $iName;
1132                                  break;                                                                
1133                  } # end switch                

1134                  return $return;
1135          } # end function

1136  
1137  /**

1138   * Function to retrieve full cPath from category ID 

1139   * @author Bobby Easland 

1140   * @version 1.1

1141   * @param mixed $cID Could contain cPath or single category_id

1142   * @param integer $original Single category_id passed back by reference

1143   * @return string Full cPath string

1144   */        
1145          function get_full_cPath($cID, &$original){
1146                  if ( is_numeric(strpos($cID, '_')) ){
1147                          $temp = @explode('_', $cID);
1148                          $original = $temp[sizeof($temp)-1];
1149                          return $cID;
1150                  } else {
1151                          $c = array();
1152                          $this->GetParentCategories($c, $cID);
1153                          $c = array_reverse($c);
1154                          $c[] = $cID;
1155                          $original = $cID;
1156                          $cID = sizeof($c) > 1 ? implode('_', $c) : $cID;
1157                          return $cID;
1158                  }
1159          } # end function

1160  
1161  /**

1162   * Recursion function to retrieve parent categories from category ID 

1163   * @author Bobby Easland 

1164   * @version 1.0

1165   * @param mixed $categories Passed by reference

1166   * @param integer $categories_id

1167   */        
1168          function GetParentCategories(&$categories, $categories_id) {
1169                  $sql = "SELECT parent_id 
1170                          FROM " . TABLE_CATEGORIES . " 
1171                                  WHERE categories_id='" . (int)$categories_id . "'";
1172                  $parent_categories_query = $this->DB->Query($sql);
1173                  while ($parent_categories = $this->DB->FetchArray($parent_categories_query)) {
1174                          if ($parent_categories['parent_id'] == 0) return true;
1175                          $categories[sizeof($categories)] = $parent_categories['parent_id'];
1176                          if ($parent_categories['parent_id'] != $categories_id) {
1177                                  $this->GetParentCategories($categories, $parent_categories['parent_id']);
1178                          }
1179                  }
1180          } # end function

1181  
1182  /**

1183   * Function to check if a value is NULL 

1184   * @author Bobby Easland as abstracted from osCommerce-MS2.2 

1185   * @version 1.0

1186   * @param mixed $value

1187   * @return boolean

1188   */        
1189          function not_null($value) {
1190                  if (is_array($value)) {
1191                          if (sizeof($value) > 0) {
1192                                  return true;
1193                          } else {
1194                                  return false;
1195                          }
1196                  } else {
1197                          if (($value != '') && (strtolower($value) != 'null') && (strlen(trim($value)) > 0)) {
1198                                  return true;
1199                          } else {
1200                                  return false;
1201                          }
1202                  }
1203          } # end function

1204  
1205  /**

1206   * Function to check if the products_id contains an attribute 

1207   * @author Bobby Easland 

1208   * @version 1.1

1209   * @param integer $pID

1210   * @return boolean

1211   */        
1212          function is_attribute_string($pID){
1213                  if ( is_numeric(strpos($pID, '{')) ){
1214                          return true;
1215                  } else {
1216                          return false;
1217                  }
1218          } # end function

1219  
1220  /**

1221   * Function to check if the params contains a products_id 

1222   * @author Bobby Easland 

1223   * @version 1.1

1224   * @param string $params

1225   * @return boolean

1226   */        
1227          function is_product_string($params){
1228                  if ( is_numeric(strpos('products_id', $params)) ){
1229                          return true;
1230                  } else {
1231                          return false;
1232                  }
1233          } # end function

1234  
1235  /**

1236   * Function to check if cPath is in the parameter string  

1237   * @author Bobby Easland 

1238   * @version 1.0

1239   * @param string $params

1240   * @return boolean

1241   */        
1242          function is_cPath_string($params){
1243                  if ( eregi('cPath', $params) ){
1244                          return true;
1245                  } else {
1246                          return false;
1247                  }
1248          } # end function

1249  
1250  /**

1251   * Function used to output class profile

1252   * @author Bobby Easland 

1253   * @version 1.0

1254   */        
1255          function profile(){
1256                  $this->calculate_performance();
1257                  $this->PrintArray($this->attributes, 'Class Attributes');
1258                  $this->PrintArray($this->cache, 'Cached Data');
1259          } # end function

1260  
1261  /**

1262   * Function used to calculate and output the performance metrics of the class

1263   * @author Bobby Easland 

1264   * @version 1.0

1265   * @return mixed Output of performance data wrapped in HTML pre tags

1266   */        
1267          function calculate_performance(){
1268                  foreach ($this->cache as $type){
1269                          $this->performance['TOTAL_CACHED_PER_PAGE_RECORDS'] += sizeof($type);                        
1270                  }
1271                  $this->performance['TIME_PER_URL'] = $this->performance['TOTAL_TIME'] / $this->performance['NUMBER_URLS_GENERATED'];
1272                  return $this->PrintArray($this->performance, 'Performance Data');
1273          } # end function

1274          
1275  /**

1276   * Function to strip the string of punctuation and white space 

1277   * @author Bobby Easland 

1278   * @version 1.1

1279   * @param string $string

1280   * @return string Stripped text. Removes all non-alphanumeric characters.

1281   */        
1282          function strip($string){
1283                  if ( is_array($this->attributes['SEO_CHAR_CONVERT_SET']) ) $string = strtr($string, $this->attributes['SEO_CHAR_CONVERT_SET']);
1284                  $pattern = $this->attributes['SEO_REMOVE_ALL_SPEC_CHARS'] == 'true'
1285                                                  ?        "([^[:alnum:]])+"
1286                                                  :        "([[:punct:]])+";
1287                  $anchor = ereg_replace($pattern, '', strtolower($string));
1288                  $pattern = "([[:space:]]|[[:blank:]])+"; 
1289                  $anchor = ereg_replace($pattern, '-', $anchor);
1290                  return $this->short_name($anchor); // return the short filtered name 

1291          } # end function

1292  
1293  /**

1294   * Function to expand the SEO_CONVERT_SET group 

1295   * @author Bobby Easland 

1296   * @version 1.0

1297   * @param string $set

1298   * @return mixed

1299   */        
1300          function expand($set){
1301                  if ( $this->not_null($set) ){
1302                          if ( $data = @explode(',', $set) ){
1303                                  foreach ( $data as $index => $valuepair){
1304                                          $p = @explode('=>', $valuepair);
1305                                          $container[trim($p[0])] = trim($p[1]);
1306                                  }
1307                                  return $container;
1308                          } else {
1309                                  return 'false';
1310                          }
1311                  } else {
1312                          return 'false';
1313                  }
1314          } # end function

1315  /**

1316   * Function to return the short word filtered string 

1317   * @author Bobby Easland 

1318   * @version 1.0

1319   * @param string $str

1320   * @param integer $limit

1321   * @return string Short word filtered

1322   */        
1323          function short_name($str, $limit=3){
1324                  if ( $this->attributes['SEO_URLS_FILTER_SHORT_WORDS'] != 'false' ) $limit = (int)$this->attributes['SEO_URLS_FILTER_SHORT_WORDS'];
1325                  $foo = @explode('-', $str);
1326                  foreach($foo as $index => $value){
1327                          switch (true){
1328                                  case ( strlen($value) <= $limit ):
1329                                          continue;
1330                                  default:
1331                                          $container[] = $value;
1332                                          break;
1333                          }                
1334                  } # end foreach

1335                  $container = ( sizeof($container) > 1 ? implode('-', $container) : $str );
1336                  return $container;
1337          }
1338          
1339  /**

1340   * Function to implode an associative array 

1341   * @author Bobby Easland 

1342   * @version 1.0

1343   * @param array $array Associative data array

1344   * @param string $inner_glue

1345   * @param string $outer_glue

1346   * @return string

1347   */        
1348          function implode_assoc($array, $inner_glue='=', $outer_glue='&') {
1349                  $output = array();
1350                  foreach( $array as $key => $item ){
1351                          if ( $this->not_null($key) && $this->not_null($item) ){
1352                                  $output[] = $key . $inner_glue . $item;
1353                          }
1354                  } # end foreach        

1355                  return @implode($outer_glue, $output);
1356          }
1357  
1358  /**

1359   * Function to print an array within pre tags, debug use 

1360   * @author Bobby Easland 

1361   * @version 1.0

1362   * @param mixed $array

1363   */        
1364          function PrintArray($array, $heading = ''){
1365                  echo '<fieldset style="border-style:solid; border-width:1px;">' . "\n";
1366                  echo '<legend style="background-color:#FFFFCC; border-style:solid; border-width:1px;">' . $heading . '</legend>' . "\n";
1367                  echo '<pre style="text-align:left;">' . "\n";
1368                  print_r($array);
1369                  echo '</pre>' . "\n";
1370                  echo '</fieldset><br/>' . "\n";
1371          } # end function

1372  
1373  /**

1374   * Function to start time for performance metric 

1375   * @author Bobby Easland 

1376   * @version 1.0

1377   * @param float $start_time

1378   */        
1379          function start(&$start_time){
1380                  $start_time = explode(' ', microtime());
1381          }
1382          
1383  /**

1384   * Function to stop time for performance metric 

1385   * @author Bobby Easland 

1386   * @version 1.0

1387   * @param float $start

1388   * @param float $time NOTE: passed by reference

1389   */        
1390          function stop($start, &$time){
1391                  $end = explode(' ', microtime());
1392                  $time = number_format( array_sum($end) - array_sum($start), 8, '.', '' );
1393          }
1394  
1395  /**

1396   * Function to translate a string 

1397   * @author Bobby Easland 

1398   * @version 1.0

1399   * @param string $data String to be translated

1400   * @param array $parse Array of tarnslation variables

1401   * @return string

1402   */        
1403          function parse_input_field_data($data, $parse) {
1404                  return strtr(trim($data), $parse);
1405          }
1406          
1407  /**

1408   * Function to output a translated or sanitized string 

1409   * @author Bobby Easland 

1410   * @version 1.0

1411   * @param string $sting String to be output

1412   * @param mixed $translate Array of translation characters

1413   * @param boolean $protected Switch for htemlspecialchars processing

1414   * @return string

1415   */        
1416          function output_string($string, $translate = false, $protected = false) {
1417                  if ($protected == true) {
1418                    return htmlspecialchars($string);
1419                  } else {
1420                    if ($translate == false) {
1421                          return $this->parse_input_field_data($string, array('"' => '&quot;'));
1422                    } else {
1423                          return $this->parse_input_field_data($string, $translate);
1424                    }
1425                  }
1426          }
1427  
1428  /**

1429   * Function to return the session ID 

1430   * @author Bobby Easland 

1431   * @version 1.0

1432   * @param string $sessid

1433   * @return string

1434   */        
1435          function SessionID($sessid = '') {
1436                  if (!empty($sessid)) {
1437                    return session_id($sessid);
1438                  } else {
1439                    return session_id();
1440                  }
1441          }
1442          
1443  /**

1444   * Function to return the session name 

1445   * @author Bobby Easland 

1446   * @version 1.0

1447   * @param string $name

1448   * @return string

1449   */        
1450          function SessionName($name = '') {
1451                  if (!empty($name)) {
1452                    return session_name($name);
1453                  } else {
1454                    return session_name();
1455                  }
1456          }
1457  
1458  /**

1459   * Function to generate products cache entries 

1460   * @author Bobby Easland 

1461   * @version 1.0

1462   */        
1463          function generate_products_cache(){
1464                  $this->is_cached($this->cache_file . 'products', $is_cached, $is_expired);          
1465                  if ( !$is_cached || $is_expired ) {
1466                  $sql = "SELECT p.products_id as id, pd.products_name as name 
1467                          FROM ".TABLE_PRODUCTS." p 
1468                                  LEFT JOIN ".TABLE_PRODUCTS_DESCRIPTION." pd 
1469                                  ON p.products_id=pd.products_id 
1470                                  AND pd.language_id='".(int)$this->languages_id."' 
1471                                  WHERE p.products_status='1'";
1472                  $product_query = $this->DB->Query( $sql );
1473                  $prod_cache = '';
1474                  while ($product = $this->DB->FetchArray($product_query)) {
1475                          $define = 'define(\'PRODUCT_NAME_' . $product['id'] . '\', \'' . $this->strip($product['name']) . '\');';
1476                          $prod_cache .= $define . "\n";
1477                          eval("$define");
1478                  }
1479                  $this->DB->Free($product_query);
1480                  $this->save_cache($this->cache_file . 'products', $prod_cache, 'EVAL', 1 , 1);
1481                  unset($prod_cache);
1482                  } else {
1483                          $this->get_cache($this->cache_file . 'products');                
1484                  }
1485          } # end function

1486                  
1487  /**

1488   * Function to generate manufacturers cache entries 

1489   * @author Bobby Easland 

1490   * @version 1.0

1491   */        
1492          function generate_manufacturers_cache(){
1493                  $this->is_cached($this->cache_file . 'manufacturers', $is_cached, $is_expired);          
1494                  if ( !$is_cached || $is_expired ) { // it's not cached so create it
1495                  $sql = "SELECT m.manufacturers_id as id, m.manufacturers_name as name 
1496                          FROM ".TABLE_MANUFACTURERS." m 
1497                                  LEFT JOIN ".TABLE_MANUFACTURERS_INFO." md 
1498                                  ON m.manufacturers_id=md.manufacturers_id 
1499                                  AND md.languages_id='".(int)$this->languages_id."'";
1500                  $manufacturers_query = $this->DB->Query( $sql );
1501                  $man_cache = '';
1502                  while ($manufacturer = $this->DB->FetchArray($manufacturers_query)) {
1503                          $define = 'define(\'MANUFACTURER_NAME_' . $manufacturer['id'] . '\', \'' . $this->strip($manufacturer['name']) . '\');';
1504                          $man_cache .= $define . "\n";
1505                          eval("$define");
1506                  }
1507                  $this->DB->Free($manufacturers_query);
1508                  $this->save_cache($this->cache_file . 'manufacturers', $man_cache, 'EVAL', 1 , 1);
1509                  unset($man_cache);
1510                  } else {
1511                          $this->get_cache($this->cache_file . 'manufacturers');                
1512                  }
1513          } # end function

1514  
1515  /**

1516   * Function to generate categories cache entries 

1517   * @author Bobby Easland 

1518   * @version 1.1

1519   */        
1520          function generate_categories_cache(){
1521                  $this->is_cached($this->cache_file . 'categories', $is_cached, $is_expired);          
1522                  if ( !$is_cached || $is_expired ) { // it's not cached so create it
1523                          switch(true){
1524                                  case ($this->attributes['SEO_ADD_CAT_PARENT'] == 'true'):
1525                                          $sql = "SELECT c.categories_id as id, c.parent_id, cd.categories_name as cName, cd2.categories_name as pName  
1526                                                          FROM ".TABLE_CATEGORIES." c, 
1527                                                          ".TABLE_CATEGORIES_DESCRIPTION." cd 
1528                                                          LEFT JOIN ".TABLE_CATEGORIES_DESCRIPTION." cd2 
1529                                                          ON c.parent_id=cd2.categories_id AND cd2.language_id='".(int)$this->languages_id."' 
1530                                                          WHERE c.categories_id=cd.categories_id 
1531                                                          AND cd.language_id='".(int)$this->languages_id."'";
1532                                          break;
1533                                  default:
1534                                          $sql = "SELECT categories_id as id, categories_name as cName 
1535                                                          FROM ".TABLE_CATEGORIES_DESCRIPTION."  
1536                                                          WHERE language_id='".(int)$this->languages_id."'";
1537                                          break;
1538                          } # end switch

1539                  $category_query = $this->DB->Query( $sql );
1540                  $cat_cache = '';
1541                  while ($category = $this->DB->FetchArray($category_query)) {        
1542                          $id = $this->get_full_cPath($category['id'], $single_cID);
1543                          $name = $this->not_null($category['pName']) ? $category['pName'] . ' ' . $category['cName'] : $category['cName']; 
1544                          $define = 'define(\'CATEGORY_NAME_' . $id . '\', \'' . $this->strip($name) . '\');';
1545                          $cat_cache .= $define . "\n";
1546                          eval("$define");
1547                  }
1548                  $this->DB->Free($category_query);
1549                  $this->save_cache($this->cache_file . 'categories', $cat_cache, 'EVAL', 1 , 1);
1550                  unset($cat_cache);
1551                  } else {
1552                          $this->get_cache($this->cache_file . 'categories');                
1553                  }
1554          } # end function

1555  
1556  /**

1557   * Function to generate articles cache entries 

1558   * @author Bobby Easland 

1559   * @version 1.0

1560   */        
1561          function generate_articles_cache(){
1562                  $this->is_cached($this->cache_file . 'articles', $is_cached, $is_expired);          
1563                  if ( !$is_cached || $is_expired ) { // it's not cached so create it
1564                          $sql = "SELECT articles_id as id, articles_name as name 
1565                                          FROM ".TABLE_ARTICLES_DESCRIPTION." 
1566                                          WHERE language_id = '".(int)$this->languages_id."'";
1567                          $article_query = $this->DB->Query( $sql );
1568                          $article_cache = '';
1569                          while ($article = $this->DB->FetchArray($article_query)) {
1570                                  $define = 'define(\'ARTICLE_NAME_' . $article['id'] . '\', \'' . $this->strip($article['name']) . '\');';
1571                                  $article_cache .= $define . "\n";
1572                                  eval("$define");
1573                          }
1574                          $this->DB->Free($article_query);
1575                          $this->save_cache($this->cache_file . 'articles', $article_cache, 'EVAL', 1 , 1);
1576                          unset($article_cache);
1577                  } else {
1578                          $this->get_cache($this->cache_file . 'articles');                
1579                  }
1580          } # end function

1581  
1582  /**

1583   * Function to generate topics cache entries 

1584   * @author Bobby Easland 

1585   * @version 1.0

1586   */        
1587          function generate_topics_cache(){
1588                  $this->is_cached($this->cache_file . 'topics', $is_cached, $is_expired);          
1589                  if ( !$is_cached || $is_expired ) { // it's not cached so create it
1590                          $sql = "SELECT topics_id as id, topics_name as name 
1591                                          FROM ".TABLE_TOPICS_DESCRIPTION." 
1592                                          WHERE language_id='".(int)$this->languages_id."'";
1593                          $topic_query = $this->DB->Query( $sql );
1594                          $topic_cache = '';
1595                          while ($topic = $this->DB->FetchArray($topic_query)) {
1596                                  $define = 'define(\'TOPIC_NAME_' . $topic['id'] . '\', \'' . $this->strip($topic['name']) . '\');';
1597                                  $topic_cache .= $define . "\n";
1598                                  eval("$define");
1599                          }
1600                          $this->DB->Free($topic_query);
1601                          $this->save_cache($this->cache_file . 'topics', $topic_cache, 'EVAL', 1 , 1);
1602                          unset($topic_cache);
1603                  } else {
1604                          $this->get_cache($this->cache_file . 'topics');                
1605                  }
1606          } # end function

1607  
1608  /**

1609   * Function to generate information cache entries 

1610   * @author Bobby Easland 

1611   * @version 1.0

1612   */        
1613          function generate_information_cache(){
1614                  $this->is_cached($this->cache_file . 'information', $is_cached, $is_expired);          
1615                  if ( !$is_cached || $is_expired ) { // it's not cached so create it
1616                          $sql = "SELECT information_id as id, info_title as name 
1617                                          FROM ".TABLE_INFORMATION." 
1618                                          WHERE languages_id='".(int)$this->languages_id."'";
1619                          $information_query = $this->DB->Query( $sql );
1620                          $information_cache = '';
1621                          while ($information = $this->DB->FetchArray($information_query)) {
1622                                  $define = 'define(\'INFO_NAME_' . $information['id'] . '\', \'' . $this->strip($information['name']) . '\');';
1623                                  $information_cache .= $define . "\n";
1624                                  eval("$define");
1625                          }
1626                          $this->DB->Free($information_query);
1627                          $this->save_cache($this->cache_file . 'information', $information_cache, 'EVAL', 1 , 1);
1628                          unset($information_cache);
1629                  } else {
1630                          $this->get_cache($this->cache_file . 'information');                
1631                  }
1632          } # end function

1633  
1634  /**

1635   * Function to save the cache to database 

1636   * @author Bobby Easland 

1637   * @version 1.0

1638   * @param string $name Cache name

1639   * @param mixed $value Can be array, string, PHP code, or just about anything

1640   * @param string $method RETURN, ARRAY, EVAL

1641   * @param integer $gzip Enables compression

1642   * @param integer $global Sets whether cache record is global is scope

1643   * @param string $expires Sets the expiration

1644   */        
1645          function save_cache($name, $value, $method='RETURN', $gzip=1, $global=0, $expires = '30/days'){
1646                  $expires = $this->convert_time($expires);                
1647                  if ($method == 'ARRAY' ) $value = serialize($value);
1648                  $value = ( $gzip === 1 ? base64_encode(gzdeflate($value, 1)) : addslashes($value) );
1649                  $sql_data_array = array('cache_id' => md5($name),
1650                                                                  'cache_language_id' => (int)$this->languages_id,
1651                                                                  'cache_name' => $name,
1652                                                                  'cache_data' => $value,
1653                                                                  'cache_global' => (int)$global,
1654                                                                  'cache_gzip' => (int)$gzip,
1655                                                                  'cache_method' => $method,
1656                                                                  'cache_date' => date("Y-m-d H:i:s"),
1657                                                                  'cache_expires' => $expires
1658                                                                  );                                                                
1659                  $this->is_cached($name, $is_cached, $is_expired);
1660                  $cache_check = ( $is_cached ? 'true' : 'false' );
1661                  switch ( $cache_check ) {
1662                          case 'true': 
1663                                  $this->DB->DBPerform('cache', $sql_data_array, 'update', "cache_id='".md5($name)."'");
1664                                  break;                                
1665                          case 'false':
1666                                  $this->DB->DBPerform('cache', $sql_data_array, 'insert');
1667                                  break;                                
1668                          default:
1669                                  break;
1670                  } # end switch ($cache check)                

1671                  # unset the variables...clean as we go

1672                  unset($value, $expires, $sql_data_array);                
1673          }# end function save_cache()

1674          
1675  /**

1676   * Function to get cache entry 

1677   * @author Bobby Easland 

1678   * @version 1.0

1679   * @param string $name

1680   * @param boolean $local_memory

1681   * @return mixed

1682   */        
1683          function get_cache($name = 'GLOBAL', $local_memory = false){
1684                  $select_list = 'cache_id, cache_language_id, cache_name, cache_data, cache_global, cache_gzip, cache_method, cache_date, cache_expires';
1685                  $global = ( $name == 'GLOBAL' ? true : false ); // was GLOBAL passed or is using the default?

1686                  switch($name){
1687                          case 'GLOBAL': 
1688                                  $this->cache_query = $this->DB->Query("SELECT ".$select_list." FROM cache WHERE cache_language_id='".(int)$this->languages_id."' AND cache_global='1'");
1689                                  break;
1690                          default: 
1691                                  $this->cache_query = $this->DB->Query("SELECT ".$select_list." FROM cache WHERE cache_id='".md5($name)."' AND cache_language_id='".(int)$this->languages_id."'");
1692                                  break;
1693                  } # end switch ($name)

1694                  $num_rows = $this->DB->NumRows($this->cache_query);
1695                  if ( $num_rows ){ 
1696                          $container = array();
1697                          while($cache = $this->DB->FetchArray($this->cache_query)){
1698                                  $cache_name = $cache['cache_name']; 
1699                                  if ( $cache['cache_expires'] > date("Y-m-d H:i:s") ) { 
1700                                          $cache_data = ( $cache['cache_gzip'] == 1 ? gzinflate(base64_decode($cache['cache_data'])) : stripslashes($cache['cache_data']) );
1701                                          switch($cache['cache_method']){
1702                                                  case 'EVAL': // must be PHP code
1703                                                          eval("$cache_data");
1704                                                          break;                                                        
1705                                                  case 'ARRAY': 
1706                                                          $cache_data = unserialize($cache_data);                                                        
1707                                                  case 'RETURN': 
1708                                                  default:
1709                                                          break;
1710                                          } # end switch ($cache['cache_method'])                                        

1711                                          if ($global) $container['GLOBAL'][$cache_name] = $cache_data; 
1712                                          else $container[$cache_name] = $cache_data; // not global                                

1713                                  } else { // cache is expired
1714                                          if ($global) $container['GLOBAL'][$cache_name] = false; 
1715                                          else $container[$cache_name] = false; 
1716                                  }# end if ( $cache['cache_expires'] > date("Y-m-d H:i:s") )                        

1717                                  if ( $this->keep_in_memory || $local_memory ) {
1718                                          if ($global) $this->data['GLOBAL'][$cache_name] = $container['GLOBAL'][$cache_name]; 
1719                                          else $this->data[$cache_name] = $container[$cache_name]; 
1720                                  }                                                        
1721                          } # end while ($cache = $this->DB->FetchArray($this->cache_query))                        

1722                          unset($cache_data);
1723                          $this->DB->Free($this->cache_query);                        
1724                          switch (true) {
1725                                  case ($num_rows == 1): 
1726                                          if ($global){
1727                                                  if ($container['GLOBAL'][$cache_name] == false || !isset($container['GLOBAL'][$cache_name])) return false;
1728                                                  else return $container['GLOBAL'][$cache_name]; 
1729                                          } else { // not global
1730                                                  if ($container[$cache_name] == false || !isset($container[$cache_name])) return false;
1731                                                  else return $container[$cache_name];
1732                                          } # end if ($global)                                        

1733                                  case ($num_rows > 1): 
1734                                  default: 
1735                                          return $container; 
1736                                          break;
1737                          }# end switch (true)                        

1738                  } else { 
1739                          return false;
1740                  }# end if ( $num_rows )                

1741          } # end function get_cache()

1742  
1743  /**

1744   * Function to get cache from memory

1745   * @author Bobby Easland 

1746   * @version 1.0

1747   * @param string $name

1748   * @param string $method

1749   * @return mixed

1750   */        
1751          function get_cache_memory($name, $method = 'RETURN'){
1752                  $data = ( isset($this->data['GLOBAL'][$name]) ? $this->data['GLOBAL'][$name] : $this->data[$name] );
1753                  if ( isset($data) && !empty($data) && $data != false ){ 
1754                          switch($method){
1755                                  case 'EVAL': // data must be PHP
1756                                          eval("$data");
1757                                          return true;
1758                                          break;
1759                                  case 'ARRAY': 
1760                                  case 'RETURN':
1761                                  default:
1762                                          return $data;
1763                                          break;
1764                          } # end switch ($method)

1765                  } else { 
1766                          return false;
1767                  } # end if (isset($data) && !empty($data) && $data != false)

1768          } # end function get_cache_memory()

1769  
1770  /**

1771   * Function to perform basic garbage collection for database cache system 

1772   * @author Bobby Easland 

1773   * @version 1.0

1774   */        
1775          function cache_gc(){
1776                  $this->DB->Query("DELETE FROM cache WHERE cache_expires <= '" . date("Y-m-d H:i:s") . "'" );
1777          }
1778  
1779  /**

1780   * Function to convert time for cache methods 

1781   * @author Bobby Easland 

1782   * @version 1.0

1783   * @param string $expires

1784   * @return string

1785   */        
1786          function convert_time($expires){ //expires date interval must be spelled out and NOT abbreviated !!
1787                  $expires = explode('/', $expires);
1788                  switch( strtolower($expires[1]) ){ 
1789                          case 'seconds':
1790                                  $expires = mktime( date("H"), date("i"), date("s")+(int)$expires[0], date("m"), date("d"), date("Y") );
1791                                  break;
1792                          case 'minutes':
1793                                  $expires = mktime( date("H"), date("i")+(int)$expires[0], date("s"), date("m"), date("d"), date("Y") );
1794                                  break;
1795                          case 'hours':
1796                                  $expires = mktime( date("H")+(int)$expires[0], date("i"), date("s"), date("m"), date("d"), date("Y") );
1797                                  break;
1798                          case 'days':
1799                                  $expires = mktime( date("H"), date("i"), date("s"), date("m"), date("d")+(int)$expires[0], date("Y") );
1800                                  break;
1801                          case 'months':
1802                                  $expires = mktime( date("H"), date("i"), date("s"), date("m")+(int)$expires[0], date("d"), date("Y") );
1803                                  break;
1804                          case 'years':
1805                                  $expires = mktime( date("H"), date("i"), date("s"), date("m"), date("d"), date("Y")+(int)$expires[0] );
1806                                  break;
1807                          default: // if something fudged up then default to 1 month
1808                                  $expires = mktime( date("H"), date("i"), date("s"), date("m")+1, date("d"), date("Y") );
1809                                  break;
1810                  } # end switch( strtolower($expires[1]) )

1811                  return date("Y-m-d H:i:s", $expires);
1812          } # end function convert_time()

1813  
1814  /**

1815   * Function to check if the cache is in the database and expired  

1816   * @author Bobby Easland 

1817   * @version 1.0

1818   * @param string $name

1819   * @param boolean $is_cached NOTE: passed by reference

1820   * @param boolean $is_expired NOTE: passed by reference

1821   */        
1822          function is_cached($name, &$is_cached, &$is_expired){ // NOTE: $is_cached and $is_expired is passed by reference !!
1823                  $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");
1824                  $is_cached = ( $this->DB->NumRows($this->cache_query ) > 0 ? true : false );
1825                  if ($is_cached){ 
1826                          $check = $this->DB->FetchArray($this->cache_query);
1827                          $is_expired = ( $check['cache_expires'] <= date("Y-m-d H:i:s") ? true : false );
1828                          unset($check);
1829                  }
1830                  $this->DB->Free($this->cache_query);
1831          }# end function is_cached()

1832  
1833  /**

1834   * Function to initialize the redirect logic

1835   * @author Bobby Easland 

1836   * @version 1.1

1837   */        
1838          function check_redirect(){
1839                  $this->need_redirect = false; 
1840                  $this->path_info = is_numeric(strpos(ltrim(getenv('PATH_INFO'), '/') , '/')) ? ltrim(getenv('PATH_INFO'), '/') : NULL;
1841                  $this->uri = ltrim( basename($_SERVER['REQUEST_URI']), '/' );
1842                  $this->real_uri = ltrim( basename($_SERVER['SCRIPT_NAME']) . '?' . $_SERVER['QUERY_STRING'], '/' );
1843                  $this->uri_parsed = $this->not_null( $this->path_info )
1844                                                                  ?        parse_url(basename($_SERVER['SCRIPT_NAME']) . '?' . $this->parse_path($this->path_info) )
1845                                                                  :        parse_url(basename($_SERVER['REQUEST_URI']));                        
1846                  $this->attributes['SEO_REDIRECT']['PATH_INFO'] = $this->path_info;                        
1847                  $this->attributes['SEO_REDIRECT']['URI'] = $this->uri;
1848                  $this->attributes['SEO_REDIRECT']['REAL_URI'] = $this->real_uri;                        
1849                  $this->attributes['SEO_REDIRECT']['URI_PARSED'] = $this->uri_parsed;                        
1850                  $this->need_redirect(); 
1851                  $this->check_seo_page();                 
1852                  if ( $this->need_redirect && $this->is_seopage && $this->attributes['USE_SEO_REDIRECT'] == 'true') $this->do_redirect();                        
1853          } # end function

1854          
1855  /**

1856   * Function to check if the URL needs to be redirected 

1857   * @author Bobby Easland 

1858   * @version 1.2

1859   */        
1860          function need_redirect(){                
1861                  foreach( $this->reg_anchors as $param => $value){
1862                          $pattern[] = $param;
1863                  }
1864                  switch(true){
1865                          case ($this->is_attribute_string($this->uri)):
1866                                  $this->need_redirect = false;
1867                                  break;
1868                          case ($this->uri != $this->real_uri && !$this->not_null($this->path_info)):
1869                                  $this->need_redirect = false;
1870                                  break;
1871                          case (is_numeric(strpos($this->uri, '.htm'))):
1872                                  $this->need_redirect = false;
1873                                  break;
1874                          case (@eregi("("[email protected]implode('|', $pattern).")", $this->uri)):
1875                                  $this->need_redirect = true;
1876                                  break;
1877                          case (@eregi("("[email protected]implode('|', $pattern).")", $this->path_info)):
1878                                  $this->need_redirect = true;
1879                                  break;
1880                          default:
1881                                  break;                        
1882                  } # end switch

1883                  $this->attributes['SEO_REDIRECT']['NEED_REDIRECT'] = $this->need_redirect ? 'true' : 'false';
1884          } # end function set_seopage

1885          
1886  /**

1887   * Function to check if it's a valid redirect page 

1888   * @author Bobby Easland 

1889   * @version 1.1

1890   */        
1891          function check_seo_page(){
1892                  switch (true){
1893                          case (in_array($this->uri_parsed['path'], $this->attributes['SEO_PAGES'])):
1894                                  $this->is_seopage = true;
1895                                  break;
1896                          case ($this->attributes['SEO_ENABLED'] == 'false'):
1897                          default:
1898                                  $this->is_seopage = false;
1899                                  break;
1900                  } # end switch

1901                  $this->attributes['SEO_REDIRECT']['IS_SEOPAGE'] = $this->is_seopage ? 'true' : 'false';
1902          } # end function check_seo_page

1903          
1904  /**

1905   * Function to parse the path for old SEF URLs 

1906   * @author Bobby Easland 

1907   * @version 1.0

1908   * @param string $path_info

1909   * @return array

1910   */        
1911          function parse_path($path_info){ 
1912                  $tmp = @explode('/', $path_info);                 
1913                  if ( sizeof($tmp) > 2 ){
1914                          $container = array();                                
1915                          for ($i=0, $n=sizeof($tmp); $i<$n; $i++) {
1916                                  $container[] = $tmp[$i] . '=' . $tmp[$i+1]; 
1917                                  $i++; 
1918                          }
1919                          return @implode('&', $container);                        
1920                  } else { 
1921                          return @implode('=', $tmp);
1922                  }                                
1923          } # end function parse_path

1924          
1925  /**

1926   * Function to perform redirect 

1927   * @author Bobby Easland 

1928   * @version 1.0

1929   */        
1930          function do_redirect(){
1931                  $p = @explode('&', $this->uri_parsed['query']);
1932                  foreach( $p as $index => $value ){                                                        
1933                          $tmp = @explode('=', $value);
1934                                  switch($tmp[0]){
1935                                          case 'products_id':
1936                                                  if ( $this->is_attribute_string($tmp[1]) ){
1937                                                          $pieces = @explode('{', $tmp[1]);                                                        
1938                                                          $params[] = $tmp[0] . '=' . $pieces[0];
1939                                                  } else {
1940                                                          $params[] = $tmp[0] . '=' . $tmp[1];
1941                                                  }
1942                                                  break;
1943                                          default:
1944                                                  $params[] = $tmp[0].'='.$tmp[1];
1945                                                  break;                                                
1946                                  }
1947                  } # end foreach( $params as $var => $value )

1948                  $params = ( sizeof($params) > 1 ? implode('&', $params) : $params[0] );                
1949                  $url = $this->href_link($this->uri_parsed['path'], $params, 'NONSSL', false);
1950                  switch(true){
1951                          case (defined('USE_SEO_REDIRECT_DEBUG') && USE_SEO_REDIRECT_DEBUG == 'true'):
1952                                  $this->attributes['SEO_REDIRECT']['REDIRECT_URL'] = $url;
1953                                  break;
1954                          case ($this->attributes['USE_SEO_REDIRECT'] == 'true'):
1955                                  header("HTTP/1.0 301 Moved Permanently");
1956                                  $url = str_replace('&amp;', '&', $url);
1957                                  header("Location: $url"); // redirect...bye bye                

1958                                  break;
1959                          default:
1960                                  $this->attributes['SEO_REDIRECT']['REDIRECT_URL'] = $url;
1961                                  break;
1962                  } # end switch

1963          } # end function do_redirect        

1964  } # end class

1965  ?>


Generated: Fri Jan 1 13:43:16 2010 Cross-referenced by PHPXref 0.7