stwalkerster /
waca
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | namespace Waca; |
||
| 4 | |||
| 5 | use Waca\DataObjects\User; |
||
| 6 | use Waca\Providers\Interfaces\IGlobalStateProvider; |
||
| 7 | |||
| 8 | /** |
||
| 9 | * Holds helper functions regarding the current request. |
||
| 10 | * |
||
| 11 | * This is the only place where it is allowed to use super-globals, but even then access MUST be pushed through the |
||
| 12 | * global state provider to allow for unit tests. It's strongly recommended to do sanitising of data here, especially |
||
| 13 | * if extra logic is required to get a deterministic value, like isHttps(). |
||
| 14 | * |
||
| 15 | * @package Waca |
||
| 16 | */ |
||
| 17 | class WebRequest |
||
| 18 | { |
||
| 19 | /** |
||
| 20 | * @var IGlobalStateProvider Provides access to the global state. |
||
| 21 | */ |
||
| 22 | private static $globalStateProvider; |
||
| 23 | |||
| 24 | /** |
||
| 25 | * Returns a boolean value if the request was submitted with the HTTP POST method. |
||
| 26 | * @return bool |
||
| 27 | */ |
||
| 28 | public static function wasPosted() |
||
| 29 | { |
||
| 30 | return self::method() === 'POST'; |
||
| 31 | } |
||
| 32 | |||
| 33 | /** |
||
| 34 | * Gets the HTTP Method used |
||
| 35 | * @return string|null |
||
| 36 | */ |
||
| 37 | View Code Duplication | public static function method() |
|
|
0 ignored issues
–
show
|
|||
| 38 | { |
||
| 39 | $server = &self::$globalStateProvider->getServerSuperGlobal(); |
||
| 40 | |||
| 41 | if (isset($server['REQUEST_METHOD'])) { |
||
| 42 | return $server['REQUEST_METHOD']; |
||
| 43 | } |
||
| 44 | |||
| 45 | return null; |
||
| 46 | } |
||
| 47 | |||
| 48 | /** |
||
| 49 | * Gets a boolean value stating whether the request was served over HTTPS or not. |
||
| 50 | * @return bool |
||
| 51 | */ |
||
| 52 | public static function isHttps() |
||
| 53 | { |
||
| 54 | $server = &self::$globalStateProvider->getServerSuperGlobal(); |
||
| 55 | |||
| 56 | View Code Duplication | if (isset($server['HTTP_X_FORWARDED_PROTO'])) { |
|
|
0 ignored issues
–
show
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...
|
|||
| 57 | if ($server['HTTP_X_FORWARDED_PROTO'] === 'https') { |
||
|
0 ignored issues
–
show
|
|||
| 58 | // Client <=> Proxy is encrypted |
||
| 59 | return true; |
||
| 60 | } |
||
| 61 | else { |
||
| 62 | // Proxy <=> Server link unknown, Client <=> Proxy is not encrypted. |
||
| 63 | return false; |
||
| 64 | } |
||
| 65 | } |
||
| 66 | |||
| 67 | View Code Duplication | if (isset($server['HTTPS'])) { |
|
|
0 ignored issues
–
show
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...
|
|||
| 68 | if ($server['HTTPS'] === 'off') { |
||
| 69 | // ISAPI on IIS breaks the spec. :( |
||
| 70 | return false; |
||
| 71 | } |
||
| 72 | |||
| 73 | if ($server['HTTPS'] !== '') { |
||
| 74 | // Set to a non-empty value |
||
| 75 | return true; |
||
| 76 | } |
||
| 77 | } |
||
| 78 | |||
| 79 | return false; |
||
| 80 | } |
||
| 81 | |||
| 82 | /** |
||
| 83 | * Gets the path info |
||
| 84 | * |
||
| 85 | * @return array Array of path info segments |
||
| 86 | */ |
||
| 87 | public static function pathInfo() |
||
| 88 | { |
||
| 89 | $server = &self::$globalStateProvider->getServerSuperGlobal(); |
||
| 90 | if (!isset($server['PATH_INFO'])) { |
||
| 91 | return array(); |
||
| 92 | } |
||
| 93 | |||
| 94 | $exploded = explode('/', $server['PATH_INFO']); |
||
| 95 | |||
| 96 | // filter out empty values, and reindex from zero. Notably, the first element is always zero, since it starts |
||
| 97 | // with a / |
||
| 98 | return array_values(array_filter($exploded)); |
||
| 99 | } |
||
| 100 | |||
| 101 | /** |
||
| 102 | * Gets the remote address of the web request |
||
| 103 | * @return null|string |
||
| 104 | */ |
||
| 105 | View Code Duplication | public static function remoteAddress() |
|
|
0 ignored issues
–
show
This method seems to be duplicated in 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...
|
|||
| 106 | { |
||
| 107 | $server = &self::$globalStateProvider->getServerSuperGlobal(); |
||
| 108 | |||
| 109 | if (isset($server['REMOTE_ADDR'])) { |
||
| 110 | return $server['REMOTE_ADDR']; |
||
| 111 | } |
||
| 112 | |||
| 113 | return null; |
||
| 114 | } |
||
| 115 | |||
| 116 | /** |
||
| 117 | * Gets the XFF header contents for the web request |
||
| 118 | * @return null|string |
||
| 119 | */ |
||
| 120 | View Code Duplication | public static function forwardedAddress() |
|
|
0 ignored issues
–
show
This method seems to be duplicated in 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...
|
|||
| 121 | { |
||
| 122 | $server = &self::$globalStateProvider->getServerSuperGlobal(); |
||
| 123 | |||
| 124 | if (isset($server['HTTP_X_FORWARDED_FOR'])) { |
||
| 125 | return $server['HTTP_X_FORWARDED_FOR']; |
||
| 126 | } |
||
| 127 | |||
| 128 | return null; |
||
| 129 | } |
||
| 130 | |||
| 131 | /** |
||
| 132 | * Sets the global state provider. |
||
| 133 | * |
||
| 134 | * Almost guaranteed this is not the method you want in production code. |
||
| 135 | * |
||
| 136 | * @param IGlobalStateProvider $globalState |
||
| 137 | */ |
||
| 138 | public static function setGlobalStateProvider($globalState) |
||
| 139 | { |
||
| 140 | self::$globalStateProvider = $globalState; |
||
| 141 | } |
||
| 142 | |||
| 143 | #region POST variables |
||
| 144 | |||
| 145 | /** |
||
| 146 | * @param string $key |
||
| 147 | * |
||
| 148 | * @return null|string |
||
| 149 | */ |
||
| 150 | View Code Duplication | public static function postString($key) |
|
|
0 ignored issues
–
show
This method seems to be duplicated in 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...
|
|||
| 151 | { |
||
| 152 | $post = &self::$globalStateProvider->getPostSuperGlobal(); |
||
| 153 | if (!array_key_exists($key, $post)) { |
||
| 154 | return null; |
||
| 155 | } |
||
| 156 | |||
| 157 | if ($post[$key] === "") { |
||
| 158 | return null; |
||
| 159 | } |
||
| 160 | |||
| 161 | return (string)$post[$key]; |
||
| 162 | } |
||
| 163 | |||
| 164 | /** |
||
| 165 | * @param string $key |
||
| 166 | * |
||
| 167 | * @return null|string |
||
| 168 | */ |
||
| 169 | View Code Duplication | public static function postEmail($key) |
|
|
0 ignored issues
–
show
This method seems to be duplicated in 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...
|
|||
| 170 | { |
||
| 171 | $post = &self::$globalStateProvider->getPostSuperGlobal(); |
||
| 172 | if (!array_key_exists($key, $post)) { |
||
| 173 | return null; |
||
| 174 | } |
||
| 175 | |||
| 176 | $filteredValue = filter_var($post[$key], FILTER_SANITIZE_EMAIL); |
||
| 177 | |||
| 178 | if ($filteredValue === false) { |
||
| 179 | return null; |
||
| 180 | } |
||
| 181 | |||
| 182 | return (string)$filteredValue; |
||
| 183 | } |
||
| 184 | |||
| 185 | /** |
||
| 186 | * @param string $key |
||
| 187 | * |
||
| 188 | * @return int|null |
||
| 189 | */ |
||
| 190 | View Code Duplication | public static function postInt($key) |
|
|
0 ignored issues
–
show
This method seems to be duplicated in 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...
|
|||
| 191 | { |
||
| 192 | $post = &self::$globalStateProvider->getPostSuperGlobal(); |
||
| 193 | if (!array_key_exists($key, $post)) { |
||
| 194 | return null; |
||
| 195 | } |
||
| 196 | |||
| 197 | $filteredValue = filter_var($post[$key], FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE); |
||
| 198 | |||
| 199 | if ($filteredValue === null) { |
||
| 200 | return null; |
||
| 201 | } |
||
| 202 | |||
| 203 | return (int)$filteredValue; |
||
| 204 | } |
||
| 205 | |||
| 206 | /** |
||
| 207 | * @param string $key |
||
| 208 | * |
||
| 209 | * @return bool |
||
| 210 | */ |
||
| 211 | View Code Duplication | public static function postBoolean($key) |
|
|
0 ignored issues
–
show
This method seems to be duplicated in 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...
|
|||
| 212 | { |
||
| 213 | $get = &self::$globalStateProvider->getPostSuperGlobal(); |
||
| 214 | if (!array_key_exists($key, $get)) { |
||
| 215 | return false; |
||
| 216 | } |
||
| 217 | |||
| 218 | // presence of parameter only |
||
| 219 | if ($get[$key] === "") { |
||
| 220 | return true; |
||
| 221 | } |
||
| 222 | |||
| 223 | if (in_array($get[$key], array(false, 'no', 'off', 0, 'false'), true)) { |
||
|
0 ignored issues
–
show
|
|||
| 224 | return false; |
||
| 225 | } |
||
| 226 | |||
| 227 | return true; |
||
| 228 | } |
||
| 229 | |||
| 230 | #endregion |
||
| 231 | |||
| 232 | #region GET variables |
||
| 233 | |||
| 234 | /** |
||
| 235 | * @param string $key |
||
| 236 | * |
||
| 237 | * @return bool |
||
| 238 | */ |
||
| 239 | View Code Duplication | public static function getBoolean($key) |
|
|
0 ignored issues
–
show
This method seems to be duplicated in 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...
|
|||
| 240 | { |
||
| 241 | $get = &self::$globalStateProvider->getGetSuperGlobal(); |
||
| 242 | if (!array_key_exists($key, $get)) { |
||
| 243 | return false; |
||
| 244 | } |
||
| 245 | |||
| 246 | // presence of parameter only |
||
| 247 | if ($get[$key] === "") { |
||
| 248 | return true; |
||
| 249 | } |
||
| 250 | |||
| 251 | if (in_array($get[$key], array(false, 'no', 'off', 0, 'false'), true)) { |
||
|
0 ignored issues
–
show
|
|||
| 252 | return false; |
||
| 253 | } |
||
| 254 | |||
| 255 | return true; |
||
| 256 | } |
||
| 257 | |||
| 258 | /** |
||
| 259 | * @param string $key |
||
| 260 | * |
||
| 261 | * @return int|null |
||
| 262 | */ |
||
| 263 | View Code Duplication | public static function getInt($key) |
|
|
0 ignored issues
–
show
This method seems to be duplicated in 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...
|
|||
| 264 | { |
||
| 265 | $get = &self::$globalStateProvider->getGetSuperGlobal(); |
||
| 266 | if (!array_key_exists($key, $get)) { |
||
| 267 | return null; |
||
| 268 | } |
||
| 269 | |||
| 270 | $filteredValue = filter_var($get[$key], FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE); |
||
| 271 | |||
| 272 | if ($filteredValue === null) { |
||
| 273 | return null; |
||
| 274 | } |
||
| 275 | |||
| 276 | return (int)$filteredValue; |
||
| 277 | } |
||
| 278 | |||
| 279 | /** |
||
| 280 | * @param string $key |
||
| 281 | * |
||
| 282 | * @return null|string |
||
| 283 | */ |
||
| 284 | View Code Duplication | public static function getString($key) |
|
|
0 ignored issues
–
show
This method seems to be duplicated in 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...
|
|||
| 285 | { |
||
| 286 | $get = &self::$globalStateProvider->getGetSuperGlobal(); |
||
| 287 | if (!array_key_exists($key, $get)) { |
||
| 288 | return null; |
||
| 289 | } |
||
| 290 | |||
| 291 | if ($get[$key] === "") { |
||
| 292 | return null; |
||
| 293 | } |
||
| 294 | |||
| 295 | return (string)$get[$key]; |
||
| 296 | } |
||
| 297 | |||
| 298 | #endregion |
||
| 299 | |||
| 300 | /** |
||
| 301 | * Sets the logged-in user to the specified user. |
||
| 302 | * |
||
| 303 | * @param User $user |
||
| 304 | */ |
||
| 305 | public static function setLoggedInUser(User $user) |
||
| 306 | { |
||
| 307 | $session = &self::$globalStateProvider->getSessionSuperGlobal(); |
||
| 308 | |||
| 309 | $session['userID'] = $user->getId(); |
||
| 310 | unset($session['partialLogin']); |
||
| 311 | } |
||
| 312 | |||
| 313 | /** |
||
| 314 | * Sets the post-login redirect |
||
| 315 | */ |
||
| 316 | public static function setPostLoginRedirect() |
||
| 317 | { |
||
| 318 | $session = &self::$globalStateProvider->getSessionSuperGlobal(); |
||
| 319 | $session['returnTo'] = self::requestUri(); |
||
| 320 | } |
||
| 321 | |||
| 322 | /** |
||
| 323 | * @return string|null |
||
| 324 | */ |
||
| 325 | View Code Duplication | public static function requestUri() |
|
|
0 ignored issues
–
show
This method seems to be duplicated in 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...
|
|||
| 326 | { |
||
| 327 | $server = &self::$globalStateProvider->getServerSuperGlobal(); |
||
| 328 | |||
| 329 | if (isset($server['REQUEST_URI'])) { |
||
| 330 | return $server['REQUEST_URI']; |
||
| 331 | } |
||
| 332 | |||
| 333 | return null; |
||
| 334 | } |
||
| 335 | |||
| 336 | /** |
||
| 337 | * Clears the post-login redirect |
||
| 338 | * @return string |
||
| 339 | */ |
||
| 340 | public static function clearPostLoginRedirect() |
||
| 341 | { |
||
| 342 | $session = &self::$globalStateProvider->getSessionSuperGlobal(); |
||
| 343 | if (array_key_exists('returnTo', $session)) { |
||
| 344 | $path = $session['returnTo']; |
||
| 345 | unset($session['returnTo']); |
||
| 346 | |||
| 347 | return $path; |
||
| 348 | } |
||
| 349 | |||
| 350 | return null; |
||
| 351 | } |
||
| 352 | |||
| 353 | /** |
||
| 354 | * @return string|null |
||
| 355 | */ |
||
| 356 | View Code Duplication | public static function serverName() |
|
|
0 ignored issues
–
show
This method seems to be duplicated in 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...
|
|||
| 357 | { |
||
| 358 | $server = &self::$globalStateProvider->getServerSuperGlobal(); |
||
| 359 | |||
| 360 | if (isset($server['SERVER_NAME'])) { |
||
| 361 | return $server['SERVER_NAME']; |
||
| 362 | } |
||
| 363 | |||
| 364 | return null; |
||
| 365 | } |
||
| 366 | |||
| 367 | /** |
||
| 368 | * You probably only want to deal with this through SessionAlert. |
||
| 369 | * @return void |
||
| 370 | */ |
||
| 371 | public static function clearSessionAlertData() |
||
| 372 | { |
||
| 373 | $session = &self::$globalStateProvider->getSessionSuperGlobal(); |
||
| 374 | if (array_key_exists('alerts', $session)) { |
||
| 375 | unset($session['alerts']); |
||
| 376 | } |
||
| 377 | } |
||
| 378 | |||
| 379 | /** |
||
| 380 | * You probably only want to deal with this through SessionAlert. |
||
| 381 | * |
||
| 382 | * @return string[] |
||
| 383 | */ |
||
| 384 | public static function getSessionAlertData() |
||
| 385 | { |
||
| 386 | $session = &self::$globalStateProvider->getSessionSuperGlobal(); |
||
| 387 | if (array_key_exists('alerts', $session)) { |
||
| 388 | return $session['alerts']; |
||
| 389 | } |
||
| 390 | |||
| 391 | return array(); |
||
| 392 | } |
||
| 393 | |||
| 394 | /** |
||
| 395 | * You probably only want to deal with this through SessionAlert. |
||
| 396 | * |
||
| 397 | * @param string[] $data |
||
| 398 | */ |
||
| 399 | public static function setSessionAlertData($data) |
||
| 400 | { |
||
| 401 | $session = &self::$globalStateProvider->getSessionSuperGlobal(); |
||
| 402 | $session['alerts'] = $data; |
||
| 403 | } |
||
| 404 | |||
| 405 | /** |
||
| 406 | * You probably only want to deal with this through TokenManager. |
||
| 407 | * |
||
| 408 | * @return string[] |
||
| 409 | */ |
||
| 410 | public static function getSessionTokenData() |
||
| 411 | { |
||
| 412 | $session = &self::$globalStateProvider->getSessionSuperGlobal(); |
||
| 413 | if (array_key_exists('tokens', $session)) { |
||
| 414 | return $session['tokens']; |
||
| 415 | } |
||
| 416 | |||
| 417 | return array(); |
||
| 418 | } |
||
| 419 | |||
| 420 | /** |
||
| 421 | * You probably only want to deal with this through TokenManager. |
||
| 422 | * |
||
| 423 | * @param string[] $data |
||
| 424 | */ |
||
| 425 | public static function setSessionTokenData($data) |
||
| 426 | { |
||
| 427 | $session = &self::$globalStateProvider->getSessionSuperGlobal(); |
||
| 428 | $session['tokens'] = $data; |
||
| 429 | } |
||
| 430 | |||
| 431 | /** |
||
| 432 | * @return int|null |
||
| 433 | */ |
||
| 434 | public static function getSessionUserId() |
||
| 435 | { |
||
| 436 | $session = &self::$globalStateProvider->getSessionSuperGlobal(); |
||
| 437 | |||
| 438 | return isset($session['userID']) ? (int)$session['userID'] : null; |
||
| 439 | } |
||
| 440 | |||
| 441 | /** |
||
| 442 | * @param User $user |
||
| 443 | */ |
||
| 444 | public static function setPartialLogin(User $user) |
||
| 445 | { |
||
| 446 | $session = &self::$globalStateProvider->getSessionSuperGlobal(); |
||
| 447 | $session['partialLogin'] = $user->getId(); |
||
| 448 | } |
||
| 449 | |||
| 450 | /** |
||
| 451 | * @return int|null |
||
| 452 | */ |
||
| 453 | public static function getPartialLogin() |
||
| 454 | { |
||
| 455 | $session = &self::$globalStateProvider->getSessionSuperGlobal(); |
||
| 456 | |||
| 457 | return isset($session['partialLogin']) ? (int)$session['partialLogin'] : null; |
||
| 458 | } |
||
| 459 | |||
| 460 | /** |
||
| 461 | * @return null|string |
||
| 462 | */ |
||
| 463 | View Code Duplication | public static function userAgent() |
|
|
0 ignored issues
–
show
This method seems to be duplicated in 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...
|
|||
| 464 | { |
||
| 465 | $server = &self::$globalStateProvider->getServerSuperGlobal(); |
||
| 466 | |||
| 467 | if (isset($server['HTTP_USER_AGENT'])) { |
||
| 468 | return $server['HTTP_USER_AGENT']; |
||
| 469 | } |
||
| 470 | |||
| 471 | return null; |
||
| 472 | } |
||
| 473 | |||
| 474 | /** |
||
| 475 | * @return null|string |
||
| 476 | */ |
||
| 477 | View Code Duplication | public static function scriptName() |
|
|
0 ignored issues
–
show
This method seems to be duplicated in 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...
|
|||
| 478 | { |
||
| 479 | $server = &self::$globalStateProvider->getServerSuperGlobal(); |
||
| 480 | |||
| 481 | if (isset($server['SCRIPT_NAME'])) { |
||
| 482 | return $server['SCRIPT_NAME']; |
||
| 483 | } |
||
| 484 | |||
| 485 | return null; |
||
| 486 | } |
||
| 487 | |||
| 488 | /** |
||
| 489 | * @return null|string |
||
| 490 | */ |
||
| 491 | View Code Duplication | public static function origin() |
|
|
0 ignored issues
–
show
This method seems to be duplicated in 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...
|
|||
| 492 | { |
||
| 493 | $server = &self::$globalStateProvider->getServerSuperGlobal(); |
||
| 494 | |||
| 495 | if (isset($server['HTTP_ORIGIN'])) { |
||
| 496 | return $server['HTTP_ORIGIN']; |
||
| 497 | } |
||
| 498 | |||
| 499 | return null; |
||
| 500 | } |
||
| 501 | } |
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.