197 lines
5.8 KiB
PHP
197 lines
5.8 KiB
PHP
<?php
|
|
/**
|
|
* MLP2 content relations reader.
|
|
*
|
|
* Reads post and term relation data from the MLP2 backup content_relations
|
|
* table. Relations are grouped by (ml_source_blogid, ml_source_elementid)
|
|
* so that each group can be written as a single MLP5 relationship.
|
|
*
|
|
* MLP2 backup table schema (mlp2bak_content_relations or mlp2bak_relationships):
|
|
* ml_source_blogid INT -- source site ID
|
|
* ml_source_elementid INT -- source element (post/term) ID
|
|
* ml_blogid INT -- target site ID
|
|
* ml_elementid INT -- target element ID
|
|
* ml_type VARCHAR -- 'post' or 'term'
|
|
*
|
|
* @package Robotstxt_Mlp2_Mlp5
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Class Robotstxt_Mlp2_Mlp5_Reader_Content_Relations
|
|
*/
|
|
class Robotstxt_Mlp2_Mlp5_Reader_Content_Relations {
|
|
|
|
/**
|
|
* Count distinct source groups for a given type.
|
|
*
|
|
* @param string $type 'post' or 'term'.
|
|
* @return int
|
|
*/
|
|
public static function count_groups( string $type ): int {
|
|
global $wpdb;
|
|
|
|
$mlp2 = new Robotstxt_Mlp2_Mlp5_Detector_Mlp2();
|
|
$table = $mlp2->get_content_relations_table();
|
|
|
|
if ( '' === $table ) {
|
|
return 0;
|
|
}
|
|
|
|
list( $src_blog, $src_elem ) = self::source_columns( $mlp2, $table );
|
|
if ( '' === $src_blog ) {
|
|
return 0;
|
|
}
|
|
|
|
$type_safe = ( 'term' === $type ) ? 'term' : 'post';
|
|
|
|
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
return (int) $wpdb->get_var(
|
|
$wpdb->prepare(
|
|
"SELECT COUNT(DISTINCT {$src_blog}, {$src_elem}) FROM `{$table}` WHERE ml_type = %s",
|
|
$type_safe
|
|
)
|
|
);
|
|
// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
}
|
|
|
|
/**
|
|
* Return a batch of distinct source groups, with all their translation members.
|
|
*
|
|
* Each returned element is:
|
|
* [
|
|
* 'type' => string, // 'post' or 'term'
|
|
* 'members' => [
|
|
* ['site_id' => int, 'element_id' => int],
|
|
* ...
|
|
* ]
|
|
* ]
|
|
*
|
|
* The source element itself is always included as a member.
|
|
*
|
|
* @param string $type 'post' or 'term'.
|
|
* @param int $offset Offset into the distinct source list.
|
|
* @param int $limit Number of groups to return.
|
|
* @return array[]
|
|
*/
|
|
public static function get_groups_batch( string $type, int $offset, int $limit ): array {
|
|
global $wpdb;
|
|
|
|
$mlp2 = new Robotstxt_Mlp2_Mlp5_Detector_Mlp2();
|
|
$table = $mlp2->get_content_relations_table();
|
|
|
|
if ( '' === $table ) {
|
|
return array();
|
|
}
|
|
|
|
list( $src_blog, $src_elem ) = self::source_columns( $mlp2, $table );
|
|
if ( '' === $src_blog ) {
|
|
return array();
|
|
}
|
|
|
|
$type_safe = ( 'term' === $type ) ? 'term' : 'post';
|
|
|
|
// Fetch a page of distinct sources.
|
|
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
$sources = $wpdb->get_results(
|
|
$wpdb->prepare(
|
|
"SELECT DISTINCT {$src_blog} AS source_blog, {$src_elem} AS source_elem FROM `{$table}` WHERE ml_type = %s ORDER BY {$src_blog}, {$src_elem} LIMIT %d OFFSET %d",
|
|
$type_safe,
|
|
$limit,
|
|
$offset
|
|
),
|
|
ARRAY_A
|
|
);
|
|
// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
|
|
if ( empty( $sources ) ) {
|
|
return array();
|
|
}
|
|
|
|
$groups = array();
|
|
|
|
foreach ( $sources as $source ) {
|
|
$src_blog_id = (int) $source['source_blog'];
|
|
$src_elem_id = (int) $source['source_elem'];
|
|
|
|
// Fetch all translations for this source.
|
|
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
$translations = $wpdb->get_results(
|
|
$wpdb->prepare(
|
|
"SELECT ml_blogid, ml_elementid FROM `{$table}` WHERE ml_type = %s AND {$src_blog} = %d AND {$src_elem} = %d",
|
|
$type_safe,
|
|
$src_blog_id,
|
|
$src_elem_id
|
|
),
|
|
ARRAY_A
|
|
);
|
|
// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
|
|
// Build members: source + all translations (deduplicated).
|
|
$seen = array();
|
|
$members = array();
|
|
|
|
$source_key = $src_blog_id . ':' . $src_elem_id;
|
|
$seen[ $source_key ] = true;
|
|
$members[] = array(
|
|
'site_id' => $src_blog_id,
|
|
'element_id' => $src_elem_id,
|
|
);
|
|
|
|
foreach ( (array) $translations as $t ) {
|
|
$key = ( (int) $t['ml_blogid'] ) . ':' . ( (int) $t['ml_elementid'] );
|
|
if ( isset( $seen[ $key ] ) ) {
|
|
continue;
|
|
}
|
|
$seen[ $key ] = true;
|
|
$members[] = array(
|
|
'site_id' => (int) $t['ml_blogid'],
|
|
'element_id' => (int) $t['ml_elementid'],
|
|
);
|
|
}
|
|
|
|
if ( count( $members ) >= 2 ) {
|
|
$groups[] = array(
|
|
'type' => $type_safe,
|
|
'members' => $members,
|
|
);
|
|
}
|
|
}
|
|
|
|
return $groups;
|
|
}
|
|
|
|
/**
|
|
* Detect the source-blog and source-element column names.
|
|
*
|
|
* Returns ['', ''] when columns cannot be determined.
|
|
*
|
|
* @param Robotstxt_Mlp2_Mlp5_Detector_Mlp2 $mlp2 MLP2 detector.
|
|
* @param string $table Content relations table name.
|
|
* @return string[] [ $source_blog_col, $source_element_col ]
|
|
*/
|
|
private static function source_columns( Robotstxt_Mlp2_Mlp5_Detector_Mlp2 $mlp2, string $table ): array {
|
|
$cols = $mlp2->describe_table( $table );
|
|
|
|
$blog_col = '';
|
|
foreach ( array( 'ml_source_blogid', 'ml_blogid' ) as $c ) {
|
|
if ( isset( $cols[ $c ] ) ) {
|
|
$blog_col = $c;
|
|
break;
|
|
}
|
|
}
|
|
|
|
$elem_col = '';
|
|
foreach ( array( 'ml_source_elementid', 'ml_elementid' ) as $c ) {
|
|
if ( isset( $cols[ $c ] ) ) {
|
|
$elem_col = $c;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return array( $blog_col, $elem_col );
|
|
}
|
|
}
|