| Server IP : 121.121.20.254 / Your IP : 216.73.216.202 Web Server : Microsoft-IIS/10.0 System : Windows NT WEB-SERVER 10.0 build 20348 (Windows Server 2022) AMD64 User : IUSR ( 0) PHP Version : 8.3.28 Disable Function : NONE MySQL : ON | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : C:/inetpub/wwwroot/KnowledgeBase/wp-content/plugins/aioseo-link-assistant/app/Models/ |
Upload File : |
<?php
namespace AIOSEO\Plugin\Addon\LinkAssistant\Models;
use AIOSEO\Plugin\Common\Models as CommonModels;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* The Link DB Model.
*
* @since 1.0.0
*/
class Link extends CommonModels\Model {
/**
* The name of the table in the database, without the prefix.
*
* @since 1.0.0
*
* @var string
*/
protected $table = 'aioseo_links';
/**
* Fields that should be numeric values.
*
* @since 1.0.0
*
* @var array
*/
protected $numericFields = [ 'id', 'post_id', 'linked_post_id' ];
/**
* Fields that are nullable.
*
* @since 1.0.0
*
* @var array
*/
protected $nullFields = [ 'linked_post_id' ];
/**
* Fields that should be boolean values.
*
* @since 1.0.0
*
* @var array
*/
protected $booleanFields = [
'internal',
'affiliate',
'external'
];
/**
* Appended as an extra column, but not stored in the DB.
*
* @since 1.0.0
*
* @var array
*/
protected $appends = [ 'context' ];
/**
* Returns the Link with the given ID.
*
* @since 1.0.0
*
* @param int $linkId The Link ID.
* @return Link The Link.
*/
public static function getLinkById( $linkId ) {
return aioseo()->core->db->start( 'aioseo_links' )
->where( 'id', $linkId )
->run()
->model( 'AIOSEO\\Plugin\\Addon\\LinkAssistant\\Models\\Link' );
}
/**
* Returns all links for the given post.
*
* @since 1.0.0
*
* @param int $postId The post ID.
* @param string $whereClause An optional WHERE clause for search queries.
* @return array[Link] The Links.
*/
public static function getLinks( $postId, $whereClause = null ) {
$query = aioseo()->core->db->start( 'aioseo_links' )
->where( 'post_id', $postId );
if ( $whereClause ) {
$query = $query->whereRaw( $whereClause );
}
return $query->run()
->models( 'AIOSEO\\Plugin\\Addon\\LinkAssistant\\Models\\Link' );
}
/**
* Returns inbound internal links that refer to the given post.
*
* @since 1.0.0
*
* @param int $linkedPostId The ID of the post the Link refers to.
* @param int $limit The limit.
* @param int $offset The offset.
* @return array[Link] The Links.
*/
public static function getInboundInternalLinks( $linkedPostId, $limit = 20, $offset = 0 ) {
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return [];
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
$links = aioseo()->core->db->start( 'aioseo_links as al' )
->select( 'al.*' )
->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" )
->where( 'al.linked_post_id', $linkedPostId )
->limit( $limit, $offset )
->run()
->models( 'AIOSEO\\Plugin\\Addon\\LinkAssistant\\Models\\Link' );
foreach ( $links as $link ) {
$link->context = new \stdClass();
$link->context->permalink = get_permalink( $link->post_id );
$link->context->postTitle = aioseo()->helpers->getPostTitle( $link->post_id );
$link->context->editLink = get_edit_post_link( $link->post_id, '' );
// Post Type data.
$postTypeObject = get_post_type_object( get_post_type( $link->post_id ) );
$link->context->postType = aioseo()->helpers->getPostType( $postTypeObject );
}
return $links;
}
/**
* Returns outbound internal links for the given post.
*
* @since 1.0.0
*
* @param int $postId The post ID.
* @param int $limit The limit.
* @param int $offset The offset.
* @return array[Link] The Links.
*/
public static function getOutboundInternalLinks( $postId, $limit = 20, $offset = 0 ) {
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return [];
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
$links = aioseo()->core->db->start( 'aioseo_links as al' )
->select( 'al.*' )
->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" )
->where( 'al.post_id', $postId )
->where( 'al.internal', 1 )
->limit( $limit, $offset )
->run()
->models( 'AIOSEO\\Plugin\\Addon\\LinkAssistant\\Models\\Link' );
foreach ( $links as $link ) {
if ( ! empty( $link->linked_post_id ) ) {
$link->context = new \stdClass();
$link->context->postTitle = aioseo()->helpers->getPostTitle( $link->linked_post_id );
$link->context->editLink = get_edit_post_link( $link->linked_post_id, '' );
// Post Type data.
$postTypeObject = get_post_type_object( get_post_type( $link->linked_post_id ) );
$link->context->postType = aioseo()->helpers->getPostType( $postTypeObject );
}
}
return $links;
}
/**
* Returns affiliate links for the given post.
*
* @since 1.0.0
*
* @param int $postId The post ID.
* @param int $limit The limit.
* @param int $offset The offset.
* @return array[Link] The Links.
*/
public static function getAffiliateLinks( $postId, $limit = 20, $offset = 0 ) {
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return [];
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
$links = aioseo()->core->db->start( 'aioseo_links as al' )
->select( 'al.*' )
->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" )
->where( 'al.post_id', $postId )
->where( 'al.affiliate', 1 )
->limit( $limit, $offset )
->run()
->models( 'AIOSEO\\Plugin\\Addon\\LinkAssistant\\Models\\Link' );
return $links;
}
/**
* Returns external links for the given post.
*
* @since 1.0.0
*
* @param int $postId The post ID.
* @param int $limit The limit.
* @param int $offset The offset.
* @return array[Link] The Links.
*/
public static function getExternalLinks( $postId, $limit = 20, $offset = 0 ) {
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return [];
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
$links = aioseo()->core->db->start( 'aioseo_links as al' )
->select( 'al.*' )
->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" )
->where( 'al.post_id', $postId )
->where( 'al.external', 1 )
->limit( $limit, $offset )
->run()
->models( 'AIOSEO\\Plugin\\Addon\\LinkAssistant\\Models\\Link' );
return $links;
}
/**
* Returns the total of inbound internal links that refer to the given post.
*
* @since 1.0.0
*
* @param int $linkedPostId The ID of the post the Link refers to.
* @return int The total.
*/
public static function getTotalInboundInternalLinks( $linkedPostId ) {
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return 0;
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
$links = aioseo()->core->db->start( 'aioseo_links as al' )
->select( 'al.*' )
->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" )
->where( 'al.linked_post_id', $linkedPostId )
->count();
return $links;
}
/**
* Returns the total of outbound internal links for the given post.
*
* @since 1.0.0
*
* @param int $postId The post ID.
* @return int The total.
*/
public static function getTotalOutboundInternalLinks( $postId ) {
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return 0;
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
$links = aioseo()->core->db->start( 'aioseo_links as al' )
->select( 'al.*' )
->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" )
->where( 'al.post_id', $postId )
->where( 'al.internal', 1 )
->count();
return $links;
}
/**
* Returns the total of affiliate links for the given post.
*
* @since 1.0.0
*
* @param int $postId The post ID.
* @return int The total.
*/
public static function getTotalAffiliateLinks( $postId ) {
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return 0;
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
$links = aioseo()->core->db->start( 'aioseo_links as al' )
->select( 'al.*' )
->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" )
->where( 'al.post_id', $postId )
->where( 'al.affiliate', 1 )
->count();
return $links;
}
/**
* Returns the total of external links for the given post.
*
* @since 1.0.0
*
* @param int $postId The post ID.
* @return int The total.
*/
public static function getTotalExternalLinks( $postId ) {
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return 0;
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
$links = aioseo()->core->db->start( 'aioseo_links as al' )
->select( 'al.*' )
->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" )
->where( 'al.post_id', $postId )
->where( 'al.external', 1 )
->count();
return $links;
}
/**
* Deletes all Links for the given post.
*
* @since 1.0.0
*
* @param int $linkId The Link ID.
* @return void
*/
public static function deleteLinks( $postId ) {
aioseo()->core->db->delete( 'aioseo_links' )
->where( 'post_id', $postId )
->run();
}
/**
* Deletes the Link with the given ID.
*
* @since 1.0.0
*
* @param int $linkId The Link ID.
* @return void
*/
public static function deleteLinkById( $linkId ) {
aioseo()->core->db->delete( 'aioseo_links' )
->where( 'id', $linkId )
->run();
}
/**
* Sanitizes the link object.
*
* @since 1.0.0
*
* @param array $link The link data.
* @return array The sanitized link data.
*/
public static function sanitizeLink( $link ) {
$nullFields = [ 'linked_post_id' ];
$booleanFields = [
'internal',
'affiliate',
'external'
];
$sanitizedLink = [];
foreach ( $link as $k => $v ) {
switch ( $k ) {
case 'post_id':
case 'linked_post_id':
if ( null === $v && in_array( $k, $nullFields, true ) ) {
break;
}
$v = intval( $v );
break;
case 'internal':
case 'external':
case 'affiliate':
$v = rest_sanitize_boolean( $v );
break;
case 'url':
$v = esc_url( $v );
break;
case 'hostname':
case 'anchor':
case 'phrase':
case 'paragraph':
$v = sanitize_text_field( $v );
break;
case 'phrase_html':
case 'paragraph_html':
$v = aioseoLinkAssistant()->helpers->wpKsesPhrase( $v );
break;
default:
break;
}
if (
empty( $v ) &&
! in_array( $k, $booleanFields, true ) &&
! in_array( $k, $nullFields, true )
) {
return [];
}
$sanitizedLink[ $k ] = esc_sql( $v );
}
return $sanitizedLink;
}
/**
* Checks whether the given link object is a valid one in the context of Link Assistant.
* There are a number of reasons why a link might be invalid, such as empty props or because the link is wrapped around HTML elements like an image but actually doesn't contain text.
*
* @since 1.0.0
*
* @param array $link The link data.
* @return bool Whether the link is valid or not.
*/
public static function validateLink( $link ) {
$propsToCheck = [
'url',
'hostname',
'anchor',
'phrase',
'phrase_html',
'paragraph',
'paragraph_html'
];
foreach ( $propsToCheck as $prop ) {
$value = wp_strip_all_tags( $link[ $prop ] );
if ( empty( $value ) ) {
return false;
}
}
return true;
}
/**
* Returns posts with their links for the Links Report.
*
* @since 1.0.0
*
* @param int $limit The limit.
* @param int $offset The offset.
* @param string $whereClause An optional WHERE clause for search queries.
* @param string $filter An optional filter for the results.
* @param int|string $termId An optional ID or "all" for term(s) the results need to be assigned to.
* @return array The posts with their links.
*/
public static function getPosts( $limit = 20, $offset = 0, $whereClause = '', $filter = '', $termId = 0 ) {
$includedPostTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$includedPostStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $includedPostTypes ) || empty( $includedPostStatuses ) ) {
return [];
}
$query = self::getPostsBaseQuery( $filter, $termId );
if ( ! empty( $whereClause ) ) {
$query = $query->whereRaw( $whereClause );
}
$query = $query->orderBy( 'p.post_date DESC' )
->limit( $limit, $offset );
$posts = $query->run()->result();
if ( empty( $posts ) ) {
return [];
}
foreach ( $posts as $post ) {
if ( ! $post->post_title ) {
$post->post_title = __( '(no title)' ); // phpcs:ignore AIOSEO.Wp.I18n.MissingArgDomain
}
$post->links = aioseoLinkAssistant()->helpers->getPostLinks( $post->ID, 5, 0 );
$post->context = new \stdClass();
$post->context->postTitle = aioseo()->helpers->getPostTitle( $post->ID );
$post->context->permalink = get_permalink( $post->ID );
$post->context->editLink = get_edit_post_link( $post->ID, '' );
// Post Type data.
$postTypeObject = get_post_type_object( get_post_type( $post->ID ) );
$post->context->postType = aioseo()->helpers->getPostType( $postTypeObject );
}
return $posts;
}
/**
* Returns the total amount of posts for the Links Report.
*
* @since 1.0.0
*
* @param string $whereClause An optional WHERE clause for search queries.
* @param string $filter An optional filter for the results.
* @param array $additionalFilters An optional array of additional filters.
* @return int The total amount of posts.
*/
public static function getTotalPosts( $whereClause = '', $filter = '', $additionalFilters = [] ) {
$includedPostTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$includedPostStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $includedPostTypes ) || empty( $includedPostStatuses ) ) {
return 0;
}
$query = self::getPostsBaseQuery( $filter, $additionalFilters );
if ( ! empty( $whereClause ) ) {
$query = $query->whereRaw( $whereClause );
}
return $query->count();
}
/**
* Returns the base query for the Links Report posts.
*
* @since 1.0.0
*
* @param string $filter An optional filter for the results.
* @param array $additionalFilters An optional array of filters to use.
* @return Database The query object.
*/
private static function getPostsBaseQuery( $filter, $additionalFilters = [] ) {
$includedPostTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$includedPostStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
$excludedPostIds = aioseoLinkAssistant()->helpers->getExcludedPostIds();
$query = aioseo()->core->db->start( 'posts as p' )
->select( 'p.ID, p.post_title, p.post_date, p.post_status' )
->join( 'aioseo_posts as ap', 'p.ID = ap.post_id' )
->whereRaw( 'ap.link_scan_date IS NOT NULL' );
if ( ! empty( $includedPostStatuses ) ) {
$includedPostStatuses = aioseo()->helpers->implodeWhereIn( $includedPostStatuses, true );
$query->whereRaw( "p.post_status IN ( $includedPostStatuses )" );
}
if ( ! empty( $includedPostTypes ) ) {
$includedPostTypes = aioseo()->helpers->implodeWhereIn( $includedPostTypes, true );
$query->whereRaw( "p.post_type IN ( $includedPostTypes )" );
}
if ( ! empty( $excludedPostIds ) ) {
$excludedPostIds = aioseo()->helpers->implodeWhereIn( $excludedPostIds, true );
$query->whereRaw( "p.ID NOT IN ( $excludedPostIds )" );
}
if ( ! empty( $filter ) ) {
$prefix = aioseo()->core->db->prefix;
switch ( $filter ) {
case 'linking-opportunities':
$tableName = $prefix . 'aioseo_links_suggestions';
$query = $query->whereRaw( "p.ID IN (
SELECT als.post_id FROM $tableName as als
WHERE dismissed = 0
GROUP BY als.post_id
)" );
break;
case 'orphaned-posts':
$tableName = $prefix . 'aioseo_links';
$query = $query->whereRaw( "p.ID IN (
SELECT al.linked_post_id FROM $tableName as al
WHERE al.internal = 1
GROUP BY al.linked_post_id
)" );
break;
default:
break;
}
}
if ( ! empty( $additionalFilters ) ) {
if ( ! empty( $additionalFilters['post-type'] ) ) {
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
if ( in_array( $additionalFilters['post-type'], $postTypes, true ) ) {
$query = $query->where( 'p.post_type', $additionalFilters['post-type'] );
}
}
if ( ! empty( $additionalFilters['term'] ) ) {
if ( 'all' === $additionalFilters['term'] ) {
$taxonomy = aioseoLinkAssistant()->helpers->getFirstTaxonomy( $filter );
if ( ! empty( $taxonomy ) ) {
$query = $query->join( 'term_relationships as tr', 'p.ID = tr.object_id' )
->join( 'term_taxonomy as tt', 'tr.term_taxonomy_id = tt.term_id' )
->where( 'tt.taxonomy', $taxonomy->name );
}
} else {
$query = $query->join( 'term_relationships as tr', 'p.ID = tr.object_id' )
->where( 'tr.term_taxonomy_id', $additionalFilters['term'] );
}
}
}
return $query;
}
/**
* Returns the total amount of links on the site.
*
* @since 1.0.0
*
* @return int The amount of links on the site.
*/
public static function getSiteTotalLinks() {
static $links = null;
if ( null === $links ) {
$query = aioseo()->core->db->start( 'aioseo_links as al' );
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return 0;
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
$query = $query->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" );
$excludedPostIds = aioseoLinkAssistant()->helpers->getExcludedPostIds();
if ( ! empty( $excludedPostIds ) ) {
$implodedPostIds = aioseo()->helpers->implodeWhereIn( $excludedPostIds );
$query = $query->whereRaw( "p.ID NOT IN ( $implodedPostIds )" );
}
$links = $query->count();
}
return $links;
}
/**
* Returns the total amount of external links on the site.
*
* @since 1.0.0
*
* @return int The amount of external links on the site.
*/
public static function getSiteTotalExternalLinks() {
static $links = null;
if ( null === $links ) {
$query = aioseo()->core->db->start( 'aioseo_links as al' )->where( 'al.external', 1 );
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return 0;
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
$query = $query->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" );
$excludedPostIds = aioseoLinkAssistant()->helpers->getExcludedPostIds();
if ( ! empty( $excludedPostIds ) ) {
$implodedPostIds = aioseo()->helpers->implodeWhereIn( $excludedPostIds );
$query = $query->whereRaw( "p.ID NOT IN ( $implodedPostIds )" );
}
$links = $query->count();
}
return $links;
}
/**
* Returns the total amount of affiliate links on the site.
*
* @since 1.0.0
*
* @return int The amount of affiliate links on the site.
*/
public static function getSiteTotalAffiliateLinks() {
static $links = null;
if ( null === $links ) {
$query = aioseo()->core->db->start( 'aioseo_links as al' )->where( 'al.affiliate', 1 );
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return 0;
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
$query = $query->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" );
$excludedPostIds = aioseoLinkAssistant()->helpers->getExcludedPostIds();
if ( ! empty( $excludedPostIds ) ) {
$implodedPostIds = aioseo()->helpers->implodeWhereIn( $excludedPostIds );
$query = $query->whereRaw( "p.ID NOT IN ( $implodedPostIds )" );
}
$links = $query->count();
}
return $links;
}
/**
* Returns the total amount of internal links on the site.
*
* @since 1.0.0
*
* @return int The amount of internal links on the site.
*/
public static function getSiteTotalInternalLinks() {
static $links = null;
if ( null === $links ) {
$query = aioseo()->core->db->start( 'aioseo_links as al' )
->where( 'al.affiliate', 0 )
->where( 'al.external', 0 );
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return 0;
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
$query = $query->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" );
$excludedPostIds = aioseoLinkAssistant()->helpers->getExcludedPostIds();
if ( ! empty( $excludedPostIds ) ) {
$implodedPostIds = aioseo()->helpers->implodeWhereIn( $excludedPostIds );
$query = $query->whereRaw( "p.ID NOT IN ( $implodedPostIds )" );
}
$links = $query->count();
}
return $links;
}
/**
* Returns the total amount of internal posts that have been linked to on the site.
*
* @since 1.0.0
*
* @return int The amount of internal links on the site.
*/
public static function getSiteTotalLinkedPosts() {
static $links = null;
if ( null === $links ) {
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
$links = 0;
return $links;
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
$query = aioseo()->core->db->start( 'aioseo_links as al' )
->where( 'al.affiliate', 0 )
->where( 'al.external', 0 )
->where( 'al.linked_post_id !=', 0 )
->where( 'ap.link_scan_date IS NOT', null )
->join( 'aioseo_posts as ap', 'ap.post_id = al.linked_post_id' )
->join( 'posts as p', 'ap.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" )
->groupBy( 'al.linked_post_id' );
$excludedPostIds = aioseoLinkAssistant()->helpers->getExcludedPostIds();
if ( ! empty( $excludedPostIds ) ) {
$implodedPostIds = aioseo()->helpers->implodeWhereIn( $excludedPostIds );
$query = $query->whereRaw( "p.ID NOT IN ( $implodedPostIds )" );
}
$links = $query->count();
}
return $links;
}
/**
* Returns links grouped per domain/hostname for the Domains Report.
*
* @since 1.0.0
*
* @param int $limit The limit.
* @param int $offset The offset.
* @param string $whereClause An optional WHERE clause for search queries.
* @return array The domains.
*/
public static function getDomains( $limit = 20, $offset = 0, $whereClause = null ) {
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return [];
}
// First, we get a list of hostnames with external links.
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
$query = aioseo()->core->db->start( 'aioseo_links as al' )
->select( 'al.hostname as hostname, count( al.hostname ) as count' )
->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" )
->where( 'al.external', 1 );
if ( $whereClause ) {
$query = $query->whereRaw( $whereClause );
}
$hostnames = $query->groupBy( 'hostname' )
->orderBy( 'count DESC, hostname ASC' )
->limit( $limit, $offset )
->run()
->result();
$hostnames = array_map( function( $hostname ) {
return $hostname->hostname;
}, $hostnames );
// Then, we get posts with links to the relevant hostname for each of the hostnames.
$domainsWithPosts = [];
foreach ( $hostnames as $hostname ) {
$domainPosts = [ $hostname => self::getDomainPostLinks( $hostname ) ];
$domainsWithPosts = array_merge( $domainsWithPosts, $domainPosts );
}
// The WpTable component requires an array so we can't have keys on the first level and need the object into an array.
$usedDomains = [];
$domainsAsArray = [];
foreach ( $domainsWithPosts as $domain => $posts ) {
if ( ! in_array( $domain, $usedDomains, true ) ) {
$usedDomains[] = $domain;
}
$index = array_search( $domain, $usedDomains, true );
$domainsAsArray[ $index ][ $domain ] = $posts;
}
// Finally, we need to re-sort the domains by the amount links they have.
$sortedDomains = [];
foreach ( $domainsAsArray as $wrapper ) {
foreach ( $wrapper as $hostname => $posts ) {
foreach ( $hostnames as $index => $hostname2 ) {
if ( $hostname === $hostname2 ) {
$sortedDomains[ $index ] = $wrapper;
}
}
}
}
ksort( $sortedDomains );
return $sortedDomains;
}
/**
* Returns the total amount of domains with links.
*
* @since 1.0.0
*
* @param string $whereClause An optional WHERE clause for search queries.
* @return int The total amount of domains.
*/
public static function getTotalDomains( $whereClause = null ) {
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return 0;
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
$query = aioseo()->core->db->start( 'aioseo_links as al' )
->where( 'al.external', 1 )
->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" );
if ( $whereClause ) {
$query = $query->whereRaw( $whereClause );
}
return $query->groupBy( 'hostname' )
->run()
->numRows();
}
/**
* Returns posts that have links to the given hostname.
*
* @since 1.0.0
*
* @param string $hostname The hostname.
* @param int $limit The limit.
* @param int $offset The offset.
* @return array The posts with their links.
*/
public static function getDomainPostLinks( $hostname, $limit = 5, $offset = 0 ) {
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return [];
}
// First, figure out which posts link to the current hostname.
// We can't use the result of this as a subquery here because MySQL doesn't support LIMIT clauses in subqueries yet.
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
$postIds = aioseo()->core->db->start( 'aioseo_links as al' )
->select( 'al.post_id, count( al.post_id ) as count' )
->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" )
->where( 'al.external', 1 )
->where( 'al.hostname', $hostname )
->groupBy( 'al.post_id' )
->limit( $limit, $offset )
->run()
->result();
$postIds = array_map( function( $postId ) {
return $postId->post_id;
}, $postIds );
// Then, get all links for those posts.
$implodedPostIds = aioseo()->helpers->implodeWhereIn( $postIds );
$links = aioseo()->core->db->start( 'aioseo_links' )
->where( 'external', 1 )
->whereRaw( "post_id IN ( $implodedPostIds )" )
->where( 'hostname', $hostname )
->run()
->result();
$posts = [];
foreach ( $links as $link ) {
$posts[ $link->post_id ]['links'][] = $link;
}
// Now, we just need to add the context.
$index = 0;
$postsWithContext = [];
foreach ( $posts as $postId => $post ) {
$postObject = aioseo()->helpers->getPost( $postId );
$postTypeObject = get_post_type_object( get_post_type( $postId ) );
$post['context'] = [
'postTitle' => aioseo()->helpers->decodeHtmlEntities( $postObject->post_title ),
'publishDate' => $postObject->post_date,
'permalink' => get_permalink( $postId ),
'editLink' => get_edit_post_link( $postId, '' ),
'postType' => aioseo()->helpers->getPostType( $postTypeObject )
];
if ( 0 === $index ) {
$totalPosts = self::getTotalDomainPosts( $hostname );
$totalLinks = self::getTotalDomainLinks( $hostname );
$post['totals'] = [
'page' => ( $offset + $limit ) / $limit,
'pages' => ceil( $totalPosts / $limit ),
'total' => $totalPosts,
'totalLinks' => $totalLinks
];
}
$postsWithContext[] = $post;
$index++;
}
return $postsWithContext;
}
/**
* Returns the total amount of posts with external links refering to the given hostname/domain.
*
* @since 1.0.0
*
* @param string $hostname The hostname.
* @return int The total amount of posts.
*/
public static function getTotalDomainPosts( $hostname ) {
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return 0;
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
return aioseo()->core->db->start( 'aioseo_links as al' )
->select( 'al.post_id, count( al.post_id ) as count' )
->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" )
->where( 'al.external', 1 )
->where( 'al.hostname', $hostname )
->groupBy( 'al.post_id' )
->count();
}
/**
* Returns all external links referring to the given hostname/domain.
*
* @since 1.0.0
*
* @param string $hostname The hostname.
* @return array[Link] The Links.
*/
public static function getDomainLinks( $hostname ) {
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return [];
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
return aioseo()->core->db->start( 'aioseo_links al' )
->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" )
->where( 'al.hostname', $hostname )
->where( 'al.external', 1 )
->run()
->models( 'AIOSEO\\Plugin\\Addon\\LinkAssistant\\Models\\Link' );
}
/**
* Returns the total amount of external links referring to the given hostname/domain.
*
* @since 1.0.0
*
* @param string $hostname The hostname.
* @return int The total amount of links.
*/
public static function getTotalDomainLinks( $hostname ) {
$postTypes = aioseoLinkAssistant()->helpers->getIncludedPostTypes();
$postStatuses = aioseoLinkAssistant()->helpers->getIncludedPostStatuses();
if ( empty( $postTypes ) || empty( $postStatuses ) ) {
return 0;
}
$implodedPostTypes = aioseo()->helpers->implodeWhereIn( $postTypes, true );
$implodedPostStatuses = aioseo()->helpers->implodeWhereIn( $postStatuses, true );
return aioseo()->core->db->start( 'aioseo_links as al' )
->join( 'posts as p', 'al.post_id = p.ID' )
->whereRaw( "p.post_type IN ( $implodedPostTypes )" )
->whereRaw( "p.post_status IN ( $implodedPostStatuses )" )
->where( 'al.hostname', $hostname )
->where( 'al.external', 1 )
->count();
}
}