Complex classes like Controller often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Controller, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
6 | class Controller |
||
7 | { |
||
8 | /** |
||
9 | * How long to store retrieved disk configuration for HTTP 304 header |
||
10 | * from git information. |
||
11 | */ |
||
12 | const GIT_MODIFIED_CONFIG_TTL = 600; // 10 minutes |
||
13 | |||
14 | /** |
||
15 | * The controller has to know the model to access the data stored there. |
||
16 | * @var Model $model contains the Model object. |
||
17 | */ |
||
18 | public $model; |
||
19 | |||
20 | protected $negotiator; |
||
21 | |||
22 | protected $languages; |
||
23 | |||
24 | /** |
||
25 | * Initializes the Model object. |
||
26 | */ |
||
27 | public function __construct($model) |
||
49 | |||
50 | /** |
||
51 | * Sets the locale language properties from the parameter (used by gettext and some Model classes). |
||
52 | * @param string $lang language parameter eg. 'fi' for Finnish. |
||
53 | */ |
||
54 | public function setLanguageProperties($lang) |
||
65 | |||
66 | /** |
||
67 | * Negotiate a MIME type according to the proposed format, the list of valid |
||
68 | * formats, and an optional proposed format. |
||
69 | * As a side effect, set the HTTP Vary header if a choice was made based on |
||
70 | * the Accept header. |
||
71 | * @param array $choices possible MIME types as strings |
||
72 | * @param string $accept HTTP Accept header value |
||
73 | * @param string $format proposed format |
||
74 | * @return string selected format, or null if negotiation failed |
||
75 | */ |
||
76 | protected function negotiateFormat($choices, $accept, $format) |
||
90 | |||
91 | private function isSecure() |
||
92 | { |
||
93 | if ($protocol = filter_input(INPUT_SERVER, 'HTTP_X_FORWARDED_PROTO', FILTER_SANITIZE_STRING)) { |
||
94 | return \in_array(strtolower($protocol), ['https', 'on', 'ssl', '1'], true); |
||
95 | } |
||
96 | |||
97 | return filter_input(INPUT_SERVER, 'HTTPS', FILTER_SANITIZE_STRING) !== null; |
||
98 | } |
||
99 | |||
100 | private function guessBaseHref() |
||
117 | |||
118 | public function getBaseHref() |
||
122 | |||
123 | /** |
||
124 | * Creates Skosmos links from uris. |
||
125 | * @param string $uri |
||
126 | * @param Vocabulary $vocab |
||
127 | * @param string $lang |
||
128 | * @param string $type |
||
129 | * @param string $clang content |
||
130 | * @param string $term |
||
131 | * @throws Exception if the vocabulary ID is not found in configuration |
||
132 | * @return string containing the Skosmos link |
||
133 | */ |
||
134 | public function linkUrlFilter($uri, $vocab, $lang, $type = 'page', $clang = null, $term = null) { |
||
172 | |||
173 | /** |
||
174 | * Echos an error message when the request can't be fulfilled. |
||
175 | * @param string $code |
||
176 | * @param string $status |
||
177 | * @param string $message |
||
178 | */ |
||
179 | protected function returnError($code, $status, $message) |
||
185 | |||
186 | protected function notModified(Modifiable $modifiable = null) |
||
195 | |||
196 | /** |
||
197 | * Return the modified date. |
||
198 | * |
||
199 | * @param Modifiable $modifiable |
||
200 | * @return DateTime|null |
||
201 | */ |
||
202 | protected function getModifiedDate(Modifiable $modifiable = null) |
||
203 | { |
||
204 | $modified = null; |
||
205 | $modifiedDate = $modifiable !== null ? $modifiable->getModifiedDate() : null; |
||
206 | $gitModifiedDate = $this->getGitModifiedDate(); |
||
207 | $configModifiedDate = $this->getConfigModifiedDate(); |
||
208 | |||
209 | // max with an empty list raises an error and returns bool |
||
210 | if ($modifiedDate || $gitModifiedDate || $configModifiedDate) { |
||
211 | $modified = max($modifiedDate, $gitModifiedDate, $configModifiedDate); |
||
212 | } |
||
213 | return $modified; |
||
214 | } |
||
215 | |||
216 | /** |
||
217 | * Return the datetime of the latest commit, or null if git is not available or if the command failed |
||
218 | * to execute. |
||
219 | * |
||
220 | * @see https://stackoverflow.com/a/33986403 |
||
221 | * @return DateTime|null |
||
222 | */ |
||
223 | protected function getGitModifiedDate() |
||
242 | |||
243 | /** |
||
244 | * Execute the git command and return a parsed date time, or null if the command failed. |
||
245 | * |
||
246 | * @param string $gitCommand git command line that returns a formatted date time |
||
247 | * @return DateTime|null |
||
248 | */ |
||
249 | protected function executeGitModifiedDateCommand($gitCommand) |
||
259 | |||
260 | /** |
||
261 | * Return the datetime of the modified time of the config file. This value is read in the GlobalConfig |
||
262 | * for every request, so we simply access that value and if not null, we will return a datetime. Otherwise, |
||
263 | * we return a null value. |
||
264 | * |
||
265 | * @see http://php.net/manual/en/function.filemtime.php |
||
266 | * @return DateTime|null |
||
267 | */ |
||
268 | protected function getConfigModifiedDate() |
||
277 | |||
278 | /** |
||
279 | * If the $modifiedDate is a valid DateTime, and if the $_SERVER variable contains the right info, and |
||
280 | * if the $modifiedDate is not more recent than the latest value in $_SERVER, then this function sets the |
||
281 | * HTTP 304 not modified and returns true.. |
||
282 | * |
||
283 | * If the $modifiedDate is still valid, then it sets the Last-Modified header, to be used by the browser for |
||
284 | * subsequent requests, and returns false. |
||
285 | * |
||
286 | * Otherwise, it returns false. |
||
287 | * |
||
288 | * @param DateTime|null $modifiedDate the last modified date to be compared against server's modified since information |
||
289 | * @return bool whether it sent the HTTP 304 not modified headers or not (useful for sending the response without |
||
290 | * further actions) |
||
291 | */ |
||
292 | protected function sendNotModifiedHeader($modifiedDate): bool |
||
304 | |||
305 | /** |
||
306 | * @return DateTime|null a DateTime object if the value exists in the $_SERVER variable, null otherwise |
||
307 | */ |
||
308 | protected function getIfModifiedSince() |
||
318 | |||
319 | /** |
||
320 | * Sends HTTP headers. Simply calls PHP built-in header function. But being |
||
321 | * a function here, it can easily be tested/mocked. |
||
322 | * |
||
323 | * @param $header string header to be sent |
||
324 | */ |
||
325 | protected function sendHeader($header) |
||
329 | } |
||
330 |
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
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.