class-wpml-score-hierarchy.php
3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<?php
class WPML_Score_Hierarchy {
private $data = array();
private $slugs = array();
/**
* WPML_Score_Hierarchy constructor.
*
* @param object[] $data_set
* @param string[] $slugs
*/
public function __construct( $data_set, $slugs ) {
$this->data = $data_set;
$this->slugs = $slugs;
}
/**
* Array of best matched post_ids. Better matches have a lower index!
*
* @return int[]
*/
public function get_possible_ids_ordered() {
$pages_with_name = $this->data;
$slugs = $this->slugs;
$parent_slugs = array_slice( $slugs, 0, - 1 );
foreach ( $this->data as $key => $page ) {
if ( $page->parent_name ) {
$slug_pos = array_keys( $slugs, $page->post_name, true );
$par_slug_pos = array_keys( $slugs, $page->parent_name, true );
if ( (bool) $par_slug_pos !== false
&& (bool) $slug_pos !== false
) {
$remove = true;
foreach ( $slug_pos as $child_slug_pos ) {
if ( in_array( $child_slug_pos - 1, $par_slug_pos ) ) {
$remove = false;
break;
}
}
if ( $remove === true ) {
unset( $pages_with_name[ $key ] );
}
}
}
}
$related_ids = array();
$matching_ids = array();
foreach ( $pages_with_name as $key => $page ) {
$correct_slug = end( $slugs );
if ( $page->post_name === $correct_slug ) {
if ( $this->is_exactly_matching_all_slugs_in_order( $page ) ) {
$matching_ids[] = (int) $page->ID;
} else {
$related_ids[ $page->ID ] = $this->calculate_score( $parent_slugs, $pages_with_name, $page );
}
}
}
arsort( $related_ids );
$related_ids = array_keys( $related_ids );
return array(
'matching_ids' => $matching_ids,
'related_ids' => $related_ids,
);
}
/**
* Get page object by its id.
*
* @param int $id
*
* @return false|object
*/
private function get_page_by_id( $id ) {
foreach ( $this->data as $page ) {
if ( (int) $page->ID === (int) $id ) {
return $page;
}
}
return false;
}
/**
* @param string[] $parent_slugs
* @param object[] $pages_with_name
* @param object $page
*
* @return int
*/
private function calculate_score( $parent_slugs, $pages_with_name, $page ) {
$parent_positions = array_keys( $parent_slugs, $page->parent_name, true );
$new_score = (bool) $parent_positions === true ? max( $parent_positions ) + 1 : ( $page->post_parent ? - 1 : 0 );
if ( $page->post_parent ) {
foreach ( $pages_with_name as $parent ) {
if ( $parent->ID == $page->post_parent ) {
$new_score += $this->calculate_score( array_slice( $parent_slugs, 0, count( $parent_slugs ) - 1 ), $pages_with_name, $parent );
break;
}
}
}
return $new_score;
}
/**
* @param object $page
*
* @return bool
*/
private function is_exactly_matching_all_slugs_in_order( $page ) {
return $this->slugs === $this->get_slugs_for_page( $page );
}
/**
* @param object $current_page
*
* @return array
*/
private function get_slugs_for_page( $current_page ) {
$slugs = array();
while ( $current_page && $current_page->post_name ) {
$slugs[] = $current_page->post_name;
$parent_name = $current_page->parent_name;
$current_page = $this->get_page_by_id( $current_page->post_parent );
if ( ! $current_page && $parent_name ) {
$slugs[] = $parent_name;
}
}
return array_reverse( $slugs );
}
}