PageRenderTime 69ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 1ms

/blog/wp-content/plugins/google-sitemap-generator/sitemap-core.php

https://bitbucket.org/abtris/phpframeworks
PHP | 2496 lines | 1550 code | 353 blank | 593 comment | 317 complexity | 81bdad61cd3fb811d6e627b18706e307 MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. $Id$
  4. */
  5. //Enable for dev! Good code doesn't generate any notices...
  6. //error_reporting(E_ALL);
  7. //ini_set("display_errors",1);
  8. #region PHP5 compat functions
  9. if (!function_exists('file_get_contents')) {
  10. /**
  11. * Replace file_get_contents()
  12. *
  13. * @category PHP
  14. * @package PHP_Compat
  15. * @link http://php.net/function.file_get_contents
  16. * @author Aidan Lister <aidan - php - net>
  17. * @version $Revision$
  18. * @internal resource_context is not supported
  19. * @since PHP 5
  20. */
  21. function file_get_contents($filename, $incpath = false, $resource_context = null) {
  22. if (false === $fh = fopen($filename, 'rb', $incpath)) {
  23. user_error('file_get_contents() failed to open stream: No such file or directory', E_USER_WARNING);
  24. return false;
  25. }
  26. clearstatcache();
  27. if ($fsize = @filesize($filename)) {
  28. $data = fread($fh, $fsize);
  29. } else {
  30. $data = '';
  31. while (!feof($fh)) {
  32. $data .= fread($fh, 8192);
  33. }
  34. }
  35. fclose($fh);
  36. return $data;
  37. }
  38. }
  39. if(!function_exists('file_put_contents')) {
  40. if (!defined('FILE_USE_INCLUDE_PATH')) {
  41. define('FILE_USE_INCLUDE_PATH', 1);
  42. }
  43. if (!defined('LOCK_EX')) {
  44. define('LOCK_EX', 2);
  45. }
  46. if (!defined('FILE_APPEND')) {
  47. define('FILE_APPEND', 8);
  48. }
  49. /**
  50. * Replace file_put_contents()
  51. *
  52. * @category PHP
  53. * @package PHP_Compat
  54. * @link http://php.net/function.file_put_contents
  55. * @author Aidan Lister <aidan - php - net>
  56. * @version $Revision$
  57. * @internal resource_context is not supported
  58. * @since PHP 5
  59. * @require PHP 4.0.0 (user_error)
  60. */
  61. function file_put_contents($filename, $content, $flags = null, $resource_context = null) {
  62. // If $content is an array, convert it to a string
  63. if (is_array($content)) {
  64. $content = implode('', $content);
  65. }
  66. // If we don't have a string, throw an error
  67. if (!is_scalar($content)) {
  68. user_error('file_put_contents() The 2nd parameter should be either a string or an array',E_USER_WARNING);
  69. return false;
  70. }
  71. // Get the length of data to write
  72. $length = strlen($content);
  73. // Check what mode we are using
  74. $mode = ($flags & FILE_APPEND)?'a':'wb';
  75. // Check if we're using the include path
  76. $use_inc_path = ($flags & FILE_USE_INCLUDE_PATH)?true:false;
  77. // Open the file for writing
  78. if (($fh = @fopen($filename, $mode, $use_inc_path)) === false) {
  79. user_error('file_put_contents() failed to open stream: Permission denied',E_USER_WARNING);
  80. return false;
  81. }
  82. // Attempt to get an exclusive lock
  83. $use_lock = ($flags & LOCK_EX) ? true : false ;
  84. if ($use_lock === true) {
  85. if (!flock($fh, LOCK_EX)) {
  86. return false;
  87. }
  88. }
  89. // Write to the file
  90. $bytes = 0;
  91. if (($bytes = @fwrite($fh, $content)) === false) {
  92. $errormsg = sprintf('file_put_contents() Failed to write %d bytes to %s',$length,$filename);
  93. user_error($errormsg, E_USER_WARNING);
  94. return false;
  95. }
  96. // Close the handle
  97. @fclose($fh);
  98. // Check all the data was written
  99. if ($bytes != $length) {
  100. $errormsg = sprintf('file_put_contents() Only %d of %d bytes written, possibly out of free disk space.',$bytes,$length);
  101. user_error($errormsg, E_USER_WARNING);
  102. return false;
  103. }
  104. // Return length
  105. return $bytes;
  106. }
  107. }
  108. #endregion
  109. /**
  110. * Represents the status (success and failures) of a building process
  111. * @author Arne Brachhold
  112. * @package sitemap
  113. * @since 3.0b5
  114. */
  115. class GoogleSitemapGeneratorStatus {
  116. function GoogleSitemapGeneratorStatus() {
  117. $this->_startTime = $this->GetMicrotimeFloat();
  118. $exists = get_option("sm_status");
  119. if($exists === false) add_option("sm_status","","Status","no");
  120. $this->Save();
  121. }
  122. function Save() {
  123. update_option("sm_status",$this);
  124. }
  125. function Load() {
  126. $status = @get_option("sm_status");
  127. if(is_a($status,"GoogleSitemapGeneratorStatus")) return $status;
  128. else return null;
  129. }
  130. /**
  131. * @var float $_startTime The start time of the building process
  132. * @access private
  133. */
  134. var $_startTime = 0;
  135. /**
  136. * @var float $_endTime The end time of the building process
  137. * @access private
  138. */
  139. var $_endTime = 0;
  140. /**
  141. * @var bool $$_hasChanged Indicates if the sitemap content has changed
  142. * @access private
  143. */
  144. var $_hasChanged = true;
  145. /**
  146. * @var int $_memoryUsage The amount of memory used in bytes
  147. * @access private
  148. */
  149. var $_memoryUsage = 0;
  150. /**
  151. * @var int $_lastPost The number of posts processed. This value is updated every 50 posts.
  152. * @access private
  153. */
  154. var $_lastPost = 0;
  155. /**
  156. * @var int $_lastTime The time when the last step-update occured. This value is updated every 50 posts.
  157. * @access private
  158. */
  159. var $_lastTime = 0;
  160. function End($hasChanged = true) {
  161. $this->_endTime = $this->GetMicrotimeFloat();
  162. $this->SetMemoryUsage();
  163. $this->_hasChanged = $hasChanged;
  164. $this->Save();
  165. }
  166. function SetMemoryUsage() {
  167. if(function_exists("memory_get_peak_usage")) {
  168. $this->_memoryUsage = memory_get_peak_usage(true);
  169. } else if(function_exists("memory_get_usage")) {
  170. $this->_memoryUsage = memory_get_usage(true);
  171. }
  172. }
  173. function GetMemoryUsage() {
  174. return round($this->_memoryUsage / 1024 / 1024,2);
  175. }
  176. function SaveStep($postCount) {
  177. $this->SetMemoryUsage();
  178. $this->_lastPost = $postCount;
  179. $this->_lastTime = $this->GetMicrotimeFloat();
  180. $this->Save();
  181. }
  182. function GetTime() {
  183. return round($this->_endTime - $this->_startTime,2);
  184. }
  185. function GetStartTime() {
  186. return round($this->_startTime, 2);
  187. }
  188. function GetLastTime() {
  189. return round($this->_lastTime - $this->_startTime,2);
  190. }
  191. function GetLastPost() {
  192. return $this->_lastPost;
  193. }
  194. var $_usedXml = false;
  195. var $_xmlSuccess = false;
  196. var $_xmlPath = '';
  197. var $_xmlUrl = '';
  198. function StartXml($path,$url) {
  199. $this->_usedXml = true;
  200. $this->_xmlPath = $path;
  201. $this->_xmlUrl = $url;
  202. $this->Save();
  203. }
  204. function EndXml($success) {
  205. $this->_xmlSuccess = $success;
  206. $this->Save();
  207. }
  208. var $_usedZip = false;
  209. var $_zipSuccess = false;
  210. var $_zipPath = '';
  211. var $_zipUrl = '';
  212. function StartZip($path,$url) {
  213. $this->_usedZip = true;
  214. $this->_zipPath = $path;
  215. $this->_zipUrl = $url;
  216. $this->Save();
  217. }
  218. function EndZip($success) {
  219. $this->_zipSuccess = $success;
  220. $this->Save();
  221. }
  222. var $_usedGoogle = false;
  223. var $_googleUrl = '';
  224. var $_gooogleSuccess = false;
  225. var $_googleStartTime = 0;
  226. var $_googleEndTime = 0;
  227. function StartGooglePing($url) {
  228. $this->_googleUrl = true;
  229. $this->_usedGoogle = true;
  230. $this->_googleStartTime = $this->GetMicrotimeFloat();
  231. $this->Save();
  232. }
  233. function EndGooglePing($success) {
  234. $this->_googleEndTime = $this->GetMicrotimeFloat();
  235. $this->_gooogleSuccess = $success;
  236. $this->Save();
  237. }
  238. function GetGoogleTime() {
  239. return round($this->_googleEndTime - $this->_googleStartTime,2);
  240. }
  241. var $_usedYahoo = false;
  242. var $_yahooUrl = '';
  243. var $_yahooSuccess = false;
  244. var $_yahooStartTime = 0;
  245. var $_yahooEndTime = 0;
  246. function StartYahooPing($url) {
  247. $this->_yahooUrl = $url;
  248. $this->_usedYahoo = true;
  249. $this->_yahooStartTime = $this->GetMicrotimeFloat();
  250. $this->Save();
  251. }
  252. function EndYahooPing($success) {
  253. $this->_yahooEndTime = $this->GetMicrotimeFloat();
  254. $this->_yahooSuccess = $success;
  255. $this->Save();
  256. }
  257. function GetYahooTime() {
  258. return round($this->_yahooEndTime - $this->_yahooStartTime,2);
  259. }
  260. var $_usedAsk = false;
  261. var $_askUrl = '';
  262. var $_askSuccess = false;
  263. var $_askStartTime = 0;
  264. var $_askEndTime = 0;
  265. function StartAskPing($url) {
  266. $this->_usedAsk = true;
  267. $this->_askUrl = $url;
  268. $this->_askStartTime = $this->GetMicrotimeFloat();
  269. $this->Save();
  270. }
  271. function EndAskPing($success) {
  272. $this->_askEndTime = $this->GetMicrotimeFloat();
  273. $this->_askSuccess = $success;
  274. $this->Save();
  275. }
  276. function GetAskTime() {
  277. return round($this->_askEndTime - $this->_askStartTime,2);
  278. }
  279. var $_usedMsn = false;
  280. var $_msnUrl = '';
  281. var $_msnSuccess = false;
  282. var $_msnStartTime = 0;
  283. var $_msnEndTime = 0;
  284. function StartMsnPing($url) {
  285. $this->_usedMsn = true;
  286. $this->_msnUrl = $url;
  287. $this->_msnStartTime = $this->GetMicrotimeFloat();
  288. $this->Save();
  289. }
  290. function EndMsnPing($success) {
  291. $this->_msnEndTime = $this->GetMicrotimeFloat();
  292. $this->_msnSuccess = $success;
  293. $this->Save();
  294. }
  295. function GetMsnTime() {
  296. return round($this->_msnEndTime - $this->_msnStartTime,2);
  297. }
  298. function GetMicrotimeFloat() {
  299. list($usec, $sec) = explode(" ", microtime());
  300. return ((float)$usec + (float)$sec);
  301. }
  302. }
  303. /**
  304. * Represents an item in the page list
  305. * @author Arne Brachhold
  306. * @package sitemap
  307. * @since 3.0
  308. */
  309. class GoogleSitemapGeneratorPage {
  310. /**
  311. * @var string $_url Sets the URL or the relative path to the blog dir of the page
  312. * @access private
  313. */
  314. var $_url;
  315. /**
  316. * @var float $_priority Sets the priority of this page
  317. * @access private
  318. */
  319. var $_priority;
  320. /**
  321. * @var string $_changeFreq Sets the chanfe frequency of the page. I want Enums!
  322. * @access private
  323. */
  324. var $_changeFreq;
  325. /**
  326. * @var int $_lastMod Sets the lastMod date as a UNIX timestamp.
  327. * @access private
  328. */
  329. var $_lastMod;
  330. /**
  331. * Initialize a new page object
  332. *
  333. * @since 3.0
  334. * @access public
  335. * @author Arne Brachhold
  336. * @param bool $enabled Should this page be included in thesitemap
  337. * @param string $url The URL or path of the file
  338. * @param float $priority The Priority of the page 0.0 to 1.0
  339. * @param string $changeFreq The change frequency like daily, hourly, weekly
  340. * @param int $lastMod The last mod date as a unix timestamp
  341. */
  342. function GoogleSitemapGeneratorPage($url="",$priority=0.0,$changeFreq="never",$lastMod=0) {
  343. $this->SetUrl($url);
  344. $this->SetProprity($priority);
  345. $this->SetChangeFreq($changeFreq);
  346. $this->SetLastMod($lastMod);
  347. }
  348. /**
  349. * Returns the URL of the page
  350. *
  351. * @return string The URL
  352. */
  353. function GetUrl() {
  354. return $this->_url;
  355. }
  356. /**
  357. * Sets the URL of the page
  358. *
  359. * @param string $url The new URL
  360. */
  361. function SetUrl($url) {
  362. $this->_url=(string) $url;
  363. }
  364. /**
  365. * Returns the priority of this page
  366. *
  367. * @return float the priority, from 0.0 to 1.0
  368. */
  369. function GetPriority() {
  370. return $this->_priority;
  371. }
  372. /**
  373. * Sets the priority of the page
  374. *
  375. * @param float $priority The new priority from 0.1 to 1.0
  376. */
  377. function SetProprity($priority) {
  378. $this->_priority=floatval($priority);
  379. }
  380. /**
  381. * Returns the change frequency of the page
  382. *
  383. * @return string The change frequncy like hourly, weekly, monthly etc.
  384. */
  385. function GetChangeFreq() {
  386. return $this->_changeFreq;
  387. }
  388. /**
  389. * Sets the change frequency of the page
  390. *
  391. * @param string $changeFreq The new change frequency
  392. */
  393. function SetChangeFreq($changeFreq) {
  394. $this->_changeFreq=(string) $changeFreq;
  395. }
  396. /**
  397. * Returns the last mod of the page
  398. *
  399. * @return int The lastmod value in seconds
  400. */
  401. function GetLastMod() {
  402. return $this->_lastMod;
  403. }
  404. /**
  405. * Sets the last mod of the page
  406. *
  407. * @param int $lastMod The lastmod of the page
  408. */
  409. function SetLastMod($lastMod) {
  410. $this->_lastMod=intval($lastMod);
  411. }
  412. function Render() {
  413. if($this->_url == "/" || empty($this->_url)) return '';
  414. $r="";
  415. $r.= "\t<url>\n";
  416. $r.= "\t\t<loc>" . $this->EscapeXML($this->_url) . "</loc>\n";
  417. if($this->_lastMod>0) $r.= "\t\t<lastmod>" . date('Y-m-d\TH:i:s+00:00',$this->_lastMod) . "</lastmod>\n";
  418. if(!empty($this->_changeFreq)) $r.= "\t\t<changefreq>" . $this->_changeFreq . "</changefreq>\n";
  419. if($this->_priority!==false && $this->_priority!=="") $r.= "\t\t<priority>" . number_format($this->_priority,1) . "</priority>\n";
  420. $r.= "\t</url>\n";
  421. return $r;
  422. }
  423. function EscapeXML($string) {
  424. return str_replace ( array ( '&', '"', "'", '<', '>'), array ( '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;'), $string);
  425. }
  426. }
  427. class GoogleSitemapGeneratorXmlEntry {
  428. var $_xml;
  429. function GoogleSitemapGeneratorXmlEntry($xml) {
  430. $this->_xml = $xml;
  431. }
  432. function Render() {
  433. return $this->_xml;
  434. }
  435. }
  436. class GoogleSitemapGeneratorDebugEntry extends GoogleSitemapGeneratorXmlEntry {
  437. function Render() {
  438. return "<!-- " . $this->_xml . " -->";
  439. }
  440. }
  441. /**
  442. * Base class for all priority providers
  443. * @author Arne Brachhold
  444. * @package sitemap
  445. * @since 3.0
  446. */
  447. class GoogleSitemapGeneratorPrioProviderBase {
  448. /**
  449. * @var int $_totalComments The total number of comments of all posts
  450. * @access protected
  451. */
  452. var $_totalComments=0;
  453. /**
  454. * @var int $_totalComments The total number of posts
  455. * @access protected
  456. */
  457. var $_totalPosts=0;
  458. /**
  459. * Returns the (translated) name of this priority provider
  460. *
  461. * @since 3.0
  462. * @access public
  463. * @author Arne Brachhold
  464. * @return string The translated name
  465. */
  466. function GetName() {
  467. return "";
  468. }
  469. /**
  470. * Returns the (translated) description of this priority provider
  471. *
  472. * @since 3.0
  473. * @access public
  474. * @author Arne Brachhold
  475. * @return string The translated description
  476. */
  477. function GetDescription() {
  478. return "";
  479. }
  480. /**
  481. * Initializes a new priority provider
  482. *
  483. * @param $totalComments int The total number of comments of all posts
  484. * @param $totalPosts int The total number of posts
  485. * @since 3.0
  486. * @access public
  487. * @author Arne Brachhold
  488. */
  489. function GoogleSitemapGeneratorPrioProviderBase($totalComments,$totalPosts) {
  490. $this->_totalComments=$totalComments;
  491. $this->_totalPosts=$totalPosts;
  492. }
  493. /**
  494. * Returns the priority for a specified post
  495. *
  496. * @param $postID int The ID of the post
  497. * @param $commentCount int The number of comments for this post
  498. * @since 3.0
  499. * @access public
  500. * @author Arne Brachhold
  501. * @return int The calculated priority
  502. */
  503. function GetPostPriority($postID,$commentCount) {
  504. return 0;
  505. }
  506. }
  507. /**
  508. * Priority Provider which calculates the priority based on the number of comments
  509. * @author Arne Brachhold
  510. * @package sitemap
  511. * @since 3.0
  512. */
  513. class GoogleSitemapGeneratorPrioByCountProvider extends GoogleSitemapGeneratorPrioProviderBase {
  514. /**
  515. * Returns the (translated) name of this priority provider
  516. *
  517. * @since 3.0
  518. * @access public
  519. * @author Arne Brachhold
  520. * @return string The translated name
  521. */
  522. function GetName() {
  523. return __("Comment Count",'sitemap');
  524. }
  525. /**
  526. * Returns the (translated) description of this priority provider
  527. *
  528. * @since 3.0
  529. * @access public
  530. * @author Arne Brachhold
  531. * @return string The translated description
  532. */
  533. function GetDescription() {
  534. return __("Uses the number of comments of the post to calculate the priority",'sitemap');
  535. }
  536. /**
  537. * Initializes a new priority provider which calculates the post priority based on the number of comments
  538. *
  539. * @param $totalComments int The total number of comments of all posts
  540. * @param $totalPosts int The total number of posts
  541. * @since 3.0
  542. * @access public
  543. * @author Arne Brachhold
  544. */
  545. function GoogleSitemapGeneratorPrioByCountProvider($totalComments,$totalPosts) {
  546. parent::GoogleSitemapGeneratorPrioProviderBase($totalComments,$totalPosts);
  547. }
  548. /**
  549. * Returns the priority for a specified post
  550. *
  551. * @param $postID int The ID of the post
  552. * @param $commentCount int The number of comments for this post
  553. * @since 3.0
  554. * @access public
  555. * @author Arne Brachhold
  556. * @return int The calculated priority
  557. */
  558. function GetPostPriority($postID,$commentCount) {
  559. $prio=0;
  560. if($this->_totalComments>0 && $commentCount>0) {
  561. $prio = round(($commentCount*100/$this->_totalComments)/100,1);
  562. } else {
  563. $prio = 0;
  564. }
  565. return $prio;
  566. }
  567. }
  568. /**
  569. * Priority Provider which calculates the priority based on the average number of comments
  570. * @author Arne Brachhold
  571. * @package sitemap
  572. * @since 3.0
  573. */
  574. class GoogleSitemapGeneratorPrioByAverageProvider extends GoogleSitemapGeneratorPrioProviderBase {
  575. /**
  576. * @var int $_average The average number of comments per post
  577. * @access protected
  578. */
  579. var $_average=0.0;
  580. /**
  581. * Returns the (translated) name of this priority provider
  582. *
  583. * @since 3.0
  584. * @access public
  585. * @author Arne Brachhold
  586. * @return string The translated name
  587. */
  588. function GetName() {
  589. return __("Comment Average",'sitemap');
  590. }
  591. /**
  592. * Returns the (translated) description of this priority provider
  593. *
  594. * @since 3.0
  595. * @access public
  596. * @author Arne Brachhold
  597. * @return string The translated description
  598. */
  599. function GetDescription() {
  600. return __("Uses the average comment count to calculate the priority",'sitemap');
  601. }
  602. /**
  603. * Initializes a new priority provider which calculates the post priority based on the average number of comments
  604. *
  605. * @param $totalComments int The total number of comments of all posts
  606. * @param $totalPosts int The total number of posts
  607. * @since 3.0
  608. * @access public
  609. * @author Arne Brachhold
  610. */
  611. function GoogleSitemapGeneratorPrioByAverageProvider($totalComments,$totalPosts) {
  612. parent::GoogleSitemapGeneratorPrioProviderBase($totalComments,$totalPosts);
  613. if($this->_totalComments>0 && $this->_totalPosts>0) {
  614. $this->_average= (double) $this->_totalComments / $this->_totalPosts;
  615. }
  616. }
  617. /**
  618. * Returns the priority for a specified post
  619. *
  620. * @param $postID int The ID of the post
  621. * @param $commentCount int The number of comments for this post
  622. * @since 3.0
  623. * @access public
  624. * @author Arne Brachhold
  625. * @return int The calculated priority
  626. */
  627. function GetPostPriority($postID,$commentCount) {
  628. $prio = 0;
  629. //Do not divide by zero!
  630. if($this->_average==0) {
  631. if($commentCount>0) $prio = 1;
  632. else $prio = 0;
  633. } else {
  634. $prio = $commentCount/$this->_average;
  635. if($prio>1) $prio = 1;
  636. else if($prio<0) $prio = 0;
  637. }
  638. return round($prio,1);
  639. }
  640. }
  641. /**
  642. * Priority Provider which calculates the priority based on the popularity by the PopularityContest Plugin
  643. * @author Arne Brachhold
  644. * @package sitemap
  645. * @since 3.0
  646. */
  647. class GoogleSitemapGeneratorPrioByPopularityContestProvider extends GoogleSitemapGeneratorPrioProviderBase {
  648. /**
  649. * Returns the (translated) name of this priority provider
  650. *
  651. * @since 3.0
  652. * @access public
  653. * @author Arne Brachhold
  654. * @return string The translated name
  655. */
  656. function GetName() {
  657. return __("Popularity Contest",'sitemap');
  658. }
  659. /**
  660. * Returns the (translated) description of this priority provider
  661. *
  662. * @since 3.0
  663. * @access public
  664. * @author Arne Brachhold
  665. * @return string The translated description
  666. */
  667. function GetDescription() {
  668. return str_replace("%4","index.php?page=popularity-contest.php",str_replace("%3","options-general.php?page=popularity-contest.php",str_replace("%2","http://www.alexking.org/",str_replace("%1","http://www.alexking.org/index.php?content=software/wordpress/content.php",__("Uses the activated <a href=\"%1\">Popularity Contest Plugin</a> from <a href=\"%2\">Alex King</a>. See <a href=\"%3\">Settings</a> and <a href=\"%4\">Most Popular Posts</a>",'sitemap')))));
  669. }
  670. /**
  671. * Initializes a new priority provider which calculates the post priority based on the popularity by the PopularityContest Plugin
  672. *
  673. * @param $totalComments int The total number of comments of all posts
  674. * @param $totalPosts int The total number of posts
  675. * @since 3.0
  676. * @access public
  677. * @author Arne Brachhold
  678. */
  679. function GoogleSitemapGeneratorPrioByPopularityContestProvider($totalComments,$totalPosts) {
  680. parent::GoogleSitemapGeneratorPrioProviderBase($totalComments,$totalPosts);
  681. }
  682. /**
  683. * Returns the priority for a specified post
  684. *
  685. * @param $postID int The ID of the post
  686. * @param $commentCount int The number of comments for this post
  687. * @since 3.0
  688. * @access public
  689. * @author Arne Brachhold
  690. * @return int The calculated priority
  691. */
  692. function GetPostPriority($postID,$commentCount) {
  693. //$akpc is the global instance of the Popularity Contest Plugin
  694. global $akpc,$posts;
  695. $res=0;
  696. //Better check if its there
  697. if(!empty($akpc) && is_object($akpc)) {
  698. //Is the method we rely on available?
  699. if(method_exists($akpc,"get_post_rank")) {
  700. if(!is_array($posts) || !$posts) $posts = array();
  701. if(!isset($posts[$postID])) $posts[$postID] = get_post($postID);
  702. //popresult comes as a percent value
  703. $popresult=$akpc->get_post_rank($postID);
  704. if(!empty($popresult) && strpos($popresult,"%")!==false) {
  705. //We need to parse it to get the priority as an int (percent)
  706. $matches=null;
  707. preg_match("/([0-9]{1,3})\%/si",$popresult,$matches);
  708. if(!empty($matches) && is_array($matches) && count($matches)==2) {
  709. //Divide it so 100% = 1, 10% = 0.1
  710. $res=round(intval($matches[1])/100,1);
  711. }
  712. }
  713. }
  714. }
  715. return $res;
  716. }
  717. }
  718. /**
  719. * Class to generate a sitemaps.org Sitemaps compliant sitemap of a WordPress blog.
  720. *
  721. * @package sitemap
  722. * @author Arne Brachhold
  723. * @since 3.0
  724. */
  725. class GoogleSitemapGenerator {
  726. /**
  727. * @var Version of the generator in SVN
  728. */
  729. var $_svnVersion = '$Id$';
  730. /**
  731. * @var array The unserialized array with the stored options
  732. */
  733. var $_options = array();
  734. /**
  735. * @var array The saved additional pages
  736. */
  737. var $_pages = array();
  738. /**
  739. * @var array The values and names of the change frequencies
  740. */
  741. var $_freqNames = array();
  742. /**
  743. * @var array A list of class names which my be called for priority calculation
  744. */
  745. var $_prioProviders = array();
  746. /**
  747. * @var bool True if init complete (options loaded etc)
  748. */
  749. var $_initiated = false;
  750. /**
  751. * @var string Holds the last error if one occurs when writing the files
  752. */
  753. var $_lastError=null;
  754. /**
  755. * @var int The last handled post ID
  756. */
  757. var $_lastPostID = 0;
  758. /**
  759. * @var bool Defines if the sitemap building process is active at the moment
  760. */
  761. var $_isActive = false;
  762. /**
  763. * @var bool Defines if the sitemap building process has been scheduled via Wp cron
  764. */
  765. var $_isScheduled = false;
  766. /**
  767. * @var object The file handle which is used to write the sitemap file
  768. */
  769. var $_fileHandle = null;
  770. /**
  771. * @var object The file handle which is used to write the zipped sitemap file
  772. */
  773. var $_fileZipHandle = null;
  774. /**
  775. * Returns the path to the blog directory
  776. *
  777. * @since 3.0
  778. * @access private
  779. * @author Arne Brachhold
  780. * @return string The full path to the blog directory
  781. */
  782. function GetHomePath() {
  783. $res="";
  784. //Check if we are in the admin area -> get_home_path() is avaiable
  785. if(function_exists("get_home_path")) {
  786. $res = get_home_path();
  787. } else {
  788. //get_home_path() is not available, but we can't include the admin
  789. //libraries because many plugins check for the "check_admin_referer"
  790. //function to detect if you are on an admin page. So we have to copy
  791. //the get_home_path function in our own...
  792. $home = get_option( 'home' );
  793. if ( $home != '' && $home != get_option( 'siteurl' ) ) {
  794. $home_path = parse_url( $home );
  795. $home_path = $home_path['path'];
  796. $root = str_replace( $_SERVER["PHP_SELF"], '', $_SERVER["SCRIPT_FILENAME"] );
  797. $home_path = trailingslashit( $root.$home_path );
  798. } else {
  799. $home_path = ABSPATH;
  800. }
  801. $res = $home_path;
  802. }
  803. return $res;
  804. }
  805. /**
  806. * Returns the path to the directory where the plugin file is located
  807. * @since 3.0b5
  808. * @access private
  809. * @author Arne Brachhold
  810. * @return string The path to the plugin directory
  811. */
  812. function GetPluginPath() {
  813. $path = dirname(__FILE__);
  814. return trailingslashit(str_replace("\\","/",$path));
  815. }
  816. /**
  817. * Returns the URL to the directory where the plugin file is located
  818. * @since 3.0b5
  819. * @access private
  820. * @author Arne Brachhold
  821. * @return string The URL to the plugin directory
  822. */
  823. function GetPluginUrl() {
  824. //Try to use WP API if possible, introduced in WP 2.6
  825. if (function_exists('plugins_url')) return trailingslashit(plugins_url(basename(dirname(__FILE__))));
  826. //Try to find manually... can't work if wp-content was renamed or is redirected
  827. $path = dirname(__FILE__);
  828. $path = str_replace("\\","/",$path);
  829. $path = trailingslashit(get_bloginfo('wpurl')) . trailingslashit(substr($path,strpos($path,"wp-content/")));
  830. return $path;
  831. }
  832. /**
  833. * Returns the URL to default XSLT style if it exists
  834. * @since 3.0b5
  835. * @access private
  836. * @author Arne Brachhold
  837. * @return string The URL to the default stylesheet, empry string if not available.
  838. */
  839. function GetDefaultStyle() {
  840. $p = $this->GetPluginPath();
  841. if(file_exists($p . "sitemap.xsl")) {
  842. return $this->GetPluginUrl() . 'sitemap.xsl';
  843. }
  844. return '';
  845. }
  846. /**
  847. * Sets up the default configuration
  848. *
  849. * @since 3.0
  850. * @access private
  851. * @author Arne Brachhold
  852. */
  853. function InitOptions() {
  854. $this->_options=array();
  855. $this->_options["sm_b_prio_provider"]="GoogleSitemapGeneratorPrioByCountProvider"; //Provider for automatic priority calculation
  856. $this->_options["sm_b_filename"]="sitemap.xml"; //Name of the Sitemap file
  857. $this->_options["sm_b_debug"]=true; //Write debug messages in the xml file
  858. $this->_options["sm_b_xml"]=true; //Create a .xml file
  859. $this->_options["sm_b_gzip"]=true; //Create a gzipped .xml file(.gz) file
  860. $this->_options["sm_b_ping"]=true; //Auto ping Google
  861. $this->_options["sm_b_pingyahoo"]=false; //Auto ping YAHOO
  862. $this->_options["sm_b_yahookey"]=''; //YAHOO Application Key
  863. $this->_options["sm_b_pingask"]=true; //Auto ping Ask.com
  864. $this->_options["sm_b_pingmsn"]=true; //Auto ping MSN
  865. $this->_options["sm_b_manual_enabled"]=false; //Allow manual creation of the sitemap via GET request
  866. $this->_options["sm_b_auto_enabled"]=true; //Rebuild sitemap when content is changed
  867. $this->_options["sm_b_auto_delay"]=true; //Use WP Cron to execute the building process in the background
  868. $this->_options["sm_b_manual_key"]=md5(microtime());//The secret key to build the sitemap via GET request
  869. $this->_options["sm_b_memory"] = ''; //Set Memory Limit (e.g. 16M)
  870. $this->_options["sm_b_time"] = -1; //Set time limit in seconds, 0 for unlimited, -1 for disabled
  871. $this->_options["sm_b_max_posts"] = -1; //Maximum number of posts, <= 0 for all
  872. $this->_options["sm_b_safemode"] = false; //Enable MySQL Safe Mode (doesn't use unbuffered results)
  873. $this->_options["sm_b_style_default"] = true; //Use default style
  874. $this->_options["sm_b_style"] = ''; //Include a stylesheet in the XML
  875. $this->_options["sm_b_robots"] = true; //Add sitemap location to WordPress' virtual robots.txt file
  876. $this->_options["sm_b_exclude"] = array(); //List of post / page IDs to exclude
  877. $this->_options["sm_b_exclude_cats"] = array(); //List of post / page IDs to exclude
  878. $this->_options["sm_b_location_mode"]="auto"; //Mode of location, auto or manual
  879. $this->_options["sm_b_filename_manual"]=""; //Manuel filename
  880. $this->_options["sm_b_fileurl_manual"]=""; //Manuel fileurl
  881. $this->_options["sm_in_home"]=true; //Include homepage
  882. $this->_options["sm_in_posts"]=true; //Include posts
  883. $this->_options["sm_in_posts_sub"]=false; //Include post pages (<!--nextpage--> tag)
  884. $this->_options["sm_in_pages"]=true; //Include static pages
  885. $this->_options["sm_in_cats"]=false; //Include categories
  886. $this->_options["sm_in_arch"]=false; //Include archives
  887. $this->_options["sm_in_auth"]=false; //Include author pages
  888. $this->_options["sm_in_tags"]=false; //Include tag pages
  889. $this->_options["sm_cf_home"]="daily"; //Change frequency of the homepage
  890. $this->_options["sm_cf_posts"]="monthly"; //Change frequency of posts
  891. $this->_options["sm_cf_pages"]="weekly"; //Change frequency of static pages
  892. $this->_options["sm_cf_cats"]="weekly"; //Change frequency of categories
  893. $this->_options["sm_cf_auth"]="weekly"; //Change frequency of author pages
  894. $this->_options["sm_cf_arch_curr"]="daily"; //Change frequency of the current archive (this month)
  895. $this->_options["sm_cf_arch_old"]="yearly"; //Change frequency of older archives
  896. $this->_options["sm_cf_tags"]="weekly"; //Change frequency of tags
  897. $this->_options["sm_pr_home"]=1.0; //Priority of the homepage
  898. $this->_options["sm_pr_posts"]=0.6; //Priority of posts (if auto prio is disabled)
  899. $this->_options["sm_pr_posts_min"]=0.2; //Minimum Priority of posts, even if autocalc is enabled
  900. $this->_options["sm_pr_pages"]=0.6; //Priority of static pages
  901. $this->_options["sm_pr_cats"]=0.3; //Priority of categories
  902. $this->_options["sm_pr_arch"]=0.3; //Priority of archives
  903. $this->_options["sm_pr_auth"]=0.3; //Priority of author pages
  904. $this->_options["sm_pr_tags"]=0.3; //Priority of tags
  905. $this->_options["sm_i_donated"]=false; //Did you donate? Thank you! :)
  906. $this->_options["sm_i_hide_donated"]=false; //And hide the thank you..
  907. $this->_options["sm_i_install_date"]=time(); //The installation date
  908. $this->_options["sm_i_hide_note"]=false; //Hide the note which appears after 30 days
  909. $this->_options["sm_i_hide_donors"]=false; //Hide the list of donations
  910. }
  911. /**
  912. * Loads the configuration from the database
  913. *
  914. * @since 3.0
  915. * @access private
  916. * @author Arne Brachhold
  917. */
  918. function LoadOptions() {
  919. $this->InitOptions();
  920. //First init default values, then overwrite it with stored values so we can add default
  921. //values with an update which get stored by the next edit.
  922. $storedoptions=get_option("sm_options");
  923. if($storedoptions && is_array($storedoptions)) {
  924. foreach($storedoptions AS $k=>$v) {
  925. $this->_options[$k]=$v;
  926. }
  927. } else update_option("sm_options",$this->_options); //First time use, store default values
  928. }
  929. /**
  930. * Initializes a new Google Sitemap Generator
  931. *
  932. * @since 3.0
  933. * @access private
  934. * @author Arne Brachhold
  935. */
  936. function GoogleSitemapGenerator() {
  937. }
  938. /**
  939. * Returns the version of the generator
  940. *
  941. * @since 3.0
  942. * @access public
  943. * @author Arne Brachhold
  944. * @return int The version
  945. */
  946. function GetVersion() {
  947. return GoogleSitemapGeneratorLoader::GetVersion();
  948. }
  949. /**
  950. * Returns all parent classes of a class
  951. *
  952. * @param $className string The name of the class
  953. *
  954. * @since 3.0
  955. * @access private
  956. * @author Arne Brachhold
  957. * @return array An array which contains the names of the parent classes
  958. */
  959. function GetParentClasses($classname) {
  960. $parent = get_parent_class($classname);
  961. $parents = array();
  962. if (!empty($parent)) {
  963. $parents = $this->GetParentClasses($parent);
  964. $parents[] = strtolower($parent);
  965. }
  966. return $parents;
  967. }
  968. /**
  969. * Returns if a class is a subclass of another class
  970. *
  971. * @param $className string The name of the class
  972. * @param $$parentName string The name of the parent class
  973. *
  974. * @since 3.0
  975. * @access private
  976. * @author Arne Brachhold
  977. * @return bool true if the given class is a subclass of the other one
  978. */
  979. function IsSubclassOf($className, $parentName) {
  980. $className = strtolower($className);
  981. $parentName = strtolower($parentName);
  982. if(empty($className) || empty($parentName) || !class_exists($className) || !class_exists($parentName)) return false;
  983. $parents=$this->GetParentClasses($className);
  984. return in_array($parentName,$parents);
  985. }
  986. /**
  987. * Loads up the configuration and validates the prioity providers
  988. *
  989. * This method is only called if the sitemaps needs to be build or the admin page is displayed.
  990. *
  991. * @since 3.0
  992. * @access private
  993. * @author Arne Brachhold
  994. */
  995. function Initate() {
  996. if(!$this->_initiated) {
  997. //Loading language file...
  998. //load_plugin_textdomain('sitemap');
  999. //Hmm, doesn't work if the plugin file has its own directory.
  1000. //Let's make it our way... load_plugin_textdomain() searches only in the wp-content/plugins dir.
  1001. $currentLocale = get_locale();
  1002. if(!empty($currentLocale)) {
  1003. $moFile = dirname(__FILE__) . "/lang/sitemap-" . $currentLocale . ".mo";
  1004. if(@file_exists($moFile) && is_readable($moFile)) load_textdomain('sitemap', $moFile);
  1005. }
  1006. $this->_freqNames = array(
  1007. "always"=>__("Always","sitemap"),
  1008. "hourly"=>__("Hourly","sitemap"),
  1009. "daily"=>__("Daily","sitemap"),
  1010. "weekly"=>__("Weekly","sitemap"),
  1011. "monthly"=>__("Monthly","sitemap"),
  1012. "yearly"=>__("Yearly","sitemap"),
  1013. "never"=>__("Never","sitemap")
  1014. );
  1015. $this->LoadOptions();
  1016. $this->LoadPages();
  1017. //Register our own priority providers
  1018. add_filter("sm_add_prio_provider",array(&$this, 'AddDefaultPrioProviders'));
  1019. //Let other plugins register their providers
  1020. $r = apply_filters("sm_add_prio_provider",$this->_prioProviders);
  1021. //Check if no plugin return null
  1022. if($r != null) $this->_prioProviders = $r;
  1023. $this->ValidatePrioProviders();
  1024. $this->_initiated = true;
  1025. }
  1026. }
  1027. /**
  1028. * Returns the instance of the Sitemap Generator
  1029. *
  1030. * @since 3.0
  1031. * @access public
  1032. * @return GoogleSitemapGenerator The instance or null if not available.
  1033. * @author Arne Brachhold
  1034. */
  1035. function &GetInstance() {
  1036. if(isset($GLOBALS["sm_instance"])) {
  1037. return $GLOBALS["sm_instance"];
  1038. } else return null;
  1039. }
  1040. /**
  1041. * Returns if the sitemap building process is currently active
  1042. *
  1043. * @since 3.0
  1044. * @access public
  1045. * @return bool true if active
  1046. * @author Arne Brachhold
  1047. */
  1048. function IsActive() {
  1049. $inst = &GoogleSitemapGenerator::GetInstance();
  1050. return ($inst != null && $inst->_isActive);
  1051. }
  1052. /**
  1053. * Returns if the compressed sitemap was activated
  1054. *
  1055. * @since 3.0b8
  1056. * @access private
  1057. * @author Arne Brachhold
  1058. * @return true if compressed
  1059. */
  1060. function IsGzipEnabled() {
  1061. return ($this->GetOption("b_gzip")===true && function_exists("gzwrite"));
  1062. }
  1063. /**
  1064. * Returns if this version of WordPress supports the new taxonomy system
  1065. *
  1066. * @since 3.0b8
  1067. * @access private
  1068. * @author Arne Brachhold
  1069. * @return true if supported
  1070. */
  1071. function IsTaxonomySupported() {
  1072. return (function_exists("get_taxonomy") && function_exists("get_terms"));
  1073. }
  1074. /**
  1075. * Enables the Google Sitemap Generator and registers the WordPress hooks
  1076. *
  1077. * @since 3.0
  1078. * @access public
  1079. * @author Arne Brachhold
  1080. */
  1081. function Enable() {
  1082. if(!isset($GLOBALS["sm_instance"])) {
  1083. $GLOBALS["sm_instance"]=new GoogleSitemapGenerator();
  1084. }
  1085. }
  1086. /**
  1087. * Checks if sitemap building after content changed is enabled and rebuild the sitemap
  1088. *
  1089. * @param int $postID The ID of the post to handle. Used to avoid double rebuilding if more than one hook was fired.
  1090. * @since 3.0
  1091. * @access public
  1092. * @author Arne Brachhold
  1093. */
  1094. function CheckForAutoBuild($postID) {
  1095. global $wp_version;
  1096. $this->Initate();
  1097. //Build one time per post and if not importing.
  1098. if($this->GetOption("b_auto_enabled")===true && $this->_lastPostID != $postID && (!defined('WP_IMPORTING') || WP_IMPORTING != true)) {
  1099. //Build the sitemap directly or schedule it with WP cron
  1100. if($this->GetOption("b_auto_delay")==true && floatval($wp_version) >= 2.1) {
  1101. if(!$this->_isScheduled) {
  1102. //Schedule in 15 seconds, this should be enough to catch all changes.
  1103. //Clear all other existing hooks, so the sitemap is only built once.
  1104. wp_clear_scheduled_hook('sm_build_cron');
  1105. wp_schedule_single_event(time()+15,'sm_build_cron');
  1106. $this->_isScheduled = true;
  1107. }
  1108. } else {
  1109. //Build sitemap only once and never in bulk mode
  1110. if(!$this->_lastPostID && (!isset($_GET["delete"]) || count((array) $_GET['delete'])<=0)) {
  1111. $this->BuildSitemap();
  1112. }
  1113. }
  1114. $this->_lastPostID = $postID;
  1115. }
  1116. }
  1117. /**
  1118. * Checks if the rebuild request was send and starts to rebuilt the sitemap
  1119. *
  1120. * @since 3.0
  1121. * @access public
  1122. * @author Arne Brachhold
  1123. */
  1124. function CheckForManualBuild() {
  1125. if(!empty($_GET["sm_command"]) && !empty($_GET["sm_key"])) {
  1126. $this->Initate();
  1127. if($this->GetOption("b_manual_enabled")===true && $_GET["sm_command"]=="build" && $_GET["sm_key"]==$this->GetOption("b_manual_key")) {
  1128. $this->BuildSitemap();
  1129. echo "DONE";
  1130. exit;
  1131. }
  1132. }
  1133. }
  1134. /**
  1135. * Validates all given Priority Providers by checking them for required methods and existence
  1136. *
  1137. * @since 3.0
  1138. * @access private
  1139. * @author Arne Brachhold
  1140. */
  1141. function ValidatePrioProviders() {
  1142. $validProviders=array();
  1143. for($i=0; $i<count($this->_prioProviders); $i++) {
  1144. if(class_exists($this->_prioProviders[$i])) {
  1145. if($this->IsSubclassOf($this->_prioProviders[$i],"GoogleSitemapGeneratorPrioProviderBase")) {
  1146. array_push($validProviders,$this->_prioProviders[$i]);
  1147. }
  1148. }
  1149. }
  1150. $this->_prioProviders=$validProviders;
  1151. if(!$this->GetOption("b_prio_provider")) {
  1152. if(!in_array($this->GetOption("b_prio_provider"),$this->_prioProviders,true)) {
  1153. $this->SetOption("b_prio_provider","");
  1154. }
  1155. }
  1156. }
  1157. /**
  1158. * Adds the default Priority Providers to the provider list
  1159. *
  1160. * @since 3.0
  1161. * @access private
  1162. * @author Arne Brachhold
  1163. */
  1164. function AddDefaultPrioProviders($providers) {
  1165. array_push($providers,"GoogleSitemapGeneratorPrioByCountProvider");
  1166. array_push($providers,"GoogleSitemapGeneratorPrioByAverageProvider");
  1167. if(class_exists("ak_popularity_contest")) {
  1168. array_push($providers,"GoogleSitemapGeneratorPrioByPopularityContestProvider");
  1169. }
  1170. return $providers;
  1171. }
  1172. /**
  1173. * Loads the stored pages from the database
  1174. *
  1175. * @since 3.0
  1176. * @access private
  1177. * @author Arne Brachhold
  1178. */
  1179. function LoadPages() {
  1180. global $wpdb;
  1181. $needsUpdate=false;
  1182. $pagesString=$wpdb->get_var("SELECT option_value FROM $wpdb->options WHERE option_name = 'sm_cpages'");
  1183. //Class sm_page was renamed with 3.0 -> rename it in serialized value for compatibility
  1184. if(!empty($pagesString) && strpos($pagesString,"sm_page")!==false) {
  1185. $pagesString = str_replace("O:7:\"sm_page\"","O:26:\"GoogleSitemapGeneratorPage\"",$pagesString);
  1186. $needsUpdate=true;
  1187. }
  1188. if(!empty($pagesString)) {
  1189. $storedpages=unserialize($pagesString);
  1190. $this->_pages=$storedpages;
  1191. } else {
  1192. $this->_pages=array();
  1193. }
  1194. if($needsUpdate) $this->SavePages();
  1195. }
  1196. /**
  1197. * Saved the additional pages back to the database
  1198. *
  1199. * @since 3.0
  1200. * @access private
  1201. * @author Arne Brachhold
  1202. * @return true on success
  1203. */
  1204. function SavePages() {
  1205. $oldvalue = get_option("sm_cpages");
  1206. if($oldvalue == $this->_pages) {
  1207. return true;
  1208. } else {
  1209. delete_option("sm_cpages");
  1210. //Add the option, Note the autoload=false because when the autoload happens, our class GoogleSitemapGeneratorPage doesn't exist
  1211. add_option("sm_cpages",$this->_pages,"Storage for custom pages of the sitemap plugin","no");
  1212. return true;
  1213. }
  1214. }
  1215. /**
  1216. * Returns the URL for the sitemap file
  1217. *
  1218. * @since 3.0
  1219. * @access private
  1220. * @author Arne Brachhold
  1221. * @param bool $forceAuto Force the return value to the autodetected value.
  1222. * @return The URL to the Sitemap file
  1223. */
  1224. function GetXmlUrl($forceAuto=false) {
  1225. if(!$forceAuto && $this->GetOption("b_location_mode")=="manual") {
  1226. return $this->GetOption("b_fileurl_manual");
  1227. } else {
  1228. return trailingslashit(get_bloginfo('siteurl')). $this->GetOption("b_filename");
  1229. }
  1230. }
  1231. /**
  1232. * Returns the URL for the gzipped sitemap file
  1233. *
  1234. * @since 3.0
  1235. * @access private
  1236. * @author Arne Brachhold
  1237. * @param bool $forceAuto Force the return value to the autodetected value.
  1238. * @return The URL to the gzipped Sitemap file
  1239. */
  1240. function GetZipUrl($forceAuto=false) {
  1241. return $this->GetXmlUrl($forceAuto) . ".gz";
  1242. }
  1243. /**
  1244. * Returns the file system path to the sitemap file
  1245. *
  1246. * @since 3.0
  1247. * @access private
  1248. * @author Arne Brachhold
  1249. * @param bool $forceAuto Force the return value to the autodetected value.
  1250. * @return The file system path;
  1251. */
  1252. function GetXmlPath($forceAuto=false) {
  1253. if(!$forceAuto && $this->GetOption("b_location_mode")=="manual") {
  1254. return $this->GetOption("b_filename_manual");
  1255. } else {
  1256. return $this->GetHomePath() . $this->GetOption("b_filename");
  1257. }
  1258. }
  1259. /**
  1260. * Returns the file system path to the gzipped sitemap file
  1261. *
  1262. * @since 3.0
  1263. * @access private
  1264. * @author Arne Brachhold
  1265. * @param bool $forceAuto Force the return value to the autodetected value.
  1266. * @return The file system path;
  1267. */
  1268. function GetZipPath($forceAuto=false) {
  1269. return $this->GetXmlPath($forceAuto) . ".gz";
  1270. }
  1271. /**
  1272. * Returns the option value for the given key
  1273. *
  1274. * @since 3.0
  1275. * @access private
  1276. * @author Arne Brachhold
  1277. * @param $key string The Configuration Key
  1278. * @return mixed The value
  1279. */
  1280. function GetOption($key) {
  1281. $key="sm_" . $key;
  1282. if(array_key_exists($key,$this->_options)) {
  1283. return $this->_options[$key];
  1284. } else return null;
  1285. }
  1286. /**
  1287. * Sets an option to a new value
  1288. *
  1289. * @since 3.0
  1290. * @access private
  1291. * @author Arne Brachhold
  1292. * @param $key string The configuration key
  1293. * @param $value mixed The new object
  1294. */
  1295. function SetOption($key,$value) {
  1296. if(strstr($key,"sm_")!==0) $key="sm_" . $key;
  1297. $this->_options[$key]=$value;
  1298. }
  1299. /**
  1300. * Saves the options back to the database
  1301. *
  1302. * @since 3.0
  1303. * @access private
  1304. * @author Arne Brachhold
  1305. * @return bool true on success
  1306. */
  1307. function SaveOptions() {
  1308. $oldvalue = get_option("sm_options");
  1309. if($oldvalue == $this->_options) {
  1310. return true;
  1311. } else return update_option("sm_options",$this->_options);
  1312. }
  1313. /**
  1314. * Retrieves the number of comments of a post in a asso. array
  1315. * The key is the postID, the value the number of comments
  1316. *
  1317. * @since 3.0
  1318. * @access private
  1319. * @author Arne Brachhold
  1320. * @return array An array with postIDs and their comment count
  1321. */
  1322. function GetComments() {
  1323. global $wpdb;
  1324. $comments=array();
  1325. //Query comments and add them into the array
  1326. $commentRes=$wpdb->get_results("SELECT `comment_post_ID` as `post_id`, COUNT(comment_ID) as `comment_count` FROM `" . $wpdb->comments . "` WHERE `comment_approved`='1' GROUP BY `comment_post_ID`");
  1327. if($commentRes) {
  1328. foreach($commentRes as $comment) {
  1329. $comments[$comment->post_id]=$comment->comment_count;
  1330. }
  1331. }
  1332. return $comments;
  1333. }
  1334. /**
  1335. * Calculates the full number of comments from an sm_getComments() generated array
  1336. *
  1337. * @since 3.0
  1338. * @access private
  1339. * @author Arne Brachhold
  1340. * @param $comments array The Array with posts and c0mment count
  1341. * @see sm_getComments
  1342. * @return The full number of comments
  1343. */
  1344. function GetCommentCount($comments) {
  1345. $commentCount=0;
  1346. foreach($comments AS $k=>$v) {
  1347. $commentCount+=$v;
  1348. }
  1349. return $commentCount;
  1350. }
  1351. /**
  1352. * Adds a url to the sitemap. You can use this method or call AddElement directly.
  1353. *
  1354. * @since 3.0
  1355. * @access public
  1356. * @author Arne Brachhold
  1357. * @param $loc string The location (url) of the page
  1358. * @param $lastMod int The last Modification time as a UNIX timestamp
  1359. * @param $changeFreq string The change frequenty of the page, Valid values are "always", "hourly", "daily", "weekly", "monthly", "yearly" and "never".
  1360. * @param $priorty float The priority of the page, between 0.0 and 1.0
  1361. * @see AddElement
  1362. * @return string The URL node
  1363. */
  1364. function AddUrl($loc,$lastMod=0,$changeFreq="monthly",$priority=0.5) {
  1365. $page = new GoogleSitemapGeneratorPage($loc,$priority,$changeFreq,$lastMod);
  1366. $this->AddElement($page);
  1367. }
  1368. /**
  1369. * Adds an element to the sitemap
  1370. *
  1371. * @since 3.0
  1372. * @access private
  1373. * @author Arne Brachhold
  1374. * @param $page The element
  1375. */
  1376. function AddElement(&$page) {
  1377. if(empty($page)) return;
  1378. $s = $page->Render();
  1379. if($this->_fileZipHandle && $this->IsGzipEnabled()) {
  1380. gzwrite($this->_fileZipHandle,$s);
  1381. }
  1382. if($this->_fileHandle && $this->GetOption("b_xml")) {
  1383. fwrite($this->_fileHandle,$s);
  1384. }
  1385. }
  1386. /**
  1387. * Checks if a file is writable and tries to make it if not.
  1388. *
  1389. * @since 3.05b
  1390. * @access private
  1391. * @author VJTD3 <http://www.VJTD3.com>
  1392. * @return bool true if writable
  1393. */
  1394. function IsFileWritable($filename) {
  1395. //can we write?
  1396. if(!is_writable($filename)) {
  1397. //no we can't.
  1398. if(!@chmod($filename, 0666)) {
  1399. $pathtofilename = dirname($filename);
  1400. //Lets check if parent directory is writable.
  1401. if(!is_writable($pathtofilename)) {
  1402. //it's not writeable too.
  1403. if(!@chmod($pathtoffilename, 0666)) {
  1404. //darn couldn't fix up parrent directory this hosting is foobar.
  1405. //Lets error because of the permissions problems.
  1406. return false;
  1407. }
  1408. }
  1409. }
  1410. }
  1411. //we can write, return 1/true/happy dance.
  1412. return true;
  1413. }
  1414. function DoRobots() {
  1415. $this->Initate();
  1416. if($this->GetOption('b_robots') === true) {
  1417. $smUrl = $this->GetXmlUrl();
  1418. if($this->IsGzipEnabled()) {
  1419. $smUrl = $this->GetZipUrl();
  1420. }
  1421. echo "\nSitemap: " . $smUrl . "\n";
  1422. }
  1423. }
  1424. /**
  1425. * Builds the sitemap and writes it into a xml file.
  1426. *
  1427. * @since 3.0
  1428. * @access public
  1429. * @author Arne Brachhold <himself [at] arnebrachhold [dot] de>
  1430. * @return array An array with messages such as failed writes etc.
  1431. */
  1432. function BuildSitemap() {
  1433. global $wpdb, $posts, $wp_version;
  1434. $this->Initate();
  1435. if($this->GetOption("b_memory")!='') {
  1436. @ini_set("memory_limit",$this->GetOption("b_memory"));
  1437. }
  1438. if($this->GetOption("b_time")!=-1) {
  1439. @set_time_limit($this->GetOption("b_time"));
  1440. }
  1441. //This object saves the status information of the script directly to the database
  1442. $status = new GoogleSitemapGeneratorStatus();
  1443. //Other plugins can detect if the building process is active
  1444. $this->_isActive = true;
  1445. //$this->AddElement(new GoogleSitemapGeneratorXmlEntry());
  1446. //Debug mode?
  1447. $debug=$this->GetOption("b_debug");
  1448. if($this->GetOption("b_xml")) {
  1449. $fileName = $this->GetXmlPath();
  1450. $status->StartXml($this->GetXmlPath(),$this->GetXmlUrl());
  1451. if($this->IsFileWritable($fileName)) {
  1452. $this->_fileHandle = fopen($fileName,"w");
  1453. if(!$this->_fileHandle) $status->EndXml(false,"Not openable");
  1454. } else $status->EndXml(false,"not writable");
  1455. }
  1456. //Write gzipped sitemap file
  1457. if($this->IsGzipEnabled()) {
  1458. $fileName = $this->GetZipPath();
  1459. $status->StartZip($this->GetZipPath(),$this->GetZipUrl());
  1460. if($this->IsFileWritable($fileName)) {
  1461. $this->_fileZipHandle = gzopen($fileName,"w1");
  1462. if(!$this->_fileZipHandle) $status->EndZip(false,"Not openable");
  1463. } else $status->EndZip(false,"not writable");
  1464. }
  1465. if(!$this->_fileHandle && !$this->_fileZipHandle) {
  1466. $status->End();
  1467. return;
  1468. }
  1469. //Content of the XML file
  1470. $this->AddElement(new GoogleSitemapGeneratorXmlEntry('<?xml version="1.0" encoding="UTF-8"' . '?' . '>'));
  1471. $styleSheet = ($this->GetDefaultStyle() && $this->GetOption('b_style_default')===true?$this->GetDefaultStyle():$this->GetOption('b_style'));
  1472. if(!empty($styleSheet)) {
  1473. $this->AddElement(new GoogleSitemapGeneratorXmlEntry('<' . '?xml-stylesheet type="text/xsl" href="' . $styleSheet . '"?' . '>'));
  1474. }
  1475. $this->AddElement(new GoogleSitemapGeneratorDebugEntry("generator=\"wordpress/" . get_bloginfo('version') . "\""));
  1476. $this->AddElement(new GoogleSitemapGeneratorDebugEntry("sitemap-generator-url=\"http://www.arnebrachhold.de\" sitemap-generator-version=\"" . $this->GetVersion() . "\""));
  1477. $this->AddElement(new GoogleSitemapGeneratorDebugEntry("generated-on=\"" . date(get_option("date_format") . " " . get_option("time_format")) . "\""));
  1478. //All comments as an asso. Array (postID=>commentCount)
  1479. $comments=($this->GetOption("b_prio_provider")!=""?$this->GetComments():array());
  1480. //Full number of comments
  1481. $commentCount=(count($comments)>0?$this->GetCommentCount($comments):0);
  1482. if($debug && $this->GetOption("b_prio_provider")!="") {
  1483. $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Total comment count: " . $commentCount));
  1484. }
  1485. //Go XML!
  1486. $this->AddElement(new GoogleSitemapGeneratorXmlEntry('<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'));
  1487. $home = get_bloginfo('url');
  1488. //Add the home page (WITH a slash!)
  1489. if($this->GetOption("in_home")) {
  1490. $this->AddUrl(trailingslashit($home),$this->GetTimestampFromMySql(get_lastpostmodified('GMT')),$this->GetOption("cf_home"),$this->GetOption("pr_home"));
  1491. }
  1492. //Add the posts
  1493. if($this->GetOption("in_posts") || $this->GetOption("in_pages")) {
  1494. if($debug) $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Start Postings"));
  1495. //Pre 2.1 compatibility. 2.1 introduced 'future' as post…

Large files files are truncated, but you can click here to view the full file