phpDocumentor Google-XML-Sitemap-Feed
[ class tree: Google-XML-Sitemap-Feed ] [ index: Google-XML-Sitemap-Feed ] [ all elements ]

Source for file sitemap.class.php

Documentation is available at sitemap.class.php

  1. <?php
  2. /**
  3. * Google XML Sitemap Feed
  4. *
  5. * The Google sitemap service was announced on 2 June 2005 and represents
  6. * a huge development in terms of crawler technology. This contribution is
  7. * designed to create the sitemap XML feed per the specification delineated
  8. * by Google.
  9. * @package Google-XML-Sitemap-Feed
  10. * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  11. * @version 1.0
  12. * @link http://www.oscommerce-freelancers.com/ osCommerce-Freelancers
  13. * @link http://www.google.com/webmasters/sitemaps/docs/en/about.html About Google Sitemap
  14. * @copyright Copyright 2005, Bobby Easland
  15. * @author Bobby Easland
  16. * @filesource
  17. */
  18.  
  19. /**
  20. * MySQL_Database Class
  21. *
  22. * The MySQL_Database class provides abstraction so the databaes can be accessed
  23. * without having to use tep API functions. This class has minimal error handling
  24. * so make sure your code is tight!
  25. * @package Google-XML-Sitemap-Feed
  26. * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  27. * @version 1.1
  28. * @link http://www.oscommerce-freelancers.com/ osCommerce-Freelancers
  29. * @copyright Copyright 2005, Bobby Easland
  30. * @author Bobby Easland
  31. */
  32. class MySQL_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 MySQL_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.  
  79. /**
  80. * Function to connect to MySQL
  81. * @author Bobby Easland
  82. * @version 1.0
  83. */
  84. function ConnectDB(){
  85. $this->link_id = mysql_connect($this->$host, $this->user, $this->pass);
  86. } # end function
  87.  
  88. /**
  89. * Function to select the database
  90. * @author Bobby Easland
  91. * @version 1.0
  92. * @return resoource
  93. */
  94. function SelectDB(){
  95. return mysql_select_db($this->db);
  96. } # end function
  97.  
  98. /**
  99. * Function to perform queries
  100. * @author Bobby Easland
  101. * @version 1.0
  102. * @param string $query SQL statement
  103. * @return resource
  104. */
  105. function Query($query){
  106. return @mysql_query($query, $this->link_id);
  107. } # end function
  108.  
  109. /**
  110. * Function to fetch array
  111. * @author Bobby Easland
  112. * @version 1.0
  113. * @param resource $resource_id
  114. * @param string $type MYSQL_BOTH or MYSQL_ASSOC
  115. * @return array
  116. */
  117. function FetchArray($resource_id, $type = MYSQL_BOTH){
  118. return @mysql_fetch_array($resource_id, $type);
  119. } # end function
  120.  
  121. /**
  122. * Function to fetch the number of rows
  123. * @author Bobby Easland
  124. * @version 1.0
  125. * @param resource $resource_id
  126. * @return mixed
  127. */
  128. function NumRows($resource_id){
  129. return @mysql_num_rows($resource_id);
  130. } # end function
  131.  
  132. /**
  133. * Function to free the resource
  134. * @author Bobby Easland
  135. * @version 1.0
  136. * @param resource $resource_id
  137. * @return boolean
  138. */
  139. function Free($resource_id){
  140. return @mysql_free_result($resource_id);
  141. } # end function
  142.  
  143.  
  144.  
  145. /**
  146. * Function to add slashes
  147. * @author Bobby Easland
  148. * @version 1.0
  149. * @param string $data
  150. * @return string
  151. */
  152. function Slashes($data){
  153. return addslashes($data);
  154. } # end function
  155.  
  156.  
  157.  
  158. /**
  159. * Function to perform DB inserts and updates - abstracted from osCommerce-MS-2.2 project
  160. * @author Bobby Easland
  161. * @version 1.0
  162. * @param string $table Database table
  163. * @param array $data Associative array of columns / values
  164. * @param string $action insert or update
  165. * @param string $parameters
  166. * @return resource
  167. */
  168. function DBPerform($table, $data, $action = 'insert', $parameters = '') {
  169. reset($data);
  170. if ($action == 'insert') {
  171. $query = 'INSERT INTO `' . $table . '` (';
  172. while (list($columns, ) = each($data)) {
  173. $query .= '`' . $columns . '`, ';
  174. }
  175. $query = substr($query, 0, -2) . ') values (';
  176. reset($data);
  177. while (list(, $value) = each($data)) {
  178. switch ((string)$value) {
  179. case 'now()':
  180. $query .= 'now(), ';
  181. break;
  182. case 'null':
  183. $query .= 'null, ';
  184. break;
  185. default:
  186. $query .= "'" . $this->Slashes($value) . "', ";
  187. break;
  188. }
  189. }
  190. $query = substr($query, 0, -2) . ')';
  191. } elseif ($action == 'update') {
  192. $query = 'UPDATE `' . $table . '` SET ';
  193. while (list($columns, $value) = each($data)) {
  194. switch ((string)$value) {
  195. case 'now()':
  196. $query .= '`' .$columns . '`=now(), ';
  197. break;
  198. case 'null':
  199. $query .= '`' .$columns .= '`=null, ';
  200. break;
  201. default:
  202. $query .= '`' .$columns . "`='" . $this->Slashes($value) . "', ";
  203. break;
  204. }
  205. }
  206. $query = substr($query, 0, -2) . ' WHERE ' . $parameters;
  207. }
  208. return $this->Query($query);
  209. } # end function
  210.  
  211. } # end class
  212.  
  213. /**
  214. * Google Sitemap Base Class
  215. *
  216. * The MySQL_Database class provides abstraction so the databaes can be accessed
  217. * @package Google-XML-Sitemap-Feed
  218. * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  219. * @version 1.0
  220. * @link http://www.oscommerce-freelancers.com/ osCommerce-Freelancers
  221. * @link http://www.google.com/webmasters/sitemaps/docs/en/about.html About Google Sitemap
  222. * @copyright Copyright 2005, Bobby Easland
  223. * @author Bobby Easland
  224. */
  225. class GoogleSitemap{
  226. /**
  227. * $DB is the database object
  228. * @var object
  229. */
  230. var $DB;
  231. /**
  232. * $filename is the base name of the feeds (i.e. - 'sitemap')
  233. * @var string
  234. */
  235. var $filename;
  236. /**
  237. * $savepath is the path where the feeds will be saved - store root
  238. * @var string
  239. */
  240. var $savepath;
  241. /**
  242. * $base_url is the URL for the catalog
  243. * @var string
  244. */
  245. var $base_url;
  246.  
  247. /**
  248. * GoogleSitemap class constructor
  249. * @author Bobby Easland
  250. * @version 1.0
  251. * @param string $host Database host setting (i.e. - localhost)
  252. * @param string $user Database user
  253. * @param string $db Database name
  254. * @param string $pass Database password
  255. */
  256. function GoogleSitemap($host, $user, $db, $pass){
  257. $this->DB = new MySQL_Database($host, $user, $db, $pass);
  258. $this->filename = "sitemap";
  259. $this->savepath = DIR_FS_CATALOG . DIR_WS_HTTP_CATALOG;
  260. $this->base_url = HTTP_SERVER . DIR_WS_HTTP_CATALOG;
  261. } # end class constructor
  262.  
  263.  
  264.  
  265. /**
  266. * Function to save the sitemap data to file as either XML or XML.GZ format
  267. * @author Bobby Easland
  268. * @version 1.0
  269. * @param string $data XML data
  270. * @param string $type Feed type (index, products, categories)
  271. * @return boolean
  272. */
  273. function SaveFile($data, $type){
  274. $filename = $this->savepath . $this->filename . $type;
  275. $compress = defined('GOOGLE_SITEMAP_COMPRESS') ? GOOGLE_SITEMAP_COMPRESS : 'false';
  276. if ($type == 'index') $compress = 'false';
  277. switch($compress){
  278. case 'true':
  279. $filename .= '.xml.gz';
  280. if ($gz = gzopen($filename,'wb9')){
  281. gzwrite($gz, $data);
  282. gzclose($gz);
  283. return true;
  284. } else {
  285. return false;
  286. }
  287. break;
  288. default:
  289. $filename .= '.xml';
  290. if ($fp = fopen($filename, 'w+')){
  291. fwrite($fp, $data);
  292. fclose($fp);
  293. return true;
  294. } else {
  295. return false;
  296. }
  297. break;
  298. } # end switch
  299. } # end function
  300.  
  301. /**
  302. * Function to compress a normal file
  303. * @author Bobby Easland
  304. * @version 1.0
  305. * @param string $file
  306. * @return boolean
  307. */
  308. function CompressFile($file){
  309. $source = $this->savepath . $file . '.xml';
  310. $filename = $this->savepath . $file . '.xml.gz';
  311. $error_encountered = false;
  312. if( $gz_out = gzopen($filename, 'wb9') ){
  313. if($fp_in = fopen($source,'rb')){
  314. while(!feof($fp_in)) gzwrite($gz_out, fread($fp_in, 1024*512));
  315. fclose($fp_in);
  316. } else {
  317. $error_encountered = true;
  318. }
  319. gzclose($gz_out);
  320. } else {
  321. $error_encountered = true;
  322. }
  323. if($error_encountered){
  324. return false;
  325. } else {
  326. return true;
  327. }
  328. } # end function
  329.  
  330.  
  331.  
  332. /**
  333. * Function to generate sitemap file from data
  334. * @author Bobby Easland
  335. * @version 1.0
  336. * @param array $data
  337. * @param string $file
  338. * @return boolean
  339. */
  340. function GenerateSitemap($data, $file){
  341. $content = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
  342. $content .= '<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">' . "\n";
  343. foreach ($data as $url){
  344. $content .= "\t" . '<url>' . "\n";
  345. $content .= "\t\t" . '<loc>'.$url['loc'].'</loc>' . "\n";
  346. $content .= "\t\t" . '<lastmod>'.$url['lastmod'].'</lastmod>' . "\n";
  347. $content .= "\t\t" . '<changefreq>'.$url['changefreq'].'</changefreq>' . "\n";
  348. $content .= "\t\t" . '<priority>'.$url['priority'].'</priority>' . "\n";
  349. $content .= "\t" . '</url>' . "\n";
  350. } # end foreach
  351. $content .= '</urlset>';
  352. return $this->SaveFile($content, $file);
  353. } # end function
  354.  
  355. /**
  356. * Function to generate sitemap index file
  357. * @author Bobby Easland
  358. * @version 1.0
  359. * @return boolean
  360. */
  361. function GenerateSitemapIndex(){
  362. $content = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
  363. $content .= '<sitemapindex xmlns="http://www.google.com/schemas/sitemap/0.84">' . "\n";
  364. $pattern = defined('GOOGLE_SITEMAP_COMPRESS')
  365. ? GOOGLE_SITEMAP_COMPRESS == 'true'
  366. ? "{sitemap*.xml.gz}"
  367. : "{sitemap*.xml}"
  368. : "{sitemap*.xml}";
  369. foreach ( glob($this->savepath . $pattern, GLOB_BRACE) as $filename ) {
  370. if ( eregi('index', $filename) ) continue;
  371. $content .= "\t" . '<sitemap>' . "\n";
  372. $content .= "\t\t" . '<loc>'.$this->base_url . basename($filename).'</loc>' . "\n";
  373. $content .= "\t\t" . '<lastmod>'.date ("Y-m-d\TH:i:s", filemtime($filename)).'</lastmod>' . "\n";
  374. $content .= "\t" . '</sitemap>' . "\n";
  375. } # end foreach
  376. $content .= '</sitemapindex>';
  377. return $this->SaveFile($content, 'index');
  378. } # end function
  379.  
  380. /**
  381. * Function to generate product sitemap data
  382. * @author Bobby Easland
  383. * @version 1.0
  384. * @return boolean
  385. */
  386. function GenerateProductSitemap(){
  387. $sql = "SELECT products_id as pID, products_date_added as date_added, products_last_modified as last_mod, products_ordered
  388. FROM " . TABLE_PRODUCTS . "
  389. WHERE products_status='1'
  390. ORDER BY products_ordered DESC";
  391. if ( $products_query = $this->DB->Query($sql) ){
  392. $container = array();
  393. $number = 0;
  394. $top = 0;
  395. while( $result = $this->DB->FetchArray($products_query) ){
  396. $top = max($top, $result['products_ordered']);
  397. $location = tep_href_link(FILENAME_PRODUCT_INFO, 'products_id=' . $result['pID'], 'NONSSL', false);
  398. $lastmod = tep_not_null($result['last_mod']) ? $result['last_mod'] : $result['date_added'];
  399. $changefreq = GOOGLE_SITEMAP_PROD_CHANGE_FREQ;
  400. $ratio = $result['products_ordered']/$top;
  401. $priority = $ratio < .1 ? .1 : number_format($ratio, 1, '.', '');
  402. $container[] = array('loc' => htmlspecialchars(utf8_encode($location)),
  403. 'lastmod' => date ("Y-m-d\TH:i:s", strtotime($lastmod)),
  404. 'changefreq' => $changefreq,
  405. 'priority' => $priority
  406. );
  407. if ( sizeof($container) >= 50000 ){
  408. $type = $number == 0 ? 'products' : 'products' . $number;
  409. $this->GenerateSitemap($container, $type);
  410. $container = array();
  411. $number++;
  412. }
  413. } # end while
  414. $this->DB->Free($products_query);
  415. if ( sizeof($container) > 1 ) {
  416. $type = $number == 0 ? 'products' : 'products' . $number;
  417. return $this->GenerateSitemap($container, $type);
  418. } # end if
  419. }
  420. } # end function
  421.  
  422. /**
  423. * Funciton to generate category sitemap data
  424. * @author Bobby Easland
  425. * @version 1.0
  426. * @return boolean
  427. */
  428. function GenerateCategorySitemap(){
  429. $sql = "SELECT categories_id as cID, date_added, last_modified as last_mod
  430. FROM " . TABLE_CATEGORIES . "
  431. ORDER BY parent_id ASC, sort_order ASC, categories_id ASC";
  432. if ( $categories_query = $this->DB->Query($sql) ){
  433. $container = array();
  434. $number = 0;
  435. while( $result = $this->DB->FetchArray($categories_query) ){
  436. $location = tep_href_link(FILENAME_DEFAULT, 'cPath=' . $result['cID'], 'NONSSL', false);
  437. $lastmod = tep_not_null($result['last_mod']) ? $result['last_mod'] : $result['date_added'];
  438. $changefreq = GOOGLE_SITEMAP_CAT_CHANGE_FREQ;
  439. $priority = .5;
  440. $container[] = array('loc' => htmlspecialchars(utf8_encode($location)),
  441. 'lastmod' => date ("Y-m-d\TH:i:s", strtotime($lastmod)),
  442. 'changefreq' => $changefreq,
  443. 'priority' => $priority
  444. );
  445. if ( sizeof($container) >= 50000 ){
  446. $type = $number == 0 ? 'categories' : 'categories' . $number;
  447. $this->GenerateSitemap($container, $type);
  448. $container = array();
  449. $number++;
  450. }
  451. } # end while
  452. $this->DB->Free($categories_query);
  453. if ( sizeof($container) > 1 ) {
  454. $type = $number == 0 ? 'categories' : 'categories' . $number;
  455. return $this->GenerateSitemap($container, $type);
  456. } # end if
  457. }
  458. } # end function
  459.  
  460.  
  461.  
  462. /**
  463. * Utility function to read and return the contents of a GZ formatted file
  464. * @author Bobby Easland
  465. * @version 1.0
  466. * @param string $file File to open
  467. * @return string
  468. */
  469. function ReadGZ( $file ){
  470. $file = $this->savepath . $file;
  471. $lines = gzfile($file);
  472. return implode('', $lines);
  473. } # end function
  474.  
  475. /**
  476. * Utility function to generate the submit URL
  477. * @author Bobby Easland
  478. * @version 1.0
  479. * @return string
  480. */
  481. function GenerateSubmitURL(){
  482. $url = urlencode($this->base_url . 'sitemapindex.xml');
  483. return htmlspecialchars(utf8_encode('http://www.google.com/webmasters/sitemaps/ping?sitemap=' . $url));
  484. } # end function
  485.  
  486. } # end class
  487. ?>

Documentation generated on Sat, 4 Jun 2005 23:45:59 -0400 by phpDocumentor 1.3.0RC3