Test Failed
Push — v2 ( 737a06 )
by Berend
03:55
created

Password   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 103
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 0
dl 0
loc 103
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A initPassword() 0 18 1
A isPassword() 0 12 3
A setPassword() 0 16 3
A getPasswordHash() 0 4 1
A getPasswordResetToken() 0 4 1
A generatePasswordResetToken() 0 4 1
A clearPasswordResetToken() 0 4 1
1
<?php
2
3
namespace miBadger\ActiveRecord\Traits;
4
5
use miBadger\ActiveRecord\ColumnProperty;
6
7
const TRAIT_PASSWORD_FIELD_PASSWORD = "password";
8
const TRAIT_PASSWORD_ENCRYPTION = \PASSWORD_BCRYPT;
9
const TRAIT_PASSWORD_STRENTH = 10;
10
const TRAIT_PASSWORD_FIELD_PASSWORD_RESET_TOKEN = "password_reset_token";
11
const TRAIT_PASSWORD_MIN_LENGTH = 8;
12
13
trait Password
14
{
15
	/** @var string The password hash. */
16
	protected $password;
17
18
	/** @var string|null The password reset token. */
19
	protected $passwordResetToken;
20
21
	protected function initPassword()
22
	{
23
		$this->extendTableDefinition(TRAIT_PASSWORD_FIELD_PASSWORD, [
0 ignored issues
show
Bug introduced by
It seems like extendTableDefinition() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
24
			'value' => &$this->password,
25
			'validate' => null,
26
			'type' => 'VARCHAR',
27
			'length' => 1024,
28
			'properties' => ColumnProperty::NOT_NULL
29
		]);
30
31
		$this->extendTableDefinition(TRAIT_PASSWORD_FIELD_PASSWORD_RESET_TOKEN, [
0 ignored issues
show
Bug introduced by
It seems like extendTableDefinition() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
32
			'value' => &$this->passwordResetToken,
33
			'validate' => null,
34
			'default' => 0,
35
			'type' => 'VARCHAR',
36
			'length' => 1024
37
		]);
38
	}
39
40
	/**
41
	 * Returns true if the credentials are correct.
42
	 *
43
	 * @param string $password
44
	 * @return boolean true if the credentials are correct
45
	 */
46
	public function isPassword($password)
47
	{
48
		if (!password_verify($password, $this->password)) {
49
			return false;
50
		}
51
52
		if (password_needs_rehash($this->password, TRAIT_PASSWORD_ENCRYPTION, ['cost' => TRAIT_PASSWORD_STRENTH])) {
53
			$this->setPassword($password)->sync();
0 ignored issues
show
Bug introduced by
It seems like sync() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
54
		}
55
56
		return true;
57
	}
58
59
	/**
60
	 * Set the password.
61
	 *
62
	 * @param string $password
63
	 * @return $this
64
	 * @throws \Exception
65
	 */
66
	public function setPassword($password)
67
	{
68
		if (strlen($password) < TRAIT_PASSWORD_MIN_LENGTH) {
69
			throw new \Exception(sprintf('\'Password\' must be atleast %s characters long. %s characters provied.', self::PASSWORD_MIN_LENGTH, strlen($password)));
70
		}
71
72
		$passwordHash = \password_hash($password, TRAIT_PASSWORD_ENCRYPTION, ['cost' => TRAIT_PASSWORD_STRENTH]);
73
74
		if ($passwordHash === false) {
75
			throw new \Exception('\'Password\' hash failed.');
76
		}
77
78
		$this->password = $passwordHash;
79
80
		return $this;
81
	}
82
83
	/**
84
	 * @return string The Hash of the password
85
	 */
86
	public function getPasswordHash()
87
	{
88
		return $this->password;
89
	}
90
91
	/**
92
	 * Returns the currently set password token for the entity, or null if not set
93
	 * @return string|null The password reset token
94
	 */
95
	public function getPasswordResetToken()
96
	{
97
		return $this->passwordResetToken;
98
	}
99
100
	/**
101
	 * Generates a new password reset token for the user
102
	 */
103
	public function generatePasswordResetToken()
104
	{
105
		$this->passwordResetToken = md5(uniqid(mt_rand(), true));
106
	}
107
108
	/**
109
	 * Clears the current password reset token
110
	 */
111
	public function clearPasswordResetToken()
112
	{
113
		$this->passwordResetToken = null;
114
	}
115
}