|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* Define the Wordlift_Mapping_Jsonld_Converter class to add JSON-LD generated from mappings. |
|
4
|
|
|
* |
|
5
|
|
|
* @since 3.25.0 |
|
6
|
|
|
* @package Wordlift |
|
7
|
|
|
* @subpackage Wordlift\Mappings |
|
8
|
|
|
*/ |
|
9
|
|
|
|
|
10
|
|
|
namespace Wordlift\Mappings; |
|
11
|
|
|
|
|
12
|
|
|
use Wordlift\Mappings\Data_Source\Data_Source_Factory; |
|
13
|
|
|
|
|
14
|
|
|
/** |
|
15
|
|
|
* This class takes the output from json-ld service and alter depends on the |
|
16
|
|
|
* rule and properties defined in sync mappings. |
|
17
|
|
|
* |
|
18
|
|
|
* @since 3.25.0 |
|
19
|
|
|
*/ |
|
20
|
|
|
class Jsonld_Converter { |
|
21
|
|
|
/** |
|
22
|
|
|
* Enumerations for the field types. |
|
23
|
|
|
*/ |
|
24
|
|
|
const FIELD_TYPE_TEXT_FIELD = 'text'; |
|
25
|
|
|
const FIELD_TYPE_CUSTOM_FIELD = 'custom_field'; |
|
26
|
|
|
const FIELD_TYPE_ACF = 'acf'; |
|
27
|
|
|
|
|
28
|
|
|
/** |
|
29
|
|
|
* Mappings can be applied to either post |
|
30
|
|
|
* or term, the below is used to specify whether it is a post or a term. |
|
31
|
|
|
*/ |
|
32
|
|
|
const POST = 'post'; |
|
33
|
|
|
const TERM = 'term'; |
|
34
|
|
|
/** |
|
35
|
|
|
* The {@link Mappings_Validator} instance to test. |
|
36
|
|
|
* |
|
37
|
|
|
* @since 3.25.0 |
|
38
|
|
|
* @access private |
|
39
|
|
|
* @var Mappings_Validator $validator The {@link Mappings_Validator} instance. |
|
40
|
|
|
*/ |
|
41
|
|
|
private $validator; |
|
42
|
|
|
|
|
43
|
|
|
/** |
|
44
|
|
|
* The {@link Mappings_Transform_Functions_Registry} instance. |
|
45
|
|
|
* |
|
46
|
|
|
* @since 3.25.0 |
|
47
|
|
|
* @access private |
|
48
|
|
|
* @var Mappings_Transform_Functions_Registry $transform_functions_registry The {@link Mappings_Transform_Functions_Registry} instance. |
|
49
|
|
|
*/ |
|
50
|
|
|
private $transform_functions_registry; |
|
51
|
|
|
|
|
52
|
|
|
/** |
|
53
|
|
|
* Initialize all dependencies required. |
|
54
|
|
|
* |
|
55
|
|
|
* @param Mappings_Validator $validator A {@link Mappings_Validator} instance. |
|
56
|
|
|
* @param Mappings_Transform_Functions_Registry $transform_functions_registry |
|
57
|
|
|
*/ |
|
58
|
|
|
public function __construct( $validator, $transform_functions_registry ) { |
|
59
|
|
|
|
|
60
|
|
|
$this->validator = $validator; |
|
61
|
|
|
$this->transform_functions_registry = $transform_functions_registry; |
|
62
|
|
|
|
|
63
|
|
|
// Hook to refactor the JSON-LD. |
|
64
|
|
|
add_filter( 'wl_post_jsonld_array', array( $this, 'wl_post_jsonld_array' ), 11, 2 ); |
|
65
|
|
|
add_filter( 'wl_entity_jsonld_array', array( $this, 'wl_post_jsonld_array' ), 11, 2 ); |
|
66
|
|
|
|
|
67
|
|
|
// Hook at add term jsonld. |
|
68
|
|
|
add_filter( 'wl_term_jsonld_array', array( $this, 'wl_term_jsonld_array' ), 11, 2 ); |
|
69
|
|
|
} |
|
70
|
|
|
|
|
71
|
|
|
/** |
|
72
|
|
|
* Hook to `wl_term_jsonld_array`. |
|
73
|
|
|
* |
|
74
|
|
|
* Receive the JSON-LD and the references in the array along with the term ID and transform them according to |
|
75
|
|
|
* the configuration. |
|
76
|
|
|
* |
|
77
|
|
|
* @param array $value { |
|
78
|
|
|
* The array containing the JSON-LD and the references. |
|
79
|
|
|
* |
|
80
|
|
|
* @type array $jsonld The JSON-LD array. |
|
81
|
|
|
* @type int[] $references An array of post ID referenced by the JSON-LD (will be expanded by the converter). |
|
82
|
|
|
* } |
|
83
|
|
|
* |
|
84
|
|
|
* @param int $term_id The Term ID. |
|
85
|
|
|
* |
|
86
|
|
|
* @return array An array with the updated JSON-LD and references. |
|
87
|
|
|
*/ |
|
88
|
|
View Code Duplication |
public function wl_term_jsonld_array( $value, $term_id ) { |
|
|
|
|
|
|
89
|
|
|
$jsonld = $value['jsonld']; |
|
90
|
|
|
$references = $value['references']; |
|
91
|
|
|
|
|
92
|
|
|
return array( |
|
93
|
|
|
'jsonld' => $this->build_jsonld( $jsonld, $term_id, $references, self::TERM ), |
|
94
|
|
|
'references' => $references, |
|
95
|
|
|
); |
|
96
|
|
|
} |
|
97
|
|
|
|
|
98
|
|
|
|
|
99
|
|
|
/** |
|
100
|
|
|
* Hook to `wl_post_jsonld_array` and `wl_entity_jsonld_array`. |
|
101
|
|
|
* |
|
102
|
|
|
* Receive the JSON-LD and the references in the array along with the post ID and transform them according to |
|
103
|
|
|
* the configuration. |
|
104
|
|
|
* |
|
105
|
|
|
* @param array $value { |
|
106
|
|
|
* The array containing the JSON-LD and the references. |
|
107
|
|
|
* |
|
108
|
|
|
* @type array $jsonld The JSON-LD array. |
|
109
|
|
|
* @type int[] $references An array of post ID referenced by the JSON-LD (will be expanded by the converter). |
|
110
|
|
|
* } |
|
111
|
|
|
* |
|
112
|
|
|
* @param int $post_id The post ID. |
|
113
|
|
|
* |
|
114
|
|
|
* @return array An array with the updated JSON-LD and references. |
|
115
|
|
|
*/ |
|
116
|
|
View Code Duplication |
public function wl_post_jsonld_array( $value, $post_id ) { |
|
|
|
|
|
|
117
|
|
|
|
|
118
|
|
|
$jsonld = $value['jsonld']; |
|
119
|
|
|
$references = $value['references']; |
|
120
|
|
|
|
|
121
|
|
|
return array( |
|
122
|
|
|
'jsonld' => $this->build_jsonld( $jsonld, $post_id, $references, self::POST ), |
|
123
|
|
|
'references' => $references, |
|
124
|
|
|
); |
|
125
|
|
|
} |
|
126
|
|
|
|
|
127
|
|
|
/** |
|
128
|
|
|
* Returns JSON-LD data after applying transformation functions. |
|
129
|
|
|
* |
|
130
|
|
|
* @param array $jsonld The JSON-LD structure. |
|
131
|
|
|
* @param int $identifier The {@link WP_Post} id or {@link \WP_Term} id. |
|
132
|
|
|
* @param array $references An array of post references. |
|
133
|
|
|
* |
|
134
|
|
|
* @param string $type Post or term. |
|
135
|
|
|
* |
|
136
|
|
|
* @return array the new refactored array structure. |
|
137
|
|
|
* @since 3.25.0 |
|
138
|
|
|
*/ |
|
139
|
|
|
private function build_jsonld( $jsonld, $identifier, &$references, $type ) { |
|
140
|
|
|
// @@todo I think there's an issue here with the Validator, because you're changing the instance state and the |
|
141
|
|
|
// instance may be reused afterwards. |
|
142
|
|
|
|
|
143
|
|
|
$properties = $this->validator->validate( $identifier, $type ); |
|
144
|
|
|
$nested_properties = array(); |
|
145
|
|
|
|
|
146
|
|
|
foreach ( $properties as $property ) { |
|
147
|
|
|
// If the property has the character '/' in the property name then it is a nested property. |
|
148
|
|
|
if ( strpos( $property['property_name'], '/' ) !== false ) { |
|
149
|
|
|
$nested_properties[] = $property; |
|
150
|
|
|
continue; |
|
151
|
|
|
} |
|
152
|
|
|
$property_transformed_data = $this->get_property_data( $property, $jsonld, $identifier, $references, $type ); |
|
153
|
|
|
if ( false !== $property_transformed_data ) { |
|
154
|
|
|
$jsonld[ $property['property_name'] ] = $property_transformed_data; |
|
155
|
|
|
} |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
$jsonld = $this->process_nested_properties( $nested_properties, $jsonld, $identifier, $references, $type ); |
|
159
|
|
|
|
|
160
|
|
|
return $jsonld; |
|
161
|
|
|
} |
|
162
|
|
|
|
|
163
|
|
|
/** |
|
164
|
|
|
* Get the property data by applying the transformation function |
|
165
|
|
|
* |
|
166
|
|
|
* @param $property |
|
167
|
|
|
* @param $jsonld |
|
168
|
|
|
* @param $identifier |
|
169
|
|
|
* @param $references |
|
170
|
|
|
* |
|
171
|
|
|
* @param $type |
|
172
|
|
|
* |
|
173
|
|
|
* @return array|bool|null |
|
174
|
|
|
*/ |
|
175
|
|
|
public function get_property_data( $property, $jsonld, $identifier, &$references, $type ) { |
|
176
|
|
|
$transform_instance = $this->transform_functions_registry->get_transform_function( $property['transform_function'] ); |
|
177
|
|
|
$data = Data_Source_Factory::get_instance()->get_data( $identifier, $property, $type ); |
|
178
|
|
|
if ( null !== $transform_instance ) { |
|
179
|
|
|
$transform_data = $transform_instance->transform_data( $data, $jsonld, $references, $identifier ); |
|
180
|
|
|
if ( null !== $transform_data ) { |
|
181
|
|
|
return $this->make_single( $transform_data ); |
|
182
|
|
|
} |
|
183
|
|
|
} else { |
|
184
|
|
|
return $this->make_single( $data ); |
|
185
|
|
|
} |
|
186
|
|
|
|
|
187
|
|
|
return false; |
|
188
|
|
|
} |
|
189
|
|
|
|
|
190
|
|
|
/** |
|
191
|
|
|
* Process all the nested properties. |
|
192
|
|
|
* |
|
193
|
|
|
* @param $nested_properties array |
|
194
|
|
|
* @param $jsonld array |
|
195
|
|
|
* |
|
196
|
|
|
* @param $identifier |
|
197
|
|
|
* @param $references |
|
198
|
|
|
* @param string $type Post or term. |
|
199
|
|
|
* |
|
200
|
|
|
* @return array |
|
201
|
|
|
*/ |
|
202
|
|
|
public function process_nested_properties( $nested_properties, $jsonld, $identifier, &$references, $type ) { |
|
203
|
|
|
foreach ( $nested_properties as $property ) { |
|
204
|
|
|
$property_data = $this->get_property_data( $property, $jsonld, $identifier, $references, $type ); |
|
205
|
|
|
if ( false === $property_data ) { |
|
206
|
|
|
// No need to create nested levels. |
|
207
|
|
|
continue; |
|
208
|
|
|
} |
|
209
|
|
|
|
|
210
|
|
|
$keys = explode( '/', $property['property_name'] ); |
|
211
|
|
|
// end is the last level of the nested property. |
|
212
|
|
|
$end = array_pop( $keys ); |
|
213
|
|
|
$current_property_pointer = &$jsonld; |
|
214
|
|
|
|
|
215
|
|
|
/** |
|
216
|
|
|
* Once we find all the nested levels from the property name |
|
217
|
|
|
* loop through it and create associative array if the levels |
|
218
|
|
|
* didnt exist. |
|
219
|
|
|
*/ |
|
220
|
|
|
while ( count( $keys ) > 0 ) { |
|
221
|
|
|
$key = array_shift( $keys ); |
|
222
|
|
|
if ( $key === "" ) { |
|
223
|
|
|
continue; |
|
224
|
|
|
} |
|
225
|
|
|
if ( ! array_key_exists( $key, $current_property_pointer ) ) { |
|
226
|
|
|
$current_property_pointer[ $key ] = array(); |
|
227
|
|
|
} |
|
228
|
|
|
// We are setting the pointer to the current key, so that at the end |
|
229
|
|
|
// we can add the data at last level. |
|
230
|
|
|
$current_property_pointer = &$current_property_pointer[ $key ]; |
|
231
|
|
|
} |
|
232
|
|
|
$current_property_pointer[ $end ] = $property_data; |
|
233
|
|
|
} |
|
234
|
|
|
|
|
235
|
|
|
return $jsonld; |
|
236
|
|
|
} |
|
237
|
|
|
|
|
238
|
|
|
private function make_single( $value ) { |
|
239
|
|
|
|
|
240
|
|
|
$values = (array) $value; |
|
241
|
|
|
|
|
242
|
|
|
if ( empty( $values ) ) { |
|
243
|
|
|
return false; |
|
244
|
|
|
} |
|
245
|
|
|
|
|
246
|
|
|
if ( 1 === count( $values ) && 0 === key( $values ) ) { |
|
247
|
|
|
return current( $values ); |
|
248
|
|
|
} |
|
249
|
|
|
|
|
250
|
|
|
return $values; |
|
251
|
|
|
} |
|
252
|
|
|
|
|
253
|
|
|
} |
|
254
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.