/** * Builds the sitemap and writes it into a xml file. * * ATTENTION PLUGIN DEVELOPERS! DONT CALL THIS METHOD DIRECTLY! * The method is probably not available, since it is only loaded when needed. * Use do_action("sm_rebuild"); if you want to rebuild the sitemap. * Please refer to the documentation.txt for more details. * * @since 3.0 * @access public * @author Arne Brachhold <himself [at] arnebrachhold [dot] de> * @return array An array with messages such as failed writes etc. */ function BuildSitemap() { global $nxtdb, $posts, $nxt_version; $this->Initate(); if ($this->GetOption("b_memory") != '') { @ini_set("memory_limit", $this->GetOption("b_memory")); } if ($this->GetOption("b_time") != -1) { @set_time_limit($this->GetOption("b_time")); } //This object saves the status information of the script directly to the database $status = new GoogleSitemapGeneratorStatus(); //Other plugins can detect if the building process is active $this->_isActive = true; //$this->AddElement(new GoogleSitemapGeneratorXmlEntry()); //Debug mode? $debug = $this->GetOption("b_debug"); if ($this->GetOption("b_xml")) { $fileName = $this->GetXmlPath(); $status->StartXml($this->GetXmlPath(), $this->GetXmlUrl()); if ($this->IsFileWritable($fileName)) { $this->_fileHandle = fopen($fileName, "w"); if (!$this->_fileHandle) { $status->EndXml(false, "Not openable"); } } else { $status->EndXml(false, "not writable"); } } //Write gzipped sitemap file if ($this->IsGzipEnabled()) { $fileName = $this->GetZipPath(); $status->StartZip($this->GetZipPath(), $this->GetZipUrl()); if ($this->IsFileWritable($fileName)) { $this->_fileZipHandle = gzopen($fileName, "w1"); if (!$this->_fileZipHandle) { $status->EndZip(false, "Not openable"); } } else { $status->EndZip(false, "not writable"); } } if (!$this->_fileHandle && !$this->_fileZipHandle) { $status->End(); return; } //Content of the XML file $this->AddElement(new GoogleSitemapGeneratorXmlEntry('<?xml version="1.0" encoding="UTF-8"' . '?' . '>')); $styleSheet = $this->GetDefaultStyle() && $this->GetOption('b_style_default') === true ? $this->GetDefaultStyle() : $this->GetOption('b_style'); if (!empty($styleSheet)) { $this->AddElement(new GoogleSitemapGeneratorXmlEntry('<' . '?xml-stylesheet type="text/xsl" href="' . $styleSheet . '"?' . '>')); } $this->AddElement(new GoogleSitemapGeneratorDebugEntry("generator=\"nxtclass/" . get_bloginfo('version') . "\"")); $this->AddElement(new GoogleSitemapGeneratorDebugEntry("sitemap-generator-url=\"http://www.arnebrachhold.de\" sitemap-generator-version=\"" . $this->GetVersion() . "\"")); $this->AddElement(new GoogleSitemapGeneratorDebugEntry("generated-on=\"" . date(get_option("date_format") . " " . get_option("time_format")) . "\"")); //All comments as an asso. Array (postID=>commentCount) $comments = $this->GetOption("b_prio_provider") != "" ? $this->GetComments() : array(); //Full number of comments $commentCount = count($comments) > 0 ? $this->GetCommentCount($comments) : 0; if ($debug && $this->GetOption("b_prio_provider") != "") { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Total comment count: " . $commentCount)); } //Go XML! $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">')); $home = get_bloginfo('url'); $homePid = 0; // Load qTranslate settings require_once "sitemap-qtranslate.php"; $qt = qt_settings(); //Add the home page (WITH a slash!) if ($this->GetOption("in_home")) { if ('page' == get_option('show_on_front') && get_option('page_on_front')) { $pageOnFront = get_option('page_on_front'); $p = get_page($pageOnFront); if ($p) { $homePid = $p->ID; if (!$qt["enabled"]) { $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")); } qt_permalink($qt, trailingslashit($home), null, $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"), $this); } } else { if (!$qt["enabled"]) { $this->AddUrl(trailingslashit($home), $this->GetTimestampFromMySql(get_lastpostmodified('GMT')), $this->GetOption("cf_home"), $this->GetOption("pr_home")); } qt_permalink($qt, trailingslashit($home), null, get_lastpostmodified('GMT'), $this->GetOption("cf_home"), $this->GetOption("pr_home"), $this); } } //Add the posts if ($this->GetOption("in_posts") || $this->GetOption("in_pages")) { if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Start Postings")); } //Pre 2.1 compatibility. 2.1 introduced 'future' as post_status so we don't need to check post_date $nxtCompat = floatval($nxt_version) < 2.1; $excludes = $this->GetOption('b_exclude'); //Excluded posts and pages (user enetered ID) $exclCats = $this->GetOption("b_exclude_cats"); // Excluded cats if ($exclCats && count($exclCats) > 0 && $this->IsTaxonomySupported()) { $excludedCatPosts = get_objects_in_term($exclCats, "category"); // Get all posts in excl. cats. Unforttunately this also gives us pages, revisions and so on... //Remove the pages, revisions etc from the exclude by category list, because they are always in the uncategorized one. if (count($excludedCatPosts) > 0) { $exclPages = $nxtdb->get_col("SELECT ID FROM `" . $nxtdb->posts . "` WHERE post_type!='post' AND ID IN ('" . implode("','", $excludedCatPosts) . "')"); $exclPages = array_map('intval', $exclPages); //Remove the pages from the exlusion list before if (count($exclPages) > 0) { $excludedCatPosts = array_diff($excludedCatPosts, $exclPages); } //Merge the category exclusion list with the users one if (count($excludedCatPosts) > 0) { $excludes = array_merge($excludes, $excludedCatPosts); } } } $contentStmt = ''; if ($qt["enabled"]) { $contentStmt .= ', post_content '; } $postPageStmt = ''; $inSubPages = $this->GetOption('in_posts_sub') === true; if ($inSubPages && $this->GetOption('in_posts') === true) { $pageDivider = '<!--nextpage-->'; $postPageStmt = ", (character_length(`post_content`) - character_length(REPLACE(`post_content`, '{$pageDivider}', ''))) / " . strlen($pageDivider) . " as postPages"; } $sql = "SELECT `ID`, `post_author`, `post_date`, `post_date_gmt`, `post_status`, `post_name`, `post_modified`, `post_modified_gmt`, `post_parent`, `post_type` {$postPageStmt} {$contentStmt} FROM `" . $nxtdb->posts . "` WHERE "; $where = '('; if ($this->GetOption('in_posts')) { //nxt < 2.1: posts are post_status = publish //nxt >= 2.1: post_type must be 'post', no date check required because future posts are post_status='future' if ($nxtCompat) { $where .= "(post_status = 'publish' AND post_date_gmt <= '" . gmdate('Y-m-d H:i:59') . "')"; } else { if ($this->IsCustomPostTypesSupported() && count($this->GetOption('in_customtypes')) > 0) { $where .= " (post_status = 'publish' AND (post_type in ('','post'"; foreach ($this->GetOption('in_customtypes') as $customType) { $where .= ",'{$customType}'"; } $where .= "))) "; } else { $where .= " (post_status = 'publish' AND (post_type = 'post' OR post_type = '')) "; } } } if ($this->GetOption('in_pages')) { if ($this->GetOption('in_posts')) { $where .= " OR "; } if ($nxtCompat) { //nxt < 2.1: posts have post_status = published, pages have post_status = static $where .= " post_status='static' "; } else { //nxt >= 2.1: posts have post_type = 'post' and pages have post_type = 'page'. Both must be published. $where .= " (post_status = 'publish' AND post_type = 'page') "; } } $where .= ") "; if (is_array($excludes) && count($excludes) > 0) { $where .= " AND ID NOT IN ('" . implode("','", $excludes) . "')"; } $where .= " AND post_password='' ORDER BY post_modified DESC"; $sql .= $where; if ($this->GetOption("b_max_posts") > 0) { $sql .= " LIMIT 0," . $this->GetOption("b_max_posts"); } $postCount = intval($nxtdb->get_var("SELECT COUNT(*) AS cnt FROM `" . $nxtdb->posts . "` WHERE " . $where, 0, 0)); //Create a new connection because we are using mysql_unbuffered_query and don't want to disturb the nxt connection //Safe Mode for other plugins which use mysql_query() without a connection handler and will destroy our resultset :( $con = $postRes = null; //In 2.2, a bug which prevented additional DB connections was fixed if (floatval($nxt_version) < 2.2) { $this->SetOption("b_safemode", true); } if ($this->GetOption("b_safemode") === true) { $postRes = mysql_query($sql, $nxtdb->dbh); if (!$postRes) { trigger_error("MySQL query failed: " . mysql_error(), E_USER_NOTICE); //E_USER_NOTICE will be displayed on our debug mode return; } } else { $con = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD, true); if (!$con) { trigger_error("MySQL Connection failed: " . mysql_error(), E_USER_NOTICE); return; } if (!mysql_select_db(DB_NAME, $con)) { trigger_error("MySQL DB Select failed: " . mysql_error(), E_USER_NOTICE); return; } $postRes = mysql_unbuffered_query($sql, $con); if (!$postRes) { trigger_error("MySQL unbuffered query failed: " . mysql_error(), E_USER_NOTICE); return; } } if ($postRes) { //#type $prioProvider GoogleSitemapGeneratorPrioProviderBase $prioProvider = NULL; if ($this->GetOption("b_prio_provider") != '') { $providerClass = $this->GetOption('b_prio_provider'); $prioProvider = new $providerClass($commentCount, $postCount); } //$posts is used by Alex King's Popularity Contest plugin //if($posts == null || !is_array($posts)) { // $posts = &$postRes; //} $z = 1; $zz = 1; //Default priorities $default_prio_posts = $this->GetOption('pr_posts'); $default_prio_pages = $this->GetOption('pr_pages'); //Change frequencies $cf_pages = $this->GetOption('cf_pages'); $cf_posts = $this->GetOption('cf_posts'); $minPrio = $this->GetOption('pr_posts_min'); //Cycle through all posts and add them while ($post = mysql_fetch_object($postRes)) { //Fill the cache with our DB result. Since it's incomplete (no text-content for example), we will clean it later. $cache = array(&$post); update_post_cache($cache); //Set the current working post for other plugins which depend on "the loop" $GLOBALS['post'] =& $post; $permalink = get_permalink($post->ID); if ($permalink != $home && $post->ID != $homePid) { $isPage = false; if ($nxtCompat) { $isPage = $post->post_status == 'static'; } else { $isPage = $post->post_type == 'page'; } //Default Priority if auto calc is disabled $prio = 0; if ($isPage) { //Priority for static pages $prio = $default_prio_pages; } else { //Priority for normal posts $prio = $default_prio_posts; } //If priority calc. is enabled, calculate (but only for posts, not pages)! if ($prioProvider !== null && !$isPage) { //Comment count for this post $cmtcnt = isset($comments[$post->ID]) ? $comments[$post->ID] : 0; $prio = $prioProvider->GetPostPriority($post->ID, $cmtcnt, $post); if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry('Debug: Priority report of postID ' . $post->ID . ': Comments: ' . $cmtcnt . ' of ' . $commentCount . ' = ' . $prio . ' points')); } } if (!$isPage && $minPrio > 0 && $prio < $minPrio) { $prio = $minPrio; } //Add it if (!$qt["enabled"]) { $this->AddUrl($permalink, $this->GetTimestampFromMySql($post->post_modified_gmt && $post->post_modified_gmt != '0000-00-00 00:00:00' ? $post->post_modified_gmt : $post->post_date_gmt), $isPage ? $cf_pages : $cf_posts, $prio); } qt_permalink($qt, $permalink, $post->post_content, $post->post_modified_gmt && $post->post_modified_gmt != '0000-00-00 00:00:00' ? $post->post_modified_gmt : $post->post_date_gmt, $isPage ? $cf_pages : $cf_posts, $prio, $this); if ($inSubPages) { $subPage = ''; for ($p = 1; $p <= $post->postPages; $p++) { if (get_option('permalink_structure') == '') { $subPage = $permalink . '&page=' . ($p + 1); } else { $subPage = trailingslashit($permalink) . user_trailingslashit($p + 1, 'single_paged'); } if (!$qt["enabled"]) { $this->AddUrl($subPage, $this->GetTimestampFromMySql($post->post_modified_gmt && $post->post_modified_gmt != '0000-00-00 00:00:00' ? $post->post_modified_gmt : $post->post_date_gmt), $isPage ? $cf_pages : $cf_posts, $prio); } //qt_permalink($qt, $subPage, $post->post_content, ($post->post_modified_gmt && $post->post_modified_gmt!='0000-00-00 00:00:00'?$post->post_modified_gmt:$post->post_date_gmt), ($isPage?$cf_pages:$cf_posts), $prio, $this); } } } //Update the status every 100 posts and at the end. //If the script breaks because of memory or time limit, //we have a "last reponded" value which can be compared to the server settings if ($zz == 100 || $z == $postCount) { $status->SaveStep($z); $zz = 0; } else { $zz++; } $z++; //Clean cache because it's incomplete if (version_compare($nxt_version, "2.5", ">=")) { //nxt 2.5 makes a mysql query for every clean_post_cache to clear the child cache //so I've copied the function here until a patch arrives... nxt_cache_delete($post->ID, 'posts'); nxt_cache_delete($post->ID, 'post_meta'); clean_object_term_cache($post->ID, 'post'); } else { clean_post_cache($post->ID); } } unset($postRes); unset($prioProvider); if ($this->GetOption("b_safemode") !== true && $con) { mysql_close($con); } } if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: End Postings")); } } //Add the cats if ($this->GetOption("in_cats")) { if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Start Cats")); } $exclCats = $this->GetOption("b_exclude_cats"); // Excluded cats if ($exclCats == null) { $exclCats = array(); } if (!$this->IsTaxonomySupported()) { $catsRes = $nxtdb->get_results("\r\n\t\t\t\t\t\t\tSELECT\r\n\t\t\t\t\t\t\t\tc.cat_ID AS ID,\r\n\t\t\t\t\t\t\t\tMAX(p.post_modified_gmt) AS last_mod\r\n\t\t\t\t\t\t\tFROM\r\n\t\t\t\t\t\t\t\t`" . $nxtdb->categories . "` c,\r\n\t\t\t\t\t\t\t\t`" . $nxtdb->post2cat . "` pc,\r\n\t\t\t\t\t\t\t\t`" . $nxtdb->posts . "` p\r\n\t\t\t\t\t\t\tWHERE\r\n\t\t\t\t\t\t\t\tpc.category_id = c.cat_ID\r\n\t\t\t\t\t\t\t\tAND p.ID = pc.post_id\r\n\t\t\t\t\t\t\t\tAND p.post_status = 'publish'\r\n\t\t\t\t\t\t\t\tAND p.post_type='post'\r\n\t\t\t\t\t\t\tGROUP\r\n\t\t\t\t\t\t\t\tBY c.cat_id\r\n\t\t\t\t\t\t\t"); if ($catsRes) { foreach ($catsRes as $cat) { if ($cat && $cat->ID && $cat->ID > 0 && !in_array($cat->ID, $exclCats)) { if ($debug) { if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Cat-ID:" . $cat->ID)); } } if (!$qt["enabled"]) { $this->AddUrl(get_category_link($cat->ID), $this->GetTimestampFromMySql($cat->last_mod), $this->GetOption("cf_cats"), $this->GetOption("pr_cats")); } qt_permalink($qt, get_category_link($cat->ID), null, $cat->last_mod, $this->GetOption("cf_cats"), $this->GetOption("pr_cats"), $this); } } } } else { $cats = get_terms("category", array("hide_empty" => true, "hierarchical" => false)); if ($cats && is_array($cats) && count($cats) > 0) { foreach ($cats as $cat) { if (!in_array($cat->term_id, $exclCats)) { if (!$qt["enabled"]) { $this->AddUrl(get_category_link($cat->term_id), 0, $this->GetOption("cf_cats"), $this->GetOption("pr_cats")); } qt_permalink($qt, get_category_link($cat->term_id), null, 0, $this->GetOption("cf_cats"), $this->GetOption("pr_cats"), $this); } } } } if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: End Cats")); } } //Add the archives if ($this->GetOption("in_arch")) { if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Start Archive")); } $now = current_time('mysql'); //nxt2.1 introduced post_status='future', for earlier nxt versions we need to check the post_date_gmt $arcresults = $nxtdb->get_results("\r\n\t\t\t\t\t\tSELECT DISTINCT\r\n\t\t\t\t\t\t\tYEAR(post_date_gmt) AS `year`,\r\n\t\t\t\t\t\t\tMONTH(post_date_gmt) AS `month`,\r\n\t\t\t\t\t\t\tMAX(post_date_gmt) as last_mod,\r\n\t\t\t\t\t\t\tcount(ID) as posts\r\n\t\t\t\t\t\tFROM\r\n\t\t\t\t\t\t\t{$nxtdb->posts}\r\n\t\t\t\t\t\tWHERE\r\n\t\t\t\t\t\t\tpost_date < '{$now}'\r\n\t\t\t\t\t\t\tAND post_status = 'publish'\r\n\t\t\t\t\t\t\tAND post_type = 'post'\r\n\t\t\t\t\t\t\t" . (floatval($nxt_version) < 2.1 ? "AND {$nxtdb->posts}.post_date_gmt <= '" . gmdate('Y-m-d H:i:59') . "'" : "") . "\r\n\t\t\t\t\t\tGROUP BY\r\n\t\t\t\t\t\t\tYEAR(post_date_gmt),\r\n\t\t\t\t\t\t\tMONTH(post_date_gmt)\r\n\t\t\t\t\t\tORDER BY\r\n\t\t\t\t\t\t\tpost_date_gmt DESC"); if ($arcresults) { foreach ($arcresults as $arcresult) { $url = get_month_link($arcresult->year, $arcresult->month); $changeFreq = ""; //Archive is the current one if ($arcresult->month == date("n") && $arcresult->year == date("Y")) { $changeFreq = $this->GetOption("cf_arch_curr"); } else { // Archive is older $changeFreq = $this->GetOption("cf_arch_old"); } if (!$qt["enabled"]) { $this->AddUrl($url, $this->GetTimestampFromMySql($arcresult->last_mod), $changeFreq, $this->GetOption("pr_arch")); } qt_permalink($qt, $url, null, $arcresult->last_mod, $changeFreq, $this->GetOption("pr_arch"), $this); } } if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: End Archive")); } } //Add the author pages if ($this->GetOption("in_auth")) { if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Start Author pages")); } $linkFunc = null; //get_author_link is deprecated in nxt 2.1, try to use get_author_posts_url first. if (function_exists('get_author_posts_url')) { $linkFunc = 'get_author_posts_url'; } else { if (function_exists('get_author_link')) { $linkFunc = 'get_author_link'; } } //Who knows what happens in later nxt versions, so check again if it worked if ($linkFunc !== null) { //Unfortunately there is no API function to get all authors, so we have to do it the dirty way... //We retrieve only users with published and not password protected posts (and not pages) //nxt2.1 introduced post_status='future', for earlier nxt versions we need to check the post_date_gmt $sql = "SELECT DISTINCT\r\n\t\t\t\t\t\t\tu.ID,\r\n\t\t\t\t\t\t\tu.user_nicename,\r\n\t\t\t\t\t\t\tMAX(p.post_modified_gmt) AS last_post\r\n\t\t\t\t\t\tFROM\r\n\t\t\t\t\t\t\t{$nxtdb->users} u,\r\n\t\t\t\t\t\t\t{$nxtdb->posts} p\r\n\t\t\t\t\t\tWHERE\r\n\t\t\t\t\t\t\tp.post_author = u.ID\r\n\t\t\t\t\t\t\tAND p.post_status = 'publish'\r\n\t\t\t\t\t\t\tAND p.post_type = 'post'\r\n\t\t\t\t\t\t\tAND p.post_password = ''\r\n\t\t\t\t\t\t\t" . (floatval($nxt_version) < 2.1 ? "AND p.post_date_gmt <= '" . gmdate('Y-m-d H:i:59') . "'" : "") . "\r\n\t\t\t\t\t\tGROUP BY\r\n\t\t\t\t\t\t\tu.ID,\r\n\t\t\t\t\t\t\tu.user_nicename"; $authors = $nxtdb->get_results($sql); if ($authors && is_array($authors)) { foreach ($authors as $author) { if ($debug) { if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Author-ID:" . $author->ID)); } } $url = $linkFunc == 'get_author_posts_url' ? get_author_posts_url($author->ID, $author->user_nicename) : get_author_link(false, $author->ID, $author->user_nicename); if (!$qt["enabled"]) { $this->AddUrl($url, $this->GetTimestampFromMySql($author->last_post), $this->GetOption("cf_auth"), $this->GetOption("pr_auth")); } qt_permalink($qt, $url, null, $author->last_post, $this->GetOption("cf_auth"), $this->GetOption("pr_auth"), $this); } } } else { //Too bad, no author pages for you :( if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: No valid author link function found")); } } if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: End Author pages")); } } //Add tag pages if ($this->GetOption("in_tags") && $this->IsTaxonomySupported()) { if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Start Tags")); } $tags = get_terms("post_tag", array("hide_empty" => true, "hierarchical" => false)); if ($tags && is_array($tags) && count($tags) > 0) { foreach ($tags as $tag) { if (!$qt["enabled"]) { $this->AddUrl(get_tag_link($tag->term_id), 0, $this->GetOption("cf_tags"), $this->GetOption("pr_tags")); } qt_permalink($qt, get_tag_link($tag->term_id), null, 0, $this->GetOption("cf_tags"), $this->GetOption("pr_tags"), $this); } } if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: End Tags")); } } //Add custom taxonomy pages if ($this->GetOption("in_tax") && $this->IsTaxonomySupported()) { if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Start custom taxonomies")); } $enabledTaxonomies = $this->GetOption("in_tax"); $taxList = array(); foreach ($enabledTaxonomies as $taxName) { $taxonomy = get_taxonomy($taxName); if ($taxonomy) { $taxList[] = $nxtdb->escape($taxonomy->name); } } if (count($taxList) > 0) { //We're selecting all term information (t.*) plus some additional fields //like the last mod date and the taxonomy name, so nxt doesnt need to make //additional queries to build the permalink structure. //This does NOT work for categories and tags yet, because nxt uses get_category_link //and get_tag_link internally and that would cause one additional query per term! $sql = "\r\n\t\t\t\t\tSELECT\r\n\t\t\t\t\t\tt.*,\r\n\t\t\t\t\t\ttt.taxonomy AS _taxonomy,\r\n\t\t\t\t\t\tUNIX_TIMESTAMP(MAX(post_date_gmt)) as _mod_date\r\n\t\t\t\t\tFROM\r\n\t\t\t\t\t\t{$nxtdb->posts} p ,\r\n\t\t\t\t\t\t{$nxtdb->term_relationships} r,\r\n\t\t\t\t\t\t{$nxtdb->terms} t,\r\n\t\t\t\t\t\t{$nxtdb->term_taxonomy} tt\r\n\t\t\t\t\tWHERE\r\n\t\t\t\t\t\tp.ID = r.object_id\r\n\t\t\t\t\t\tAND p.post_status = 'publish'\r\n\t\t\t\t\t\tAND p.post_type = 'post'\r\n\t\t\t\t\t\tAND p.post_password = ''\r\n\t\t\t\t\t\tAND r.term_taxonomy_id = t.term_id\r\n\t\t\t\t\t\tAND t.term_id = tt.term_id\r\n\t\t\t\t\t\tAND tt.count > 0\r\n\t\t\t\t\t\tAND tt.taxonomy IN ('" . implode("','", $taxList) . "')\r\n\t\t\t\t\tGROUP BY\r\n\t\t\t\t\t\tt.term_id"; $termInfo = $nxtdb->get_results($sql); foreach ($termInfo as $term) { $this->AddUrl(get_term_link($term, $term->_taxonomy), $term->_mod_date, $this->GetOption("cf_tags"), $this->GetOption("pr_tags")); } } if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: End custom taxonomies")); } } //Add the custom pages if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Start Custom Pages")); } if ($this->_pages && is_array($this->_pages) && count($this->_pages) > 0) { //#type $page GoogleSitemapGeneratorPage foreach ($this->_pages as $page) { $this->AddUrl($page->GetUrl(), $page->getLastMod(), $page->getChangeFreq(), $page->getPriority()); } } if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: End Custom Pages")); } if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Start additional URLs")); } do_action('sm_buildmap'); if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: End additional URLs")); } $this->AddElement(new GoogleSitemapGeneratorXmlEntry("</urlset>")); $pingUrl = ''; if ($this->GetOption("b_xml")) { if ($this->_fileHandle && fclose($this->_fileHandle)) { $this->_fileHandle = null; $status->EndXml(true); $pingUrl = $this->GetXmlUrl(); } else { $status->EndXml(false, "Could not close the sitemap file."); } } if ($this->IsGzipEnabled()) { if ($this->_fileZipHandle && fclose($this->_fileZipHandle)) { $this->_fileZipHandle = null; $status->EndZip(true); $pingUrl = $this->GetZipUrl(); } else { $status->EndZip(false, "Could not close the zipped sitemap file"); } } //Ping Google if ($this->GetOption("b_ping") && !empty($pingUrl)) { $sPingUrl = "http://www.google.com/webmasters/sitemaps/ping?sitemap=" . urlencode($pingUrl); $status->StartGooglePing($sPingUrl); $pingres = $this->RemoteOpen($sPingUrl); if ($pingres == NULL || $pingres === false) { $status->EndGooglePing(false, $this->_lastError); trigger_error("Failed to ping Google: " . htmlspecialchars(strip_tags($pingres)), E_USER_NOTICE); } else { $status->EndGooglePing(true); } } //Ping Ask.com if ($this->GetOption("b_pingask") && !empty($pingUrl)) { $sPingUrl = "http://submissions.ask.com/ping?sitemap=" . urlencode($pingUrl); $status->StartAskPing($sPingUrl); $pingres = $this->RemoteOpen($sPingUrl); if ($pingres == NULL || $pingres === false || strpos($pingres, "successfully received and added") === false) { //Ask.com returns 200 OK even if there was an error, so we need to check the content. $status->EndAskPing(false, $this->_lastError); trigger_error("Failed to ping Ask.com: " . htmlspecialchars(strip_tags($pingres)), E_USER_NOTICE); } else { $status->EndAskPing(true); } } //Ping Bing if ($this->GetOption("b_pingmsn") && !empty($pingUrl)) { $sPingUrl = "http://www.bing.com/webmaster/ping.aspx?siteMap=" . urlencode($pingUrl); $status->StartMsnPing($sPingUrl); $pingres = $this->RemoteOpen($sPingUrl); //Bing returns ip/country-based success messages, so there is no way to check the content. Rely on HTTP 500 only then... if ($pingres == NULL || $pingres === false || strpos($pingres, " ") === false) { trigger_error("Failed to ping Bing: " . htmlspecialchars(strip_tags($pingres)), E_USER_NOTICE); $status->EndMsnPing(false, $this->_lastError); } else { $status->EndMsnPing(true); } } $status->End(); $this->_isActive = false; //done... return $status; }
/** * Builds the sitemap and writes it into a xml file. * * @since 3.0 * @access public * @author Arne Brachhold <himself [at] arnebrachhold [dot] de> * @return array An array with messages such as failed writes etc. */ function BuildSitemap() { global $wpdb, $posts, $wp_version; $this->Initate(); if ($this->GetOption("b_memory") != '') { @ini_set("memory_limit", $this->GetOption("b_memory")); } if ($this->GetOption("sm_b_time") != -1) { @set_time_limit($this->GetOption("sm_b_time")); } //This object saves the status information of the script directly to the database $status = new GoogleSitemapGeneratorStatus(); //Other plugins can detect if the building process is active $this->_isActive = true; //$this->AddElement(new GoogleSitemapGeneratorXmlEntry()); //Debug mode? $debug = $this->GetOption("b_debug"); if ($this->GetOption("b_xml")) { $fileName = $this->GetXmlPath(); $status->StartXml($this->GetXmlPath(), $this->GetXmlUrl()); if ($this->IsFileWritable($fileName)) { $this->_fileHandle = fopen($fileName, "w"); if (!$this->_fileHandle) { $status->EndXml(false, "Not openable"); } } else { $status->EndXml(false, "not writable"); } } //Write gzipped sitemap file if ($this->IsGzipEnabled()) { $fileName = $this->GetZipPath(); $status->StartZip($this->GetZipPath(), $this->GetZipUrl()); if ($this->IsFileWritable($fileName)) { $this->_fileZipHandle = gzopen($fileName, "w1"); if (!$this->_fileZipHandle) { $status->EndZip(false, "Not openable"); } } else { $status->EndZip(false, "not writable"); } } if (!$this->_fileHandle && !$this->_fileZipHandle) { $status->End(); return; } //Content of the XML file $this->AddElement(new GoogleSitemapGeneratorXmlEntry('<?xml version="1.0" encoding="UTF-8"' . '?' . '>')); if ($this->GetOption("b_style") != '') { $this->AddElement(new GoogleSitemapGeneratorXmlEntry('<' . '?xml-stylesheet type="text/xsl" href="' . $this->GetOption("b_style") . '"?' . '>')); } $this->AddElement(new GoogleSitemapGeneratorDebugEntry("generator=\"wordpress/" . get_bloginfo('version') . "\"")); $this->AddElement(new GoogleSitemapGeneratorDebugEntry("sitemap-generator-url=\"http://www.arnebrachhold.de\" sitemap-generator-version=\"" . $this->GetVersion() . "\"")); $this->AddElement(new GoogleSitemapGeneratorDebugEntry("generated-on=\"" . date(get_option("date_format") . " " . get_option("time_format")) . "\"")); //All comments as an asso. Array (postID=>commentCount) $comments = $this->GetOption("b_prio_provider") != "" ? $this->GetComments() : array(); //Full number of comments $commentCount = count($comments) > 0 ? $this->GetCommentCount($comments) : 0; if ($debug && $this->GetOption("b_prio_provider") != "") { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Total comment count: " . $commentCount)); } //Go XML! $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">')); $home = get_bloginfo('url'); //Add the home page (WITH a slash!) if ($this->GetOption("in_home")) { $this->AddUrl(trailingslashit($home), $this->GetTimestampFromMySql(get_lastpostmodified('GMT')), $this->GetOption("cf_home"), $this->GetOption("pr_home")); } //Add the posts if ($this->GetOption("in_posts") || $this->GetOption("in_pages")) { if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Start Postings")); } //Pre 2.1 compatibility. 2.1 introduced 'future' as post_status so we don't need to check post_date $wpCompat = floatval($wp_version) < 2.1; $sql = "SELECT `ID`, `post_author`, `post_date`, `post_date_gmt`, `post_status`, `post_name`, `post_modified`, `post_modified_gmt`, `post_parent`, `post_type` FROM `" . $wpdb->posts . "` WHERE "; $where = '('; if ($this->GetOption('in_posts')) { //WP < 2.1: posts are post_status = publish //WP >= 2.1: post_type must be 'post', no date check required because future posts are post_status='future' if ($wpCompat) { $where .= "(post_status = 'publish' AND post_date_gmt <= '" . gmdate('Y-m-d H:i:59') . "')"; } else { $where .= " (post_status = 'publish' AND (post_type = 'post' OR post_type = '')) "; } } if ($this->GetOption('in_pages')) { if ($this->GetOption('in_posts')) { $where .= " OR "; } if ($wpCompat) { //WP < 2.1: posts have post_status = published, pages have post_status = static $where .= " post_status='static' "; } else { //WP >= 2.1: posts have post_type = 'post' and pages have post_type = 'page'. Both must be published. $where .= " (post_status = 'publish' AND post_type = 'page') "; } } $where .= ") "; $excludes = $this->GetOption('b_exclude'); if (is_array($excludes) && count($excludes) > 0) { $where .= " AND ID NOT IN ('" . implode("','", $excludes) . "')"; } $where .= " AND post_password='' ORDER BY post_modified DESC"; $sql .= $where; if ($this->GetOption("sm_b_max_posts") > 0) { $sql .= " LIMIT 0," . $this->GetOption("sm_b_max_posts"); } $postCount = intval($wpdb->get_var("SELECT COUNT(*) AS cnt FROM `" . $wpdb->posts . "` WHERE " . $where, 0, 0)); //Create a new connection because we are using mysql_unbuffered_query and don't want to disturb the WP connection //Safe Mode for other plugins which use mysql_query() without a connection handler and will destroy our resultset :( $con = $postRes = null; if ($this->GetOption("b_safemode") === true) { $postRes = mysql_query($sql, $wpdb->dbh); if (!$postRes) { trigger_error("MySQL query failed: " . mysql_error(), E_USER_NOTICE); //E_NOTE will be displayed on our debug mode return; } } else { $con = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD, true); if (!$con) { trigger_error("MySQL Connection failed: " . mysql_error(), E_USER_NOTICE); return; } if (!mysql_select_db(DB_NAME, $con)) { trigger_error("MySQL DB Select failed: " . mysql_error(), E_USER_NOTICE); return; } $postRes = mysql_unbuffered_query($sql, $con); if (!$postRes) { trigger_error("MySQL unbuffered query failed: " . mysql_error(), E_USER_NOTICE); return; } } if ($postRes) { //#type $prioProvider GoogleSitemapGeneratorPrioProviderBase $prioProvider = NULL; if ($this->GetOption("b_prio_provider") != '') { $providerClass = $this->GetOption('b_prio_provider'); $prioProvider = new $providerClass($commentCount, $postCount); } //$posts is used by Alex King's Popularity Contest plugin //if($posts == null || !is_array($posts)) { // $posts = &$postRes; //} $z = 1; $zz = 1; //Default priorities $default_prio_posts = $this->GetOption('pr_posts'); $default_prio_pages = $this->GetOption('pr_pages'); //Change frequencies $cf_pages = $this->GetOption('sm_cf_pages'); $cf_posts = $this->GetOption('sm_cf_posts'); $minPrio = $this->GetOption('pr_posts_min'); //Cycle through all posts and add them while ($post = mysql_fetch_object($postRes)) { //Fill the cache with our DB result. Since it's incomplete (no text-content for example), we will clean it later. $cache = array(&$post); update_post_cache($cache); $permalink = get_permalink($post->ID); if ($permalink != $home) { $isPage = false; if ($wpCompat) { $isPage = $post->post_status == 'static'; } else { $isPage = $post->post_type == 'page'; } //Set the current working post $GLOBALS['post'] =& $post; //Default Priority if auto calc is disabled $prio = 0; if ($isPage) { //Priority for static pages $prio = $default_prio_pages; } else { //Priority for normal posts $prio = $default_prio_posts; } //If priority calc. is enabled, calculate (but only for posts, not pages)! if ($prioProvider !== null && !$isPage) { //Comment count for this post $cmtcnt = isset($comments[$post->ID]) ? $comments[$post->ID] : 0; $prio = $prioProvider->GetPostPriority($post->ID, $cmtcnt); if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry('Debug: Priority report of postID ' . $post->ID . ': Comments: ' . $cmtcnt . ' of ' . $commentCount . ' = ' . $prio . ' points')); } } if (!$isPage && $minPrio > 0 && $prio < $minPrio) { $prio = $minPrio; } //Add it $this->AddUrl($permalink, $this->GetTimestampFromMySql($post->post_modified_gmt && $post->post_modified_gmt != '0000-00-00 00:00:00' ? $post->post_modified_gmt : $post->post_date_gmt), $isPage ? $cf_pages : $cf_posts, $prio); } //Update the status every 100 posts and at the end. //If the script breaks because of memory or time limit, //we have a "last reponded" value which can be compared to the server settings if ($zz == 100 || $z == $postCount) { $status->SaveStep($z); $zz = 0; } else { $zz++; } $z++; //Clean cache because it's incomplete clean_post_cache($post->ID); } unset($postRes); unset($prioProvider); if ($this->GetOption("b_safemode") !== true && $con) { mysql_close($con); } } if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: End Postings")); } } //Add the cats if ($this->GetOption("in_cats")) { if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Start Cats")); } if (!$this->IsTaxonomySupported()) { $catsRes = $wpdb->get_results("\r\n\t\t\t\t\t\t\tSELECT \r\n\t\t\t\t\t\t\t\tc.cat_ID AS ID, \r\n\t\t\t\t\t\t\t\tMAX(p.post_modified_gmt) AS last_mod \r\n\t\t\t\t\t\t\tFROM \r\n\t\t\t\t\t\t\t\t`" . $wpdb->categories . "` c,\r\n\t\t\t\t\t\t\t\t`" . $wpdb->post2cat . "` pc,\r\n\t\t\t\t\t\t\t\t`" . $wpdb->posts . "` p\r\n\t\t\t\t\t\t\tWHERE\r\n\t\t\t\t\t\t\t\tpc.category_id = c.cat_ID\r\n\t\t\t\t\t\t\t\tAND p.ID = pc.post_id\r\n\t\t\t\t\t\t\t\tAND p.post_status = 'publish'\r\n\t\t\t\t\t\t\t\tAND p.post_type='post'\r\n\t\t\t\t\t\t\tGROUP\r\n\t\t\t\t\t\t\t\tBY c.cat_id\r\n\t\t\t\t\t\t\t"); if ($catsRes) { foreach ($catsRes as $cat) { if ($cat && $cat->ID && $cat->ID > 0) { if ($debug) { if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Cat-ID:" . $cat->ID)); } } $this->AddUrl(get_category_link($cat->ID), $this->GetTimestampFromMySql($cat->last_mod), $this->GetOption("cf_cats"), $this->GetOption("pr_cats")); } } } } else { $cats = get_terms("category", array("hide_empty" => true, "hierarchical" => false)); if ($cats && is_array($cats) && count($cats) > 0) { foreach ($cats as $cat) { $this->AddUrl(get_category_link($cat->term_id), 0, $this->GetOption("cf_cats"), $this->GetOption("pr_cats")); } } } if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: End Cats")); } } //Add the archives if ($this->GetOption("in_arch")) { if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Start Archive")); } $now = current_time('mysql'); //WP2.1 introduced post_status='future', for earlier WP versions we need to check the post_date_gmt $arcresults = $wpdb->get_results("\r\n\t\t\t\t\t\tSELECT DISTINCT \r\n\t\t\t\t\t\t\tYEAR(post_date_gmt) AS `year`, \r\n\t\t\t\t\t\t\tMONTH(post_date_gmt) AS `month`, \r\n\t\t\t\t\t\t\tMAX(post_date_gmt) as last_mod, \r\n\t\t\t\t\t\t\tcount(ID) as posts \r\n\t\t\t\t\t\tFROM \r\n\t\t\t\t\t\t\t{$wpdb->posts} \r\n\t\t\t\t\t\tWHERE \r\n\t\t\t\t\t\t\tpost_date < '{$now}' \r\n\t\t\t\t\t\t\tAND post_status = 'publish' \r\n\t\t\t\t\t\t\tAND post_type = 'post'\r\n\t\t\t\t\t\t\t" . (floatval($wp_version) < 2.1 ? "AND {$wpdb->posts}.post_date_gmt <= '" . gmdate('Y-m-d H:i:59') . "'" : "") . "\r\n\t\t\t\t\t\tGROUP BY \r\n\t\t\t\t\t\t\tYEAR(post_date_gmt), \r\n\t\t\t\t\t\t\tMONTH(post_date_gmt) \r\n\t\t\t\t\t\tORDER BY \r\n\t\t\t\t\t\t\tpost_date_gmt DESC"); if ($arcresults) { foreach ($arcresults as $arcresult) { $url = get_month_link($arcresult->year, $arcresult->month); $changeFreq = ""; //Archive is the current one if ($arcresult->month == date("n") && $arcresult->year == date("Y")) { $changeFreq = $this->GetOption("cf_arch_curr"); } else { // Archive is older $changeFreq = $this->GetOption("cf_arch_old"); } $this->AddUrl($url, $this->GetTimestampFromMySql($arcresult->last_mod), $changeFreq, $this->GetOption("pr_arch")); } } if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: End Archive")); } } //Add the author pages if ($this->GetOption("in_auth")) { if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Start Author pages")); } $linkFunc = null; //get_author_link is deprecated in WP 2.1, try to use get_author_posts_url first. if (function_exists('get_author_posts_url')) { $linkFunc = 'get_author_posts_url'; } else { if (function_exists('get_author_link')) { $linkFunc = 'get_author_link'; } } //Who knows what happens in later WP versions, so check again if it worked if ($linkFunc !== null) { //Unfortunately there is no API function to get all authors, so we have to do it the dirty way... //We retrieve only users with published and not password protected posts (and not pages) //WP2.1 introduced post_status='future', for earlier WP versions we need to check the post_date_gmt $sql = "SELECT DISTINCT \r\n\t\t\t\t\t\t\t{$wpdb->users}.ID, \r\n\t\t\t\t\t\t\t{$wpdb->users}.user_nicename, \r\n\t\t\t\t\t\t\tMAX({$wpdb->posts}.post_modified_gmt) AS last_post \r\n\t\t\t\t\t\tFROM \r\n\t\t\t\t\t\t\t{$wpdb->users}, \r\n\t\t\t\t\t\t\t{$wpdb->posts} \r\n\t\t\t\t\t\tWHERE \r\n\t\t\t\t\t\t\t{$wpdb->posts}.post_author = {$wpdb->posts}.ID \r\n\t\t\t\t\t\t\tAND {$wpdb->posts}.post_status = 'publish'\r\n\t\t\t\t\t\t\tAND {$wpdb->posts}.post_type = 'post' \r\n\t\t\t\t\t\t\tAND {$wpdb->posts}.post_password = '' \r\n\t\t\t\t\t\t\t" . (floatval($wp_version) < 2.1 ? "AND {$wpdb->posts}.post_date_gmt <= '" . gmdate('Y-m-d H:i:59') . "'" : "") . "\r\n\t\t\t\t\t\tGROUP BY \r\n\t\t\t\t\t\t\t{$wpdb->posts}.ID, \r\n\t\t\t\t\t\t\t{$wpdb->users}.user_nicename"; $authors = $wpdb->get_results($sql); if ($authors && is_array($authors)) { foreach ($authors as $author) { if ($debug) { if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Author-ID:" . $author->ID)); } } $url = $linkFunc == 'get_author_posts_url' ? get_author_posts_url($author->ID, $author->user_nicename) : get_author_link(false, $author->ID, $author->user_nicename); $this->AddUrl($url, $this->GetTimestampFromMySql($author->last_post), $this->GetOption("cf_auth"), $this->GetOption("pr_auth")); } } } else { //Too bad, no author pages for you :( if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: No valid author link function found")); } } if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: End Author pages")); } } //Add tag pages if ($this->GetOption("in_tags") && $this->IsTaxonomySupported()) { if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Start Tags")); } $tags = get_terms("post_tag", array("hide_empty" => true, "hierarchical" => false)); if ($tags && is_array($tags) && count($tags) > 0) { foreach ($tags as $tag) { $this->AddUrl(get_tag_link($tag->term_id), 0, $this->GetOption("cf_tags"), $this->GetOption("pr_tags")); } } if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: End Tags")); } } //Add the custom pages if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Start Custom Pages")); } if ($this->_pages && is_array($this->_pages) && count($this->_pages) > 0) { //#type $page GoogleSitemapGeneratorPage foreach ($this->_pages as $page) { $this->AddUrl($page->GetUrl(), $page->getLastMod(), $page->getChangeFreq(), $page->getPriority()); } } if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: End Custom Pages")); } if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: Start additional URLs")); } do_action("sm_buildmap"); if ($debug) { $this->AddElement(new GoogleSitemapGeneratorDebugEntry("Debug: End additional URLs")); } $this->AddElement(new GoogleSitemapGeneratorXmlEntry("</urlset>")); $pingUrl = ''; if ($this->GetOption("b_xml")) { if ($this->_fileHandle && fclose($this->_fileHandle)) { $this->_fileHandle = null; $status->EndXml(true); $pingUrl = $this->GetXmlUrl(); } else { $status->EndXml(false, "Could not close the sitemap file."); } } if ($this->IsGzipEnabled()) { if ($this->_fileZipHandle && fclose($this->_fileZipHandle)) { $this->_fileZipHandle = null; $status->EndZip(true); $pingUrl = $this->GetZipUrl(); } else { $status->EndZip(false, "Could not close the zipped sitemap file"); } } //Ping Google if ($this->GetOption("b_ping") && !empty($pingUrl)) { $sPingUrl = "http://www.google.com/webmasters/sitemaps/ping?sitemap=" . urlencode($pingUrl); $status->StartGooglePing($sPingUrl); $pingres = $this->RemoteOpen($sPingUrl); if ($pingres == NULL || $pingres === false) { $status->EndGooglePing(false, $this->_lastError); } else { $status->EndGooglePing(true); } } //Ping Ask.com if ($this->GetOption("b_pingask") && !empty($pingUrl)) { $sPingUrl = "http://submissions.ask.com/ping?sitemap=" . urlencode($pingUrl); $status->StartAskPing($sPingUrl); $pingres = $this->RemoteOpen($sPingUrl); if ($pingres == NULL || $pingres === false || strpos($pingres, "successfully received and added") === false) { //Ask.com returns 200 OK even if there was an error, so we need to check the content. $status->EndAskPing(false, $this->_lastError); } else { $status->EndAskPing(true); } } //Ping YAHOO if ($this->GetOption("sm_b_pingyahoo") === true && $this->GetOption("sm_b_yahookey") != "" && !empty($pingUrl)) { $sPingUrl = "http://search.yahooapis.com/SiteExplorerService/V1/updateNotification?appid=" . $this->GetOption("sm_b_yahookey") . "&url=" . urlencode($pingUrl); $status->StartYahooPing($sPingUrl); $pingres = $this->RemoteOpen($sPingUrl); if ($pingres == NULL || $pingres === false || strpos(strtolower($pingres), "success") === false) { $status->EndYahooPing(false, $this->_lastError); } else { $status->EndYahooPing(true); } } //Ping MSN if ($this->GetOption("b_pingmsn") && !empty($pingUrl)) { $sPingUrl = "http://webmaster.live.com/ping.aspx?siteMap=" . urlencode($pingUrl); $status->StartMsnPing($sPingUrl); $pingres = $this->RemoteOpen($sPingUrl); if ($pingres == NULL || $pingres === false || strpos($pingres, "Thanks for submitting your sitemap") === false) { $status->EndMsnPing(false, $this->_lastError); } else { $status->EndMsnPing(true); } } $status->End(); $this->_isActive = false; //done... return $status; }