Completed
Pull Request — develop (#1161)
by Naveen
02:33
created

Jsonld_Converter   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 235
Duplicated Lines 8.09 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 19
loc 235
rs 10
c 0
b 0
f 0
wmc 20
lcom 1
cbo 4

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 1
A wl_term_jsonld_array() 9 9 1
A wl_post_jsonld_array() 10 10 1
A build_jsonld() 0 24 4
A get_property_data() 0 14 3
B process_nested_properties() 0 35 6
A make_single() 0 14 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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
		// This is wrong: `wl_term_jsonld_array` will provide a term ID not a post ID (that `wl_post_jsonld_array` expects).
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 ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
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 ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
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
141
		// @@todo I think there's an issue here with the Validator, because you're changing the instance state and the
142
		// instance may be reused afterwards.
143
144
		$properties        = $this->validator->validate( $identifier, $type );
145
		$nested_properties = array();
146
147
		foreach ( $properties as $property ) {
148
			// If the property has the character '/' in the property name then it is a nested property.
149
			if ( strpos( $property['property_name'], '/' ) !== false ) {
150
				$nested_properties[] = $property;
151
				continue;
152
			}
153
			$property_transformed_data = $this->get_property_data( $property, $jsonld, $identifier, $references, $type );
154
			if ( false !== $property_transformed_data ) {
155
				$jsonld[ $property['property_name'] ] = $property_transformed_data;
156
			}
157
		}
158
159
		$jsonld = $this->process_nested_properties( $nested_properties, $jsonld, $identifier, $references, $type );
160
161
		return $jsonld;
162
	}
163
164
	/**
165
	 * Get the property data by applying the transformation function
166
	 *
167
	 * @param $property
168
	 * @param $jsonld
169
	 * @param $post_id
170
	 * @param $references
171
	 *
172
	 * @param $type
173
	 *
174
	 * @return array|bool|null
175
	 */
176
	public function get_property_data( $property, $jsonld, $post_id, &$references, $type ) {
177
		$transform_instance = $this->transform_functions_registry->get_transform_function( $property['transform_function'] );
178
		$data               = Data_Source_Factory::get_instance()->get_data( $post_id, $property, $type );
179
		if ( null !== $transform_instance ) {
180
			$transform_data = $transform_instance->transform_data( $data, $jsonld, $references, $post_id );
181
			if ( null !== $transform_data ) {
182
				return $this->make_single( $transform_data );
183
			}
184
		} else {
185
			return $this->make_single( $data );
186
		}
187
188
		return false;
189
	}
190
191
	/**
192
	 * Process all the nested properties.
193
	 *
194
	 * @param $nested_properties array
195
	 * @param $jsonld array
196
	 *
197
	 * @param $post_id
198
	 * @param $references
199
	 * @param string $type Post or term.
200
	 *
201
	 * @return array
202
	 */
203
	public function process_nested_properties( $nested_properties, $jsonld, $post_id, &$references, $type ) {
204
		foreach ( $nested_properties as $property ) {
205
			$property_data = $this->get_property_data( $property, $jsonld, $post_id, $references, $type );
206
			if ( false === $property_data ) {
207
				// No need to create nested levels.
208
				continue;
209
			}
210
211
			$keys = explode( '/', $property['property_name'] );
212
			// end is the last level of the nested property.
213
			$end                      = array_pop( $keys );
214
			$current_property_pointer = &$jsonld;
215
216
			/**
217
			 * Once we find all the nested levels from the property name
218
			 * loop through it and create associative array if the levels
219
			 * didnt exist.
220
			 */
221
			while ( count( $keys ) > 0 ) {
222
				$key = array_shift( $keys );
223
				if ( $key === "" ) {
224
					continue;
225
				}
226
				if ( ! array_key_exists( $key, $current_property_pointer ) ) {
227
					$current_property_pointer[ $key ] = array();
228
				}
229
				// We are setting the pointer to the current key, so that at the end
230
				// we can add the data at last level.
231
				$current_property_pointer = &$current_property_pointer[ $key ];
232
			}
233
			$current_property_pointer[ $end ] = $property_data;
234
		}
235
236
		return $jsonld;
237
	}
238
239
	private function make_single( $value ) {
240
241
		$values = (array) $value;
242
243
		if ( empty( $values ) ) {
244
			return false;
245
		}
246
247
		if ( 1 === count( $values ) && 0 === key( $values ) ) {
248
			return current( $values );
249
		}
250
251
		return $values;
252
	}
253
254
}
255