Completed
Push — master ( 47d32e...f7d774 )
by David
09:25
created

Wordlift_Query_Builder::statement()   D

Complexity

Conditions 9
Paths 129

Size

Total Lines 35
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 16
nc 129
nop 6
dl 0
loc 35
rs 4.6666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * A builder to build SPARQL queries.
5
 *
6
 * @since 3.1.7
7
 */
8
class Wordlift_Query_Builder {
9
10
	/**
11
	 * The INSERT statement template.
12
	 *
13
	 * @since 3.1.7
14
	 */
15
	const INSERT = 'INSERT DATA { %s };';
16
17
	/**
18
	 * The DELETE statement template (it repeats the statements in the WHERE clause.
19
	 *
20
	 * @since 3.1.7
21
	 */
22
	const DELETE = 'DELETE { %s } WHERE { %1$s };';
23
24
	/**
25
	 * Tell the statement function to guess the object type (URI, value or parameter).
26
	 *
27
	 * @since 3.1.7
28
	 */
29
	const OBJECT_AUTO = - 1;
30
31
	/**
32
	 * Tell the statement function that the object is a URI.
33
	 *
34
	 * @since 3.1.7
35
	 */
36
	const OBJECT_URI = 0;
37
38
	/**
39
	 * Tell the statement function that the object is a value.
40
	 *
41
	 * @since 3.1.7
42
	 */
43
	const OBJECT_VALUE = 1;
44
45
	/**
46
	 * Tell the statement function that the object is a parameter.
47
	 *
48
	 * @since 3.1.7
49
	 */
50
	const OBJECT_PARAMETER = 2;
51
52
	/**
53
	 * The RDFS type.
54
	 *
55
	 * @since 3.1.7
56
	 */
57
	const RDFS_TYPE_URI = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type';
58
59
	/**
60
	 * The schema.org/Person type.
61
	 *
62
	 * @since 3.1.7
63
	 */
64
	const SCHEMA_PERSON_URI = 'http://schema.org/Person';
65
66
	/**
67
	 * The schema.org given name predicate.
68
	 *
69
	 * @since 3.1.7
70
	 */
71
	const SCHEMA_GIVEN_NAME_URI = 'http://schema.org/givenName';
72
73
	/**
74
	 * The schema.org family name predicate.
75
	 *
76
	 * @since 3.1.7
77
	 */
78
	const SCHEMA_FAMILY_NAME_URI = 'http://schema.org/familyName';
79
80
	/**
81
	 * The schema.org url predicate.
82
	 *
83
	 * @since 3.1.7
84
	 */
85
	const SCHEMA_URL_URI = 'http://schema.org/url';
86
87
	/**
88
	 * @since 3.14.0
89
	 */
90
	const SCHEMA_IMAGE_URI = 'http://schema.org/image';
91
92
	/**
93
	 * The location created predicate.
94
	 *
95
	 * @since 3.14.0
96
	 */
97
	const SCHEMA_LOCATION_CREATED_URI = 'http://schema.org/locationCreated';
98
99
	/**
100
	 * @since 3.14.0
101
	 */
102
	const SCHEMA_AUTHOR_URI = 'http://schema.org/author';
103
104
	/**
105
	 * @since 3.14.0
106
	 */
107
	const SCHEMA_INTERACTION_COUNT_URI = 'http://schema.org/interactionCount';
108
109
	/**
110
	 * @since 3.14.0
111
	 */
112
	const DCTERMS_SUBJECT_URI = 'http://purl.org/dc/terms/subject';
113
114
	/**
115
	 * @since 3.14.0
116
	 */
117
	const DCTERMS_REFERENCES_URI = 'http://purl.org/dc/terms/references';
118
119
	/**
120
	 * The RDF label.
121
	 *
122
	 * @since 3.1.7
123
	 */
124
	const RDFS_LABEL_URI = 'http://www.w3.org/2000/01/rdf-schema#label';
125
126
	/**
127
	 * Hold the template (INSERT or DELETE).
128
	 *
129
	 * @since  3.1.7
130
	 * @access private
131
	 * @var string $template The query template.
132
	 */
133
	private $template;
134
135
	/**
136
	 * An array of statements (in the form of subject, predicate, object).
137
	 *
138
	 * @since  3.1.7
139
	 * @access private
140
	 * @var array $statements An array of statements.
141
	 */
142
	private $statements = array();
143
144
	/**
145
	 * Create a new instance of the Query builder (compatible with PHP 5.3).
146
	 *
147
	 * @since 3.1.7
148
	 * @return Wordlift_Query_Builder A new instance of the Query builder.
149
	 */
150
	public static function new_instance() {
151
152
		return new Wordlift_Query_Builder();
153
	}
154
155
	/**
156
	 * Set the query to INSERT.
157
	 *
158
	 * @since 3.1.7
159
	 * @return Wordlift_Query_Builder The Query builder.
160
	 */
161
	public function insert() {
162
163
		$this->template = self::INSERT;
164
165
		return $this;
166
	}
167
168
	/**
169
	 * Set the query to DELETE.
170
	 *
171
	 * @since 3.1.7
172
	 * @return $this \Wordlift_Query_Builder The Query builder.
173
	 */
174
	public function delete() {
175
176
		$this->template = self::DELETE;
177
178
		return $this;
179
	}
180
181
	/**
182
	 * Set the query to SELECT.
183
	 *
184
	 * @since 3.12.2
185
	 *
186
	 * @param string $props The list of properties to read.
187
	 *
188
	 * @return $this \Wordlift_Query_Builder The Query builder.
189
	 */
190
	public function select( $props = '*' ) {
191
192
		$this->template = "SELECT $props WHERE { %s }";
193
194
		return $this;
195
	}
196
197
	/**
198
	 * Add a statement.
199
	 *
200
	 * @since 3.1.7
201
	 *
202
	 * @param string      $subject     The subject of the statement (must be a URI).
203
	 * @param string      $predicate   The predicate (must be a URI).
204
	 * @param string      $object      The object, can be a URI or a value.
205
	 * @param int         $object_type The object type, either a {@link OBJECT_URI} or a value {@link OBJECT_VALUE}. If set to {@link OBJECT_AUTO}, the Query builder will try to guess.
206
	 * @param string|null $data_type   The data type (or null).
207
	 * @param string|null $language    The language code (or null).
208
	 *
209
	 * @return $this \Wordlift_Query_Builder The Query builder.
210
	 */
211
	public function statement( $subject, $predicate, $object, $object_type = self::OBJECT_AUTO, $data_type = null, $language = null ) {
212
213
		// If no value has been provided, we don't set any statement.
214
		if ( empty( $object ) ) {
215
			return $this;
216
		}
217
218
		// Guess the subject type.
219
		$subject_value_type = $this->guess_object_type( $predicate, $object );
220
221
		// Get the object type if set, otherwise try to guess it.
222
		$object_value_type = ( self::OBJECT_AUTO === $object_type ? $this->guess_object_type( $predicate, $object ) : $object_type );
223
224
		// Prepare the statement template.
225
		$template =
226
			// Subject as a parameter, no `<`, `>`.
227
			( self::OBJECT_PARAMETER === $subject_value_type ? '%1$s' : '<%1$s>' ) .
228
			// Predicate.
229
			' <%2$s> ' .
230
			// Object.
231
			( self::OBJECT_URI === $object_value_type ? '<%3$s>' :
232
				( self::OBJECT_PARAMETER === $object_value_type ? '%3$s' :
233
					// self::OBJECT_VALUE === $object_value_type
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
234
					'"%3$s"' . ( isset( $data_type ) ? '^^%4$s' : '' ) . ( isset( $language ) ? '@%5$s' : '' ) ) );
235
236
		// Escape the subject, predicate and object.
237
		$escaped_subject   = Wordlift_Sparql_Service::escape_uri( $subject );
238
		$escaped_predicate = Wordlift_Sparql_Service::escape_uri( $predicate );
239
		$escaped_object    = ( self::OBJECT_URI === $object_value_type ? Wordlift_Sparql_Service::escape_uri( $object ) : Wordlift_Sparql_Service::escape( $object ) );
240
241
		// Prepare the statement and add it to the list of statements.
242
		$this->statements[] = sprintf( $template, $escaped_subject, $escaped_predicate, $escaped_object, $data_type, $language );
243
244
		return $this;
245
	}
246
247
	/**
248
	 * Build the query.
249
	 *
250
	 * @since 3.1.7
251
	 * @return string The query string.
252
	 */
253
	public function build() {
254
255
		// If there are no statements return an empty string.
256
		if ( 0 === count( $this->statements ) ) {
257
			return '';
258
		}
259
260
		return sprintf( $this->template, implode( ' . ', $this->statements ) ) . "\n";
261
	}
262
263
	/**
264
	 * Guess the statement object type.
265
	 *
266
	 * @since 3.1.7
267
	 *
268
	 * @param string $predicate The predicate.
269
	 * @param string $object    The object.
270
	 *
271
	 * @return int {@link Wordlift_Query_Builder::OBJECT_URI} if the Query builder thinks the object must be an URI, {@link Wordlift_Query_Builder::OBJECT_VALUE} otherwise.
272
	 */
273
	private function guess_object_type( $predicate, $object ) {
274
275
		// If the object starts with a question mark, it's a parameter.
276
		if ( 0 === strpos( $object, '?' ) ) {
277
			return self::OBJECT_PARAMETER;
278
		}
279
280
		// Guess based on the predicate.
281
		switch ( $predicate ) {
282
283
			case self::DCTERMS_REFERENCES_URI:
284
			case self::DCTERMS_SUBJECT_URI:
285
			case self::RDFS_TYPE_URI:
286
			case self::SCHEMA_AUTHOR_URI:
287
			case self::SCHEMA_LOCATION_CREATED_URI:
288
			case self::SCHEMA_URL_URI:
289
			case self::SCHEMA_IMAGE_URI:
290
				return self::OBJECT_URI;
291
292
		}
293
294
		return self::OBJECT_VALUE;
295
	}
296
297
}
298