PageRenderTime 68ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

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

https://bitbucket.org/chileagil/website
PHP | 2606 lines | 1599 code | 365 blank | 642 comment | 325 complexity | 1a4dd73798991d6a04e92841f58f1a8c MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0, LGPL-2.1

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

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

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