GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

FrontControllerA::getErrorResponse()   B
last analyzed

Complexity

Conditions 7
Paths 32

Size

Total Lines 56

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 25
CRAP Score 7.1284

Importance

Changes 0
Metric Value
cc 7
nc 32
nop 2
dl 0
loc 56
ccs 25
cts 29
cp 0.8621
crap 7.1284
rs 8.0266
c 0
b 0
f 0

How to fix   Long Method   

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
 * @package application
4
 * @subpackage controllers
5
 * @author marius orcsik <[email protected]>
6
 * @date 09.08.30
7
 */
8
namespace vsc\application\controllers;
9
10
use vsc\application\processors\ErrorProcessor;
11
use vsc\application\processors\ProcessorA;
12
use vsc\application\sitemaps\ClassMap;
13
use vsc\application\sitemaps\ContentTypeMappingInterface;
14
use vsc\application\sitemaps\MappingA;
15
use vsc\domain\models\EmptyModel;
16
use vsc\domain\models\ErrorModel;
17
use vsc\domain\models\ModelA;
18
use vsc\infrastructure\BaseObject;
19
use vsc\infrastructure\vsc;
20
use vsc\presentation\responses\ExceptionResponseRedirect;
21
use vsc\presentation\responses\HttpResponseA;
22
use vsc\presentation\responses\HttpResponseType;
23
use vsc\presentation\views\ExceptionView;
24
use vsc\presentation\requests\HttpRequestA;
25
use vsc\presentation\views\ViewA;
26
use vsc\ExceptionPath;
27
use vsc\presentation\responses\ExceptionResponse;
28
29
abstract class FrontControllerA extends BaseObject {
30
	/**
31
	 * @var string
32
	 */
33
	private $sTemplatePath;
34
35
	/**
36
	 * @var ContentTypeMappingInterface
37
	 */
38
	private $oCurrentMap;
39
40
	/**
41
	 * @var ViewA
42
	 */
43
	private $oView;
44
45
	/**
46
	 * @returns ViewA
47
	 */
48
	abstract public function getDefaultView();
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
49
50
	/**
51
	 * @throws ExceptionView
52
	 * @returns ClassMap
53
	 */
54 6
	public function getMap() {
55 6
		if (!ClassMap::isValid($this->oCurrentMap)) {
0 ignored issues
show
Documentation introduced by
$this->oCurrentMap is of type object<vsc\application\s...ntTypeMappingInterface>, but the function expects a object<vsc\application\sitemaps\MappingA>.

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...
56
			$Mirror = new \ReflectionClass($this);
57
			$this->oCurrentMap = new ClassMap($Mirror->getName(), '.*');
0 ignored issues
show
Bug introduced by
Consider using $Mirror->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
58
		}
59 6
		return $this->oCurrentMap;
60
	}
61
62
	/**
63
	 * @param ContentTypeMappingInterface $oMap
64
	 */
65 5
	public function setMap(ContentTypeMappingInterface $oMap) {
66 5
		$this->oCurrentMap = $oMap;
67 5
	}
68
69
	/**
70
	 * @param $sIncPath
71
	 * @return bool
72
	 * @throws ExceptionController
73
	 */
74 2
	public function setTemplatePath($sIncPath) {
75 2
		if (is_dir($sIncPath)) {
76 1
			$this->sTemplatePath = $sIncPath;
77 1
			return true;
78
		} else {
79 1
			throw new ExceptionController('The template path [' . $sIncPath . '] is not a valid folder.');
80
		}
81
	}
82
83
	/**
84
	 * @param HttpRequestA $oRequest
85
	 * @param ProcessorA $oProcessor
0 ignored issues
show
Documentation introduced by
Should the type for parameter $oProcessor not be ProcessorA|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
86
	 * @return ViewA
87
	 * @throws ExceptionPath
88
	 */
89 2
	protected function loadView($oRequest, $oProcessor = null) {
90
		// we didn't set any special view
91
		// this means that the developer needs to provide his own views
92 2
		$oView = $this->getView();
93 2
		$oMyMap = $this->getMap();
94
95 2
		if (ProcessorA::isValid($oProcessor)) {
96 1
			$oProcessor->init();
0 ignored issues
show
Bug introduced by
It seems like $oProcessor is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
97 1
			$oModel = $oProcessor->handleRequest($oRequest);
98
			/* @var ClassMap $oMap */
99 1
			$oMap = $oProcessor->getMap();
100 1
			if (MappingA::isValid($oMap)) {
101 1
				if (MappingA::isValid($oMyMap)) {
102 1
					$oMap->merge($oMyMap);
0 ignored issues
show
Documentation introduced by
$oMyMap is of type object<vsc\application\s...ntTypeMappingInterface>, but the function expects a object<vsc\application\sitemaps\MappingA>|null.

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...
103
				}
104
			}
105
			// setting the processor map
106 1
			$oView->setMap($oMap);
107
			try {
108 1
				if ((ClassMap::isValid($oMap) && !$oMap->isStatic() && !$oMyMap->isStatic()) && ClassMap::isValid($oMyMap)) {
0 ignored issues
show
Documentation introduced by
$oMyMap is of type object<vsc\application\s...ntTypeMappingInterface>, but the function expects a object<vsc\application\sitemaps\MappingA>.

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...
109 1
					$oView->setMainTemplate(
110 1
						$oMyMap->getMainTemplatePath() .
111 1
						$oView->getViewFolder() . DIRECTORY_SEPARATOR .
112 1
						$oMyMap->getMainTemplate()
113
					);
114
				}
115 1
			} catch (ExceptionPath $e) {
116
				// fallback to html5
117
				// @todo verify main template path and main template exist
118 1
				$oView->setMainTemplate($oMyMap->getMainTemplatePath() . DIRECTORY_SEPARATOR . 'html5' . DIRECTORY_SEPARATOR . $oMyMap->getMainTemplate());
119
			}
120 1
			if (!ModelA::isValid($oModel)) {
121
				$oModel = new EmptyModel();
122
				if (!ClassMap::isValid($oMap) || $oMap->getTitle() == '') {
123
					$oModel->setPageTitle('Warning');
124
				}
125
				$oModel->setPageContent('Warning: the processor didn\'t return a valid model. This is probably an error');
126
			}
127 1
			$oView->setModel($oModel);
128
		}
129 2
		return $oView;
130
	}
131
132
	/**
133
	 * @param HttpRequestA $oRequest
134
	 * @param ProcessorA $oProcessor
0 ignored issues
show
Documentation introduced by
Should the type for parameter $oProcessor not be ProcessorA|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
135
	 * @throws ExceptionPath
136
	 * @throws ExceptionResponse
137
	 * @throws ExceptionView
138
	 * @returns HttpResponseA
139
	 */
140 2
	public function getResponse(HttpRequestA $oRequest, $oProcessor = null) {
141 2
		$oResponse = vsc::getEnv()->getHttpResponse();
142 2
		if ($oResponse->getStatus() == 0) {
143
			$oResponse->setStatus(HttpResponseType::OK);
144
		}
145
146
		try {
147 2
			$oView = $this->loadView($oRequest, $oProcessor);
148 2
			$oResponse->setView($oView);
149 2
			if (ProcessorA::isValid($oProcessor)) {
150 1
				$oMap = $oProcessor->getMap();
0 ignored issues
show
Bug introduced by
It seems like $oProcessor is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
151 1
				if (MappingA::isValid($oMap)) {
152 1
					$aHeaders = $oMap->getHeaders();
153 1
					if (count($aHeaders) > 0) {
154
						foreach ($aHeaders as $sName => $sHeader) {
155
							$oResponse->addHeader($sName, $sHeader);
156
						}
157
					}
158 1
					$iProcessorSetStatus = $oMap->getResponseStatus();
159 1
					if (HttpResponseType::isValidStatus($iProcessorSetStatus)) {
160
						$oResponse->setStatus($iProcessorSetStatus);
161
					}
162
				}
163
			}
164 2
			return $oResponse;
165
		} catch (ExceptionResponseRedirect $e) {
166
			$oResponse->setStatus($e->getRedirectCode());
167
			$oResponse->setLocation($e->getLocation());
168
169
			return $oResponse;
170
		} catch (\Exception $e) {
171
			// we had error in the controller
172
			// @todo make more error processors
173
			return $this->getErrorResponse($e, $oRequest);
174
		}
175
	}
176
177
	/**
178
	 * @param \Exception $e
179
	 * @param HttpRequestA $oRequest
0 ignored issues
show
Documentation introduced by
Should the type for parameter $oRequest not be HttpRequestA|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
180
	 * @return HttpResponseA
181
	 * @throws ExceptionPath
182
	 * @throws ExceptionResponse
183
	 */
184 1
	public function getErrorResponse(\Exception $e, $oRequest = null) {
185 1
		$oResponse = vsc::getEnv()->getHttpResponse();
186
187 1
		$oProcessor = new ErrorProcessor($e);
188
189
		/* @var ClassMap $oMyMap */
190 1
		$oMyMap = $this->getMap();
191
192 1
		$oMyMap->setMainTemplatePath(VSC_SRC_PATH . 'templates');
193 1
		$oMyMap->setMainTemplate('main.php');
194
195 1
		if (!HttpRequestA::isValid($oRequest)) {
196 1
			$oRequest = vsc::getEnv()->getHttpRequest();
197
		}
198
199
		/** @var ErrorModel $oModel */
200 1
		$oModel = $oProcessor->handleRequest($oRequest);
0 ignored issues
show
Bug introduced by
It seems like $oRequest defined by parameter $oRequest on line 184 can be null; however, vsc\application\processo...cessor::handleRequest() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
201
202 1
		$iCode = $oModel->getHttpStatus();
203 1
		if (HttpResponseType::isValidStatus($iCode)) {
204 1
			$oResponse->setStatus($iCode);
205
		} else {
206
			$oResponse->setStatus(500);
207
		}
208
209
		// we didn't set any special view
210
		// this means that the developer needs to provide his own views
211 1
		$oView = $this->getView();
212
213
		/* @var ClassMap $oMap */
214 1
		$oMap = $oProcessor->getMap();
215 1
		$oMap->merge($oMyMap);
216 1
		$oProcessorResponse = $oMap->getResponse();
217
218 1
		if (HttpResponseA::isValid($oProcessorResponse)) {
219
			$oResponse = $oProcessorResponse;
220
		}
221
222
		// setting the processor map
223 1
		$oView->setMap($oMap);
224 1
		if (ClassMap::isValid($oMyMap)) {
225 1
			$oView->setMainTemplate($oMyMap->getMainTemplatePath() . DIRECTORY_SEPARATOR . $oView->getViewFolder() . DIRECTORY_SEPARATOR . $oMyMap->getMainTemplate());
226
		}
227 1
		$oView->setModel($oModel);
228
229 1
		$oResponse->setView($oView);
230
231 1
		$aHeaders = $oMap->getHeaders();
232 1
		if (count($aHeaders) > 0) {
233
			foreach ($aHeaders as $sName => $sHeader) {
234
				$oResponse->addHeader($sName, $sHeader);
235
			}
236
		}
237
238 1
		return $oResponse;
239
	}
240
241
	/**
242
	 * @returns ViewA
243
	 * @throws ExceptionView
244
	 */
245 4
	public function getView() {
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
246 4
		if (ViewA::isValid($this->oView)) {
247
			return $this->oView;
248
		}
249 4
		$oMapView = $this->getMap()->getView();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface vsc\application\sitemaps...entTypeMappingInterface as the method getView() does only exist in the following implementations of said interface: vsc\application\sitemaps\ClassMap, vsc\application\sitemaps\ErrorControllerMap, vsc\application\sitemaps\ErrorProcessorMap.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
250 4
		if (ViewA::isValid($oMapView)) {
251 2
			return $oMapView;
252
		}
253 2
		$this->oView = $this->getDefaultView();
254 2
		return $this->oView;
255
	}
256
}
257