| Current Path : /home/x/b/o/xbodynamge/namtation/wp-content/ |
| Current File : /home/x/b/o/xbodynamge/namtation/wp-content/Content.php.tar |
home/xbodynamge/namtation/wp-content/plugins/all-in-one-seo-pack/app/Common/Sitemap/Content.php 0000644 00000074527 15112700446 0026611 0 ustar 00 <?php
namespace AIOSEO\Plugin\Common\Sitemap;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\Plugin\Common\Integrations\BuddyPress as BuddyPressIntegration;
/**
* Determines which content should be included in the sitemap.
*
* @since 4.0.0
*/
class Content {
/**
* Returns the entries for the requested sitemap.
*
* @since 4.0.0
*
* @return array The sitemap entries.
*/
public function get() {
if ( ! in_array( aioseo()->sitemap->type, [ 'general', 'rss' ], true ) || ! $this->isEnabled() ) {
return [];
}
if ( 'rss' === aioseo()->sitemap->type ) {
return $this->rss();
}
if ( 'general' !== aioseo()->sitemap->type ) {
return [];
}
$indexesEnabled = aioseo()->options->sitemap->general->indexes;
if ( ! $indexesEnabled ) {
if ( 'root' === aioseo()->sitemap->indexName ) {
// If indexes are disabled, throw all entries together into one big file.
return $this->nonIndexed();
}
return [];
}
if ( 'root' === aioseo()->sitemap->indexName ) {
return aioseo()->sitemap->root->indexes();
}
// Check if requested index has a dedicated method.
$methodName = aioseo()->helpers->dashesToCamelCase( aioseo()->sitemap->indexName );
if ( method_exists( $this, $methodName ) ) {
return $this->$methodName();
}
// Check if requested index is a registered post type.
if ( in_array( aioseo()->sitemap->indexName, aioseo()->sitemap->helpers->includedPostTypes(), true ) ) {
return $this->posts( aioseo()->sitemap->indexName );
}
// Check if requested index is a registered taxonomy.
if (
in_array( aioseo()->sitemap->indexName, aioseo()->sitemap->helpers->includedTaxonomies(), true ) &&
'product_attributes' !== aioseo()->sitemap->indexName
) {
return $this->terms( aioseo()->sitemap->indexName );
}
if (
aioseo()->helpers->isWooCommerceActive() &&
in_array( aioseo()->sitemap->indexName, aioseo()->sitemap->helpers->includedTaxonomies(), true ) &&
'product_attributes' === aioseo()->sitemap->indexName
) {
return $this->productAttributes();
}
return [];
}
/**
* Returns the total entries number for the requested sitemap.
*
* @since 4.1.5
*
* @return int The total entries number.
*/
public function getTotal() {
if ( ! in_array( aioseo()->sitemap->type, [ 'general', 'rss' ], true ) || ! $this->isEnabled() ) {
return 0;
}
if ( 'rss' === aioseo()->sitemap->type ) {
return count( $this->rss() );
}
if ( 'general' !== aioseo()->sitemap->type ) {
return 0;
}
$indexesEnabled = aioseo()->options->sitemap->general->indexes;
if ( ! $indexesEnabled ) {
if ( 'root' === aioseo()->sitemap->indexName ) {
// If indexes are disabled, throw all entries together into one big file.
return count( $this->nonIndexed() );
}
return 0;
}
if ( 'root' === aioseo()->sitemap->indexName ) {
return count( aioseo()->sitemap->root->indexes() );
}
// Check if requested index has a dedicated method.
$methodName = aioseo()->helpers->dashesToCamelCase( aioseo()->sitemap->indexName );
if ( method_exists( $this, $methodName ) ) {
$res = $this->$methodName();
return ! empty( $res ) ? count( $res ) : 0;
}
// Check if requested index is a registered post type.
if ( in_array( aioseo()->sitemap->indexName, aioseo()->sitemap->helpers->includedPostTypes(), true ) ) {
return aioseo()->sitemap->query->posts( aioseo()->sitemap->indexName, [ 'count' => true ] );
}
// Check if requested index is a registered taxonomy.
if ( in_array( aioseo()->sitemap->indexName, aioseo()->sitemap->helpers->includedTaxonomies(), true ) ) {
return aioseo()->sitemap->query->terms( aioseo()->sitemap->indexName, [ 'count' => true ] );
}
return 0;
}
/**
* Checks if the requested sitemap is enabled.
*
* @since 4.0.0
*
* @return boolean Whether the sitemap is enabled.
*/
public function isEnabled() {
$options = aioseo()->options->noConflict();
if ( ! $options->sitemap->{aioseo()->sitemap->type}->enable ) {
return false;
}
if ( $options->sitemap->{aioseo()->sitemap->type}->postTypes->all ) {
return true;
}
$included = aioseo()->sitemap->helpers->includedPostTypes();
return ! empty( $included );
}
/**
* Returns all sitemap entries if indexing is disabled.
*
* @since 4.0.0
*
* @return array $entries The sitemap entries.
*/
private function nonIndexed() {
$additional = $this->addl();
$postTypes = aioseo()->sitemap->helpers->includedPostTypes();
$isStaticHomepage = 'page' === get_option( 'show_on_front' );
$blogPageEntry = [];
$homePageEntry = ! $isStaticHomepage ? [ array_shift( $additional ) ] : [];
$entries = array_merge( $additional, $this->author(), $this->date(), $this->postArchive() );
if ( $postTypes ) {
foreach ( $postTypes as $postType ) {
$postTypeEntries = $this->posts( $postType );
// If we don't have a static homepage, it's business as usual.
if ( ! $isStaticHomepage ) {
$entries = array_merge( $entries, $postTypeEntries );
continue;
}
$homePageId = (int) get_option( 'page_on_front' );
$blogPageId = (int) get_option( 'page_for_posts' );
if ( 'post' === $postType && $blogPageId ) {
$blogPageEntry[] = array_shift( $postTypeEntries );
}
if ( 'page' === $postType && $homePageId ) {
$homePageEntry[] = array_shift( $postTypeEntries );
}
$entries = array_merge( $entries, $postTypeEntries );
}
}
$taxonomies = aioseo()->sitemap->helpers->includedTaxonomies();
if ( $taxonomies ) {
foreach ( $taxonomies as $taxonomy ) {
$entries = array_merge( $entries, $this->terms( $taxonomy ) );
}
}
// Sort first by priority, then by last modified date.
usort( $entries, function ( $a, $b ) {
// If the priorities are equal, sort by last modified date.
if ( $a['priority'] === $b['priority'] ) {
return $a['lastmod'] > $b['lastmod'] ? -1 : 1;
}
return $a['priority'] > $b['priority'] ? -1 : 1;
} );
// Merge the arrays with the home page always first.
return array_merge( $homePageEntry, $blogPageEntry, $entries );
}
/**
* Returns all post entries for a given post type.
*
* @since 4.0.0
*
* @param string $postType The name of the post type.
* @param array $additionalArgs Any additional arguments for the post query.
* @return array The sitemap entries.
*/
public function posts( $postType, $additionalArgs = [] ) {
$posts = aioseo()->sitemap->query->posts( $postType, $additionalArgs );
if ( ! $posts ) {
return [];
}
// Return if we're determining the root indexes.
if ( ! empty( $additionalArgs['root'] ) && $additionalArgs['root'] ) {
return $posts;
}
$entries = [];
$isStaticHomepage = 'page' === get_option( 'show_on_front' );
$homePageId = (int) get_option( 'page_on_front' );
$excludeImages = aioseo()->sitemap->helpers->excludeImages();
foreach ( $posts as $post ) {
$entry = [
'loc' => get_permalink( $post->ID ),
'lastmod' => aioseo()->helpers->dateTimeToIso8601( $this->getLastModified( $post ) ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'postTypes', $post, $postType ),
'priority' => aioseo()->sitemap->priority->priority( 'postTypes', $post, $postType ),
];
if ( ! $excludeImages ) {
$entry['images'] = ! empty( $post->images ) ? json_decode( $post->images ) : [];
}
// Override priority/frequency for static homepage.
if ( $isStaticHomepage && ( $homePageId === $post->ID || aioseo()->helpers->wpmlIsHomePage( $post->ID ) ) ) {
$entry['loc'] = aioseo()->helpers->maybeRemoveTrailingSlash( aioseo()->helpers->wpmlHomeUrl( $post->ID ) ?: $entry['loc'] );
$entry['changefreq'] = aioseo()->sitemap->priority->frequency( 'homePage' );
$entry['priority'] = aioseo()->sitemap->priority->priority( 'homePage' );
}
$entries[] = apply_filters( 'aioseo_sitemap_post', $entry, $post->ID, $postType, 'post' );
}
// We can't remove the post type here because other plugins rely on it.
return apply_filters( 'aioseo_sitemap_posts', $entries, $postType );
}
/**
* Returns all post archive entries.
*
* @since 4.0.0
*
* @return array $entries The sitemap entries.
*/
private function postArchive() {
$entries = [];
foreach ( aioseo()->sitemap->helpers->includedPostTypes( true ) as $postType ) {
if (
aioseo()->dynamicOptions->noConflict()->searchAppearance->archives->has( $postType ) &&
! aioseo()->dynamicOptions->searchAppearance->archives->$postType->advanced->robotsMeta->default &&
aioseo()->dynamicOptions->searchAppearance->archives->$postType->advanced->robotsMeta->noindex
) {
continue;
}
$post = aioseo()->core->db
->start( aioseo()->core->db->db->posts . ' as p', true )
->select( 'p.ID' )
->where( 'p.post_status', 'publish' )
->where( 'p.post_type', $postType )
->limit( 1 )
->run()
->result();
if ( ! $post ) {
continue;
}
$url = get_post_type_archive_link( $postType );
if ( $url ) {
$entry = [
'loc' => $url,
'lastmod' => aioseo()->sitemap->helpers->lastModifiedPostTime( $postType ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'archive' ),
'priority' => aioseo()->sitemap->priority->priority( 'archive' ),
];
// To be consistent with our other entry filters, we need to pass the entry ID as well, but as null in this case.
$entries[] = apply_filters( 'aioseo_sitemap_archive_entry', $entry, null, $postType, 'archive' );
}
}
return apply_filters( 'aioseo_sitemap_post_archives', $entries );
}
/**
* Returns all term entries for a given taxonomy.
*
* @since 4.0.0
*
* @param string $taxonomy The name of the taxonomy.
* @param array $additionalArgs Any additional arguments for the term query.
* @return array The sitemap entries.
*/
public function terms( $taxonomy, $additionalArgs = [] ) {
$terms = aioseo()->sitemap->query->terms( $taxonomy, $additionalArgs );
if ( ! $terms ) {
return [];
}
// Get all registered post types for the taxonomy.
$postTypes = [];
foreach ( get_post_types() as $postType ) {
$taxonomies = get_object_taxonomies( $postType );
foreach ( $taxonomies as $name ) {
if ( $taxonomy === $name ) {
$postTypes[] = $postType;
}
}
}
// Return if we're determining the root indexes.
if ( ! empty( $additionalArgs['root'] ) && $additionalArgs['root'] ) {
return $terms;
}
$entries = [];
foreach ( $terms as $term ) {
$entry = [
'loc' => get_term_link( $term->term_id ),
'lastmod' => $this->getTermLastModified( $term ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'taxonomies', $term, $taxonomy ),
'priority' => aioseo()->sitemap->priority->priority( 'taxonomies', $term, $taxonomy ),
'images' => aioseo()->sitemap->image->term( $term )
];
$entries[] = apply_filters( 'aioseo_sitemap_term', $entry, $term->term_id, $term->taxonomy, 'term' );
}
return apply_filters( 'aioseo_sitemap_terms', $entries );
}
/**
* Returns the last modified date for a given term.
*
* @since 4.0.0
*
* @param int|object $term The term data object.
* @return string The lastmod timestamp.
*/
public function getTermLastModified( $term ) {
$termRelationshipsTable = aioseo()->core->db->db->prefix . 'term_relationships';
$termTaxonomyTable = aioseo()->core->db->db->prefix . 'term_taxonomy';
// If the term is an ID, get the term object.
if ( is_numeric( $term ) ) {
$term = aioseo()->helpers->getTerm( $term );
}
// First, check the count of the term. If it's 0, then we're dealing with a parent term that does not have
// posts assigned to it. In this case, we need to get the last modified date of all its children.
if ( empty( $term->count ) ) {
$lastModified = aioseo()->core->db
->start( aioseo()->core->db->db->posts . ' as p', true )
->select( 'MAX(`p`.`post_modified_gmt`) as last_modified' )
->where( 'p.post_status', 'publish' )
->whereRaw( "
( `p`.`ID` IN
(
SELECT CONVERT(`tr`.`object_id`, unsigned)
FROM `$termRelationshipsTable` as tr
JOIN `$termTaxonomyTable` as tt ON `tr`.`term_taxonomy_id` = `tt`.`term_taxonomy_id`
WHERE `tt`.`term_id` IN
(
SELECT `tt`.`term_id`
FROM `$termTaxonomyTable` as tt
WHERE `tt`.`parent` = '{$term->term_id}'
)
)
)" )
->run()
->result();
} else {
$lastModified = aioseo()->core->db
->start( aioseo()->core->db->db->posts . ' as p', true )
->select( 'MAX(`p`.`post_modified_gmt`) as last_modified' )
->where( 'p.post_status', 'publish' )
->whereRaw( "
( `p`.`ID` IN
(
SELECT CONVERT(`tr`.`object_id`, unsigned)
FROM `$termRelationshipsTable` as tr
JOIN `$termTaxonomyTable` as tt ON `tr`.`term_taxonomy_id` = `tt`.`term_taxonomy_id`
WHERE `tt`.`term_id` = '{$term->term_id}'
)
)" )
->run()
->result();
}
$lastModified = $lastModified[0]->last_modified ?? '';
return aioseo()->helpers->dateTimeToIso8601( $lastModified );
}
/**
* Returns all additional pages.
*
* @since 4.0.0
*
* @param bool $shouldChunk Whether the entries should be chuncked. Is set to false when the static sitemap is generated.
* @return array The sitemap entries.
*/
public function addl( $shouldChunk = true ) {
$additionalPages = [];
if ( aioseo()->options->sitemap->general->additionalPages->enable ) {
$additionalPages = array_map( 'json_decode', aioseo()->options->sitemap->general->additionalPages->pages );
$additionalPages = array_filter( $additionalPages, function( $additionalPage ) {
return ! empty( $additionalPage->url );
} );
}
$entries = [];
foreach ( $additionalPages as $additionalPage ) {
$entries[] = [
'loc' => $additionalPage->url,
'lastmod' => aioseo()->sitemap->helpers->lastModifiedAdditionalPage( $additionalPage ),
'changefreq' => $additionalPage->frequency->value,
'priority' => $additionalPage->priority->value,
'isTimezone' => true
];
}
$postTypes = aioseo()->sitemap->helpers->includedPostTypes();
$shouldIncludeHomepage = 'posts' === get_option( 'show_on_front' ) || ! in_array( 'page', $postTypes, true );
if ( $shouldIncludeHomepage ) {
$frontPageId = (int) get_option( 'page_on_front' );
$frontPageUrl = aioseo()->helpers->localizedUrl( '/' );
$post = aioseo()->helpers->getPost( $frontPageId );
$homepageEntry = [
'loc' => aioseo()->helpers->maybeRemoveTrailingSlash( $frontPageUrl ),
'lastmod' => $post ? aioseo()->helpers->dateTimeToIso8601( $this->getLastModified( $post ) ) : aioseo()->sitemap->helpers->lastModifiedPostTime(),
'changefreq' => aioseo()->sitemap->priority->frequency( 'homePage' ),
'priority' => aioseo()->sitemap->priority->priority( 'homePage' )
];
$translatedHomepages = aioseo()->helpers->wpmlHomePages();
foreach ( $translatedHomepages as $languageCode => $translatedHomepage ) {
if ( untrailingslashit( $translatedHomepage['url'] ) !== untrailingslashit( $homepageEntry['loc'] ) ) {
$homepageEntry['languages'][] = [
'language' => $languageCode,
'location' => $translatedHomepage['url']
];
}
}
// Add homepage to the first position.
array_unshift( $entries, $homepageEntry );
}
if ( aioseo()->options->sitemap->general->additionalPages->enable ) {
$entries = apply_filters( 'aioseo_sitemap_additional_pages', $entries );
}
if ( empty( $entries ) ) {
return [];
}
if ( aioseo()->options->sitemap->general->indexes && $shouldChunk ) {
$entries = aioseo()->sitemap->helpers->chunkEntries( $entries );
$entries = $entries[ aioseo()->sitemap->pageNumber ] ?? [];
}
return $entries;
}
/**
* Returns all author archive entries.
*
* @since 4.0.0
*
* @return array The sitemap entries.
*/
public function author() {
if (
! aioseo()->sitemap->helpers->lastModifiedPost() ||
! aioseo()->options->sitemap->general->author ||
! aioseo()->options->searchAppearance->archives->author->show ||
(
! aioseo()->options->searchAppearance->archives->author->advanced->robotsMeta->default &&
aioseo()->options->searchAppearance->archives->author->advanced->robotsMeta->noindex
) ||
(
aioseo()->options->searchAppearance->archives->author->advanced->robotsMeta->default &&
(
! aioseo()->options->searchAppearance->advanced->globalRobotsMeta->default &&
aioseo()->options->searchAppearance->advanced->globalRobotsMeta->noindex
)
)
) {
return [];
}
// Allow users to filter the authors in case their sites use a membership plugin or have custom code that affect the authors on their site.
// e.g. there might be additional roles/conditions that need to be checked here.
$authors = apply_filters( 'aioseo_sitemap_authors', [] );
if ( empty( $authors ) ) {
$usersTableName = aioseo()->core->db->db->users; // We get the table name from WPDB since multisites share the same table.
$authors = aioseo()->core->db->start( "$usersTableName as u", true )
->select( 'u.ID as ID, u.user_nicename as nicename, MAX(p.post_modified_gmt) as lastModified' )
->join( 'posts as p', 'u.ID = p.post_author' )
->where( 'p.post_status', 'publish' )
->whereIn( 'p.post_type', aioseo()->sitemap->helpers->getAuthorPostTypes() )
->groupBy( 'u.ID' )
->orderBy( 'lastModified DESC' )
->limit( aioseo()->sitemap->linksPerIndex, aioseo()->sitemap->pageNumber * aioseo()->sitemap->linksPerIndex )
->run()
->result();
}
if ( empty( $authors ) ) {
return [];
}
$entries = [];
foreach ( $authors as $authorData ) {
$entry = [
'loc' => ! empty( $authorData->authorUrl )
? $authorData->authorUrl
: get_author_posts_url( $authorData->ID, $authorData->nicename ?: '' ),
'lastmod' => aioseo()->helpers->dateTimeToIso8601( $authorData->lastModified ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'author' ),
'priority' => aioseo()->sitemap->priority->priority( 'author' )
];
$entries[] = apply_filters( 'aioseo_sitemap_author_entry', $entry, $authorData->ID, $authorData->nicename, 'author' );
}
return apply_filters( 'aioseo_sitemap_author_archives', $entries );
}
/**
* Returns all data archive entries.
*
* @since 4.0.0
*
* @return array The sitemap entries.
*/
public function date() {
if (
! aioseo()->sitemap->helpers->lastModifiedPost() ||
! aioseo()->options->sitemap->general->date ||
! aioseo()->options->searchAppearance->archives->date->show ||
(
! aioseo()->options->searchAppearance->archives->date->advanced->robotsMeta->default &&
aioseo()->options->searchAppearance->archives->date->advanced->robotsMeta->noindex
) ||
(
aioseo()->options->searchAppearance->archives->date->advanced->robotsMeta->default &&
(
! aioseo()->options->searchAppearance->advanced->globalRobotsMeta->default &&
aioseo()->options->searchAppearance->advanced->globalRobotsMeta->noindex
)
)
) {
return [];
}
$postsTable = aioseo()->core->db->db->posts;
$dates = aioseo()->core->db->execute(
"SELECT
YEAR(post_date) AS `year`,
MONTH(post_date) AS `month`,
post_date_gmt,
post_modified_gmt
FROM {$postsTable}
WHERE post_type = 'post' AND post_status = 'publish'
GROUP BY
YEAR(post_date),
MONTH(post_date)
ORDER BY post_date ASC
LIMIT 50000",
true
)->result();
if ( empty( $dates ) ) {
return [];
}
$entries = [];
$year = '';
foreach ( $dates as $date ) {
$entry = [
'lastmod' => aioseo()->helpers->dateTimeToIso8601( $this->getLastModified( $date ) ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'date' ),
'priority' => aioseo()->sitemap->priority->priority( 'date' ),
];
// Include each year only once.
if ( $year !== $date->year ) {
$year = $date->year;
$entry['loc'] = get_year_link( $date->year );
$entries[] = apply_filters( 'aioseo_sitemap_date_entry', $entry, $date, 'year', 'date' );
}
$entry['loc'] = get_month_link( $date->year, $date->month );
$entries[] = apply_filters( 'aioseo_sitemap_date_entry', $entry, $date, 'month', 'date' );
}
return apply_filters( 'aioseo_sitemap_date_archives', $entries );
}
/**
* Returns all entries for the RSS Sitemap.
*
* @since 4.0.0
*
* @return array The sitemap entries.
*/
public function rss() {
$posts = aioseo()->sitemap->query->posts(
aioseo()->sitemap->helpers->includedPostTypes(),
[ 'orderBy' => '`p`.`post_modified_gmt` DESC' ]
);
if ( ! count( $posts ) ) {
return [];
}
$entries = [];
foreach ( $posts as $post ) {
$entry = [
'guid' => get_permalink( $post->ID ),
'title' => get_the_title( $post ),
'description' => get_post_field( 'post_excerpt', $post->ID ),
'pubDate' => aioseo()->helpers->dateTimeToRfc822( $this->getLastModified( $post ) )
];
// If the entry is the homepage, we need to check if the permalink structure
// does not have a trailing slash. If so, we need to strip it because WordPress adds it
// regardless for the home_url() in get_page_link() which is used in the get_permalink() function.
static $homeId = null;
if ( null === $homeId ) {
$homeId = get_option( 'page_for_posts' );
}
if ( aioseo()->helpers->getHomePageId() === $post->ID ) {
$entry['guid'] = aioseo()->helpers->maybeRemoveTrailingSlash( $entry['guid'] );
}
$entries[] = apply_filters( 'aioseo_sitemap_post_rss', $entry, $post->ID, $post->post_type, 'post' );
}
usort( $entries, function( $a, $b ) {
return $a['pubDate'] < $b['pubDate'] ? 1 : 0;
});
return apply_filters( 'aioseo_sitemap_rss', $entries );
}
/**
* Returns the last modified date for a given post.
*
* @since 4.6.3
*
* @param object $post The post object.
*
* @return string The last modified date.
*/
public function getLastModified( $post ) {
$publishDate = $post->post_date_gmt;
$lastModifiedDate = $post->post_modified_gmt;
// Get the date which is the latest.
return $lastModifiedDate > $publishDate ? $lastModifiedDate : $publishDate;
}
/**
* Returns all entries for the BuddyPress Activity Sitemap.
* This method is automagically called from {@see get()} if the current index name equals to 'bp-activity'
*
* @since 4.7.6
*
* @return array The sitemap entries.
*/
public function bpActivity() {
$entries = [];
if ( ! in_array( aioseo()->sitemap->indexName, aioseo()->sitemap->helpers->includedPostTypes(), true ) ) {
return $entries;
}
$postType = 'bp-activity';
$query = aioseo()->core->db
->start( 'bp_activity as a' )
->select( '`a`.`id`, `a`.`date_recorded`' )
->whereRaw( "a.is_spam = 0 AND a.hide_sitewide = 0 AND a.type NOT IN ('activity_comment', 'last_activity')" )
->limit( aioseo()->sitemap->linksPerIndex, aioseo()->sitemap->offset )
->orderBy( 'a.date_recorded DESC' );
$items = $query->run()
->result();
foreach ( $items as $item ) {
$entry = [
'loc' => BuddyPressIntegration::getComponentSingleUrl( 'activity', $item->id ),
'lastmod' => aioseo()->helpers->dateTimeToIso8601( $item->date_recorded ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'postTypes', false, $postType ),
'priority' => aioseo()->sitemap->priority->priority( 'postTypes', false, $postType ),
];
$entries[] = apply_filters( 'aioseo_sitemap_post', $entry, $item->id, $postType );
}
$archiveUrl = BuddyPressIntegration::getComponentArchiveUrl( 'activity' );
if (
aioseo()->helpers->isUrl( $archiveUrl ) &&
! in_array( $postType, aioseo()->helpers->getNoindexedObjects( 'archives' ), true )
) {
$lastMod = ! empty( $items[0] ) ? $items[0]->date_recorded : current_time( 'mysql' );
$entry = [
'loc' => $archiveUrl,
'lastmod' => $lastMod,
'changefreq' => aioseo()->sitemap->priority->frequency( 'postTypes', false, $postType ),
'priority' => aioseo()->sitemap->priority->priority( 'postTypes', false, $postType ),
];
array_unshift( $entries, $entry );
}
return apply_filters( 'aioseo_sitemap_posts', $entries, $postType );
}
/**
* Returns all entries for the BuddyPress Group Sitemap.
* This method is automagically called from {@see get()} if the current index name equals to 'bp-group'
*
* @since 4.7.6
*
* @return array The sitemap entries.
*/
public function bpGroup() {
$entries = [];
if ( ! in_array( aioseo()->sitemap->indexName, aioseo()->sitemap->helpers->includedPostTypes(), true ) ) {
return $entries;
}
$postType = 'bp-group';
$query = aioseo()->core->db
->start( 'bp_groups as g' )
->select( '`g`.`id`, `g`.`date_created`, `gm`.`meta_value` as date_modified' )
->leftJoin( 'bp_groups_groupmeta as gm', 'g.id = gm.group_id' )
->whereRaw( "g.status = 'public' AND gm.meta_key = 'last_activity'" )
->limit( aioseo()->sitemap->linksPerIndex, aioseo()->sitemap->offset )
->orderBy( 'gm.meta_value DESC' )
->orderBy( 'g.date_created DESC' );
$items = $query->run()
->result();
foreach ( $items as $item ) {
$lastMod = $item->date_modified ?: $item->date_created;
$entry = [
'loc' => BuddyPressIntegration::getComponentSingleUrl( 'group', BuddyPressIntegration::callFunc( 'bp_get_group_by', 'id', $item->id ) ),
'lastmod' => aioseo()->helpers->dateTimeToIso8601( $lastMod ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'postTypes', false, $postType ),
'priority' => aioseo()->sitemap->priority->priority( 'postTypes', false, $postType ),
];
$entries[] = apply_filters( 'aioseo_sitemap_post', $entry, $item->id, $postType );
}
$archiveUrl = BuddyPressIntegration::getComponentArchiveUrl( 'group' );
if (
aioseo()->helpers->isUrl( $archiveUrl ) &&
! in_array( $postType, aioseo()->helpers->getNoindexedObjects( 'archives' ), true )
) {
$lastMod = ! empty( $items[0] ) ? $items[0]->date_modified : current_time( 'mysql' );
$entry = [
'loc' => $archiveUrl,
'lastmod' => $lastMod,
'changefreq' => aioseo()->sitemap->priority->frequency( 'postTypes', false, $postType ),
'priority' => aioseo()->sitemap->priority->priority( 'postTypes', false, $postType ),
];
array_unshift( $entries, $entry );
}
return apply_filters( 'aioseo_sitemap_posts', $entries, $postType );
}
/**
* Returns all entries for the BuddyPress Member Sitemap.
* This method is automagically called from {@see get()} if the current index name equals to 'bp-member'
*
* @since 4.7.6
*
* @return array The sitemap entries.
*/
public function bpMember() {
$entries = [];
if ( ! in_array( aioseo()->sitemap->indexName, aioseo()->sitemap->helpers->includedPostTypes(), true ) ) {
return $entries;
}
$postType = 'bp-member';
$query = aioseo()->core->db
->start( 'bp_activity as a' )
->select( '`a`.`user_id` as id, `a`.`date_recorded`' )
->whereRaw( "a.component = 'members' AND a.type = 'last_activity'" )
->limit( aioseo()->sitemap->linksPerIndex, aioseo()->sitemap->offset )
->orderBy( 'a.date_recorded DESC' );
$items = $query->run()
->result();
foreach ( $items as $item ) {
$entry = [
'loc' => BuddyPressIntegration::getComponentSingleUrl( 'member', $item->id ),
'lastmod' => aioseo()->helpers->dateTimeToIso8601( $item->date_recorded ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'postTypes', false, $postType ),
'priority' => aioseo()->sitemap->priority->priority( 'postTypes', false, $postType ),
];
$entries[] = apply_filters( 'aioseo_sitemap_post', $entry, $item->id, $postType );
}
$archiveUrl = BuddyPressIntegration::getComponentArchiveUrl( 'member' );
if (
aioseo()->helpers->isUrl( $archiveUrl ) &&
! in_array( $postType, aioseo()->helpers->getNoindexedObjects( 'archives' ), true )
) {
$lastMod = ! empty( $items[0] ) ? $items[0]->date_recorded : current_time( 'mysql' );
$entry = [
'loc' => $archiveUrl,
'lastmod' => $lastMod,
'changefreq' => aioseo()->sitemap->priority->frequency( 'postTypes', false, $postType ),
'priority' => aioseo()->sitemap->priority->priority( 'postTypes', false, $postType ),
];
array_unshift( $entries, $entry );
}
return apply_filters( 'aioseo_sitemap_posts', $entries, $postType );
}
/**
* Returns all entries for the WooCommerce Product Attributes sitemap.
* Note: This sitemap does not support pagination.
*
* @since 4.7.8
*
* @param bool $count Whether to return the count of the entries. This is used to determine the indexes.
* @return array The sitemap entries.
*/
public function productAttributes( $count = false ) {
$aioseoTermsTable = aioseo()->core->db->prefix . 'aioseo_terms';
$wcAttributeTaxonomiesTable = aioseo()->core->db->prefix . 'woocommerce_attribute_taxonomies';
$termTaxonomyTable = aioseo()->core->db->prefix . 'term_taxonomy';
$selectClause = 'COUNT(*) as childProductAttributes';
if ( ! $count ) {
$selectClause = aioseo()->pro ? 'tt.term_id, tt.taxonomy, at.frequency, at.priority' : 'tt.term_id, tt.taxonomy';
}
$joinClause = aioseo()->pro ? "LEFT JOIN {$aioseoTermsTable} AS at ON tt.term_id = at.term_id" : '';
$whereClause = aioseo()->pro ? 'AND (at.robots_noindex IS NULL OR at.robots_noindex = 0)' : '';
$limitClause = $count ? '' : 'LIMIT 50000';
$result = aioseo()->core->db->execute(
"SELECT {$selectClause}
FROM {$termTaxonomyTable} AS tt
JOIN {$wcAttributeTaxonomiesTable} AS wat ON tt.taxonomy = CONCAT('pa_', wat.attribute_name)
{$joinClause}
WHERE wat.attribute_public = 1
{$whereClause}
AND tt.count > 0
{$limitClause};",
true
)->result();
if ( $count ) {
return ! empty( $result[0]->childProductAttributes ) ? (int) $result[0]->childProductAttributes : 0;
}
if ( empty( $result ) ) {
return [];
}
$entries = [];
foreach ( $result as $term ) {
$term = (object) $term;
$termId = (int) $term->term_id;
$entry = [
'loc' => get_term_link( $termId ),
'lastmod' => $this->getTermLastModified( $termId ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'taxonomies', $term, 'product_attributes' ),
'priority' => aioseo()->sitemap->priority->priority( 'taxonomies', $term, 'product_attributes' ),
'images' => aioseo()->sitemap->image->term( $term )
];
$entries[] = apply_filters( 'aioseo_sitemap_product_attributes', $entry, $termId, $term->taxonomy, 'term' );
}
return $entries;
}
} xbodynamge/dev/wp-content/plugins/all-in-one-seo-pack/app/Common/EmailReports/Summary/Content.php 0000644 00000050371 15113647246 0027757 0 ustar 00 home <?php
namespace AIOSEO\Plugin\Common\EmailReports\Summary;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\Plugin\Common\Models;
/**
* Summary content class.
*
* @since 4.7.2
*/
class Content {
/**
* The date range data.
*
* @since 4.7.2
*
* @var array
*/
public $dateRange;
/**
* The SEO Statistics data.
*
* @since 4.7.2
*
* @var array
*/
private $seoStatistics = [];
/**
* The Keywords data.
*
* @since 4.7.2
*
* @var array
*/
private $keywords = [];
/**
* The Search Statistics page URL.
*
* @since 4.7.2
*
* @var string
*/
public $searchStatisticsUrl;
/**
* The featured image placeholder URL.
*
* @since 4.7.3
*
* @var string
*/
public $featuredImagePlaceholder = 'https://static.aioseo.io/report/ste/featured-image-placeholder.png';
/**
* Class constructor.
*
* @since 4.7.2
*
* @param array $dateRange The date range data.
* @return void
*/
public function __construct( $dateRange ) {
$this->dateRange = $dateRange;
$this->searchStatisticsUrl = admin_url( 'admin.php?page=aioseo-search-statistics' );
$this->setSeoStatistics();
$this->setKeywords();
}
/**
* Sets the SEO Statistics data.
*
* @since 4.7.2
*
* @return void
*/
private function setSeoStatistics() {
try {
$seoStatistics = aioseo()->searchStatistics->getSeoStatisticsData( [
'startDate' => gmdate( 'Y-m-d', $this->dateRange['startDateRaw'] ),
'endDate' => gmdate( 'Y-m-d', $this->dateRange['endDateRaw'] ),
'orderBy' => 'clicks',
'orderDir' => 'desc',
'limit' => '5',
'offset' => '0',
'filter' => 'all',
] );
if ( empty( $seoStatistics['data'] ) ) {
return;
}
$this->seoStatistics = $seoStatistics['data'];
} catch ( \Exception $e ) {
// Do nothing.
}
}
/**
* Sets the Keywords data.
*
* @since 4.7.2
*
* @return void
*/
private function setKeywords() {
try {
$keywords = aioseo()->searchStatistics->getKeywordsData( [
'startDate' => gmdate( 'Y-m-d', $this->dateRange['startDateRaw'] ),
'endDate' => gmdate( 'Y-m-d', $this->dateRange['endDateRaw'] ),
'orderBy' => 'clicks',
'orderDir' => 'desc',
'limit' => '5',
'offset' => '0',
'filter' => 'all',
] );
if ( empty( $keywords['data'] ) ) {
return;
}
$this->keywords = $keywords['data'];
} catch ( \Exception $e ) {
// Do nothing.
}
}
/**
* Retrieves the content performance data.
*
* @since 4.7.2
*
* @return array The content performance data or an empty array.
*/
public function getPostsStatistics() {
if ( ! $this->seoStatistics ) {
return [];
}
$result = [
'winning' => [
'url' => add_query_arg( [
'aioseo-scroll' => 'aioseo-search-statistics-post-table',
'aioseo-tab' => 'seo-statistics',
'table-filter' => 'TopWinningPages'
], $this->searchStatisticsUrl ),
'items' => []
],
'losing' => [
'url' => add_query_arg( [
'aioseo-scroll' => 'aioseo-search-statistics-post-table',
'aioseo-tab' => 'seo-statistics',
'table-filter' => 'TopLosingPages'
], $this->searchStatisticsUrl ),
'items' => []
]
];
foreach ( array_slice( $this->seoStatistics['pages']['topWinning']['rows'], 0, 3 ) as $row ) {
$postId = $row['objectId'] ?? 0;
$result['winning']['items'][] = [
'title' => $row['objectTitle'],
'url' => get_permalink( $postId ),
'tru_seo' => aioseo()->helpers->isTruSeoEligible( $postId ) ? $this->parseSeoScore( $row['seoScore'] ?? 0 ) : [],
'clicks' => $this->parseClicks( $row['clicks'] ),
'difference' => [
'clicks' => $this->parseDifference( $row['difference']['clicks'] ?? '' ),
]
];
}
$result['winning']['show_tru_seo'] = ! empty( array_filter( array_column( $result['winning']['items'], 'tru_seo' ) ) );
foreach ( array_slice( $this->seoStatistics['pages']['topLosing']['rows'], 0, 3 ) as $row ) {
$postId = $row['objectId'] ?? 0;
$result['losing']['items'][] = [
'title' => $row['objectTitle'],
'url' => get_permalink( $postId ),
'tru_seo' => aioseo()->helpers->isTruSeoEligible( $postId ) ? $this->parseSeoScore( $row['seoScore'] ?? 0 ) : [],
'clicks' => $this->parseClicks( $row['clicks'] ),
'difference' => [
'clicks' => $this->parseDifference( $row['difference']['clicks'] ?? '' ),
]
];
}
$result['losing']['show_tru_seo'] = ! empty( array_filter( array_column( $result['losing']['items'], 'tru_seo' ) ) );
return $result;
}
/**
* Retrieves the milestones data.
*
* @since 4.7.2
*
* @return array The milestones data or an empty array.
*/
public function getMilestones() { // phpcs:ignore Generic.Files.LineLength.MaxExceeded
$milestones = [];
if ( ! $this->seoStatistics ) {
return $milestones;
}
$currentData = [
'impressions' => $this->seoStatistics['statistics']['impressions'] ?? null,
'clicks' => $this->seoStatistics['statistics']['clicks'] ?? null,
'ctr' => $this->seoStatistics['statistics']['ctr'] ?? null,
'keywords' => $this->seoStatistics['statistics']['keywords'] ?? null,
];
$difference = [
'impressions' => $this->seoStatistics['statistics']['difference']['impressions'] ?? null,
'clicks' => $this->seoStatistics['statistics']['difference']['clicks'] ?? null,
'ctr' => $this->seoStatistics['statistics']['difference']['ctr'] ?? null,
'keywords' => $this->seoStatistics['statistics']['difference']['keywords'] ?? null,
];
if ( is_numeric( $currentData['impressions'] ) && is_numeric( $difference['impressions'] ) ) {
$intDifference = intval( $difference['impressions'] );
$message = esc_html__( 'Your site has received the same number of impressions compared to the previous period.', 'all-in-one-seo-pack' );
if ( $intDifference > 0 ) {
// Translators: 1 - The number of impressions, 2 - The percentage increase.
$message = esc_html__( 'Your site has received %1$s more impressions compared to the previous period, which is a %2$s increase.', 'all-in-one-seo-pack' );
}
if ( $intDifference < 0 ) {
// Translators: 1 - The number of impressions, 2 - The percentage increase.
$message = esc_html__( 'Your site has received %1$s fewer impressions compared to the previous period, which is a %2$s decrease.', 'all-in-one-seo-pack' );
}
if ( false !== strpos( $message, '%1' ) ) {
$percentageDiff = 0 === absint( $currentData['impressions'] )
? 100
: round( ( absint( $intDifference ) / absint( $currentData['impressions'] ) ) * 100, 2 );
$percentageDiff = false !== strpos( $percentageDiff, '.' )
? number_format_i18n( $percentageDiff, count( explode( '.', $percentageDiff ) ) )
: $percentageDiff;
$message = sprintf(
$message,
'<strong>' . aioseo()->helpers->compactNumber( absint( $intDifference ) ) . '</strong>',
'<strong>' . $percentageDiff . '%</strong>'
);
}
$milestones[] = [
'message' => $message,
'background' => '#f0f6ff',
'color' => '#004F9D',
'icon' => 'icon-milestone-impressions'
];
}
if ( is_numeric( $currentData['clicks'] ) && is_numeric( $difference['clicks'] ) ) {
$intDifference = intval( $difference['clicks'] );
$message = esc_html__( 'Your site has received the same number of clicks compared to the previous period.', 'all-in-one-seo-pack' );
if ( $intDifference > 0 ) {
// Translators: 1 - The number of clicks, 2 - The percentage increase.
$message = esc_html__( 'Your site has received %1$s more clicks compared to the previous period, which is a %2$s increase.', 'all-in-one-seo-pack' );
}
if ( $intDifference < 0 ) {
// Translators: 1 - The number of clicks, 2 - The percentage increase.
$message = esc_html__( 'Your site has received %1$s fewer clicks compared to the previous period, which is a %2$s decrease.', 'all-in-one-seo-pack' );
}
if ( false !== strpos( $message, '%1' ) ) {
$percentageDiff = 0 === absint( $currentData['clicks'] )
? 100
: round( ( absint( $intDifference ) / absint( $currentData['clicks'] ) ) * 100, 2 );
$percentageDiff = false !== strpos( $percentageDiff, '.' )
? number_format_i18n( $percentageDiff, count( explode( '.', $percentageDiff ) ) )
: $percentageDiff;
$message = sprintf(
$message,
'<strong>' . aioseo()->helpers->compactNumber( absint( $intDifference ) ) . '</strong>',
'<strong>' . $percentageDiff . '%</strong>'
);
}
$milestones[] = [
'message' => $message,
'background' => '#ecfdf5',
'color' => '#077647',
'icon' => 'icon-milestone-clicks'
];
}
if ( is_numeric( $currentData['ctr'] ) && is_numeric( $difference['ctr'] ) ) {
$intDifference = floatval( $difference['ctr'] );
$message = esc_html__( 'Your site has the same CTR compared to the previous period.', 'all-in-one-seo-pack' );
if ( $intDifference > 0 ) {
// Translators: 1 - The CTR.
$message = esc_html__( 'Your site has a %1$s higher CTR compared to the previous period.', 'all-in-one-seo-pack' );
}
if ( $intDifference < 0 ) {
// Translators: 1 - The CTR.
$message = esc_html__( 'Your site has a %1$s lower CTR compared to the previous period.', 'all-in-one-seo-pack' );
}
if ( false !== strpos( $message, '%1' ) ) {
$message = sprintf(
$message,
'<strong>' . number_format_i18n( abs( $intDifference ), count( explode( '.', $intDifference ) ) ) . '%</strong>'
);
}
$milestones[] = [
'message' => $message,
'background' => '#fffbeb',
'color' => '#be6903',
'icon' => 'icon-milestone-ctr'
];
}
if ( is_numeric( $currentData['keywords'] ) && is_numeric( $difference['keywords'] ) ) {
$intDifference = intval( $difference['keywords'] );
$message = esc_html__( 'Your site ranked for the same number of keywords compared to the previous period.', 'all-in-one-seo-pack' );
if ( $intDifference > 0 ) {
// Translators: 1 - The number of keywords, 2 - The percentage increase.
$message = esc_html__( 'Your site ranked for %1$s more keywords compared to the previous period, which is a %2$s increase.', 'all-in-one-seo-pack' );
}
if ( $intDifference < 0 ) {
// Translators: 1 - The number of keywords, 2 - The percentage increase.
$message = esc_html__( 'Your site ranked for %1$s fewer keywords compared to the previous period, which is a %2$s decrease.', 'all-in-one-seo-pack' );
}
if ( false !== strpos( $message, '%1' ) ) {
$percentageDiff = 0 === absint( $currentData['keywords'] )
? 100
: round( ( absint( $intDifference ) / absint( $currentData['keywords'] ) ) * 100, 2 );
$percentageDiff = false !== strpos( $percentageDiff, '.' )
? number_format_i18n( $percentageDiff, count( explode( '.', $percentageDiff ) ) )
: $percentageDiff;
$message = sprintf(
$message,
'<strong>' . aioseo()->helpers->compactNumber( absint( $intDifference ) ) . '</strong>',
'<strong>' . $percentageDiff . '%</strong>'
);
}
$milestones[] = [
'message' => $message,
'background' => '#fef2f2',
'color' => '#ab2039',
'icon' => 'icon-milestone-keywords'
];
}
return $milestones;
}
/**
* Retrieves the keyword performance data.
*
* @since 4.7.2
*
* @return array The keyword performance data or an empty array.
*/
public function getKeywords() {
if ( ! $this->keywords ) {
return [];
}
$result = [
'winning' => [
'url' => add_query_arg( [
'aioseo-scroll' => 'aioseo-search-statistics-keywords-table',
'aioseo-tab' => 'keyword-rank-tracker',
'tab' => 'AllKeywords',
'table-filter' => 'TopWinningKeywords'
], $this->searchStatisticsUrl ),
'items' => []
],
'losing' => [
'url' => add_query_arg( [
'aioseo-scroll' => 'aioseo-search-statistics-keywords-table',
'aioseo-tab' => 'keyword-rank-tracker',
'tab' => 'AllKeywords',
'table-filter' => 'TopLosingKeywords'
], $this->searchStatisticsUrl ),
'items' => []
]
];
foreach ( array_slice( $this->keywords['topWinning'], 0, 3 ) as $row ) {
$result['winning']['items'][] = [
'title' => $row['keyword'],
'clicks' => $this->parseClicks( $row['clicks'] ),
'difference' => [
'clicks' => $this->parseDifference( $row['difference']['clicks'] ?? '' ),
]
];
}
foreach ( array_slice( $this->keywords['topLosing'], 0, 3 ) as $row ) {
$result['losing']['items'][] = [
'title' => $row['keyword'],
'clicks' => $this->parseClicks( $row['clicks'] ),
'difference' => [
'clicks' => $this->parseDifference( $row['difference']['clicks'] ?? '' ),
]
];
}
return $result;
}
/**
* Retrieves the posts data.
*
* @since 4.7.2
*
* @return array The posts' data.
*/
public function getAioPosts() {
$result = [
'publish' => [],
'optimize' => [],
'cta' => [
'text' => esc_html__( 'Create New Post', 'all-in-one-seo-pack' ),
'url' => admin_url( 'post-new.php' )
],
];
// 1. Retrieve the published posts.
$publishPosts = aioseo()->core->db
->start( 'posts as wp' )
->select( 'wp.ID, wp.post_title, aio.seo_score' )
->join( 'aioseo_posts as aio', 'aio.post_id = wp.ID', 'INNER' )
->whereIn( 'wp.post_type', [ 'post' ] )
->whereIn( 'wp.post_status', [ 'publish' ] )
->orderBy( 'wp.post_date DESC' )
->limit( 5 )
->run()
->result();
if ( $publishPosts ) {
$items = $this->parsePosts( $publishPosts );
$result['publish'] = [
'url' => admin_url( 'edit.php?post_status=publish&post_type=post' ),
'items' => $items,
'show_stats' => ! empty( array_filter( array_column( $items, 'stats' ) ) ),
'show_tru_seo' => ! empty( array_filter( array_column( $items, 'tru_seo' ) ) ),
];
}
// 2. Retrieve the posts to optimize.
$optimizePosts = aioseo()->searchStatistics->getContentRankingsData( [
'endDate' => gmdate( 'Y-m-d', $this->dateRange['endDateRaw'] ),
'orderBy' => 'decayPercent',
'orderDir' => 'asc',
'limit' => '3',
'offset' => '0',
'filter' => 'all',
] );
if ( is_array( $optimizePosts['data']['paginated']['rows'] ?? '' ) ) {
$items = [];
foreach ( array_slice( $optimizePosts['data']['paginated']['rows'], 0, 3 ) as $i => $row ) {
$postId = $row['objectId'] ?? 0;
$items[ $i ] = [
'title' => $row['objectTitle'],
'url' => get_permalink( $postId ),
'image_url' => $this->getThumbnailUrl( $postId ),
'tru_seo' => aioseo()->helpers->isTruSeoEligible( $postId ) ? $this->parseSeoScore( $row['seoScore'] ?? 0 ) : [],
'decay_percent' => $this->parseDifference( $row['decayPercent'] ?? '', true ),
'issues' => [
'url' => add_query_arg( [
'aioseo-tab' => 'post-detail',
'post' => $postId
], $this->searchStatisticsUrl ),
'items' => []
]
];
$aioPost = Models\Post::getPost( $postId );
if ( $aioPost ) {
$items[ $i ]['issues']['items'] = aioseo()->searchStatistics->helpers->getSuggestedChanges( $aioPost );
}
}
$result['optimize'] = [
'url' => add_query_arg( [
'aioseo-tab' => 'content-rankings',
], $this->searchStatisticsUrl ),
'items' => $items,
'show_tru_seo' => ! empty( array_filter( array_column( $items, 'tru_seo' ) ) ),
];
}
return $result;
}
/**
* Retrieves the resources data.
*
* @since 4.7.2
*
* @return array The resources' data.
*/
public function getResources() {
$items = aioseo()->helpers->fetchAioseoArticles( true );
return array_slice( array_filter( $items ), 0, 3 );
}
/**
* Returns if Search Statistics content is allowed.
*
* @since 4.7.3
*
* @return bool Whether Search Statistics content is allowed.
*/
public function allowSearchStatistics() {
static $return = null;
if ( isset( $return ) ) {
return $return;
}
$return = aioseo()->searchStatistics->api->auth->isConnected() &&
aioseo()->license &&
aioseo()->license->hasCoreFeature( 'search-statistics', 'seo-statistics' ) &&
aioseo()->license->hasCoreFeature( 'search-statistics', 'keyword-rankings' );
return $return;
}
/**
* Parses the SEO score.
*
* @since 4.7.2
*
* @param int|string $score The SEO score.
* @return array The parsed SEO score.
*/
private function parseSeoScore( $score ) {
$score = intval( $score );
$parsed = [
'value' => $score,
'color' => '#a1a1a1',
'text' => $score ? "$score/100" : esc_html__( 'N/A', 'all-in-one-seo-pack' ),
];
if ( $parsed['value'] > 79 ) {
$parsed['color'] = '#00aa63';
} elseif ( $parsed['value'] > 49 ) {
$parsed['color'] = '#ff8c00';
} elseif ( $parsed['value'] > 0 ) {
$parsed['color'] = '#df2a4a';
}
return $parsed;
}
/**
* Parses a difference.
*
* @since 4.7.2
*
* @param int|string $number The number to parse.
* @param bool $percentage Whether to return the text result as a percentage.
* @return array The parsed result.
*/
private function parseDifference( $number, $percentage = false ) {
$parsed = [
'color' => '#a1a1a1',
'text' => esc_html__( 'N/A', 'all-in-one-seo-pack' ),
];
if ( ! is_numeric( $number ) ) {
return $parsed;
}
$number = intval( $number );
$parsed['text'] = aioseo()->helpers->compactNumber( absint( $number ) );
if ( $percentage ) {
$parsed['text'] = $number . '%';
}
if ( $number > 0 ) {
$parsed['color'] = '#00aa63';
} elseif ( $number < 0 ) {
$parsed['color'] = '#df2a4a';
}
return $parsed;
}
/**
* Parses the clicks number.
*
* @since 4.7.2
*
* @param float|int|string $number The number of clicks.
* @return string The parsed number of clicks.
*/
private function parseClicks( $number ) {
return aioseo()->helpers->compactNumber( $number );
}
/**
* Parses the posts data.
*
* @since 4.7.2
*
* @param array $posts The posts.
* @return array The parsed posts' data.
*/
private function parsePosts( $posts ) {
$parsed = [];
foreach ( $posts as $k => $item ) {
$parsed[ $k ] = [
'title' => aioseo()->helpers->truncate( $item->post_title, 75 ),
'url' => get_permalink( $item->ID ),
'image_url' => $this->getThumbnailUrl( $item->ID ),
'tru_seo' => aioseo()->helpers->isTruSeoEligible( $item->ID ) ? $this->parseSeoScore( $item->seo_score ?? 0 ) : [],
'stats' => []
];
try {
$statistics = [];
if (
$this->allowSearchStatistics() &&
method_exists( aioseo()->searchStatistics, 'getPostDetailSeoStatisticsData' )
) {
$statistics = aioseo()->searchStatistics->getPostDetailSeoStatisticsData( [
'startDate' => gmdate( 'Y-m-d', $this->dateRange['startDateRaw'] ),
'endDate' => gmdate( 'Y-m-d', $this->dateRange['endDateRaw'] ),
'postId' => $item->ID,
], false );
}
if ( isset( $statistics['data']['statistics']['position'] ) ) {
$parsed[ $k ]['stats'][] = [
'icon' => 'position',
'label' => esc_html__( 'Position', 'all-in-one-seo-pack' ),
'value' => round( floatval( $statistics['data']['statistics']['position'] ) ),
];
}
if ( isset( $statistics['data']['statistics']['ctr'] ) ) {
$value = round( floatval( $statistics['data']['statistics']['ctr'] ), 2 );
$parsed[ $k ]['stats'][] = [
'icon' => 'ctr',
'label' => 'CTR',
'value' => ( number_format_i18n( $value, count( explode( '.', $value ) ) ) ) . '%',
];
}
if ( isset( $statistics['data']['statistics']['impressions'] ) ) {
$parsed[ $k ]['stats'][] = [
'icon' => 'impressions',
'label' => esc_html__( 'Impressions', 'all-in-one-seo-pack' ),
'value' => aioseo()->helpers->compactNumber( $statistics['data']['statistics']['impressions'] ),
];
}
} catch ( \Exception $e ) {
// Do nothing.
}
}
return $parsed;
}
/**
* Retrieves the thumbnail URL.
*
* @since 4.7.2
*
* @param int $postId The post ID.
* @return string The post featured image URL (thumbnail size).
*/
private function getThumbnailUrl( $postId ) {
$imageUrl = get_the_post_thumbnail_url( $postId );
return $imageUrl ?: $this->featuredImagePlaceholder;
}
} namtation/wp-content/plugins/all-in-one-seo-pack/app/Common/EmailReports/Summary/Content.php 0000644 00000050371 15115172054 0031163 0 ustar 00 home/xbodynamge <?php
namespace AIOSEO\Plugin\Common\EmailReports\Summary;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\Plugin\Common\Models;
/**
* Summary content class.
*
* @since 4.7.2
*/
class Content {
/**
* The date range data.
*
* @since 4.7.2
*
* @var array
*/
public $dateRange;
/**
* The SEO Statistics data.
*
* @since 4.7.2
*
* @var array
*/
private $seoStatistics = [];
/**
* The Keywords data.
*
* @since 4.7.2
*
* @var array
*/
private $keywords = [];
/**
* The Search Statistics page URL.
*
* @since 4.7.2
*
* @var string
*/
public $searchStatisticsUrl;
/**
* The featured image placeholder URL.
*
* @since 4.7.3
*
* @var string
*/
public $featuredImagePlaceholder = 'https://static.aioseo.io/report/ste/featured-image-placeholder.png';
/**
* Class constructor.
*
* @since 4.7.2
*
* @param array $dateRange The date range data.
* @return void
*/
public function __construct( $dateRange ) {
$this->dateRange = $dateRange;
$this->searchStatisticsUrl = admin_url( 'admin.php?page=aioseo-search-statistics' );
$this->setSeoStatistics();
$this->setKeywords();
}
/**
* Sets the SEO Statistics data.
*
* @since 4.7.2
*
* @return void
*/
private function setSeoStatistics() {
try {
$seoStatistics = aioseo()->searchStatistics->getSeoStatisticsData( [
'startDate' => gmdate( 'Y-m-d', $this->dateRange['startDateRaw'] ),
'endDate' => gmdate( 'Y-m-d', $this->dateRange['endDateRaw'] ),
'orderBy' => 'clicks',
'orderDir' => 'desc',
'limit' => '5',
'offset' => '0',
'filter' => 'all',
] );
if ( empty( $seoStatistics['data'] ) ) {
return;
}
$this->seoStatistics = $seoStatistics['data'];
} catch ( \Exception $e ) {
// Do nothing.
}
}
/**
* Sets the Keywords data.
*
* @since 4.7.2
*
* @return void
*/
private function setKeywords() {
try {
$keywords = aioseo()->searchStatistics->getKeywordsData( [
'startDate' => gmdate( 'Y-m-d', $this->dateRange['startDateRaw'] ),
'endDate' => gmdate( 'Y-m-d', $this->dateRange['endDateRaw'] ),
'orderBy' => 'clicks',
'orderDir' => 'desc',
'limit' => '5',
'offset' => '0',
'filter' => 'all',
] );
if ( empty( $keywords['data'] ) ) {
return;
}
$this->keywords = $keywords['data'];
} catch ( \Exception $e ) {
// Do nothing.
}
}
/**
* Retrieves the content performance data.
*
* @since 4.7.2
*
* @return array The content performance data or an empty array.
*/
public function getPostsStatistics() {
if ( ! $this->seoStatistics ) {
return [];
}
$result = [
'winning' => [
'url' => add_query_arg( [
'aioseo-scroll' => 'aioseo-search-statistics-post-table',
'aioseo-tab' => 'seo-statistics',
'table-filter' => 'TopWinningPages'
], $this->searchStatisticsUrl ),
'items' => []
],
'losing' => [
'url' => add_query_arg( [
'aioseo-scroll' => 'aioseo-search-statistics-post-table',
'aioseo-tab' => 'seo-statistics',
'table-filter' => 'TopLosingPages'
], $this->searchStatisticsUrl ),
'items' => []
]
];
foreach ( array_slice( $this->seoStatistics['pages']['topWinning']['rows'], 0, 3 ) as $row ) {
$postId = $row['objectId'] ?? 0;
$result['winning']['items'][] = [
'title' => $row['objectTitle'],
'url' => get_permalink( $postId ),
'tru_seo' => aioseo()->helpers->isTruSeoEligible( $postId ) ? $this->parseSeoScore( $row['seoScore'] ?? 0 ) : [],
'clicks' => $this->parseClicks( $row['clicks'] ),
'difference' => [
'clicks' => $this->parseDifference( $row['difference']['clicks'] ?? '' ),
]
];
}
$result['winning']['show_tru_seo'] = ! empty( array_filter( array_column( $result['winning']['items'], 'tru_seo' ) ) );
foreach ( array_slice( $this->seoStatistics['pages']['topLosing']['rows'], 0, 3 ) as $row ) {
$postId = $row['objectId'] ?? 0;
$result['losing']['items'][] = [
'title' => $row['objectTitle'],
'url' => get_permalink( $postId ),
'tru_seo' => aioseo()->helpers->isTruSeoEligible( $postId ) ? $this->parseSeoScore( $row['seoScore'] ?? 0 ) : [],
'clicks' => $this->parseClicks( $row['clicks'] ),
'difference' => [
'clicks' => $this->parseDifference( $row['difference']['clicks'] ?? '' ),
]
];
}
$result['losing']['show_tru_seo'] = ! empty( array_filter( array_column( $result['losing']['items'], 'tru_seo' ) ) );
return $result;
}
/**
* Retrieves the milestones data.
*
* @since 4.7.2
*
* @return array The milestones data or an empty array.
*/
public function getMilestones() { // phpcs:ignore Generic.Files.LineLength.MaxExceeded
$milestones = [];
if ( ! $this->seoStatistics ) {
return $milestones;
}
$currentData = [
'impressions' => $this->seoStatistics['statistics']['impressions'] ?? null,
'clicks' => $this->seoStatistics['statistics']['clicks'] ?? null,
'ctr' => $this->seoStatistics['statistics']['ctr'] ?? null,
'keywords' => $this->seoStatistics['statistics']['keywords'] ?? null,
];
$difference = [
'impressions' => $this->seoStatistics['statistics']['difference']['impressions'] ?? null,
'clicks' => $this->seoStatistics['statistics']['difference']['clicks'] ?? null,
'ctr' => $this->seoStatistics['statistics']['difference']['ctr'] ?? null,
'keywords' => $this->seoStatistics['statistics']['difference']['keywords'] ?? null,
];
if ( is_numeric( $currentData['impressions'] ) && is_numeric( $difference['impressions'] ) ) {
$intDifference = intval( $difference['impressions'] );
$message = esc_html__( 'Your site has received the same number of impressions compared to the previous period.', 'all-in-one-seo-pack' );
if ( $intDifference > 0 ) {
// Translators: 1 - The number of impressions, 2 - The percentage increase.
$message = esc_html__( 'Your site has received %1$s more impressions compared to the previous period, which is a %2$s increase.', 'all-in-one-seo-pack' );
}
if ( $intDifference < 0 ) {
// Translators: 1 - The number of impressions, 2 - The percentage increase.
$message = esc_html__( 'Your site has received %1$s fewer impressions compared to the previous period, which is a %2$s decrease.', 'all-in-one-seo-pack' );
}
if ( false !== strpos( $message, '%1' ) ) {
$percentageDiff = 0 === absint( $currentData['impressions'] )
? 100
: round( ( absint( $intDifference ) / absint( $currentData['impressions'] ) ) * 100, 2 );
$percentageDiff = false !== strpos( $percentageDiff, '.' )
? number_format_i18n( $percentageDiff, count( explode( '.', $percentageDiff ) ) )
: $percentageDiff;
$message = sprintf(
$message,
'<strong>' . aioseo()->helpers->compactNumber( absint( $intDifference ) ) . '</strong>',
'<strong>' . $percentageDiff . '%</strong>'
);
}
$milestones[] = [
'message' => $message,
'background' => '#f0f6ff',
'color' => '#004F9D',
'icon' => 'icon-milestone-impressions'
];
}
if ( is_numeric( $currentData['clicks'] ) && is_numeric( $difference['clicks'] ) ) {
$intDifference = intval( $difference['clicks'] );
$message = esc_html__( 'Your site has received the same number of clicks compared to the previous period.', 'all-in-one-seo-pack' );
if ( $intDifference > 0 ) {
// Translators: 1 - The number of clicks, 2 - The percentage increase.
$message = esc_html__( 'Your site has received %1$s more clicks compared to the previous period, which is a %2$s increase.', 'all-in-one-seo-pack' );
}
if ( $intDifference < 0 ) {
// Translators: 1 - The number of clicks, 2 - The percentage increase.
$message = esc_html__( 'Your site has received %1$s fewer clicks compared to the previous period, which is a %2$s decrease.', 'all-in-one-seo-pack' );
}
if ( false !== strpos( $message, '%1' ) ) {
$percentageDiff = 0 === absint( $currentData['clicks'] )
? 100
: round( ( absint( $intDifference ) / absint( $currentData['clicks'] ) ) * 100, 2 );
$percentageDiff = false !== strpos( $percentageDiff, '.' )
? number_format_i18n( $percentageDiff, count( explode( '.', $percentageDiff ) ) )
: $percentageDiff;
$message = sprintf(
$message,
'<strong>' . aioseo()->helpers->compactNumber( absint( $intDifference ) ) . '</strong>',
'<strong>' . $percentageDiff . '%</strong>'
);
}
$milestones[] = [
'message' => $message,
'background' => '#ecfdf5',
'color' => '#077647',
'icon' => 'icon-milestone-clicks'
];
}
if ( is_numeric( $currentData['ctr'] ) && is_numeric( $difference['ctr'] ) ) {
$intDifference = floatval( $difference['ctr'] );
$message = esc_html__( 'Your site has the same CTR compared to the previous period.', 'all-in-one-seo-pack' );
if ( $intDifference > 0 ) {
// Translators: 1 - The CTR.
$message = esc_html__( 'Your site has a %1$s higher CTR compared to the previous period.', 'all-in-one-seo-pack' );
}
if ( $intDifference < 0 ) {
// Translators: 1 - The CTR.
$message = esc_html__( 'Your site has a %1$s lower CTR compared to the previous period.', 'all-in-one-seo-pack' );
}
if ( false !== strpos( $message, '%1' ) ) {
$message = sprintf(
$message,
'<strong>' . number_format_i18n( abs( $intDifference ), count( explode( '.', $intDifference ) ) ) . '%</strong>'
);
}
$milestones[] = [
'message' => $message,
'background' => '#fffbeb',
'color' => '#be6903',
'icon' => 'icon-milestone-ctr'
];
}
if ( is_numeric( $currentData['keywords'] ) && is_numeric( $difference['keywords'] ) ) {
$intDifference = intval( $difference['keywords'] );
$message = esc_html__( 'Your site ranked for the same number of keywords compared to the previous period.', 'all-in-one-seo-pack' );
if ( $intDifference > 0 ) {
// Translators: 1 - The number of keywords, 2 - The percentage increase.
$message = esc_html__( 'Your site ranked for %1$s more keywords compared to the previous period, which is a %2$s increase.', 'all-in-one-seo-pack' );
}
if ( $intDifference < 0 ) {
// Translators: 1 - The number of keywords, 2 - The percentage increase.
$message = esc_html__( 'Your site ranked for %1$s fewer keywords compared to the previous period, which is a %2$s decrease.', 'all-in-one-seo-pack' );
}
if ( false !== strpos( $message, '%1' ) ) {
$percentageDiff = 0 === absint( $currentData['keywords'] )
? 100
: round( ( absint( $intDifference ) / absint( $currentData['keywords'] ) ) * 100, 2 );
$percentageDiff = false !== strpos( $percentageDiff, '.' )
? number_format_i18n( $percentageDiff, count( explode( '.', $percentageDiff ) ) )
: $percentageDiff;
$message = sprintf(
$message,
'<strong>' . aioseo()->helpers->compactNumber( absint( $intDifference ) ) . '</strong>',
'<strong>' . $percentageDiff . '%</strong>'
);
}
$milestones[] = [
'message' => $message,
'background' => '#fef2f2',
'color' => '#ab2039',
'icon' => 'icon-milestone-keywords'
];
}
return $milestones;
}
/**
* Retrieves the keyword performance data.
*
* @since 4.7.2
*
* @return array The keyword performance data or an empty array.
*/
public function getKeywords() {
if ( ! $this->keywords ) {
return [];
}
$result = [
'winning' => [
'url' => add_query_arg( [
'aioseo-scroll' => 'aioseo-search-statistics-keywords-table',
'aioseo-tab' => 'keyword-rank-tracker',
'tab' => 'AllKeywords',
'table-filter' => 'TopWinningKeywords'
], $this->searchStatisticsUrl ),
'items' => []
],
'losing' => [
'url' => add_query_arg( [
'aioseo-scroll' => 'aioseo-search-statistics-keywords-table',
'aioseo-tab' => 'keyword-rank-tracker',
'tab' => 'AllKeywords',
'table-filter' => 'TopLosingKeywords'
], $this->searchStatisticsUrl ),
'items' => []
]
];
foreach ( array_slice( $this->keywords['topWinning'], 0, 3 ) as $row ) {
$result['winning']['items'][] = [
'title' => $row['keyword'],
'clicks' => $this->parseClicks( $row['clicks'] ),
'difference' => [
'clicks' => $this->parseDifference( $row['difference']['clicks'] ?? '' ),
]
];
}
foreach ( array_slice( $this->keywords['topLosing'], 0, 3 ) as $row ) {
$result['losing']['items'][] = [
'title' => $row['keyword'],
'clicks' => $this->parseClicks( $row['clicks'] ),
'difference' => [
'clicks' => $this->parseDifference( $row['difference']['clicks'] ?? '' ),
]
];
}
return $result;
}
/**
* Retrieves the posts data.
*
* @since 4.7.2
*
* @return array The posts' data.
*/
public function getAioPosts() {
$result = [
'publish' => [],
'optimize' => [],
'cta' => [
'text' => esc_html__( 'Create New Post', 'all-in-one-seo-pack' ),
'url' => admin_url( 'post-new.php' )
],
];
// 1. Retrieve the published posts.
$publishPosts = aioseo()->core->db
->start( 'posts as wp' )
->select( 'wp.ID, wp.post_title, aio.seo_score' )
->join( 'aioseo_posts as aio', 'aio.post_id = wp.ID', 'INNER' )
->whereIn( 'wp.post_type', [ 'post' ] )
->whereIn( 'wp.post_status', [ 'publish' ] )
->orderBy( 'wp.post_date DESC' )
->limit( 5 )
->run()
->result();
if ( $publishPosts ) {
$items = $this->parsePosts( $publishPosts );
$result['publish'] = [
'url' => admin_url( 'edit.php?post_status=publish&post_type=post' ),
'items' => $items,
'show_stats' => ! empty( array_filter( array_column( $items, 'stats' ) ) ),
'show_tru_seo' => ! empty( array_filter( array_column( $items, 'tru_seo' ) ) ),
];
}
// 2. Retrieve the posts to optimize.
$optimizePosts = aioseo()->searchStatistics->getContentRankingsData( [
'endDate' => gmdate( 'Y-m-d', $this->dateRange['endDateRaw'] ),
'orderBy' => 'decayPercent',
'orderDir' => 'asc',
'limit' => '3',
'offset' => '0',
'filter' => 'all',
] );
if ( is_array( $optimizePosts['data']['paginated']['rows'] ?? '' ) ) {
$items = [];
foreach ( array_slice( $optimizePosts['data']['paginated']['rows'], 0, 3 ) as $i => $row ) {
$postId = $row['objectId'] ?? 0;
$items[ $i ] = [
'title' => $row['objectTitle'],
'url' => get_permalink( $postId ),
'image_url' => $this->getThumbnailUrl( $postId ),
'tru_seo' => aioseo()->helpers->isTruSeoEligible( $postId ) ? $this->parseSeoScore( $row['seoScore'] ?? 0 ) : [],
'decay_percent' => $this->parseDifference( $row['decayPercent'] ?? '', true ),
'issues' => [
'url' => add_query_arg( [
'aioseo-tab' => 'post-detail',
'post' => $postId
], $this->searchStatisticsUrl ),
'items' => []
]
];
$aioPost = Models\Post::getPost( $postId );
if ( $aioPost ) {
$items[ $i ]['issues']['items'] = aioseo()->searchStatistics->helpers->getSuggestedChanges( $aioPost );
}
}
$result['optimize'] = [
'url' => add_query_arg( [
'aioseo-tab' => 'content-rankings',
], $this->searchStatisticsUrl ),
'items' => $items,
'show_tru_seo' => ! empty( array_filter( array_column( $items, 'tru_seo' ) ) ),
];
}
return $result;
}
/**
* Retrieves the resources data.
*
* @since 4.7.2
*
* @return array The resources' data.
*/
public function getResources() {
$items = aioseo()->helpers->fetchAioseoArticles( true );
return array_slice( array_filter( $items ), 0, 3 );
}
/**
* Returns if Search Statistics content is allowed.
*
* @since 4.7.3
*
* @return bool Whether Search Statistics content is allowed.
*/
public function allowSearchStatistics() {
static $return = null;
if ( isset( $return ) ) {
return $return;
}
$return = aioseo()->searchStatistics->api->auth->isConnected() &&
aioseo()->license &&
aioseo()->license->hasCoreFeature( 'search-statistics', 'seo-statistics' ) &&
aioseo()->license->hasCoreFeature( 'search-statistics', 'keyword-rankings' );
return $return;
}
/**
* Parses the SEO score.
*
* @since 4.7.2
*
* @param int|string $score The SEO score.
* @return array The parsed SEO score.
*/
private function parseSeoScore( $score ) {
$score = intval( $score );
$parsed = [
'value' => $score,
'color' => '#a1a1a1',
'text' => $score ? "$score/100" : esc_html__( 'N/A', 'all-in-one-seo-pack' ),
];
if ( $parsed['value'] > 79 ) {
$parsed['color'] = '#00aa63';
} elseif ( $parsed['value'] > 49 ) {
$parsed['color'] = '#ff8c00';
} elseif ( $parsed['value'] > 0 ) {
$parsed['color'] = '#df2a4a';
}
return $parsed;
}
/**
* Parses a difference.
*
* @since 4.7.2
*
* @param int|string $number The number to parse.
* @param bool $percentage Whether to return the text result as a percentage.
* @return array The parsed result.
*/
private function parseDifference( $number, $percentage = false ) {
$parsed = [
'color' => '#a1a1a1',
'text' => esc_html__( 'N/A', 'all-in-one-seo-pack' ),
];
if ( ! is_numeric( $number ) ) {
return $parsed;
}
$number = intval( $number );
$parsed['text'] = aioseo()->helpers->compactNumber( absint( $number ) );
if ( $percentage ) {
$parsed['text'] = $number . '%';
}
if ( $number > 0 ) {
$parsed['color'] = '#00aa63';
} elseif ( $number < 0 ) {
$parsed['color'] = '#df2a4a';
}
return $parsed;
}
/**
* Parses the clicks number.
*
* @since 4.7.2
*
* @param float|int|string $number The number of clicks.
* @return string The parsed number of clicks.
*/
private function parseClicks( $number ) {
return aioseo()->helpers->compactNumber( $number );
}
/**
* Parses the posts data.
*
* @since 4.7.2
*
* @param array $posts The posts.
* @return array The parsed posts' data.
*/
private function parsePosts( $posts ) {
$parsed = [];
foreach ( $posts as $k => $item ) {
$parsed[ $k ] = [
'title' => aioseo()->helpers->truncate( $item->post_title, 75 ),
'url' => get_permalink( $item->ID ),
'image_url' => $this->getThumbnailUrl( $item->ID ),
'tru_seo' => aioseo()->helpers->isTruSeoEligible( $item->ID ) ? $this->parseSeoScore( $item->seo_score ?? 0 ) : [],
'stats' => []
];
try {
$statistics = [];
if (
$this->allowSearchStatistics() &&
method_exists( aioseo()->searchStatistics, 'getPostDetailSeoStatisticsData' )
) {
$statistics = aioseo()->searchStatistics->getPostDetailSeoStatisticsData( [
'startDate' => gmdate( 'Y-m-d', $this->dateRange['startDateRaw'] ),
'endDate' => gmdate( 'Y-m-d', $this->dateRange['endDateRaw'] ),
'postId' => $item->ID,
], false );
}
if ( isset( $statistics['data']['statistics']['position'] ) ) {
$parsed[ $k ]['stats'][] = [
'icon' => 'position',
'label' => esc_html__( 'Position', 'all-in-one-seo-pack' ),
'value' => round( floatval( $statistics['data']['statistics']['position'] ) ),
];
}
if ( isset( $statistics['data']['statistics']['ctr'] ) ) {
$value = round( floatval( $statistics['data']['statistics']['ctr'] ), 2 );
$parsed[ $k ]['stats'][] = [
'icon' => 'ctr',
'label' => 'CTR',
'value' => ( number_format_i18n( $value, count( explode( '.', $value ) ) ) ) . '%',
];
}
if ( isset( $statistics['data']['statistics']['impressions'] ) ) {
$parsed[ $k ]['stats'][] = [
'icon' => 'impressions',
'label' => esc_html__( 'Impressions', 'all-in-one-seo-pack' ),
'value' => aioseo()->helpers->compactNumber( $statistics['data']['statistics']['impressions'] ),
];
}
} catch ( \Exception $e ) {
// Do nothing.
}
}
return $parsed;
}
/**
* Retrieves the thumbnail URL.
*
* @since 4.7.2
*
* @param int $postId The post ID.
* @return string The post featured image URL (thumbnail size).
*/
private function getThumbnailUrl( $postId ) {
$imageUrl = get_the_post_thumbnail_url( $postId );
return $imageUrl ?: $this->featuredImagePlaceholder;
}
} home/xbodynamge/dev/wp-content/plugins/all-in-one-seo-pack/app/Common/Sitemap/Content.php 0000644 00000074527 15115527142 0025400 0 ustar 00 <?php
namespace AIOSEO\Plugin\Common\Sitemap;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\Plugin\Common\Integrations\BuddyPress as BuddyPressIntegration;
/**
* Determines which content should be included in the sitemap.
*
* @since 4.0.0
*/
class Content {
/**
* Returns the entries for the requested sitemap.
*
* @since 4.0.0
*
* @return array The sitemap entries.
*/
public function get() {
if ( ! in_array( aioseo()->sitemap->type, [ 'general', 'rss' ], true ) || ! $this->isEnabled() ) {
return [];
}
if ( 'rss' === aioseo()->sitemap->type ) {
return $this->rss();
}
if ( 'general' !== aioseo()->sitemap->type ) {
return [];
}
$indexesEnabled = aioseo()->options->sitemap->general->indexes;
if ( ! $indexesEnabled ) {
if ( 'root' === aioseo()->sitemap->indexName ) {
// If indexes are disabled, throw all entries together into one big file.
return $this->nonIndexed();
}
return [];
}
if ( 'root' === aioseo()->sitemap->indexName ) {
return aioseo()->sitemap->root->indexes();
}
// Check if requested index has a dedicated method.
$methodName = aioseo()->helpers->dashesToCamelCase( aioseo()->sitemap->indexName );
if ( method_exists( $this, $methodName ) ) {
return $this->$methodName();
}
// Check if requested index is a registered post type.
if ( in_array( aioseo()->sitemap->indexName, aioseo()->sitemap->helpers->includedPostTypes(), true ) ) {
return $this->posts( aioseo()->sitemap->indexName );
}
// Check if requested index is a registered taxonomy.
if (
in_array( aioseo()->sitemap->indexName, aioseo()->sitemap->helpers->includedTaxonomies(), true ) &&
'product_attributes' !== aioseo()->sitemap->indexName
) {
return $this->terms( aioseo()->sitemap->indexName );
}
if (
aioseo()->helpers->isWooCommerceActive() &&
in_array( aioseo()->sitemap->indexName, aioseo()->sitemap->helpers->includedTaxonomies(), true ) &&
'product_attributes' === aioseo()->sitemap->indexName
) {
return $this->productAttributes();
}
return [];
}
/**
* Returns the total entries number for the requested sitemap.
*
* @since 4.1.5
*
* @return int The total entries number.
*/
public function getTotal() {
if ( ! in_array( aioseo()->sitemap->type, [ 'general', 'rss' ], true ) || ! $this->isEnabled() ) {
return 0;
}
if ( 'rss' === aioseo()->sitemap->type ) {
return count( $this->rss() );
}
if ( 'general' !== aioseo()->sitemap->type ) {
return 0;
}
$indexesEnabled = aioseo()->options->sitemap->general->indexes;
if ( ! $indexesEnabled ) {
if ( 'root' === aioseo()->sitemap->indexName ) {
// If indexes are disabled, throw all entries together into one big file.
return count( $this->nonIndexed() );
}
return 0;
}
if ( 'root' === aioseo()->sitemap->indexName ) {
return count( aioseo()->sitemap->root->indexes() );
}
// Check if requested index has a dedicated method.
$methodName = aioseo()->helpers->dashesToCamelCase( aioseo()->sitemap->indexName );
if ( method_exists( $this, $methodName ) ) {
$res = $this->$methodName();
return ! empty( $res ) ? count( $res ) : 0;
}
// Check if requested index is a registered post type.
if ( in_array( aioseo()->sitemap->indexName, aioseo()->sitemap->helpers->includedPostTypes(), true ) ) {
return aioseo()->sitemap->query->posts( aioseo()->sitemap->indexName, [ 'count' => true ] );
}
// Check if requested index is a registered taxonomy.
if ( in_array( aioseo()->sitemap->indexName, aioseo()->sitemap->helpers->includedTaxonomies(), true ) ) {
return aioseo()->sitemap->query->terms( aioseo()->sitemap->indexName, [ 'count' => true ] );
}
return 0;
}
/**
* Checks if the requested sitemap is enabled.
*
* @since 4.0.0
*
* @return boolean Whether the sitemap is enabled.
*/
public function isEnabled() {
$options = aioseo()->options->noConflict();
if ( ! $options->sitemap->{aioseo()->sitemap->type}->enable ) {
return false;
}
if ( $options->sitemap->{aioseo()->sitemap->type}->postTypes->all ) {
return true;
}
$included = aioseo()->sitemap->helpers->includedPostTypes();
return ! empty( $included );
}
/**
* Returns all sitemap entries if indexing is disabled.
*
* @since 4.0.0
*
* @return array $entries The sitemap entries.
*/
private function nonIndexed() {
$additional = $this->addl();
$postTypes = aioseo()->sitemap->helpers->includedPostTypes();
$isStaticHomepage = 'page' === get_option( 'show_on_front' );
$blogPageEntry = [];
$homePageEntry = ! $isStaticHomepage ? [ array_shift( $additional ) ] : [];
$entries = array_merge( $additional, $this->author(), $this->date(), $this->postArchive() );
if ( $postTypes ) {
foreach ( $postTypes as $postType ) {
$postTypeEntries = $this->posts( $postType );
// If we don't have a static homepage, it's business as usual.
if ( ! $isStaticHomepage ) {
$entries = array_merge( $entries, $postTypeEntries );
continue;
}
$homePageId = (int) get_option( 'page_on_front' );
$blogPageId = (int) get_option( 'page_for_posts' );
if ( 'post' === $postType && $blogPageId ) {
$blogPageEntry[] = array_shift( $postTypeEntries );
}
if ( 'page' === $postType && $homePageId ) {
$homePageEntry[] = array_shift( $postTypeEntries );
}
$entries = array_merge( $entries, $postTypeEntries );
}
}
$taxonomies = aioseo()->sitemap->helpers->includedTaxonomies();
if ( $taxonomies ) {
foreach ( $taxonomies as $taxonomy ) {
$entries = array_merge( $entries, $this->terms( $taxonomy ) );
}
}
// Sort first by priority, then by last modified date.
usort( $entries, function ( $a, $b ) {
// If the priorities are equal, sort by last modified date.
if ( $a['priority'] === $b['priority'] ) {
return $a['lastmod'] > $b['lastmod'] ? -1 : 1;
}
return $a['priority'] > $b['priority'] ? -1 : 1;
} );
// Merge the arrays with the home page always first.
return array_merge( $homePageEntry, $blogPageEntry, $entries );
}
/**
* Returns all post entries for a given post type.
*
* @since 4.0.0
*
* @param string $postType The name of the post type.
* @param array $additionalArgs Any additional arguments for the post query.
* @return array The sitemap entries.
*/
public function posts( $postType, $additionalArgs = [] ) {
$posts = aioseo()->sitemap->query->posts( $postType, $additionalArgs );
if ( ! $posts ) {
return [];
}
// Return if we're determining the root indexes.
if ( ! empty( $additionalArgs['root'] ) && $additionalArgs['root'] ) {
return $posts;
}
$entries = [];
$isStaticHomepage = 'page' === get_option( 'show_on_front' );
$homePageId = (int) get_option( 'page_on_front' );
$excludeImages = aioseo()->sitemap->helpers->excludeImages();
foreach ( $posts as $post ) {
$entry = [
'loc' => get_permalink( $post->ID ),
'lastmod' => aioseo()->helpers->dateTimeToIso8601( $this->getLastModified( $post ) ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'postTypes', $post, $postType ),
'priority' => aioseo()->sitemap->priority->priority( 'postTypes', $post, $postType ),
];
if ( ! $excludeImages ) {
$entry['images'] = ! empty( $post->images ) ? json_decode( $post->images ) : [];
}
// Override priority/frequency for static homepage.
if ( $isStaticHomepage && ( $homePageId === $post->ID || aioseo()->helpers->wpmlIsHomePage( $post->ID ) ) ) {
$entry['loc'] = aioseo()->helpers->maybeRemoveTrailingSlash( aioseo()->helpers->wpmlHomeUrl( $post->ID ) ?: $entry['loc'] );
$entry['changefreq'] = aioseo()->sitemap->priority->frequency( 'homePage' );
$entry['priority'] = aioseo()->sitemap->priority->priority( 'homePage' );
}
$entries[] = apply_filters( 'aioseo_sitemap_post', $entry, $post->ID, $postType, 'post' );
}
// We can't remove the post type here because other plugins rely on it.
return apply_filters( 'aioseo_sitemap_posts', $entries, $postType );
}
/**
* Returns all post archive entries.
*
* @since 4.0.0
*
* @return array $entries The sitemap entries.
*/
private function postArchive() {
$entries = [];
foreach ( aioseo()->sitemap->helpers->includedPostTypes( true ) as $postType ) {
if (
aioseo()->dynamicOptions->noConflict()->searchAppearance->archives->has( $postType ) &&
! aioseo()->dynamicOptions->searchAppearance->archives->$postType->advanced->robotsMeta->default &&
aioseo()->dynamicOptions->searchAppearance->archives->$postType->advanced->robotsMeta->noindex
) {
continue;
}
$post = aioseo()->core->db
->start( aioseo()->core->db->db->posts . ' as p', true )
->select( 'p.ID' )
->where( 'p.post_status', 'publish' )
->where( 'p.post_type', $postType )
->limit( 1 )
->run()
->result();
if ( ! $post ) {
continue;
}
$url = get_post_type_archive_link( $postType );
if ( $url ) {
$entry = [
'loc' => $url,
'lastmod' => aioseo()->sitemap->helpers->lastModifiedPostTime( $postType ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'archive' ),
'priority' => aioseo()->sitemap->priority->priority( 'archive' ),
];
// To be consistent with our other entry filters, we need to pass the entry ID as well, but as null in this case.
$entries[] = apply_filters( 'aioseo_sitemap_archive_entry', $entry, null, $postType, 'archive' );
}
}
return apply_filters( 'aioseo_sitemap_post_archives', $entries );
}
/**
* Returns all term entries for a given taxonomy.
*
* @since 4.0.0
*
* @param string $taxonomy The name of the taxonomy.
* @param array $additionalArgs Any additional arguments for the term query.
* @return array The sitemap entries.
*/
public function terms( $taxonomy, $additionalArgs = [] ) {
$terms = aioseo()->sitemap->query->terms( $taxonomy, $additionalArgs );
if ( ! $terms ) {
return [];
}
// Get all registered post types for the taxonomy.
$postTypes = [];
foreach ( get_post_types() as $postType ) {
$taxonomies = get_object_taxonomies( $postType );
foreach ( $taxonomies as $name ) {
if ( $taxonomy === $name ) {
$postTypes[] = $postType;
}
}
}
// Return if we're determining the root indexes.
if ( ! empty( $additionalArgs['root'] ) && $additionalArgs['root'] ) {
return $terms;
}
$entries = [];
foreach ( $terms as $term ) {
$entry = [
'loc' => get_term_link( $term->term_id ),
'lastmod' => $this->getTermLastModified( $term ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'taxonomies', $term, $taxonomy ),
'priority' => aioseo()->sitemap->priority->priority( 'taxonomies', $term, $taxonomy ),
'images' => aioseo()->sitemap->image->term( $term )
];
$entries[] = apply_filters( 'aioseo_sitemap_term', $entry, $term->term_id, $term->taxonomy, 'term' );
}
return apply_filters( 'aioseo_sitemap_terms', $entries );
}
/**
* Returns the last modified date for a given term.
*
* @since 4.0.0
*
* @param int|object $term The term data object.
* @return string The lastmod timestamp.
*/
public function getTermLastModified( $term ) {
$termRelationshipsTable = aioseo()->core->db->db->prefix . 'term_relationships';
$termTaxonomyTable = aioseo()->core->db->db->prefix . 'term_taxonomy';
// If the term is an ID, get the term object.
if ( is_numeric( $term ) ) {
$term = aioseo()->helpers->getTerm( $term );
}
// First, check the count of the term. If it's 0, then we're dealing with a parent term that does not have
// posts assigned to it. In this case, we need to get the last modified date of all its children.
if ( empty( $term->count ) ) {
$lastModified = aioseo()->core->db
->start( aioseo()->core->db->db->posts . ' as p', true )
->select( 'MAX(`p`.`post_modified_gmt`) as last_modified' )
->where( 'p.post_status', 'publish' )
->whereRaw( "
( `p`.`ID` IN
(
SELECT CONVERT(`tr`.`object_id`, unsigned)
FROM `$termRelationshipsTable` as tr
JOIN `$termTaxonomyTable` as tt ON `tr`.`term_taxonomy_id` = `tt`.`term_taxonomy_id`
WHERE `tt`.`term_id` IN
(
SELECT `tt`.`term_id`
FROM `$termTaxonomyTable` as tt
WHERE `tt`.`parent` = '{$term->term_id}'
)
)
)" )
->run()
->result();
} else {
$lastModified = aioseo()->core->db
->start( aioseo()->core->db->db->posts . ' as p', true )
->select( 'MAX(`p`.`post_modified_gmt`) as last_modified' )
->where( 'p.post_status', 'publish' )
->whereRaw( "
( `p`.`ID` IN
(
SELECT CONVERT(`tr`.`object_id`, unsigned)
FROM `$termRelationshipsTable` as tr
JOIN `$termTaxonomyTable` as tt ON `tr`.`term_taxonomy_id` = `tt`.`term_taxonomy_id`
WHERE `tt`.`term_id` = '{$term->term_id}'
)
)" )
->run()
->result();
}
$lastModified = $lastModified[0]->last_modified ?? '';
return aioseo()->helpers->dateTimeToIso8601( $lastModified );
}
/**
* Returns all additional pages.
*
* @since 4.0.0
*
* @param bool $shouldChunk Whether the entries should be chuncked. Is set to false when the static sitemap is generated.
* @return array The sitemap entries.
*/
public function addl( $shouldChunk = true ) {
$additionalPages = [];
if ( aioseo()->options->sitemap->general->additionalPages->enable ) {
$additionalPages = array_map( 'json_decode', aioseo()->options->sitemap->general->additionalPages->pages );
$additionalPages = array_filter( $additionalPages, function( $additionalPage ) {
return ! empty( $additionalPage->url );
} );
}
$entries = [];
foreach ( $additionalPages as $additionalPage ) {
$entries[] = [
'loc' => $additionalPage->url,
'lastmod' => aioseo()->sitemap->helpers->lastModifiedAdditionalPage( $additionalPage ),
'changefreq' => $additionalPage->frequency->value,
'priority' => $additionalPage->priority->value,
'isTimezone' => true
];
}
$postTypes = aioseo()->sitemap->helpers->includedPostTypes();
$shouldIncludeHomepage = 'posts' === get_option( 'show_on_front' ) || ! in_array( 'page', $postTypes, true );
if ( $shouldIncludeHomepage ) {
$frontPageId = (int) get_option( 'page_on_front' );
$frontPageUrl = aioseo()->helpers->localizedUrl( '/' );
$post = aioseo()->helpers->getPost( $frontPageId );
$homepageEntry = [
'loc' => aioseo()->helpers->maybeRemoveTrailingSlash( $frontPageUrl ),
'lastmod' => $post ? aioseo()->helpers->dateTimeToIso8601( $this->getLastModified( $post ) ) : aioseo()->sitemap->helpers->lastModifiedPostTime(),
'changefreq' => aioseo()->sitemap->priority->frequency( 'homePage' ),
'priority' => aioseo()->sitemap->priority->priority( 'homePage' )
];
$translatedHomepages = aioseo()->helpers->wpmlHomePages();
foreach ( $translatedHomepages as $languageCode => $translatedHomepage ) {
if ( untrailingslashit( $translatedHomepage['url'] ) !== untrailingslashit( $homepageEntry['loc'] ) ) {
$homepageEntry['languages'][] = [
'language' => $languageCode,
'location' => $translatedHomepage['url']
];
}
}
// Add homepage to the first position.
array_unshift( $entries, $homepageEntry );
}
if ( aioseo()->options->sitemap->general->additionalPages->enable ) {
$entries = apply_filters( 'aioseo_sitemap_additional_pages', $entries );
}
if ( empty( $entries ) ) {
return [];
}
if ( aioseo()->options->sitemap->general->indexes && $shouldChunk ) {
$entries = aioseo()->sitemap->helpers->chunkEntries( $entries );
$entries = $entries[ aioseo()->sitemap->pageNumber ] ?? [];
}
return $entries;
}
/**
* Returns all author archive entries.
*
* @since 4.0.0
*
* @return array The sitemap entries.
*/
public function author() {
if (
! aioseo()->sitemap->helpers->lastModifiedPost() ||
! aioseo()->options->sitemap->general->author ||
! aioseo()->options->searchAppearance->archives->author->show ||
(
! aioseo()->options->searchAppearance->archives->author->advanced->robotsMeta->default &&
aioseo()->options->searchAppearance->archives->author->advanced->robotsMeta->noindex
) ||
(
aioseo()->options->searchAppearance->archives->author->advanced->robotsMeta->default &&
(
! aioseo()->options->searchAppearance->advanced->globalRobotsMeta->default &&
aioseo()->options->searchAppearance->advanced->globalRobotsMeta->noindex
)
)
) {
return [];
}
// Allow users to filter the authors in case their sites use a membership plugin or have custom code that affect the authors on their site.
// e.g. there might be additional roles/conditions that need to be checked here.
$authors = apply_filters( 'aioseo_sitemap_authors', [] );
if ( empty( $authors ) ) {
$usersTableName = aioseo()->core->db->db->users; // We get the table name from WPDB since multisites share the same table.
$authors = aioseo()->core->db->start( "$usersTableName as u", true )
->select( 'u.ID as ID, u.user_nicename as nicename, MAX(p.post_modified_gmt) as lastModified' )
->join( 'posts as p', 'u.ID = p.post_author' )
->where( 'p.post_status', 'publish' )
->whereIn( 'p.post_type', aioseo()->sitemap->helpers->getAuthorPostTypes() )
->groupBy( 'u.ID' )
->orderBy( 'lastModified DESC' )
->limit( aioseo()->sitemap->linksPerIndex, aioseo()->sitemap->pageNumber * aioseo()->sitemap->linksPerIndex )
->run()
->result();
}
if ( empty( $authors ) ) {
return [];
}
$entries = [];
foreach ( $authors as $authorData ) {
$entry = [
'loc' => ! empty( $authorData->authorUrl )
? $authorData->authorUrl
: get_author_posts_url( $authorData->ID, $authorData->nicename ?: '' ),
'lastmod' => aioseo()->helpers->dateTimeToIso8601( $authorData->lastModified ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'author' ),
'priority' => aioseo()->sitemap->priority->priority( 'author' )
];
$entries[] = apply_filters( 'aioseo_sitemap_author_entry', $entry, $authorData->ID, $authorData->nicename, 'author' );
}
return apply_filters( 'aioseo_sitemap_author_archives', $entries );
}
/**
* Returns all data archive entries.
*
* @since 4.0.0
*
* @return array The sitemap entries.
*/
public function date() {
if (
! aioseo()->sitemap->helpers->lastModifiedPost() ||
! aioseo()->options->sitemap->general->date ||
! aioseo()->options->searchAppearance->archives->date->show ||
(
! aioseo()->options->searchAppearance->archives->date->advanced->robotsMeta->default &&
aioseo()->options->searchAppearance->archives->date->advanced->robotsMeta->noindex
) ||
(
aioseo()->options->searchAppearance->archives->date->advanced->robotsMeta->default &&
(
! aioseo()->options->searchAppearance->advanced->globalRobotsMeta->default &&
aioseo()->options->searchAppearance->advanced->globalRobotsMeta->noindex
)
)
) {
return [];
}
$postsTable = aioseo()->core->db->db->posts;
$dates = aioseo()->core->db->execute(
"SELECT
YEAR(post_date) AS `year`,
MONTH(post_date) AS `month`,
post_date_gmt,
post_modified_gmt
FROM {$postsTable}
WHERE post_type = 'post' AND post_status = 'publish'
GROUP BY
YEAR(post_date),
MONTH(post_date)
ORDER BY post_date ASC
LIMIT 50000",
true
)->result();
if ( empty( $dates ) ) {
return [];
}
$entries = [];
$year = '';
foreach ( $dates as $date ) {
$entry = [
'lastmod' => aioseo()->helpers->dateTimeToIso8601( $this->getLastModified( $date ) ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'date' ),
'priority' => aioseo()->sitemap->priority->priority( 'date' ),
];
// Include each year only once.
if ( $year !== $date->year ) {
$year = $date->year;
$entry['loc'] = get_year_link( $date->year );
$entries[] = apply_filters( 'aioseo_sitemap_date_entry', $entry, $date, 'year', 'date' );
}
$entry['loc'] = get_month_link( $date->year, $date->month );
$entries[] = apply_filters( 'aioseo_sitemap_date_entry', $entry, $date, 'month', 'date' );
}
return apply_filters( 'aioseo_sitemap_date_archives', $entries );
}
/**
* Returns all entries for the RSS Sitemap.
*
* @since 4.0.0
*
* @return array The sitemap entries.
*/
public function rss() {
$posts = aioseo()->sitemap->query->posts(
aioseo()->sitemap->helpers->includedPostTypes(),
[ 'orderBy' => '`p`.`post_modified_gmt` DESC' ]
);
if ( ! count( $posts ) ) {
return [];
}
$entries = [];
foreach ( $posts as $post ) {
$entry = [
'guid' => get_permalink( $post->ID ),
'title' => get_the_title( $post ),
'description' => get_post_field( 'post_excerpt', $post->ID ),
'pubDate' => aioseo()->helpers->dateTimeToRfc822( $this->getLastModified( $post ) )
];
// If the entry is the homepage, we need to check if the permalink structure
// does not have a trailing slash. If so, we need to strip it because WordPress adds it
// regardless for the home_url() in get_page_link() which is used in the get_permalink() function.
static $homeId = null;
if ( null === $homeId ) {
$homeId = get_option( 'page_for_posts' );
}
if ( aioseo()->helpers->getHomePageId() === $post->ID ) {
$entry['guid'] = aioseo()->helpers->maybeRemoveTrailingSlash( $entry['guid'] );
}
$entries[] = apply_filters( 'aioseo_sitemap_post_rss', $entry, $post->ID, $post->post_type, 'post' );
}
usort( $entries, function( $a, $b ) {
return $a['pubDate'] < $b['pubDate'] ? 1 : 0;
});
return apply_filters( 'aioseo_sitemap_rss', $entries );
}
/**
* Returns the last modified date for a given post.
*
* @since 4.6.3
*
* @param object $post The post object.
*
* @return string The last modified date.
*/
public function getLastModified( $post ) {
$publishDate = $post->post_date_gmt;
$lastModifiedDate = $post->post_modified_gmt;
// Get the date which is the latest.
return $lastModifiedDate > $publishDate ? $lastModifiedDate : $publishDate;
}
/**
* Returns all entries for the BuddyPress Activity Sitemap.
* This method is automagically called from {@see get()} if the current index name equals to 'bp-activity'
*
* @since 4.7.6
*
* @return array The sitemap entries.
*/
public function bpActivity() {
$entries = [];
if ( ! in_array( aioseo()->sitemap->indexName, aioseo()->sitemap->helpers->includedPostTypes(), true ) ) {
return $entries;
}
$postType = 'bp-activity';
$query = aioseo()->core->db
->start( 'bp_activity as a' )
->select( '`a`.`id`, `a`.`date_recorded`' )
->whereRaw( "a.is_spam = 0 AND a.hide_sitewide = 0 AND a.type NOT IN ('activity_comment', 'last_activity')" )
->limit( aioseo()->sitemap->linksPerIndex, aioseo()->sitemap->offset )
->orderBy( 'a.date_recorded DESC' );
$items = $query->run()
->result();
foreach ( $items as $item ) {
$entry = [
'loc' => BuddyPressIntegration::getComponentSingleUrl( 'activity', $item->id ),
'lastmod' => aioseo()->helpers->dateTimeToIso8601( $item->date_recorded ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'postTypes', false, $postType ),
'priority' => aioseo()->sitemap->priority->priority( 'postTypes', false, $postType ),
];
$entries[] = apply_filters( 'aioseo_sitemap_post', $entry, $item->id, $postType );
}
$archiveUrl = BuddyPressIntegration::getComponentArchiveUrl( 'activity' );
if (
aioseo()->helpers->isUrl( $archiveUrl ) &&
! in_array( $postType, aioseo()->helpers->getNoindexedObjects( 'archives' ), true )
) {
$lastMod = ! empty( $items[0] ) ? $items[0]->date_recorded : current_time( 'mysql' );
$entry = [
'loc' => $archiveUrl,
'lastmod' => $lastMod,
'changefreq' => aioseo()->sitemap->priority->frequency( 'postTypes', false, $postType ),
'priority' => aioseo()->sitemap->priority->priority( 'postTypes', false, $postType ),
];
array_unshift( $entries, $entry );
}
return apply_filters( 'aioseo_sitemap_posts', $entries, $postType );
}
/**
* Returns all entries for the BuddyPress Group Sitemap.
* This method is automagically called from {@see get()} if the current index name equals to 'bp-group'
*
* @since 4.7.6
*
* @return array The sitemap entries.
*/
public function bpGroup() {
$entries = [];
if ( ! in_array( aioseo()->sitemap->indexName, aioseo()->sitemap->helpers->includedPostTypes(), true ) ) {
return $entries;
}
$postType = 'bp-group';
$query = aioseo()->core->db
->start( 'bp_groups as g' )
->select( '`g`.`id`, `g`.`date_created`, `gm`.`meta_value` as date_modified' )
->leftJoin( 'bp_groups_groupmeta as gm', 'g.id = gm.group_id' )
->whereRaw( "g.status = 'public' AND gm.meta_key = 'last_activity'" )
->limit( aioseo()->sitemap->linksPerIndex, aioseo()->sitemap->offset )
->orderBy( 'gm.meta_value DESC' )
->orderBy( 'g.date_created DESC' );
$items = $query->run()
->result();
foreach ( $items as $item ) {
$lastMod = $item->date_modified ?: $item->date_created;
$entry = [
'loc' => BuddyPressIntegration::getComponentSingleUrl( 'group', BuddyPressIntegration::callFunc( 'bp_get_group_by', 'id', $item->id ) ),
'lastmod' => aioseo()->helpers->dateTimeToIso8601( $lastMod ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'postTypes', false, $postType ),
'priority' => aioseo()->sitemap->priority->priority( 'postTypes', false, $postType ),
];
$entries[] = apply_filters( 'aioseo_sitemap_post', $entry, $item->id, $postType );
}
$archiveUrl = BuddyPressIntegration::getComponentArchiveUrl( 'group' );
if (
aioseo()->helpers->isUrl( $archiveUrl ) &&
! in_array( $postType, aioseo()->helpers->getNoindexedObjects( 'archives' ), true )
) {
$lastMod = ! empty( $items[0] ) ? $items[0]->date_modified : current_time( 'mysql' );
$entry = [
'loc' => $archiveUrl,
'lastmod' => $lastMod,
'changefreq' => aioseo()->sitemap->priority->frequency( 'postTypes', false, $postType ),
'priority' => aioseo()->sitemap->priority->priority( 'postTypes', false, $postType ),
];
array_unshift( $entries, $entry );
}
return apply_filters( 'aioseo_sitemap_posts', $entries, $postType );
}
/**
* Returns all entries for the BuddyPress Member Sitemap.
* This method is automagically called from {@see get()} if the current index name equals to 'bp-member'
*
* @since 4.7.6
*
* @return array The sitemap entries.
*/
public function bpMember() {
$entries = [];
if ( ! in_array( aioseo()->sitemap->indexName, aioseo()->sitemap->helpers->includedPostTypes(), true ) ) {
return $entries;
}
$postType = 'bp-member';
$query = aioseo()->core->db
->start( 'bp_activity as a' )
->select( '`a`.`user_id` as id, `a`.`date_recorded`' )
->whereRaw( "a.component = 'members' AND a.type = 'last_activity'" )
->limit( aioseo()->sitemap->linksPerIndex, aioseo()->sitemap->offset )
->orderBy( 'a.date_recorded DESC' );
$items = $query->run()
->result();
foreach ( $items as $item ) {
$entry = [
'loc' => BuddyPressIntegration::getComponentSingleUrl( 'member', $item->id ),
'lastmod' => aioseo()->helpers->dateTimeToIso8601( $item->date_recorded ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'postTypes', false, $postType ),
'priority' => aioseo()->sitemap->priority->priority( 'postTypes', false, $postType ),
];
$entries[] = apply_filters( 'aioseo_sitemap_post', $entry, $item->id, $postType );
}
$archiveUrl = BuddyPressIntegration::getComponentArchiveUrl( 'member' );
if (
aioseo()->helpers->isUrl( $archiveUrl ) &&
! in_array( $postType, aioseo()->helpers->getNoindexedObjects( 'archives' ), true )
) {
$lastMod = ! empty( $items[0] ) ? $items[0]->date_recorded : current_time( 'mysql' );
$entry = [
'loc' => $archiveUrl,
'lastmod' => $lastMod,
'changefreq' => aioseo()->sitemap->priority->frequency( 'postTypes', false, $postType ),
'priority' => aioseo()->sitemap->priority->priority( 'postTypes', false, $postType ),
];
array_unshift( $entries, $entry );
}
return apply_filters( 'aioseo_sitemap_posts', $entries, $postType );
}
/**
* Returns all entries for the WooCommerce Product Attributes sitemap.
* Note: This sitemap does not support pagination.
*
* @since 4.7.8
*
* @param bool $count Whether to return the count of the entries. This is used to determine the indexes.
* @return array The sitemap entries.
*/
public function productAttributes( $count = false ) {
$aioseoTermsTable = aioseo()->core->db->prefix . 'aioseo_terms';
$wcAttributeTaxonomiesTable = aioseo()->core->db->prefix . 'woocommerce_attribute_taxonomies';
$termTaxonomyTable = aioseo()->core->db->prefix . 'term_taxonomy';
$selectClause = 'COUNT(*) as childProductAttributes';
if ( ! $count ) {
$selectClause = aioseo()->pro ? 'tt.term_id, tt.taxonomy, at.frequency, at.priority' : 'tt.term_id, tt.taxonomy';
}
$joinClause = aioseo()->pro ? "LEFT JOIN {$aioseoTermsTable} AS at ON tt.term_id = at.term_id" : '';
$whereClause = aioseo()->pro ? 'AND (at.robots_noindex IS NULL OR at.robots_noindex = 0)' : '';
$limitClause = $count ? '' : 'LIMIT 50000';
$result = aioseo()->core->db->execute(
"SELECT {$selectClause}
FROM {$termTaxonomyTable} AS tt
JOIN {$wcAttributeTaxonomiesTable} AS wat ON tt.taxonomy = CONCAT('pa_', wat.attribute_name)
{$joinClause}
WHERE wat.attribute_public = 1
{$whereClause}
AND tt.count > 0
{$limitClause};",
true
)->result();
if ( $count ) {
return ! empty( $result[0]->childProductAttributes ) ? (int) $result[0]->childProductAttributes : 0;
}
if ( empty( $result ) ) {
return [];
}
$entries = [];
foreach ( $result as $term ) {
$term = (object) $term;
$termId = (int) $term->term_id;
$entry = [
'loc' => get_term_link( $termId ),
'lastmod' => $this->getTermLastModified( $termId ),
'changefreq' => aioseo()->sitemap->priority->frequency( 'taxonomies', $term, 'product_attributes' ),
'priority' => aioseo()->sitemap->priority->priority( 'taxonomies', $term, 'product_attributes' ),
'images' => aioseo()->sitemap->image->term( $term )
];
$entries[] = apply_filters( 'aioseo_sitemap_product_attributes', $entry, $termId, $term->taxonomy, 'term' );
}
return $entries;
}
}