Completed
Push — master ( 1da492...320203 )
by Henry
07:00
created

Recover::_getUsers()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 0
cts 7
cp 0
rs 9.8666
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 6
1
<?php
2
namespace Redaxscript\Controller;
3
4
use Redaxscript\Filter;
5
use Redaxscript\Html;
6
use Redaxscript\Mailer;
7
use Redaxscript\Model;
8
use Redaxscript\Validator;
9
use function sha1;
10
11
/**
12
 * children class to process the recover request
13
 *
14
 * @since 3.0.0
15
 *
16
 * @package Redaxscript
17
 * @category Controller
18
 * @author Henry Ruhs
19
 * @author Balázs Szilágyi
20
 */
21
22
class Recover extends ControllerAbstract
23
{
24
	/**
25
	 * process the class
26
	 *
27
	 * @since 3.0.0
28
	 *
29
	 * @return string
30
	 */
31
32
	public function process() : string
33
	{
34
		$postArray = $this->_normalizePost($this->_sanitizePost());
35
		$validateArray = $this->_validatePost($postArray);
0 ignored issues
show
Bug introduced by
It seems like $postArray defined by $this->_normalizePost($this->_sanitizePost()) on line 34 can also be of type null; however, Redaxscript\Controller\Recover::_validatePost() does only seem to accept array, 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...
36
		$users = $this->_getUsers($postArray);
0 ignored issues
show
Bug introduced by
It seems like $postArray defined by $this->_normalizePost($this->_sanitizePost()) on line 34 can also be of type null; however, Redaxscript\Controller\Recover::_getUsers() does only seem to accept array, 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...
37
38
		/* validate post */
39
40
		if ($validateArray)
0 ignored issues
show
Bug Best Practice introduced by
The expression $validateArray 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...
41
		{
42
			return $this->_error(
43
			[
44
				'route' => 'login/recover',
45
				'message' => $validateArray
46
			]);
47
		}
48
49
		/* handle mail and validate user */
50
51
		$validateArray = [];
52
		foreach ($users as $user)
0 ignored issues
show
Bug introduced by
The expression $users of type object|null 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...
53
		{
54
			$mailArray =
55
			[
56
				'id' => $user->id,
57
				'name' => $user->name,
58
				'user' => $user->user,
59
				'password' => $user->password,
60
				'email' => $user->email
61
			];
62
			if (!$this->_mail($mailArray))
63
			{
64
				return $this->_error(
65
				[
66
					'route' => 'login/recover',
67
					'message' => $this->_language->get('email_failed')
68
				]);
69
			}
70
			$validateArray[] = $user->name . $this->_language->get('colon') . ' ' . $this->_language->get('recovery_sent');
71
		}
72
		if ($validateArray)
0 ignored issues
show
Bug Best Practice introduced by
The expression $validateArray 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...
73
		{
74
			return $this->_success(
75
			[
76
				'route' => 'login',
77
				'timeout' => 2,
78
				'message' => $validateArray
79
			]);
80
		}
81
82
		/* handle error */
83
84
		return $this->_error(
85
		[
86
			'route' => 'login/recover'
87
		]);
88
	}
89
90
	/**
91
	 * sanitize the post
92
	 *
93
	 * @since 4.0.0
94
	 *
95
	 * @return array
96
	 */
97
98
	protected function _sanitizePost() : array
99
	{
100
		$numberFilter = new Filter\Number();
101
		$emailFilter = new Filter\Email();
102
103
		/* sanitize post */
104
105
		return
106
		[
107
			'email' => $emailFilter->sanitize($this->_request->getPost('email')),
0 ignored issues
show
Bug introduced by
It seems like $this->_request->getPost('email') targeting Redaxscript\Request::getPost() can also be of type array; however, Redaxscript\Filter\Email::sanitize() does only seem to accept null|string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
108
			'task' => $numberFilter->sanitize($this->_request->getPost('task')),
0 ignored issues
show
Bug introduced by
It seems like $this->_request->getPost('task') targeting Redaxscript\Request::getPost() can also be of type array; however, Redaxscript\Filter\Number::sanitize() does only seem to accept null|string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
109
			'solution' => $this->_request->getPost('solution')
110
		];
111
	}
112
113
	/**
114
	 * validate the post
115
	 *
116
	 * @since 3.0.0
117
	 *
118
	 * @param array $postArray array of the post
119
	 *
120
	 * @return array
121
	 */
122
123
	protected function _validatePost(array $postArray = []) : array
124
	{
125
		$emailValidator = new Validator\Email();
126
		$captchaValidator = new Validator\Captcha();
127
		$userModel = new Model\User();
128
		$settingModel = new Model\Setting();
129
		$validateArray = [];
130
131
		/* validate post */
132
133
		if (!$postArray['email'])
134
		{
135
			$validateArray[] = $this->_language->get('email_empty');
136
		}
137
		else if (!$emailValidator->validate($postArray['email']))
138
		{
139
			$validateArray[] = $this->_language->get('email_incorrect');
140
		}
141
		else if (!$userModel->query()->where('email', $postArray['email'])->findOne()->id)
142
		{
143
			$validateArray[] = $this->_language->get('email_unknown');
144
		}
145
		if ($settingModel->get('captcha') > 0 && !$captchaValidator->validate($postArray['task'], $postArray['solution']))
146
		{
147
			$validateArray[] = $this->_language->get('captcha_incorrect');
148
		}
149
		return $validateArray;
150
	}
151
152
	/**
153
	 * get the users
154
	 *
155
	 * @since 4.0.0
156
	 *
157
	 * @param array $postArray array of the post
158
	 *
159
	 * @return object|null
160
	 */
161
162
	protected function _getUsers(array $postArray = []) : ?object
163
	{
164
		$userModel = new Model\User();
165
		return $userModel
166
			->query()
167
			->where(
168
			[
169
				'email' => $postArray['email'],
170
				'status' => 1
171
			])
172
			->findMany() ? : null;
173
	}
174
175
	/**
176
	 * send the mail
177
	 *
178
	 * @since 3.0.0
179
	 *
180
	 * @param array $mailArray array of the mail
181
	 *
182
	 * @return bool
183
	 */
184
185
	protected function _mail(array $mailArray = []) : bool
186
	{
187
		$settingModel = new Model\Setting();
188
		$urlReset = $this->_registry->get('root') . '/' . $this->_registry->get('parameterRoute') . 'login/reset/' . sha1($mailArray['password']) . '/' . $mailArray['id'];
189
190
		/* html element */
191
192
		$linkElement = new Html\Element();
193
		$linkElement
194
			->init('a',
195
			[
196
				'href' => $urlReset
197
			])
198
			->text($urlReset);
199
200
		/* prepare mail */
201
202
		$toArray =
203
		[
204
			$mailArray['name'] => $mailArray['email']
205
		];
206
		$fromArray =
207
		[
208
			$settingModel->get('author') => $settingModel->get('email')
209
		];
210
		$subject = $this->_language->get('recovery');
211
		$bodyArray =
212
		[
213
			$this->_language->get('user') . $this->_language->get('colon') . ' ' . $mailArray['user'],
214
			'<br />',
215
			$this->_language->get('password_reset') . $this->_language->get('colon') . ' ' . $linkElement
216
		];
217
218
		/* send mail */
219
220
		$mailer = new Mailer();
221
		$mailer->init($toArray, $fromArray, $subject, $bodyArray);
0 ignored issues
show
Bug introduced by
It seems like $subject defined by $this->_language->get('recovery') on line 210 can also be of type array; however, Redaxscript\Mailer::init() does only seem to accept null|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...
222
		return $mailer->send();
223
	}
224
}
225