Completed
Push — develop ( d7af47...af6017 )
by David
03:12
created

Wordlift_Entity_Uri_Service::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Services: Entity Uri Service
4
 *
5
 * Provides access to entities' URIs, i.e. URIs stored as `entity_url` (the main
6
 * entity item ID) or as `same_as`.
7
 *
8
 * @since      3.16.3
9
 * @package    Wordlift
10
 * @subpackage Wordlift/includes
11
 */
12
13
/**
14
 * Define the {@link Wordlift_Entity_Uri_Service} class.
15
 *
16
 * @since 3.16.3
17
 */
18
class Wordlift_Entity_Uri_Service {
19
20
	/**
21
	 * A {@link Wordlift_Log_Service} instance.
22
	 *
23
	 * @since  3.16.3
24
	 * @access private
25
	 * @var \Wordlift_Log_Service $log A {@link Wordlift_Log_Service} instance.
26
	 */
27
	private $log;
28
29
	/**
30
	 * The {@link Wordlift_Configuration_Service} instance.
31
	 *
32
	 * @since  3.16.3
33
	 * @access private
34
	 * @var \Wordlift_Configuration_Service $configuration_service The {@link Wordlift_Configuration_Service} instance.
35
	 */
36
	private $configuration_service;
37
38
	/**
39
	 * An array of URIs to post ID valid for the current request.
40
	 *
41
	 * @since  3.16.3
42
	 * @access private
43
	 * @var array $uri_to_post An array of URIs to post ID valid for the current request.
44
	 */
45
	protected $uri_to_post;
46
47
	/**
48
	 * Create a {@link Wordlift_Entity_Uri_Service} instance.
49
	 *
50
	 * @since 3.16.3
51
	 *
52
	 * @param \Wordlift_Configuration_Service $configuration_service The {@link Wordlift_Configuration_Service} instance.
53
	 */
54
	public function __construct( $configuration_service ) {
55
56
		$this->log = Wordlift_Log_Service::get_logger( get_class() );
57
58
		$this->configuration_service = $configuration_service;
59
60
	}
61
62
	/**
63
	 * Preload the provided URIs in the local cache.
64
	 *
65
	 * This function will populate the local `$uri_to_post` array by running a
66
	 * single query with all the URIs and returning the mappings in the array.
67
	 *
68
	 * @since 3.16.3
69
	 *
70
	 * @param array $uris An array of URIs.
71
	 */
72
	public function preload_uris( $uris ) {
73
74
		// Bail out if there are no URIs.
75
		if ( 0 === count( $uris ) ) {
76
			return;
77
		}
78
79
		$this->log->trace( 'Preloading ' . count( $uris ) . ' URI(s)...' );
80
81
		$that          = $this;
82
		$external_uris = array_filter( $uris, function ( $item ) use ( $that ) {
83
			return ! $that->is_internal( $item );
84
		} );
85
86
		$query_args = array(
87
			// See https://github.com/insideout10/wordlift-plugin/issues/654.
88
			'ignore_sticky_posts' => 1,
89
			'cache_results'       => false,
90
			'numberposts'         => - 1,
91
			'post_status'         => 'any',
92
			'post_type'           => Wordlift_Entity_Service::valid_entity_post_types(),
93
			'meta_query'          => array(
94
				array(
95
					'key'     => WL_ENTITY_URL_META_NAME,
96
					'value'   => $uris,
97
					'compare' => 'IN',
98
				),
99
			),
100
		);
101
102
		// Only if the current uri is not an internal uri, entity search is
103
		// performed also looking at sameAs values.
104
		//
105
		// This solve issues like https://github.com/insideout10/wordlift-plugin/issues/237
106 View Code Duplication
		if ( 0 < count( $external_uris ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
107
108
			$query_args['meta_query']['relation'] = 'OR';
109
			$query_args['meta_query'][]           = array(
110
				'key'     => Wordlift_Schema_Service::FIELD_SAME_AS,
111
				'value'   => $external_uris,
112
				'compare' => 'IN',
113
			);
114
115
		}
116
117
		// Get the posts.
118
		$posts = get_posts( $query_args );
119
120
		// Populate the array. We reinitialize the array on purpose because
121
		// we don't want these data to long live.
122
		$this->uri_to_post = array_reduce( $posts, function ( $carry, $item ) use ( $that ) {
0 ignored issues
show
Documentation Bug introduced by
It seems like array_reduce($posts, fun...is, $item); }, array()) of type * is incompatible with the declared type array of property $uri_to_post.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
123
			$uris = get_post_meta( $item->ID, WL_ENTITY_URL_META_NAME )
124
					+ get_post_meta( $item->ID, Wordlift_Schema_Service::FIELD_SAME_AS );
125
126
			return $carry
127
				   // Get the URI related to the post and fill them with the item id.
128
				   + array_fill_keys( $uris, $item );
129
		}, array() );
130
131
		// Add the not found URIs.
132
		$this->uri_to_post += array_fill_keys( $uris, null );
133
134
		$this->log->debug( count( $this->uri_to_post ) . " URI(s) preloaded." );
135
136
	}
137
138
	/**
139
	 * Reset the URI to post local cache.
140
	 *
141
	 * @since 3.16.3
142
	 */
143
	public function reset_uris() {
144
145
		$this->uri_to_post = array();
146
147
	}
148
149
	/**
150
	 * Find entity posts by the entity URI. Entity as searched by their entity URI or same as.
151
	 *
152
	 * @since 3.2.0
153
	 *
154
	 * @param string $uri The entity URI.
155
	 *
156
	 * @return WP_Post|null A WP_Post instance or null if not found.
157
	 */
158
	public function get_entity( $uri ) {
159
160
		$this->log->trace( "Getting an entity post for URI $uri..." );
161
162
		// Check if we've been provided with a value otherwise return null.
163
		if ( empty( $uri ) ) {
164
			return null;
165
		}
166
167
		$this->log->debug( "Querying post for $uri..." );
168
169
		$query_args = array(
170
			// See https://github.com/insideout10/wordlift-plugin/issues/654.
171
			'ignore_sticky_posts' => 1,
172
			'posts_per_page'      => 1,
173
			'post_status'         => 'any',
174
			'post_type'           => Wordlift_Entity_Service::valid_entity_post_types(),
175
			'meta_query'          => array(
176
				array(
177
					'key'     => WL_ENTITY_URL_META_NAME,
178
					'value'   => $uri,
179
					'compare' => '=',
180
				),
181
			),
182
		);
183
184
		// Only if the current uri is not an internal uri, entity search is
185
		// performed also looking at sameAs values.
186
		//
187
		// This solve issues like https://github.com/insideout10/wordlift-plugin/issues/237
188 View Code Duplication
		if ( ! $this->is_internal( $uri ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
189
190
			$query_args['meta_query']['relation'] = 'OR';
191
			$query_args['meta_query'][]           = array(
192
				'key'     => Wordlift_Schema_Service::FIELD_SAME_AS,
193
				'value'   => $uri,
194
				'compare' => '=',
195
			);
196
		}
197
198
		$posts = get_posts( $query_args );
199
200
		// Return null if no post is found.
201
		if ( 0 === count( $posts ) ) {
202
			$this->log->warn( "No post for URI $uri." );
203
204
			return null;
205
		}
206
207
		// Return the found post.
208
		return current( $posts );
209
	}
210
211
	/**
212
	 * Determines whether a given uri is an internal uri or not.
213
	 *
214
	 * @since 3.16.3
215
	 *
216
	 * @param int $uri An uri.
217
	 *
218
	 * @return true if the uri internal to the current dataset otherwise false.
219
	 */
220
	public function is_internal( $uri ) {
221
222
		return ( 0 === strrpos( $uri, $this->configuration_service->get_dataset_uri() ) );
223
	}
224
225
}