Passed
Push — solr-crawler-auth ( a245d5...f76e9d )
by Ilia
19:01
created

crawler_user   A

Complexity

Total Complexity 3

Size/Duplication

Total Lines 15
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 0

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
dl 0
loc 15
ccs 0
cts 7
cp 0
rs 10
c 0
b 0
f 0
wmc 3
lcom 0
cbo 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A __call() 0 9 3
1
<?php
2
3
use Symfony\Component\HttpFoundation\Session\SessionInterface;
4
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
5
use Symfony\Component\HttpFoundation\Session\Session;
6
7 1
if (getenv('SOLR_CRAWLER') != '' && $_SERVER['HTTP_USER_AGENT'] === getenv('SOLR_CRAWLER')){
8
	class crawler_user {
9
		private $mock_false = array( '' );
0 ignored issues
show
Unused Code introduced by
The property $mock_false is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
10
11
		public $user_type = 'bot';
12
13
		public function __call($method, $args)
14
		{
15
			if (isset($this->$method)) {
16
				$func = $this->$method;
17
				return call_user_func_array($func, $args);
18
			}
19
			else if ( in_array( $method, $mock_false) ) { return false; }
0 ignored issues
show
Bug introduced by
The variable $mock_false does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
20
			else error_log("FUNCTION:   $method");
21
		}
22
	}
23
}
24
25
/**
26
 * Elgg Session Management
27
 *
28
 * Reserved keys: last_forward_from, msg, sticky_forms, user, guid, id, code, name, username
29
 * Deprecated keys: user, id, name, username
30
 * 
31
 * \ArrayAccess was deprecated in Elgg 1.9. This means you should use 
32
 * $session->get('foo') rather than $session['foo'].
33
 * Warning: You can not access multidimensional arrays through \ArrayAccess like
34
 * this $session['foo']['bar']
35
 *
36
 * @package    Elgg.Core
37
 * @subpackage Session
38
 * @see        elgg_get_session()
39
 */
40
class ElggSession implements \ArrayAccess {
41
42
	/**
43
	 * @var SessionInterface
44
	 */
45
	protected $storage;
46
47
	/**
48
	 * @var \ElggUser|null
49
	 */
50
	protected $logged_in_user;
51
52
	/**
53
	 * @var bool
54
	 */
55
	protected $ignore_access = false;
56
57
	/**
58
	 * Constructor
59
	 *
60
	 * @param SessionInterface $storage The underlying Session implementation
61
	 * @access private Use elgg_get_session()
62
	 */
63 79
	public function __construct(SessionInterface $storage) {
64 79
		$this->storage = $storage;
65 79
	}
66
67
	/**
68
	 * Start the session
69
	 *
70
	 * @return boolean
71
	 * @throws RuntimeException If session fails to start.
72
	 * @since 1.9
73
	 */
74 3
	public function start() {
75 3
		$result = $this->storage->start();
76 3
		$this->generateSessionToken();
77 3
		return $result;
78
	}
79
80
	/**
81
	 * Migrates the session to a new session id while maintaining session attributes
82
	 *
83
	 * @param boolean $destroy Whether to delete the session or let gc handle clean up
84
	 * @return boolean
85
	 * @since 1.9
86
	 */
87 2
	public function migrate($destroy = false) {
88 2
		return $this->storage->migrate($destroy);
89
	}
90
91
	/**
92
	 * Invalidates the session
93
	 *
94
	 * Deletes session data and session persistence. Starts a new session.
95
	 *
96
	 * @return boolean
97
	 * @since 1.9
98
	 */
99 1
	public function invalidate() {
100 1
		$this->storage->clear();
101 1
		$this->logged_in_user = null;
102 1
		$result = $this->migrate(true);
103 1
		$this->generateSessionToken();
104 1
		return $result;
105
	}
106
107
	/**
108
	 * Has the session been started
109
	 *
110
	 * @return boolean
111
	 * @since 1.9
112
	 */
113
	public function isStarted() {
114
		return $this->storage->isStarted();
115
	}
116
117
	/**
118
	 * Get the session ID
119
	 *
120
	 * @return string
121
	 * @since 1.9
122
	 */
123 2
	public function getId() {
124 2
		return $this->storage->getId();
125
	}
126
127
	/**
128
	 * Set the session ID
129
	 *
130
	 * @param string $id Session ID
131
	 * @return void
132
	 * @since 1.9
133
	 */
134
	public function setId($id) {
135
		$this->storage->setId($id);
136
	}
137
138
	/**
139
	 * Get the session name
140
	 *
141
	 * @return string
142
	 * @since 1.9
143
	 */
144
	public function getName() {
145
		return $this->storage->getName();
146
	}
147
148
	/**
149
	 * Set the session name
150
	 *
151
	 * @param string $name Session name
152
	 * @return void
153
	 * @since 1.9
154
	 */
155
	public function setName($name) {
156
		$this->storage->setName($name);
157
	}
158
159
	/**
160
	 * Get an attribute of the session
161
	 *
162
	 * @param string $name    Name of the attribute to get
163
	 * @param mixed  $default Value to return if attribute is not set (default is null)
164
	 * @return mixed
165
	 */
166 13
	public function get($name, $default = null) {
167 13
		return $this->storage->get($name, $default);
168
	}
169
170
	/**
171
	 * Set an attribute
172
	 *
173
	 * @param string $name  Name of the attribute to set
174
	 * @param mixed  $value Value to be set
175
	 * @return void
176
	 */
177 11
	public function set($name, $value) {
178 11
		$this->storage->set($name, $value);
179 11
	}
180
181
	/**
182
	 * Remove an attribute
183
	 *
184
	 * @param string $name The name of the attribute to remove
185
	 * @return mixed The removed attribute
186
	 * @since 1.9
187
	 */
188 2
	public function remove($name) {
189 2
		return $this->storage->remove($name);
190
	}
191
192
	/**
193
	 * Alias to offsetUnset()
194
	 *
195
	 * @param string $key Name
196
	 * @return void
197
	 * @deprecated 1.9 Use remove()
198
	 */
199
	public function del($key) {
200
		elgg_deprecated_notice(__METHOD__ . " has been deprecated.", 1.9);
201
		$this->remove($key);
202
	}
203
204
	/**
205
	 * Has the attribute been defined
206
	 *
207
	 * @param string $name Name of the attribute
208
	 * @return bool
209
	 * @since 1.9
210
	 */
211 3
	public function has($name) {
212 3
		return $this->storage->has($name);
213
	}
214
215
	/**
216
	 * Sets the logged in user
217
	 * 
218
	 * @param \ElggUser $user The user who is logged in
219
	 * @return void
220
	 * @since 1.9
221
	 */
222
	public function setLoggedInUser(\ElggUser $user) {
223
		$this->set('guid', $user->guid);
224
		$this->logged_in_user = $user;
225
	}
226
227
	/**
228
	 * Gets the logged in user
229
	 * 
230
	 * @return \ElggUser
231
	 * @since 1.9
232
	 */
233 37
	public function getLoggedInUser() {
0 ignored issues
show
Coding Style introduced by
getLoggedInUser uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
234 37
		if (getenv('SOLR_CRAWLER') != '' && $_SERVER['HTTP_USER_AGENT'] === getenv('SOLR_CRAWLER')){
235
			// create a mock user for the crawler
236
			$solr_user = new crawler_user();
237
			$solr_user->canEdit = function(){ return false;};
0 ignored issues
show
Bug introduced by
The property canEdit does not seem to exist in crawler_user.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
238
			$solr_user->isBanned = function(){ return false;};
0 ignored issues
show
Bug introduced by
The property isBanned does not seem to exist in crawler_user.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
239
240
			return $solr_user;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $solr_user; (crawler_user) is incompatible with the return type documented by ElggSession::getLoggedInUser of type ElggUser|null.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
241
		}
242 37
		return $this->logged_in_user;
243
	}
244
245
	/**
246
	 * Return the current logged in user by guid.
247
	 *
248
	 * @see elgg_get_logged_in_user_entity()
249
	 * @return int
250
	 */
251 32
	public function getLoggedInUserGuid() {
252 32
		$user = $this->getLoggedInUser();
253 32
		return $user ? $user->guid : 0;
254
	}
255
	
256
	/**
257
	 * Returns whether or not the viewer is currently logged in and an admin user.
258
	 *
259
	 * @return bool
260
	 */
261
	public function isAdminLoggedIn() {
262
		$user = $this->getLoggedInUser();
263
	
264
		return $user && $user->isAdmin();
265
	}
266
	
267
	/**
268
	 * Returns whether or not the user is currently logged in
269
	 *
270
	 * @return bool
271
	 */
272
	public function isLoggedIn() {
0 ignored issues
show
Coding Style introduced by
isLoggedIn uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
273 View Code Duplication
		if (getenv('SOLR_CRAWLER') != '' && $_SERVER['HTTP_USER_AGENT'] === getenv('SOLR_CRAWLER')) return true;
274
		return (bool)$this->getLoggedInUser();
275
	}
276
277
	/**
278
	 * Remove the logged in user
279
	 * 
280
	 * @return void
281
	 * @since 1.9
282
	 */
283
	public function removeLoggedInUser() {
284
		$this->logged_in_user = null;
285
		$this->remove('guid');
286
	}
287
288
	/**
289
	 * Get current ignore access setting.
290
	 *
291
	 * @return bool
292
	 */
293
	public function getIgnoreAccess() {
294
		return $this->ignore_access;
295
	}
296
297
	/**
298
	 * Set ignore access.
299
	 *
300
	 * @param bool $ignore Ignore access
301
	 *
302
	 * @return bool Previous setting
303
	 */
304 3
	public function setIgnoreAccess($ignore = true) {
305 3
		_elgg_services()->accessCache->clear();
306
307 3
		$prev = $this->ignore_access;
308 3
		$this->ignore_access = $ignore;
309
310 3
		return $prev;
311
	}
312
313
	// @codingStandardsIgnoreStart
314
	/**
315
	 * Alias of getIgnoreAccess()
316
	 *
317
	 * @todo remove with elgg_get_access_object()
318
	 *
319
	 * @return bool
320
	 * @deprecated 1.8 Use elgg_get_ignore_access()
321
	 */
322
	public function get_ignore_access() {
323
		return $this->getIgnoreAccess();
324
	}
325
	// @codingStandardsIgnoreEnd
326
327
	// @codingStandardsIgnoreStart
328
	/**
329
	 * Alias of setIgnoreAccess()
330
	 *
331
	 * @todo remove with elgg_get_access_object()
332
	 *
333
	 * @param bool $ignore Ignore access
334
	 *
335
	 * @return bool Previous setting
336
	 *
337
	 * @deprecated 1.8 Use elgg_set_ignore_access()
338
	 */
339
	public function set_ignore_access($ignore = true) {
340
		return $this->setIgnoreAccess($ignore);
341
	}
342
	// @codingStandardsIgnoreEnd
343
344
	/**
345
	 * Adds a token to the session
346
	 * 
347
	 * This is used in creation of CSRF token, and is passed to the client to allow validating tokens
348
	 * later, even if the PHP session was destroyed.
349
	 * 
350
	 * @return void
351
	 */
352 3
	protected function generateSessionToken() {
353
		// Generate a simple token that we store server side
354 3
		if (!$this->has('__elgg_session')) {
355 3
			$this->set('__elgg_session', _elgg_services()->crypto->getRandomString(22));
356 3
		}
357 3
	}
358
359
	/**
360
	 * Test if property is set either as an attribute or metadata.
361
	 *
362
	 * @param string $key The name of the attribute or metadata.
363
	 *
364
	 * @return bool
365
	 * @deprecated 1.9 Use has()
366
	 */
367
	public function __isset($key) {
368
		elgg_deprecated_notice(__METHOD__ . " has been deprecated.", 1.9);
369
		// Note: We use offsetExists() for BC
370
		return $this->offsetExists($key);
0 ignored issues
show
Deprecated Code introduced by
The method ElggSession::offsetExists() has been deprecated with message: 1.9 Use has()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

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

Loading history...
371
	}
372
373
	/**
374
	 * Set a value, go straight to session.
375
	 *
376
	 * @param string $key   Name
377
	 * @param mixed  $value Value
378
	 *
379
	 * @return void
380
	 * @deprecated 1.9 Use set()
381
	 */
382
	public function offsetSet($key, $value) {
383
		elgg_deprecated_notice(__METHOD__ . " has been deprecated.", 1.9);
384
		$this->set($key, $value);
385
	}
386
387
	/**
388
	 * Get a variable from either the session, or if its not in the session
389
	 * attempt to get it from an api call.
390
	 *
391
	 * @see \ArrayAccess::offsetGet()
392
	 *
393
	 * @param mixed $key Name
394
	 *
395
	 * @return mixed
396
	 * @deprecated 1.9 Use get()
397
	 */
398
	public function offsetGet($key) {
399
		elgg_deprecated_notice(__METHOD__ . " has been deprecated.", 1.9);
400
401
		if (in_array($key, array('user', 'id', 'name', 'username'))) {
402
			elgg_deprecated_notice("Only 'guid' is stored in session for user now", 1.9);
403
			if ($this->logged_in_user) {
404
				switch ($key) {
405
					case 'user':
406
						return $this->logged_in_user;
407
						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...
408
					case 'id':
409
						return $this->logged_in_user->guid;
410
						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...
411
					case 'name':
412
					case 'username':
413
						return $this->logged_in_user->$key;
414
						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...
415
				}
416
			} else {
417
				return null;
418
			}
419
		}
420
421
		if ($this->has($key)) {
422
			return $this->get($key);
423
		}
424
425
		$orig_value = null;
426
		$value = _elgg_services()->hooks->trigger('session:get', $key, null, $orig_value);
427
		if ($orig_value !== $value) {
428
			elgg_deprecated_notice("Plugin hook session:get has been deprecated.", 1.9);
429
		}
430
431
		$this->set($key, $value);
432
		return $value;
433
	}
434
435
	/**
436
	 * Unset a value from the cache and the session.
437
	 *
438
	 * @see \ArrayAccess::offsetUnset()
439
	 *
440
	 * @param mixed $key Name
441
	 *
442
	 * @return void
443
	 * @deprecated 1.9 Use remove()
444
	 */
445
	public function offsetUnset($key) {
446
		elgg_deprecated_notice(__METHOD__ . " has been deprecated.", 1.9);
447
		$this->remove($key);
448
	}
449
450
	/**
451
	 * Return whether the value is set in either the session or the cache.
452
	 *
453
	 * @see \ArrayAccess::offsetExists()
454
	 *
455
	 * @param int $offset Offset
456
	 *
457
	 * @return bool
458
	 * @deprecated 1.9 Use has()
459
	 */
460
	public function offsetExists($offset) {
461
		elgg_deprecated_notice(__METHOD__ . " has been deprecated.", 1.9);
462
463
		if (in_array($offset, array('user', 'id', 'name', 'username'))) {
464
			elgg_deprecated_notice("Only 'guid' is stored in session for user now", 1.9);
465
			return (bool)$this->logged_in_user;
466
		}
467
468
		if ($this->has($offset)) {
469
			return true;
470
		}
471
472
		// Note: We use offsetGet() for BC
473
		if ($this->offsetGet($offset)) {
0 ignored issues
show
Deprecated Code introduced by
The method ElggSession::offsetGet() has been deprecated with message: 1.9 Use get()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

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

Loading history...
474
			return true;
475
		}
476
477
		return false;
478
	}
479
480
	/**
481
	 * Get an isolated ElggSession that does not persist between requests
482
	 *
483
	 * @return self
484
	 */
485 79
	public static function getMock() {
486 79
		$storage = new MockArraySessionStorage();
487 79
		$session = new Session($storage);
488 79
		return new self($session);
489
	}
490
}
491