Test Setup Failed
Branch gcconnex (718fe4)
by Ilia
20:37 queued 07:59
created

functions.php ➔ elgg_solr_reindex()   F

Complexity

Conditions 21
Paths > 20000

Size

Total Lines 206
Code Lines 138

Duplication

Lines 11
Ratio 5.34 %

Importance

Changes 0
Metric Value
cc 21
eloc 138
nc 33536
nop 0
dl 11
loc 206
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
function elgg_solr_reindex() {
4
	set_time_limit(0);
5
6
	$is_elgg18 = elgg_solr_is_elgg18();
7
8
	$guid_getter = 'elgg_solr_get_entity_guids';
9
	if ($is_elgg18) {
10
		$guid_getter = 'elgg_solr_get_entity_guids_18';
11
	}
12
13
	$ia = elgg_set_ignore_access(true);
14
	$show_hidden = access_get_show_hidden_status();
15
	access_show_hidden_entities(true);
16
17
	// lock the function
18
	elgg_set_plugin_setting('reindex_running', 1, 'elgg_solr');
19
20 View Code Duplication
	if (!file_exists(elgg_get_config('dataroot') . 'elgg_solr')) {
21
		mkdir(elgg_get_config('dataroot') . 'elgg_solr');
22
	}
23
24
	$logtime = elgg_get_config('elgg_solr_restart_logtime');
25
	if (!$logtime) {
26
		$logtime = time();
27
	}
28
	$log = elgg_get_config('dataroot') . 'elgg_solr/' . $logtime . '.txt';
29
	elgg_set_plugin_setting('current_log', $logtime, 'elgg_solr');
30
31
	// initialize the csv
32
	$report = array(
33
		'percent' => '',
34
		'count' => 0, // report prior to indexing this entity
35
		'typecount' => 0,
36
		'fullcount' => 0,
37
		'type' => '',
38
		'querytime' => 0,
39
		'message' => 'Initializing Reindex',
40
		'date' => date('Y-M-j H:i:s'),
41
		'logtime' => $logtime
42
	);
43
	file_put_contents($log, json_encode($report) . "\n", FILE_APPEND);
44
45
46
	$debug = get_input('debug', false);
47
	if ($debug) {
48
		elgg_set_config('elgg_solr_debug', 1);
49
	}
50
51
	$registered_types = elgg_get_config('elgg_solr_reindex_options');
52
	if (!$registered_types) {
53
		$registered_types = get_registered_entity_types();
54
	}
55
56
	// build our options and cache them in case we need to restart it
57
	$cacheoptions = array(
58
		'types' => $registered_types
59
	);
60
61
	$options = array();
62
	$time = elgg_get_config('elgg_solr_time_options');
63
	if ($time && is_array($time)) {
64
		$options['wheres'] = array(
65
			"e.time_created >= {$time['starttime']}",
66
			"e.time_created <= {$time['endtime']}",
67
		);
68
69
		$cacheoptions['starttime'] = $time['starttime'];
70
		$cacheoptions['endtime'] = $time['endtime'];
71
	}
72
73
	elgg_set_config('elgg_solr_nocommit', true); // tell our indexer not to commit right away
74
75
	$fullcount = 0;
76
	foreach ($registered_types as $type => $subtypes) {
77
		$options['type'] = $type;
78
		$options['subtypes'] = ELGG_ENTITIES_ANY_VALUE;
79
		$options['limit'] = false;
80
81
		$restart_time = elgg_get_config('elgg_solr_restart_time');
82
		if ($restart_time) {
83
			elgg_set_config('elgg_solr_restart_time', false);
84
85
			$options['wheres'][1] = "e.time_created <= {$restart_time}";
86
		} elseif ($time['endtime']) {
87
			$options['wheres'][1] = "e.time_created <= {$time['endtime']}";
88
		}
89
90 View Code Duplication
		if ($subtypes) {
91
			if (!is_array($subtypes)) {
92
				$options['subtypes'] = array($subtypes);
93
			}
94
			else {
95
				$options['subtypes'] = $subtypes;
96
			}
97
		}
98
99
		// this iteration fixes a bug https://github.com/Elgg/Elgg/issues/7561
100
		// uses a custom getter which only fetches the guids in a single large-batch query
101
		// which is much more efficient than standard egef
102
		$batch_size = elgg_get_plugin_setting('reindex_batch_size', 'elgg_solr');
103
		$entities = new ElggBatch($guid_getter, $options, null, $batch_size);
104
		$final_count = $guid_getter(array_merge($options, array('count' => true)));
105
106
		elgg_set_config('elgg_solr_nocommit', true); // disable committing on each entity for performance
107
		$count = 0;
108
		$fetch_time_start = microtime(true);
109
		foreach ($entities as $e) {
110
			$count++;
111
			$fullcount++;
112
			$first_entity = (bool) (($count % $batch_size) == 1);
113
			$last_entity = (bool) (($count % $batch_size) == 0);
114
115
			if ($first_entity) {
116
				// this is the first entity in the new batch
117
				$fetch_time = microtime(true) - $fetch_time_start; // the query time in seconds
118
			}
119
120
			$entity = get_entity($e->guid);
121
			if ($entity) {
122
				elgg_solr_add_update_entity(null, null, $entity);
123
				elgg_set_config('elgg_solr_nocommit', true);
124
			}
125
126
			if (!($count % 200)) {
127
				$qtime = round($fetch_time, 4);
0 ignored issues
show
Bug introduced by
The variable $fetch_time does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
128
				$percent = round($count / $final_count * 100);
129
				if ($entity) {
130
					$restart_time = $entity->time_created;
131
				}
132
				$report = array(
133
					'percent' => $percent,
134
					'count' => $count,
135
					'typecount' => $final_count,
136
					'fullcount' => $fullcount,
137
					'type' => $type,
138
					'querytime' => $qtime,
139
					'message' => '',
140
					'date' => date('Y-M-j H:i:s'),
141
					'cacheoptions' => $cacheoptions,
142
					'logtime' => $logtime,
143
					'restart_time' => $restart_time
144
				);
145
146
				file_put_contents($log, json_encode($report) . "\n", FILE_APPEND);
147
				elgg_set_config('elgg_solr_nocommit', false); // push a commit on this one
148
149
				// check for the termination signal
150
				if ($logtime == elgg_get_plugin_setting('stop_reindex', 'elgg_solr')) {
151
					$report = array(
152
						'percent' => $percent,
153
						'count' => $count,
154
						'typecount' => $final_count,
155
						'fullcount' => $fullcount,
156
						'type' => $type,
157
						'querytime' => $qtime,
158
						'message' => 'Reindex has been stopped',
159
						'date' => date('Y-M-j H:i:s'),
160
						'cacheoptions' => $cacheoptions,
161
						'logtime' => $logtime,
162
						'restart_time' => $restart_time
163
					);
164
					
165
					file_put_contents($log, json_encode($report) . "\n", FILE_APPEND);
166
					error_log('Stopping reindex due to termination signal');
167
					exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The function elgg_solr_reindex() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
168
				}
169
			}
170
171
			if ($last_entity) {
172
				$fetch_time_start = microtime(true);
173
			}
174
		}
175
176
		// we've finished this type, unset from the cache options
177
		unset($cacheoptions['types'][$type]);
178
	}
179
180
	$report = array(
181
		'percent' => '',
182
		'count' => 0, // report prior to indexing this entity
183
		'typecount' => 0,
184
		'fullcount' => 0,
185
		'type' => '',
186
		'querytime' => 0,
187
		'message' => 'Reindex complete',
188
		'date' => date('Y-M-j H:i:s'),
189
		'logtime' => $logtime
190
	);
191
	file_put_contents($log, json_encode($report) . "\n", FILE_APPEND);
192
	elgg_set_plugin_setting('reindex_running', 0, 'elgg_solr');
193
194
	// commit the last of the entities
195
	$client = elgg_solr_get_client();
196
	$query = $client->createUpdate();
197
	$query->addCommit();
198
199
	try {
200
		$client->update($query);
201
	} catch (Exception $e) {
202
		error_log($e->getMessage());
203
		return false;
204
	}
205
206
	access_show_hidden_entities($show_hidden);
207
	elgg_set_ignore_access($ia);
208
}
209
210
function elgg_solr_comment_reindex() {
211
	set_time_limit(0);
212
213
	$ia = elgg_set_ignore_access(true);
214
	$show_hidden = access_get_show_hidden_status();
215
	access_show_hidden_entities(true);
216
217
	$debug = get_input('debug', false);
218
	if ($debug) {
219
		elgg_set_config('elgg_solr_debug', 1);
220
	}
221
222
	// lock the function
223
	elgg_set_plugin_setting('reindex_running', 1, 'elgg_solr');
224
225 View Code Duplication
	if (!file_exists(elgg_get_config('dataroot') . 'elgg_solr')) {
226
		mkdir(elgg_get_config('dataroot') . 'elgg_solr');
227
	}
228
229
	$time = time();
230
	$log = elgg_get_config('dataroot') . 'elgg_solr/' . $time . '.txt';
231
	elgg_set_plugin_setting('current_log', $time, 'elgg_solr');
232
233
	// initialize the csv
234
	$report = array(
235
		'percent' => '',
236
		'count' => 0, // report prior to indexing this entity
237
		'typecount' => 0,
238
		'fullcount' => 0,
239
		'type' => 'Comments',
240
		'querytime' => 0,
241
		'message' => 'Initializing Reindex',
242
		'date' => date('Y-M-j H:i:s')
243
	);
244
	file_put_contents($log, json_encode($report) . "\n", FILE_APPEND);
245
246
247
	elgg_set_config('elgg_solr_nocommit', true); // tell our indexer not to commit right away
248
249
	$count = 0;
250
251
	// index comments
252
	$options = array(
253
		'annotation_name' => 'generic_comment',
254
		'limit' => false
255
	);
256
257
	$time = elgg_get_config('elgg_solr_time_options');
258
	if ($time && is_array($time)) {
259
		$options['annotation_created_time_lower'] = $time['starttime'];
260
		$options['annotation_created_time_upper'] = $time['endtime'];
261
	}
262
263
	$batch_size = elgg_get_plugin_setting('reindex_batch_size', 'elgg_solr');
264
	$comments = new ElggBatch('elgg_get_annotations', $options, null, $batch_size);
265
266
	$final_count = elgg_get_annotations(array_merge($options, array('count' => true)));
267
	$fetch_time_start = microtime(true);
268
269
	foreach ($comments as $comment) {
270
		$count++;
271
		$first_entity = (bool) (($count % $batch_size) == 1);
272
		$last_entity = (bool) (($count % $batch_size) == 0);
273
274
		if ($first_entity) {
275
			// this is the first entity in the new batch
276
			$fetch_time = microtime(true) - $fetch_time_start; // the query time in seconds
277
		}
278
279
		if ($count % 10000) {
280
			elgg_set_config('elgg_solr_nocommit', false); // push a commit on this one
281
		}
282
283
		if ($comment) {
284
			elgg_solr_index_annotation($comment);
285
			elgg_set_config('elgg_solr_nocommit', true);
286
		}
287
288
		if (!($count % 200)) {
289
			$qtime = round($fetch_time, 4);
0 ignored issues
show
Bug introduced by
The variable $fetch_time does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
290
			$percent = round($count / $final_count * 100);
291
			$report = array(
292
				'percent' => $percent,
293
				'count' => $count,
294
				'typecount' => $final_count,
295
				'fullcount' => $count,
296
				'type' => 'Comments',
297
				'querytime' => $qtime,
298
				'message' => '',
299
				'date' => date('Y-M-j H:i:s')
300
			);
301
302
			file_put_contents($log, json_encode($report) . "\n", FILE_APPEND);
303
		}
304
305
		if ($last_entity) {
306
			$fetch_time_start = microtime(true);
307
		}
308
	}
309
310
	if ($debug) {
311
		elgg_solr_debug_log($count . ' entities sent to Solr');
312
	}
313
314
	$report = array(
315
		'percent' => 100,
316
		'count' => $count,
317
		'typecount' => $final_count,
318
		'fullcount' => $count,
319
		'type' => 'Comments',
320
		'querytime' => 0,
321
		'message' => 'Comment Reindex has been completed',
322
		'date' => date('Y-M-j H:i:s')
323
	);
324
325
	file_put_contents($log, json_encode($report) . "\n", FILE_APPEND);
326
327
	elgg_set_ignore_access($ia);
328
	access_show_hidden_entities($show_hidden);
329
	elgg_set_plugin_setting('reindex_running', 0, 'elgg_solr');
330
}
331
332
function elgg_solr_get_indexable_count() {
333
	$registered_types = get_registered_entity_types();
334
335
	$ia = elgg_set_ignore_access(true);
336
337
	$count = 0;
338
	foreach ($registered_types as $type => $subtypes) {
0 ignored issues
show
Bug introduced by
The expression $registered_types of type array|false is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
339
		$options = array(
340
			'type' => $type,
341
			'count' => true
342
		);
343
344
		if ($subtypes) {
345
			$options['subtypes'] = $subtypes;
346
		}
347
348
		$count += elgg_get_entities($options);
349
	}
350
351
	// count comments
352
	$options = array(
353
		'annotation_name' => 'generic_comment',
354
		'count' => true
355
	);
356
	$count += elgg_get_annotations($options);
357
358
	elgg_set_ignore_access($ia);
359
360
	return $count;
361
}
362
363
function elgg_solr_get_indexed_count($query = '*:*', $fq = array()) {
364
	$select = array(
365
		'query' => $query,
366
		'start' => 0,
367
		'rows' => 1,
368
		'fields' => array('id'),
369
	);
370
371
	// create a client instance
372
	$client = elgg_solr_get_client();
373
374
	// get an update query instance
375
	$query = $client->createSelect($select);
376
377
	if (!empty($fq)) {
378
		foreach ($fq as $key => $value) {
379
			$query->createFilterQuery($key)->setQuery($value);
380
		}
381
	}
382
383
	try {
384
		$resultset = $client->select($query);
385
	} catch (Exception $e) {
386
		error_log($e->getMessage());
387
		return false;
388
	}
389
390
	return $resultset->getNumFound();
391
}
392
393
function elgg_solr_get_client() {
394
	elgg_load_library('Solarium');
395
396
	Solarium\Autoloader::register();
397
398
	$options = elgg_solr_get_adapter_options();
399
400
	$config = array('endpoint' => array(
401
			'localhost' => $options
402
	));
403
404
	// create a client instance
405
	return new Solarium\Client($config);
406
}
407
408
function elgg_solr_get_adapter_options() {
409
	return array(
410
		'host' => elgg_get_plugin_setting('host', 'elgg_solr'),
411
		'port' => elgg_get_plugin_setting('port', 'elgg_solr'),
412
		'path' => elgg_get_plugin_setting('solr_path', 'elgg_solr'),
413
		'core' => elgg_get_plugin_setting('solr_core', 'elgg_solr'),
414
	);
415
}
416
417
function elgg_solr_has_settings() {
418
	$host = elgg_get_plugin_setting('host', 'elgg_solr');
419
	$port = elgg_get_plugin_setting('port', 'elgg_solr');
420
	$path = elgg_get_plugin_setting('path', 'elgg_solr');
421
422
	if (empty($host) || empty($port) || empty($path)) {
423
		return false;
424
	}
425
426
	return true;
427
}
428
429
/**
430
 * get default filter queries based on search params
431
 * 
432
 * @param type $params
433
 * 
434
 * return array
435
 */
436
function elgg_solr_get_default_fq($params) {
437
	$fq = array();
438
439
	// type/types
440 View Code Duplication
	if (isset($params['type']) && $params['type'] !== ELGG_ENTITIES_ANY_VALUE) {
441
		if ($params['type'] === ELGG_ENTITIES_NO_VALUE) {
442
			//$fq['type'] = '-type:[* TO *]';
443
			$fq['type'] = 'type:""';
444
		} else {
445
			$fq['type'] = 'type:' . $params['type'];
446
		}
447
	}
448
449 View Code Duplication
	if ($params['types'] && $params['types'] !== ELGG_ENTITIES_ANY_VALUE) {
450
		if (is_array($params['types'])) {
451
			$fq['type'] = 'type:(' . implode(' OR ', $params['types']) . ')';
452
		} else {
453
			if ($params['types'] === ELGG_ENTITIES_NO_VALUE) {
454
				//$fq['type'] = '-type:[* TO *]';
455
				$fq['type'] = 'type:""';
456
			} else {
457
				$fq['type'] = 'type:' . $params['types'];
458
			}
459
		}
460
	}
461
462
	//subtype
463 View Code Duplication
	if (isset($params['subtype']) && $params['subtype'] !== ELGG_ENTITIES_ANY_VALUE) {
464
		if ($params['subtype'] === ELGG_ENTITIES_NO_VALUE) {
465
			//$fq['subtype'] = '-subtype:[* TO *]';
466
			$fq['subtype'] = 'subtype:""';
467
		} else {
468
			$fq['subtype'] = 'subtype:' . $params['subtype'];
469
		}
470
	}
471
472 View Code Duplication
	if (isset($params['subtypes']) && $params['subtypes'] !== ELGG_ENTITIES_ANY_VALUE) {
473
		if (is_array($params['subtypes'])) {
474
			$fq['subtype'] = 'subtype:(' . implode(' OR ', $params['subtypes']) . ')';
475
		} else {
476
			if ($params['subtypes'] === ELGG_ENTITIES_NO_VALUE) {
477
				//$fq['subtype'] = '-subtype:[* TO *]';
478
				$fq['subtype'] = 'subtype:""';
479
			} else {
480
				$fq['subtype'] = 'subtype:' . $params['subtypes'];
481
			}
482
		}
483
	}
484
485
486
	//container
487
	if (isset($params['container_guid']) && $params['container_guid'] !== ELGG_ENTITIES_ANY_VALUE) {
488
		$fq['container'] = 'container_guid:' . $params['container_guid'];
489
	}
490
491 View Code Duplication
	if (isset($params['container_guids']) && $params['container_guids'] !== ELGG_ENTITIES_ANY_VALUE) {
492
		if (is_array($params['container_guids'])) {
493
			$fq['container'] = 'container_guid:(' . implode(' OR ', $params['container_guids']) . ')';
494
		} else {
495
			$fq['container'] = 'container_guid:' . $params['container_guid'];
496
		}
497
	}
498
499
	//owner
500
	if (isset($params['owner_guid']) && $params['owner_guid'] !== ELGG_ENTITIES_ANY_VALUE) {
501
		$fq['owner'] = 'owner_guid:' . $params['owner_guid'];
502
	}
503
504 View Code Duplication
	if (isset($params['owner_guids']) && $params['owner_guids'] !== ELGG_ENTITIES_ANY_VALUE) {
505
		if (is_array($params['owner_guids'])) {
506
			$fq['owner'] = 'owner_guid:(' . implode(' OR ', $params['owner_guids']) . ')';
507
		} else {
508
			$fq['owner'] = 'owner_guid:' . $params['owner_guid'];
509
		}
510
	}
511
512
	$access_query = elgg_solr_get_access_query();
513
	if ($access_query) {
514
		$fq['access'] = $access_query;
515
	}
516
517
	if (!access_get_show_hidden_status()) {
518
		$fq['enabled'] = 'enabled:"yes"';
519
	}
520
521
	return $fq;
522
}
523
524
/**
525
 * Register a function to define specific configuration of an entity in solr
526
 * 
527
 * @param type $type - the entity type
528
 * @param type $subtype - the entity subtype
529
 * @param type $function - the function to call for updating an entity in solr
530
 */
531 View Code Duplication
function elgg_solr_register_solr_entity_type($type, $subtype, $function) {
0 ignored issues
show
Duplication introduced by
This function 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...
532
	$solr_entities = elgg_get_config('solr_entities');
533
534
	if (!is_array($solr_entities)) {
535
		$solr_entities = array();
536
	}
537
538
	$solr_entities[$type][$subtype] = $function;
539
540
	elgg_set_config('solr_entities', $solr_entities);
541
}
542
543
/**
544
 * 
545
 * 
546
 * @param type $type
547
 * @param type $subtype
548
 * @return boolean
549
 */
550
function elgg_solr_get_solr_function($type, $subtype) {
551
	if (elgg_get_config('elgg_solr_debug')) {
552
		$debug = true;
553
	}
554
555
	$solr_entities = elgg_get_config('solr_entities');
556
557
	if (isset($solr_entities[$type][$subtype]) && is_callable($solr_entities[$type][$subtype])) {
558
		return $solr_entities[$type][$subtype];
559
	}
560
561
	if (isset($solr_entities[$type]['default']) && is_callable($solr_entities[$type]['default'])) {
562
		return $solr_entities[$type]['default'];
563
	}
564
565
	if (isset($solr_entities['entity']['default']) && is_callable($solr_entities['entity']['default'])) {
566
		return $solr_entities['entity']['default'];
567
	}
568
569
	if ($debug) {
0 ignored issues
show
Bug introduced by
The variable $debug does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
570
		elgg_solr_debug_log('Solr function not callable for type: ' . $type . ', subtype: ' . $subtype);
571
	}
572
573
	return false;
574
}
575
576
/**
577
 * Index a file entity
578
 * 
579
 * @param type $entity
580
 * @return boolean
581
 */
582
function elgg_solr_add_update_file($entity) {
583
584
	$client = elgg_solr_get_client();
585
	$commit = elgg_get_config('elgg_solr_nocommit') ? false : true;
586
587
	$extract = elgg_get_plugin_setting('extract_handler', 'elgg_solr');
588
	$extracting = false;
589
	if (file_exists($entity->getFilenameOnFilestore()) && $extract == 'yes') {
590
		$extracting = true;
591
	}
592
593
	if ($extracting) {
594
		// get an extract query instance and add settings
595
		$query = $client->createExtract();
596
		$query->setFile($entity->getFilenameOnFilestore());
597
		$query->addFieldMapping('content', 'attr_content');
598
		$query->setUprefix('attr_');
599
		$query->setOmitHeader(true);
600
	} else {
601
		$query = $client->createUpdate();
602
	}
603
	
604
	$subtype = $entity->getSubtype() ? $entity->getSubtype() : '';
605
606
	// add document
607
	$doc = $query->createDocument();
608
	$doc->id = $entity->guid;
609
	$doc->type = $entity->type;
610
	$doc->subtype = $subtype;
611
	$doc->owner_guid = $entity->owner_guid;
612
	$doc->container_guid = $entity->container_guid;
613
	$doc->access_id = $entity->access_id;
614
	$doc->title = gc_explode_translation(elgg_strip_tags($entity->title), get_current_language());
615
	$doc->description = gc_explode_translation(elgg_strip_tags($entity->description), get_current_language());
616
	$doc->time_created = $entity->time_created;
617
	$doc = elgg_solr_add_tags($doc, $entity);
618
	$doc->enabled = $entity->enabled;
619
620
	$params = array('entity' => $entity);
621
	$doc = elgg_trigger_plugin_hook('elgg_solr:index', $entity->type, $params, $doc);
622
	
623
	if (!$doc) {
624
		return true; // a plugin hook has stopped the indexing
625
	}
626
627
	if ($extracting) {
628
		$query->setDocument($doc);
629
		if ($commit) {
630
			$query->setCommit(true);
631
		}
632
		try {
633
			$client->extract($query);
634
		} catch (Exception $exc) {
635
			error_log($exc->getMessage());
636
		}
637
	} else {
638
		$query->addDocument($doc);
639
		if ($commit) {
640
			$query->addCommit();
641
		}
642
643
		try {
644
			$client->update($query);
645
		} catch (Exception $exc) {
646
			error_log($exc->getMessage());
647
		}
648
	}
649
650
	return true;
651
}
652
653
/**
654
 * Index a generic elgg object
655
 * 
656
 * @param type $entity
657
 * @return boolean
658
 */
659
function elgg_solr_add_update_object_default($entity) {
660
661
	if (!is_registered_entity_type($entity->type, $entity->getSubtype())) {
662
		return false;
663
	}
664
665
	$client = elgg_solr_get_client();
666
	$commit = elgg_get_config('elgg_solr_nocommit') ? false : true;
667
668
	$query = $client->createUpdate();
669
	
670
	$subtype = $entity->getSubtype() ? $entity->getSubtype() : '';
671
672
	// add document
673
	$doc = $query->createDocument();
674
	$doc->id = $entity->guid;
675
	$doc->type = $entity->type;
676
	$doc->subtype = $subtype;
677
	$doc->owner_guid = $entity->owner_guid;
678
	$doc->container_guid = $entity->container_guid;
679
	$doc->access_id = $entity->access_id;
680
	$doc->title = gc_explode_translation(elgg_strip_tags($entity->title), get_current_language());
681
	$doc->name = gc_explode_translation(elgg_strip_tags($entity->name), get_current_language());
682
	$doc->description = gc_explode_translation(elgg_strip_tags($entity->description), get_current_language());
683
	$doc->time_created = $entity->time_created;
684
	$doc = elgg_solr_add_tags($doc, $entity);
685
	$doc->enabled = $entity->enabled;
686
687
	$params = array('entity' => $entity);
688
	$doc = elgg_trigger_plugin_hook('elgg_solr:index', $entity->type, $params, $doc);
689
	
690
	if (!$doc) {
691
		return true; // a plugin has stopped the index
692
	}
693
694
	$query->addDocument($doc);
695
	if ($commit) {
696
		$query->addCommit($commit);
697
	}
698
699
	// this executes the query and returns the result
700
	try {
701
		$client->update($query);
702
	} catch (Exception $exc) {
703
		error_log($exc->getMessage());
704
	}
705
706
	return true;
707
}
708
709
function elgg_solr_add_update_user($entity) {
710
711
	if (!elgg_instanceof($entity, 'user')) {
712
		return false;
713
	}
714
715
	if (!is_registered_entity_type($entity->type, $entity->getSubtype())) {
716
		return false;
717
	}
718
719
	// lump public profile fields in with description
720
	$profile_fields = elgg_get_config('profile_fields');
721
	$desc = '';
722
	if (is_array($profile_fields) && sizeof($profile_fields) > 0) {
723
		$walled = elgg_get_config('walled_garden');
724
		foreach ($profile_fields as $shortname => $valtype) {
725
			$md = elgg_get_metadata(array(
726
				'guid' => $entity->guid,
727
				'metadata_names' => array($shortname)
728
			));
729
730
			foreach ($md as $m) {
0 ignored issues
show
Bug introduced by
The expression $md of type array<integer,object<ElggExtender>>|integer is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
731
				if ($m->access_id == ACCESS_PUBLIC || ($walled && $m->access_id == ACCESS_LOGGED_IN)) {
732
					$desc .= $m->value . ' ';
733
				}
734
			}
735
		}
736
	}
737
738
	$client = elgg_solr_get_client();
739
	$commit = elgg_get_config('elgg_solr_nocommit') ? false : true;
740
741
	$query = $client->createUpdate();
742
	$subtype = $entity->getSubtype() ? $entity->getSubtype() : '';
743
744
	// add document
745
	$doc = $query->createDocument();
746
	$doc->id = $entity->guid;
747
	$doc->type = $entity->type;
748
	$doc->subtype = $subtype;
749
	$doc->owner_guid = $entity->owner_guid;
750
	$doc->container_guid = $entity->container_guid;
751
	$doc->access_id = $entity->access_id;
752
	$doc->title = elgg_strip_tags($entity->title);
753
	$doc->name = elgg_strip_tags($entity->name);
754
	$doc->username = $entity->username;
755
	$doc->description = elgg_strip_tags($desc);
756
	$doc->time_created = $entity->time_created;
757
	$doc = elgg_solr_add_tags($doc, $entity);
758
	$doc->enabled = $entity->enabled;
759
	$doc->user_type = $entity->user_type;
760
761
	$params = array('entity' => $entity);
762
	$doc = elgg_trigger_plugin_hook('elgg_solr:index', $entity->type, $params, $doc);
763
	
764
	if (!$doc) {
765
		return true; // a plugin has stopped the index
766
	}
767
768
	$query->addDocument($doc, true);
769
	if ($commit) {
770
		$query->addCommit();
771
	}
772
773
	// this executes the query and returns the result
774
	try {
775
		$client->update($query);
776
	} catch (Exception $exc) {
777
		error_log($exc->getMessage());
778
	}
779
	return true;
780
}
781
782
function elgg_solr_debug_log($message) {
783
	error_log($message);
784
}
785
786
function elgg_solr_get_access_query() {
787
788
	if (elgg_is_admin_logged_in() || elgg_get_ignore_access()) {
789
		return false; // no access limit
790
	}
791
792
	static $return;
793
794
	if ($return) {
795
		return $return;
796
	}
797
798
	$access = get_access_array();
799
800
	// access filter query
801
	if ($access) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $access of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
802
		$access_list = implode(' ', $access);
803
	}
804
805
	if (elgg_is_logged_in()) {
806
807
		// get friends
808
		// @TODO - is there a better way? Not sure if there's a limit on solr if
809
		// someone has a whole lot of friends...
810
		$friends = elgg_get_entities_from_relationship(array(
811
			'type' => 'user',
812
			'relationship' => 'friend',
813
			'relationship_guid' => elgg_get_logged_in_user_guid(),
814
			'inverse_relationship' => true,
815
			'limit' => false,
816
			'callback' => false // keep the query fast
817
		));
818
819
		$friend_guids = array();
820
		foreach ($friends as $friend) {
0 ignored issues
show
Bug introduced by
The expression $friends of type false|integer|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
821
			$friend_guids[] = $friend->guid;
822
		}
823
824
		$friends_list = '';
825
		if ($friend_guids) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $friend_guids of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
826
			$friends_list = elgg_solr_escape_special_chars(implode(' ', $friend_guids));
827
		}
828
	}
829
830
	//$query->createFilterQuery('access')->setQuery("owner_guid: {guid} OR access_id:({$access_list}) OR (access_id:" . ACCESS_FRIENDS . " AND owner_guid:({$friends}))");
831
	if (elgg_is_logged_in()) {
832
		$return = "owner_guid:" . elgg_get_logged_in_user_guid();
833
	} else {
834
		$return = '';
835
	}
836
837
	if ($access_list) {
838
		if ($return) {
839
			$return .= ' OR ';
840
		}
841
		$return .= "access_id:(" . elgg_solr_escape_special_chars($access_list) . ")";
0 ignored issues
show
Bug introduced by
The variable $access_list does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
842
	}
843
844
	$fr_prefix = '';
845
	$fr_suffix = '';
846
	if ($return && $friends_list) {
0 ignored issues
show
Bug introduced by
The variable $friends_list does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
847
		$return .= ' OR ';
848
		$fr_prefix = '(';
849
		$fr_suffix = ')';
850
	}
851
852
	if ($friends_list) {
853
		$return .= $fr_prefix . 'access_id:' . elgg_solr_escape_special_chars(ACCESS_FRIENDS) . ' AND owner_guid:(' . $friends_list . ')' . $fr_suffix;
854
	}
855
856
	return $return;
857
}
858
859
/**
860
 * by default there's nothing we need to do different with this
861
 * so it's just a wrapper for object add
862
 * 
863
 * @param type $entity
864
 */
865
function elgg_solr_add_update_group_default($entity) {
866
	elgg_solr_add_update_object_default($entity);
867
}
868
869
function elgg_solr_escape_special_chars($string) {
870
	// Lucene characters that need escaping with \ are + - && || ! ( ) { } [ ] ^ " ~ * ? : \
871
	$luceneReservedCharacters = preg_quote('+-&|!(){}[]^"~*?:\\');
872
	$query = preg_replace_callback('/([' . $luceneReservedCharacters . '])/', 'elgg_solr_escape_special_chars_callback', $string);
873
	return $query;
874
}
875
876
function elgg_solr_escape_special_chars_callback($matches) {
877
	return '\\' . $matches[0];
878
}
879
880
/**
881
 * 
882
 * @param type $time - timestamp of the start of the block
883
 * @param type $block - the block of time, hour/day/month/year/all
884
 * @param type $type
885
 * @param type $subtype
886
 * @return type
887
 */
888
function elgg_solr_get_stats($time, $block, $type, $subtype) {
889
	$options = array(
890
		'type' => $type
891
	);
892
893
	$fq = array();
894
895
	if ($subtype) {
896
		$options['subtype'] = $subtype;
897
		$fq['subtype'] = "subtype:{$subtype}";
898
	} else {
899
		$options['subtype'] = ELGG_ENTITIES_NO_VALUE;
900
	}
901
902
	$stats = array();
903
	switch ($block) {
904
		case 'minute':
905
			for ($i = 0; $i < 60; $i++) {
906
				$starttime = mktime(date('G', $time), date('i', $time), $i, date('m', $time), date('j', $time), date('Y', $time));
907
				$endtime = mktime(date('G', $time), date('i', $time), $i + 1, date('m', $time), date('j', $time), date('Y', $time));
908
909
				$fq['time_created'] = "time_created:[{$starttime} TO {$endtime}]";
910
				$indexed = elgg_solr_get_indexed_count("type:{$type}", $fq);
911
				$system = elgg_solr_get_system_count($options, $starttime, $endtime);
912
913
				$stats[date('s', $starttime)] = array(
914
					'count' => $system,
915
					'indexed' => $indexed,
916
					'starttime' => $starttime,
917
					'endtime' => $endtime,
918
					'block' => false
919
				);
920
			}
921
			break;
922
		case 'hour':
923
			for ($i = 0; $i < 60; $i++) {
924
				$starttime = mktime(date('G', $time), $i, 0, date('m', $time), date('j', $time), date('Y', $time));
925
				$endtime = mktime(date('G', $time), $i + 1, 0, date('m', $time), date('j', $time), date('Y', $time)) - 1;
926
927
				$fq['time_created'] = "time_created:[{$starttime} TO {$endtime}]";
928
				$indexed = elgg_solr_get_indexed_count("type:{$type}", $fq);
929
				$system = elgg_solr_get_system_count($options, $starttime, $endtime);
930
931
				$stats[date('i', $starttime)] = array(
932
					'count' => $system,
933
					'indexed' => $indexed,
934
					'starttime' => $starttime,
935
					'endtime' => $endtime,
936
					'block' => false
937
				);
938
			}
939
			break;
940 View Code Duplication
		case 'day':
941
			for ($i = 0; $i < 24; $i++) {
942
				$starttime = mktime($i, 0, 0, date('m', $time), date('j', $time), date('Y', $time));
943
				$endtime = mktime($i + 1, 0, 0, date('m', $time), date('j', $time), date('Y', $time)) - 1;
944
945
				$fq['time_created'] = "time_created:[{$starttime} TO {$endtime}]";
946
				$indexed = elgg_solr_get_indexed_count("type:{$type}", $fq);
947
				$system = elgg_solr_get_system_count($options, $starttime, $endtime);
948
949
				$stats[date('H', $starttime)] = array(
950
					'count' => $system,
951
					'indexed' => $indexed,
952
					'starttime' => $starttime,
953
					'endtime' => $endtime,
954
					'block' => 'hour'
955
				);
956
			}
957
			break;
958 View Code Duplication
		case 'month':
959
			for ($i = 1; $i < date('t', $time) + 1; $i++) {
960
				$starttime = mktime(0, 0, 0, date('m', $time), $i, date('Y', $time));
961
				$endtime = mktime(0, 0, 0, date('m', $time), $i + 1, date('Y', $time)) - 1;
962
963
				$fq['time_created'] = "time_created:[{$starttime} TO {$endtime}]";
964
				$indexed = elgg_solr_get_indexed_count("type:{$type}", $fq);
965
				$system = elgg_solr_get_system_count($options, $starttime, $endtime);
966
967
				$stats[date('d', $starttime)] = array(
968
					'count' => $system,
969
					'indexed' => $indexed,
970
					'starttime' => $starttime,
971
					'endtime' => $endtime,
972
					'block' => 'day'
973
				);
974
			}
975
			break;
976
		case 'year':
977
			for ($i = 1; $i < 13; $i++) {
978
				$starttime = mktime(0, 0, 0, $i, 1, date('Y', $time));
979
				$endtime = mktime(0, 0, 0, $i + 1, 1, date('Y', $time)) - 1;
980
981
				$fq['time_created'] = "time_created:[{$starttime} TO {$endtime}]";
982
				$indexed = elgg_solr_get_indexed_count("type:{$type}", $fq);
983
				$system = elgg_solr_get_system_count($options, $starttime, $endtime);
984
985
				$stats[date('F', $starttime)] = array(
986
					'count' => $system,
987
					'indexed' => $indexed,
988
					'starttime' => $starttime,
989
					'endtime' => $endtime,
990
					'block' => 'month'
991
				);
992
			}
993
			break;
994
995
		case 'all':
996
		default:
997
			$startyear = date('Y', elgg_get_site_entity()->time_created);
998
			$currentyear = date('Y');
999
1000
			for ($i = $currentyear; $i > $startyear - 1; $i--) {
1001
				$starttime = mktime(0, 0, 0, 1, 1, $i);
1002
				$endtime = mktime(0, 0, 0, 1, 1, $i + 1) - 1;
1003
1004
				$fq['time_created'] = "time_created:[{$starttime} TO {$endtime}]";
1005
				$indexed = elgg_solr_get_indexed_count("type:{$type}", $fq);
1006
				$system = elgg_solr_get_system_count($options, $starttime, $endtime);
1007
1008
				$stats[$i] = array(
1009
					'count' => $system,
1010
					'indexed' => $indexed,
1011
					'starttime' => $starttime,
1012
					'endtime' => $endtime,
1013
					'block' => 'year'
1014
				);
1015
			}
1016
1017
			break;
1018
	}
1019
1020
	return $stats;
1021
}
1022
1023
function elgg_solr_get_system_count($options, $starttime, $endtime) {
1024
	$options['wheres'] = array(
1025
		"e.time_created >= {$starttime}",
1026
		"e.time_created <= {$endtime}"
1027
	);
1028
1029
	$options['count'] = true;
1030
1031
	$access = access_get_show_hidden_status();
1032
	access_show_hidden_entities(true);
1033
	$count = elgg_get_entities($options);
1034
	access_show_hidden_entities($access);
1035
1036
	return $count;
1037
}
1038
1039
function elgg_solr_get_display_datetime($time, $block) {
1040
1041
	switch ($block) {
1042
		case 'year':
1043
			$format = 'Y';
1044
			break;
1045
		case 'month':
1046
			$format = 'F Y';
1047
			break;
1048
		case 'day':
1049
			$format = 'F j, Y';
1050
			break;
1051
		case 'hour':
1052
			$format = 'F j, Y H:00';
1053
			break;
1054
		case 'minute':
1055
			$format = 'F j, Y H:i';
1056
			break;
1057
		case 'all':
1058
		default:
1059
			return elgg_echo('elgg_solr:time:all');
1060
			break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1061
	}
1062
1063
	return date($format, $time);
1064
}
1065
1066
/**
1067
 * Returns an array of tags for indexing
1068
 * 
1069
 * @param type $entity
1070
 * @return string
1071
 */
1072
function elgg_solr_get_tags_array($entity) {
1073
	$valid_tag_names = elgg_get_registered_tag_metadata_names();
1074
1075
	$t = array();
1076
	if ($valid_tag_names && is_array($valid_tag_names)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $valid_tag_names of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1077
		foreach ($valid_tag_names as $tagname) {
1078
			$tags = $entity->$tagname;
1079
			if ($tags && !is_array($tags)) {
1080
				$tags = array($tags);
1081
			}
1082
1083
			if ($tags && is_array($tags)) {
1084
				foreach ($tags as $tag) {
1085
					$t[] = $tagname . '%%' . $tag;
1086
				}
1087
			}
1088
		}
1089
	}
1090
1091
	return $t;
1092
}
1093
1094
1095
function elgg_solr_add_tags($doc, $entity) {
1096
	if (!elgg_instanceof($entity)) {
1097
		return $doc;
1098
	}
1099
	
1100
	// store tags the old way - lumped together in $doc->tags as $name . '%%' . $value'
1101
	$doc->tags = elgg_solr_get_tags_array($entity);
1102
	
1103
	// also store them separately with magick fields
1104
	// store in different field types for different search types
1105
	$valid_tag_names = elgg_get_registered_tag_metadata_names();
1106
1107
	if ($valid_tag_names && is_array($valid_tag_names)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $valid_tag_names of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1108
		foreach ($valid_tag_names as $tagname) {
1109
			$tags = $entity->$tagname;
1110
			if ($tags && !is_array($tags)) {
1111
				$tags = array($tags);
1112
			}
1113
1114
			$name = 'tag_' . $tagname . '_ss'; // multivalued string
1115
			$doc->$name = $tags;
1116
		}
1117
	}
1118
	
1119
	return $doc;
1120
}
1121
1122 View Code Duplication
function elgg_solr_get_title_boost() {
0 ignored issues
show
Duplication introduced by
This function 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...
1123
	static $title_boost;
1124
1125
	if ($title_boost) {
1126
		return $title_boost;
1127
	}
1128
1129
	$title_boost = elgg_get_plugin_setting('title_boost', 'elgg_solr');
1130
	if (!is_numeric($title_boost)) {
1131
		$title_boost = 1.5;
1132
	}
1133
1134
	return $title_boost;
1135
}
1136
1137 View Code Duplication
function elgg_solr_get_description_boost() {
0 ignored issues
show
Duplication introduced by
This function 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...
1138
	static $description_boost;
1139
1140
	if ($description_boost) {
1141
		return $description_boost;
1142
	}
1143
1144
	$description_boost = elgg_get_plugin_setting('description_boost', 'elgg_solr');
1145
	if (!is_numeric($description_boost)) {
1146
		$description_boost = 1.5;
1147
	}
1148
1149
	return $description_boost;
1150
}
1151
1152
function elgg_solr_get_boost_query() {
1153
	static $boostquery;
1154
1155
	if ($boostquery || $boostquery === false) {
1156
		return $boostquery;
1157
	}
1158
1159
	$use_boostquery = elgg_get_plugin_setting('use_time_boost', 'elgg_solr');
1160
	if ($use_boostquery != 'yes') {
1161
		$boostquery = false;
1162
		return $boostquery;
1163
	}
1164
1165
	$num = elgg_get_plugin_setting('time_boost_num', 'elgg_solr');
1166
	$interval = elgg_get_plugin_setting('time_boost_interval', 'elgg_solr');
1167
	$time_boost = elgg_get_plugin_setting('time_boost', 'elgg_solr');
1168
	$starttime = strtotime("-{$num} {$interval}");
1169
	$now = time();
1170
1171
	if (!is_numeric($num) || !is_numeric($starttime) || !is_numeric($time_boost)) {
1172
		$boostquery = false;
1173
		return $boostquery;
1174
	}
1175
1176
	$boostquery = "time_created:[{$starttime} TO {$now}]^{$time_boost}";
1177
	return $boostquery;
1178
}
1179
1180
function elgg_solr_get_hl_prefix() {
1181
	static $hl_prefix;
1182
1183
	if ($hl_prefix) {
1184
		return $hl_prefix;
1185
	}
1186
1187
	$hl_prefix = elgg_get_plugin_setting('hl_prefix', 'elgg_solr');
1188
1189
	return $hl_prefix;
1190
}
1191
1192
function elgg_solr_get_hl_suffix() {
1193
	static $hl_suffix;
1194
1195
	if ($hl_suffix) {
1196
		return $hl_suffix;
1197
	}
1198
1199
	$hl_suffix = elgg_get_plugin_setting('hl_suffix', 'elgg_solr');
1200
1201
	return $hl_suffix;
1202
}
1203
1204 View Code Duplication
function elgg_solr_defer_index_update($guid) {
0 ignored issues
show
Duplication introduced by
This function 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...
1205
	$guids = elgg_get_config('elgg_solr_sync');
1206
	if (!is_array($guids)) {
1207
		$guids = array();
1208
	}
1209
	$guids[$guid] = 1; // use key to keep it unique
1210
1211
	elgg_set_config('elgg_solr_sync', $guids);
1212
}
1213
1214 View Code Duplication
function elgg_solr_defer_index_delete($guid) {
0 ignored issues
show
Duplication introduced by
This function 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...
1215
	$delete_guids = elgg_get_config('elgg_solr_delete');
1216
	if (!is_array($delete_guids)) {
1217
		$delete_guids = array();
1218
	}
1219
1220
	$delete_guids[$guid] = 1;
1221
1222
	elgg_set_config('elgg_solr_delete', $delete_guids);
1223
}
1224
1225 View Code Duplication
function elgg_solr_defer_annotation_delete($id) {
0 ignored issues
show
Duplication introduced by
This function 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...
1226
	$delete_ids = elgg_get_config('elgg_solr_annotation_delete');
1227
	if (!is_array($delete_ids)) {
1228
		$delete_ids = array();
1229
	}
1230
1231
	$delete_ids[$id] = 1;
1232
1233
	elgg_set_config('elgg_solr_annotation_delete', $delete_ids);
1234
}
1235
1236
1237
// 1.8 only
1238
// copy of elgg_get_entities
1239
// but only returns guids for performance
1240
// ignores access
1241
function elgg_solr_get_entity_guids_18($options) {
1242
	global $CONFIG;
1243
1244
	$defaults = array(
1245
		'types' => ELGG_ENTITIES_ANY_VALUE,
1246
		'subtypes' => ELGG_ENTITIES_ANY_VALUE,
1247
		'type_subtype_pairs' => ELGG_ENTITIES_ANY_VALUE,
1248
		'guids' => ELGG_ENTITIES_ANY_VALUE,
1249
		'owner_guids' => ELGG_ENTITIES_ANY_VALUE,
1250
		'container_guids' => ELGG_ENTITIES_ANY_VALUE,
1251
		'site_guids' => $CONFIG->site_guid,
1252
		'modified_time_lower' => ELGG_ENTITIES_ANY_VALUE,
1253
		'modified_time_upper' => ELGG_ENTITIES_ANY_VALUE,
1254
		'created_time_lower' => ELGG_ENTITIES_ANY_VALUE,
1255
		'created_time_upper' => ELGG_ENTITIES_ANY_VALUE,
1256
		'reverse_order_by' => false,
1257
		'order_by' => 'e.guid desc',
1258
		'group_by' => ELGG_ENTITIES_ANY_VALUE,
1259
		'limit' => 10,
1260
		'offset' => 0,
1261
		'count' => FALSE,
1262
		'selects' => array(),
1263
		'wheres' => array(),
1264
		'joins' => array(),
1265
		'callback' => false,
1266
		'__ElggBatch' => null,
1267
	);
1268
1269
	$options = array_merge($defaults, $options);
1270
1271
	// can't use helper function with type_subtype_pair because
1272
	// it's already an array...just need to merge it
1273 View Code Duplication
	if (isset($options['type_subtype_pair'])) {
1274
		if (isset($options['type_subtype_pairs'])) {
1275
			$options['type_subtype_pairs'] = array_merge($options['type_subtype_pairs'], $options['type_subtype_pair']);
1276
		} else {
1277
			$options['type_subtype_pairs'] = $options['type_subtype_pair'];
1278
		}
1279
	}
1280
1281
	$singulars = array('type', 'subtype', 'guid', 'owner_guid', 'container_guid', 'site_guid');
1282
	$options = elgg_normalise_plural_options_array($options, $singulars);
1283
1284
	// evaluate where clauses
1285
	if (!is_array($options['wheres'])) {
1286
		$options['wheres'] = array($options['wheres']);
1287
	}
1288
1289
	$wheres = $options['wheres'];
1290
1291
	$wheres[] = elgg_get_entity_type_subtype_where_sql('e', $options['types'], $options['subtypes'], $options['type_subtype_pairs']);
1292
1293
	$wheres[] = elgg_get_guid_based_where_sql('e.guid', $options['guids']);
1294
	$wheres[] = elgg_get_guid_based_where_sql('e.owner_guid', $options['owner_guids']);
1295
	$wheres[] = elgg_get_guid_based_where_sql('e.container_guid', $options['container_guids']);
1296
	$wheres[] = elgg_get_guid_based_where_sql('e.site_guid', $options['site_guids']);
1297
1298
	$wheres[] = elgg_get_entity_time_where_sql('e', $options['created_time_upper'], $options['created_time_lower'], $options['modified_time_upper'], $options['modified_time_lower']);
1299
1300
	// see if any functions failed
1301
	// remove empty strings on successful functions
1302 View Code Duplication
	foreach ($wheres as $i => $where) {
1303
		if ($where === FALSE) {
1304
			return FALSE;
1305
		} elseif (empty($where)) {
1306
			unset($wheres[$i]);
1307
		}
1308
	}
1309
1310
	// remove identical where clauses
1311
	$wheres = array_unique($wheres);
1312
1313
	// evaluate join clauses
1314
	if (!is_array($options['joins'])) {
1315
		$options['joins'] = array($options['joins']);
1316
	}
1317
1318
	// remove identical join clauses
1319
	$joins = array_unique($options['joins']);
1320
1321 View Code Duplication
	foreach ($joins as $i => $join) {
1322
		if ($join === FALSE) {
1323
			return FALSE;
1324
		} elseif (empty($join)) {
1325
			unset($joins[$i]);
1326
		}
1327
	}
1328
1329
	// evalutate selects
1330 View Code Duplication
	if ($options['selects']) {
1331
		$selects = '';
1332
		foreach ($options['selects'] as $select) {
1333
			$selects .= ", $select";
1334
		}
1335
	} else {
1336
		$selects = '';
0 ignored issues
show
Unused Code introduced by
$selects is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1337
	}
1338
1339 View Code Duplication
	if (!$options['count']) {
1340
		$distinct = '';
1341
		if ($options['require_distinct']) {
1342
			$distinct = ' DISTINCT';
1343
		}
1344
		$query = "SELECT{$distinct} e.guid FROM {$CONFIG->dbprefix}entities e ";
1345
	} else {
1346
		$query = "SELECT count(DISTINCT e.guid) as total FROM {$CONFIG->dbprefix}entities e ";
1347
	}
1348
1349
	// add joins
1350
	foreach ($joins as $j) {
1351
		$query .= " $j ";
1352
	}
1353
1354
	// add wheres
1355
	$query .= ' WHERE ';
1356
1357
	foreach ($wheres as $w) {
1358
		$query .= " $w AND ";
1359
	}
1360
1361
	// Add access controls
1362
	$query .= get_access_sql_suffix('e');
0 ignored issues
show
Deprecated Code introduced by
The function get_access_sql_suffix() has been deprecated with message: 1.9 Use _elgg_get_access_where_sql()

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
1363
1364
	// reverse order by
1365
	if ($options['reverse_order_by']) {
1366
		$options['order_by'] = elgg_sql_reverse_order_by_clause($options['order_by']);
1367
	}
1368
1369
	if (!$options['count']) {
1370
		if ($options['group_by']) {
1371
			$query .= " GROUP BY {$options['group_by']}";
1372
		}
1373
1374
		if ($options['order_by']) {
1375
			$query .= " ORDER BY {$options['order_by']}";
1376
		}
1377
1378 View Code Duplication
		if ($options['limit']) {
1379
			$limit = sanitise_int($options['limit'], false);
1380
			$offset = sanitise_int($options['offset'], false);
1381
			$query .= " LIMIT $offset, $limit";
1382
		}
1383
1384
		$dt = get_data($query);
1385
1386
		return $dt;
1387
	} else {
1388
		$total = get_data_row($query);
1389
		return (int) $total->total;
1390
	}
1391
}
1392
1393
function elgg_solr_get_entity_guids(array $options = array()) {
1394
	global $CONFIG;
1395
1396
	$defaults = array(
1397
		'types' => ELGG_ENTITIES_ANY_VALUE,
1398
		'subtypes' => ELGG_ENTITIES_ANY_VALUE,
1399
		'type_subtype_pairs' => ELGG_ENTITIES_ANY_VALUE,
1400
		'guids' => ELGG_ENTITIES_ANY_VALUE,
1401
		'owner_guids' => ELGG_ENTITIES_ANY_VALUE,
1402
		'container_guids' => ELGG_ENTITIES_ANY_VALUE,
1403
		'site_guids' => $CONFIG->site_guid,
1404
		'modified_time_lower' => ELGG_ENTITIES_ANY_VALUE,
1405
		'modified_time_upper' => ELGG_ENTITIES_ANY_VALUE,
1406
		'created_time_lower' => ELGG_ENTITIES_ANY_VALUE,
1407
		'created_time_upper' => ELGG_ENTITIES_ANY_VALUE,
1408
		'reverse_order_by' => false,
1409
		'order_by' => 'e.time_created desc',
1410
		'group_by' => ELGG_ENTITIES_ANY_VALUE,
1411
		'limit' => 10,
1412
		'offset' => 0,
1413
		'count' => false,
1414
		'selects' => array(),
1415
		'wheres' => array(),
1416
		'joins' => array(),
1417
		'callback' => false,
1418
		'__ElggBatch' => null,
1419
	);
1420
1421
	$options = array_merge($defaults, $options);
1422
1423
	// can't use helper function with type_subtype_pair because
1424
	// it's already an array...just need to merge it
1425 View Code Duplication
	if (isset($options['type_subtype_pair'])) {
1426
		if (isset($options['type_subtype_pairs'])) {
1427
			$options['type_subtype_pairs'] = array_merge($options['type_subtype_pairs'], $options['type_subtype_pair']);
1428
		} else {
1429
			$options['type_subtype_pairs'] = $options['type_subtype_pair'];
1430
		}
1431
	}
1432
1433
	$singulars = array('type', 'subtype', 'guid', 'owner_guid', 'container_guid', 'site_guid');
1434
	$options = _elgg_normalize_plural_options_array($options, $singulars);
1435
1436
	// evaluate where clauses
1437
	if (!is_array($options['wheres'])) {
1438
		$options['wheres'] = array($options['wheres']);
1439
	}
1440
1441
	$wheres = $options['wheres'];
1442
1443
	$wheres[] = _elgg_get_entity_type_subtype_where_sql('e', $options['types'], $options['subtypes'], $options['type_subtype_pairs']);
1444
1445
	$wheres[] = _elgg_get_guid_based_where_sql('e.guid', $options['guids']);
1446
	$wheres[] = _elgg_get_guid_based_where_sql('e.owner_guid', $options['owner_guids']);
1447
	$wheres[] = _elgg_get_guid_based_where_sql('e.container_guid', $options['container_guids']);
1448
	$wheres[] = _elgg_get_guid_based_where_sql('e.site_guid', $options['site_guids']);
1449
1450
	$wheres[] = _elgg_get_entity_time_where_sql('e', $options['created_time_upper'], $options['created_time_lower'], $options['modified_time_upper'], $options['modified_time_lower']);
1451
1452
	// see if any functions failed
1453
	// remove empty strings on successful functions
1454 View Code Duplication
	foreach ($wheres as $i => $where) {
1455
		if ($where === false) {
1456
			return false;
1457
		} elseif (empty($where)) {
1458
			unset($wheres[$i]);
1459
		}
1460
	}
1461
1462
	// remove identical where clauses
1463
	$wheres = array_unique($wheres);
1464
1465
	// evaluate join clauses
1466
	if (!is_array($options['joins'])) {
1467
		$options['joins'] = array($options['joins']);
1468
	}
1469
1470
	// remove identical join clauses
1471
	$joins = array_unique($options['joins']);
1472
1473 View Code Duplication
	foreach ($joins as $i => $join) {
1474
		if ($join === false) {
1475
			return false;
1476
		} elseif (empty($join)) {
1477
			unset($joins[$i]);
1478
		}
1479
	}
1480
1481
	// evalutate selects
1482 View Code Duplication
	if ($options['selects']) {
1483
		$selects = '';
1484
		foreach ($options['selects'] as $select) {
1485
			$selects .= ", $select";
1486
		}
1487
	} else {
1488
		$selects = '';
1489
	}
1490
1491 View Code Duplication
	if (!$options['count']) {
1492
		$distinct = '';
1493
		if ($options['require_distinct']) {
1494
			$distinct = ' DISTINCT';
1495
		}
1496
		$query = "SELECT{$distinct} e.guid{$selects} FROM {$CONFIG->dbprefix}entities e ";
1497
	} else {
1498
		$query = "SELECT count(DISTINCT e.guid) as total FROM {$CONFIG->dbprefix}entities e ";
1499
	}
1500
1501
	// add joins
1502
	foreach ($joins as $j) {
1503
		$query .= " $j ";
1504
	}
1505
1506
	// add wheres
1507
	$query .= ' WHERE ';
1508
1509
	foreach ($wheres as $w) {
1510
		$query .= " $w AND ";
1511
	}
1512
1513
	// Add access controls
1514
	$query .= _elgg_get_access_where_sql();
1515
1516
	// reverse order by
1517
	if ($options['reverse_order_by']) {
1518
		$options['order_by'] = _elgg_sql_reverse_order_by_clause($options['order_by']);
0 ignored issues
show
Documentation introduced by
$options['order_by'] is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1519
	}
1520
1521
	if (!$options['count']) {
1522
		if ($options['group_by']) {
1523
			$query .= " GROUP BY {$options['group_by']}";
1524
		}
1525
1526
		if ($options['order_by']) {
1527
			$query .= " ORDER BY {$options['order_by']}";
1528
		}
1529
1530 View Code Duplication
		if ($options['limit']) {
1531
			$limit = sanitise_int($options['limit'], false);
0 ignored issues
show
Documentation introduced by
$options['limit'] is of type array|string, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1532
			$offset = sanitise_int($options['offset'], false);
0 ignored issues
show
Documentation introduced by
$options['offset'] is of type array|string, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1533
			$query .= " LIMIT $offset, $limit";
1534
		}
1535
1536
		if ($options['callback'] === 'entity_row_to_elggstar') {
1537
			$dt = _elgg_fetch_entities_from_sql($query, $options['__ElggBatch']);
1538
		} else {
1539
			$dt = get_data($query, $options['callback']);
0 ignored issues
show
Bug introduced by
It seems like $options['callback'] can also be of type array; however, get_data() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1540
		}
1541
1542
		if ($dt) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $dt of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1543
			// populate entity and metadata caches
1544
			$guids = array();
1545 View Code Duplication
			foreach ($dt as $item) {
1546
				// A custom callback could result in items that aren't ElggEntity's, so check for them
1547
				if ($item instanceof ElggEntity) {
1548
					_elgg_cache_entity($item);
1549
					// plugins usually have only settings
1550
					if (!$item instanceof ElggPlugin) {
1551
						$guids[] = $item->guid;
1552
					}
1553
				}
1554
			}
1555
			// @todo Without this, recursive delete fails. See #4568
1556
			reset($dt);
1557
1558
			if ($guids) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $guids of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1559
				_elgg_get_metadata_cache()->populateFromEntities($guids);
1560
			}
1561
		}
1562
		return $dt;
1563
	} else {
1564
		$total = get_data_row($query);
1565
		return (int) $total->total;
1566
	}
1567
}
1568
1569
function elgg_solr_index_annotation($annotation) {
1570
	$client = elgg_solr_get_client();
1571
	$commit = elgg_get_config('elgg_solr_nocommit') ? false : true;
1572
1573
	$query = $client->createUpdate();
1574
1575
	// add document
1576
	$doc = $query->createDocument();
1577
	$doc->id = 'annotation:' . $annotation->id;
1578
	$doc->type = 'annotation';
1579
	$doc->subtype = $annotation->name;
1580
	$doc->owner_guid = $annotation->owner_guid;
1581
	$doc->container_guid = $annotation->entity_guid;
1582
	$doc->access_id = $annotation->access_id;
1583
	$doc->description = elgg_strip_tags($annotation->value);
1584
	$doc->time_created = $annotation->time_created;
1585
	$doc->enabled = $annotation->enabled;
1586
1587
	$doc = elgg_trigger_plugin_hook('elgg_solr:index', 'annotation', array('annotation' => $annotation), $doc);
1588
	
1589
	if (!$doc) {
1590
		return true; // a plugin has stopped the index
1591
	}
1592
1593
	$query->addDocument($doc);
1594
	if ($commit) {
1595
		$query->addCommit($commit);
1596
	}
1597
1598
	// this executes the query and returns the result
1599
	try {
1600
		$client->update($query);
1601
	} catch (Exception $exc) {
1602
		error_log($exc->getMessage());
1603
	}
1604
}
1605
1606
/**
1607
 * Note - only needed for 1.8
1608
 * 
1609
 * @param type $time
1610
 * @param type $block
1611
 * @return type
1612
 */
1613
function elgg_solr_get_comment_stats($time, $block) {
1614
	$type = 'annotation';
1615
	$fq = array(
1616
		'subtype' => "subtype:generic_comment"
1617
	);
1618
	$stats = array();
1619
	switch ($block) {
1620
		case 'hour':
1621
			// I don't think we need minute resolution right now...
1622
			break;
1623
		case 'day':
1624
			for ($i = 0; $i < 24; $i++) {
1625
				$starttime = mktime($i, 0, 0, date('m', $time), date('j', $time), date('Y', $time));
1626
				$endtime = mktime($i + 1, 0, 0, date('m', $time), date('j', $time), date('Y', $time)) - 1;
1627
1628
				$fq['time_created'] = "time_created:[{$starttime} TO {$endtime}]";
1629
				$indexed = elgg_solr_get_indexed_count("type:{$type}", $fq);
1630
				$system = elgg_get_annotations(array(
1631
					'annotation_name' => 'generic_comment',
1632
					'annotation_created_time_lower' => $starttime,
1633
					'annotation_created_time_upper' => $endtime,
1634
					'count' => true
1635
				));
1636
1637
				$stats[date('H', $starttime)] = array(
1638
					'count' => $system,
1639
					'indexed' => $indexed,
1640
					'starttime' => $starttime,
1641
					'endtime' => $endtime,
1642
					'block' => false
1643
				);
1644
			}
1645
			break;
1646
		case 'month':
1647
			for ($i = 1; $i < date('t', $time) + 1; $i++) {
1648
				$starttime = mktime(0, 0, 0, date('m', $time), $i, date('Y', $time));
1649
				$endtime = mktime(0, 0, 0, date('m', $time), $i + 1, date('Y', $time)) - 1;
1650
1651
				$fq['time_created'] = "time_created:[{$starttime} TO {$endtime}]";
1652
				$indexed = elgg_solr_get_indexed_count("type:{$type}", $fq);
1653
				$system = elgg_get_annotations(array(
1654
					'annotation_name' => 'generic_comment',
1655
					'annotation_created_time_lower' => $starttime,
1656
					'annotation_created_time_upper' => $endtime,
1657
					'count' => true
1658
				));
1659
1660
				$stats[date('d', $starttime)] = array(
1661
					'count' => $system,
1662
					'indexed' => $indexed,
1663
					'starttime' => $starttime,
1664
					'endtime' => $endtime,
1665
					'block' => 'day'
1666
				);
1667
			}
1668
			break;
1669
		case 'year':
1670
			for ($i = 1; $i < 13; $i++) {
1671
				$starttime = mktime(0, 0, 0, $i, 1, date('Y', $time));
1672
				$endtime = mktime(0, 0, 0, $i + 1, 1, date('Y', $time)) - 1;
1673
1674
				$fq['time_created'] = "time_created:[{$starttime} TO {$endtime}]";
1675
				$indexed = elgg_solr_get_indexed_count("type:{$type}", $fq);
1676
				$system = elgg_get_annotations(array(
1677
					'annotation_name' => 'generic_comment',
1678
					'annotation_created_time_lower' => $starttime,
1679
					'annotation_created_time_upper' => $endtime,
1680
					'count' => true
1681
				));
1682
1683
				$stats[date('F', $starttime)] = array(
1684
					'count' => $system,
1685
					'indexed' => $indexed,
1686
					'starttime' => $starttime,
1687
					'endtime' => $endtime,
1688
					'block' => 'month'
1689
				);
1690
			}
1691
			break;
1692
1693
		case 'all':
1694
		default:
1695
			$startyear = date('Y', elgg_get_site_entity()->time_created);
1696
			$currentyear = date('Y');
1697
1698
			for ($i = $currentyear; $i > $startyear - 1; $i--) {
1699
				$starttime = mktime(0, 0, 0, 1, 1, $i);
1700
				$endtime = mktime(0, 0, 0, 1, 1, $i + 1) - 1;
1701
1702
				$fq['time_created'] = "time_created:[{$starttime} TO {$endtime}]";
1703
				$indexed = elgg_solr_get_indexed_count("type:{$type}", $fq);
1704
				$system = elgg_get_annotations(array(
1705
					'annotation_name' => 'generic_comment',
1706
					'annotation_created_time_lower' => $starttime,
1707
					'annotation_created_time_upper' => $endtime,
1708
					'count' => true
1709
				));
1710
1711
				$stats[$i] = array(
1712
					'count' => $system,
1713
					'indexed' => $indexed,
1714
					'starttime' => $starttime,
1715
					'endtime' => $endtime,
1716
					'block' => 'year'
1717
				);
1718
			}
1719
1720
			break;
1721
	}
1722
1723
	return $stats;
1724
}
1725
1726 View Code Duplication
function elgg_solr_get_log_line($filename) {
0 ignored issues
show
Duplication introduced by
This function 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...
1727
	$line = false;
1728
	$f = false;
1729
	if (file_exists($filename)) {
1730
		$f = @fopen($filename, 'r');
1731
	}
1732
1733
	if ($f === false) {
1734
		return false;
1735
	} else {
1736
		$cursor = -1;
1737
1738
		fseek($f, $cursor, SEEK_END);
1739
		$char = fgetc($f);
1740
1741
		/**
1742
		 * Trim trailing newline chars of the file
1743
		 */
1744
		while ($char === "\n" || $char === "\r") {
1745
			fseek($f, $cursor--, SEEK_END);
1746
			$char = fgetc($f);
1747
		}
1748
1749
		/**
1750
		 * Read until the start of file or first newline char
1751
		 */
1752
		while ($char !== false && $char !== "\n" && $char !== "\r") {
1753
			/**
1754
			 * Prepend the new char
1755
			 */
1756
			$line = $char . $line;
1757
			fseek($f, $cursor--, SEEK_END);
1758
			$char = fgetc($f);
1759
		}
1760
	}
1761
1762
	return $line;
1763
}
1764
1765
1766
function elgg_solr_get_cores() {
1767
	$options = elgg_solr_get_adapter_options();
1768
	
1769
	if (!$options['host'] || !$options['port'] || !$options['path']) {
1770
		return array();
1771
	}
1772
	
1773
	$cores = array();
1774
1775
    $url = "http://{$options['host']}:{$options['port']}{$options['path']}admin/cores?action=STATUS&wt=json";
1776
1777
    // Initialize cURL
1778
    $ch = curl_init();
1779
1780
    curl_setopt($ch, CURLOPT_URL, $url);
1781
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: text/xml"));
1782
    curl_setopt($ch, CURLOPT_POST, 1);
1783
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
1784
    curl_setopt($ch, CURLOPT_VERBOSE, 1);
1785
1786
    $response = curl_exec($ch);
1787
1788
    $status = json_decode($response);
1789
1790
	if (is_object($status)) {
1791
		$array = json_decode(json_encode($status), true);
1792
		
1793
		foreach ($array['status'] as $name => $params) {
1794
			$cores[] = $name;
1795
		}
1796
	}
1797
	
1798
	return $cores;
1799
}
1800
1801
1802
function elgg_solr_is_elgg18() {
1803
	$version_getter = 'get_version';
1804
	if (is_callable('elgg_get_version')) {
1805
		$version_getter = 'elgg_get_version';
1806
	}
1807
	
1808
	$is_elgg18 = (strpos($version_getter(true), '1.8') === 0);
1809
	
1810
	return $is_elgg18;
1811
}
1812
1813
1814
function elgg_solr_get_fragsize() {
1815
	static $fragsize;
1816
	if ($fragsize) {
1817
		return (int) $fragsize;
1818
	}
1819
	
1820
	$setting = elgg_get_plugin_setting('fragsize', 'elgg_solr');
1821
	if (is_numeric($setting)) {
1822
		$fragsize = (int) $setting;
1823
	}
1824
	else {
1825
		$fragsize = 100;
1826
	}
1827
	
1828
	return $fragsize;
1829
}