VirtualminChangePasswordDriver::ChangePassword()   D
last analyzed

Complexity

Conditions 15
Paths 21

Size

Total Lines 99

Duplication

Lines 4
Ratio 4.04 %

Importance

Changes 0
Metric Value
cc 15
nc 21
nop 3
dl 4
loc 99
rs 4.7551
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
/*
4
 * This Virtualmin Password Change Plugin was developed by Icedman21
5
 * http://icedman21.com
6
 */
7
class VirtualminChangePasswordDriver implements \RainLoop\Providers\ChangePassword\ChangePasswordInterface
8
{
9
	/**
10
	 * @var string
11
	 */
12
	private $sAllowedEmails = '';
13
14
	/**
15
	 * @var string
16
	 */
17
	private $sHost = '';
18
19
	/**
20
	 * @var string
21
	 */
22
	private $sAdminUser = '';
23
24
	/**
25
	 * @var string
26
	 */
27
	private $sAdminPassword = '';
28
29
	/**
30
	 * @var \MailSo\Log\Logger
31
	 */
32
	private $oLogger = null;
33
34
	/**
35
	 * @param string $sHost
36
	 * @param string $sAdminUser
37
	 * @param string $sAdminPassword
38
	 *
39
	 * @return \VirtualminChangePasswordDriver
40
	 */
41
	public function SetConfig($sHost, $sAdminUser, $sAdminPassword)
42
	{
43
		$this->sHost = $sHost;
44
		$this->sAdminUser = $sAdminUser;
45
		$this->sAdminPassword = $sAdminPassword;
46
47
		return $this;
48
	}
49
50
	/**
51
	 * @param string $sAllowedEmails
52
	 *
53
	 * @return \VirtualminChangePasswordDriver
54
	 */
55
	public function SetAllowedEmails($sAllowedEmails)
56
	{
57
		$this->sAllowedEmails = $sAllowedEmails;
58
59
		return $this;
60
	}
61
62
	/**
63
	 * @param \MailSo\Log\Logger $oLogger
64
	 *
65
	 * @return \VirtualminChangePasswordDriver
66
	 */
67
	public function SetLogger($oLogger)
68
	{
69
		if ($oLogger instanceof \MailSo\Log\Logger)
0 ignored issues
show
Bug introduced by
The class MailSo\Log\Logger does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
70
		{
71
			$this->oLogger = $oLogger;
72
		}
73
74
		return $this;
75
	}
76
77
	/**
78
	 * @param string $sDesc
79
	 * @param int $iType = \MailSo\Log\Enumerations\Type::INFO
80
	 *
81
	 * @return \VirtualminChangePasswordDriver
82
	 */
83
	public function WriteLog($sDesc, $iType = \MailSo\Log\Enumerations\Type::INFO)
84
	{
85
		if ($this->oLogger)
86
		{
87
			$this->oLogger->Write($sDesc, $iType);
88
		}
89
90
		return $this;
91
	}
92
93
	/**
94
	 * @param \RainLoop\Model\Account $oAccount
95
	 *
96
	 * @return bool
97
	 */
98
	public function PasswordChangePossibility($oAccount)
99
	{
100
		return $oAccount && $oAccount->Email() &&
101
			\RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->sAllowedEmails);
102
	}
103
104
	/**
105
	 * @param \RainLoop\Model\Account $oAccount
106
	 * @param string $sPrevPassword
107
	 * @param string $sNewPassword
108
	 *
109
	 * @return bool
110
	 */
111
	public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword)
112
	{
113
		$this->WriteLog('Virtualmin: Try to change password for '.$oAccount->Email());
114
115
		$bResult = false;
116
		if (!empty($this->sHost) && !empty($this->sAdminUser) && !empty($this->sAdminPassword) && $oAccount)
117
		{
118
			$this->WriteLog('Virtualmin:[Check] Required Fields Present');
119
120
			$sEmail = \trim(\strtolower($oAccount->Email()));
121
			$sEmailUser = \MailSo\Base\Utils::GetAccountNameFromEmail($sEmail);
122
			$sEmailDomain = \MailSo\Base\Utils::GetDomainFromEmail($sEmail);
123
124
			$sHost = \rtrim(\trim($this->sHost), '/');
125
			$sUrl = $sHost.'/virtual-server/remote.cgi';
126
127
			$sAdminUser = $this->sAdminUser;
128
			$sAdminPassword = $this->sAdminPassword;
129
130
			$iCode = 0;
0 ignored issues
show
Unused Code introduced by
$iCode 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...
131
132
			$aPost = array(
133
				'user'		=> $sEmailUser,
134
				'pass'		=> $sNewPassword,
135
				'domain'	=> $sEmailDomain,
136
				'program'	=> 'modify-user'
137
			);
138
139
			$aOptions = array(
140
				CURLOPT_URL => $sUrl,
141
				CURLOPT_HEADER => false,
142
				CURLOPT_FAILONERROR => true,
143
				CURLOPT_SSL_VERIFYPEER => false,
144
				CURLOPT_RETURNTRANSFER => true,
145
				CURLOPT_POST => true,
146
				CURLOPT_POSTFIELDS => \http_build_query($aPost, '', '&'),
147
				CURLOPT_TIMEOUT => 20,
148
				CURLOPT_SSL_VERIFYHOST => false,
149
				CURLOPT_USERPWD => $sAdminUser.':'.$sAdminPassword
150
			);
151
152
			$oCurl = \curl_init();
153
			\curl_setopt_array($oCurl, $aOptions);
154
155
			$this->WriteLog('Virtualmin: Send post request: '.$sUrl);
156
157
			$mResult = \curl_exec($oCurl);
158
159
			$iCode = (int) \curl_getinfo($oCurl, CURLINFO_HTTP_CODE);
160
			$sContentType = (string) \curl_getinfo($oCurl, CURLINFO_CONTENT_TYPE);
161
162
			$this->WriteLog('Virtualmin: Post request result: (Status: '.$iCode.', ContentType: '.$sContentType.')');
163 View Code Duplication
			if (false === $mResult || 200 !== $iCode)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
164
			{
165
				$this->WriteLog('Virtualmin: Error: '.\curl_error($oCurl), \MailSo\Log\Enumerations\Type::WARNING);
166
			}
167
168
			if (\is_resource($oCurl))
169
			{
170
				\curl_close($oCurl);
171
			}
172
173
			if (false !== $mResult && 200 === $iCode)
174
			{
175
				$aRes = null;
176
				@\parse_str($mResult, $aRes);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
177
				if (\is_array($aRes) && (!isset($aRes['error']) || (int) $aRes['error'] !== 1))
178
				{
179
					$iPos = \strpos($mResult, 'Exit status: ');
180
181
					if ($iPos !== false)
182
					{
183
						$aStatus = \explode(' ', $mResult);
184
						$sStatus = \trim(\array_pop($aStatus));
185
186
						if ('0' === $sStatus)
187
						{
188
							$this->WriteLog('Virtualmin: Password Change Status: Success');
189
							$bResult = true;
190
						}
191
						else
192
						{
193
							$this->WriteLog('Virtualmin[Error]: Response: '.$mResult);
194
						}
195
					}
196
				}
197
				else
198
				{
199
					$this->WriteLog('Virtualmin[Error]: Response: '.$mResult);
200
				}
201
			}
202
			else
203
			{
204
				$this->WriteLog('Virtualmin[Error]: Empty Response: Code: '.$iCode);
205
			}
206
		}
207
208
		return $bResult;
209
	}
210
}
211