PageRenderTime 81ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://bitbucket.org/openfarmtech/weblog-content
PHP | 2606 lines | 1599 code | 365 blank | 642 comment | 324 complexity | cbb6ba1814c51b469140adc2fcb4211b MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0, LGPL-2.0, LGPL-3.0, BSD-3-Clause, GPL-3.0, LGPL-2.1, AGPL-3.0, CC-BY-SA-3.0

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

  1. <?php
  2. /*
  3. $Id: sitemap-core.php 246875 2010-05-29 07:22:02Z 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","",null,"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 246875 2010-05-29 07:22:02Z 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( 'url' ) ) {
  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,null,"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('url')). $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...
  1462. //Remove the pages, revisions etc from the exclude by ca…

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