Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | <?php  | 
            ||
| 37 | class Http  | 
            ||
| 38 | { | 
            ||
| 39 | /**  | 
            ||
| 40 | * The URL we are scanning  | 
            ||
| 41 | *  | 
            ||
| 42 | * @var string  | 
            ||
| 43 | */  | 
            ||
| 44 | public $url;  | 
            ||
| 45 | |||
| 46 | /**  | 
            ||
| 47 | * Request object  | 
            ||
| 48 | *  | 
            ||
| 49 | * @var \MageScan\Request  | 
            ||
| 50 | */  | 
            ||
| 51 | protected $request;  | 
            ||
| 52 | |||
| 53 | /**  | 
            ||
| 54 | * Start a check  | 
            ||
| 55 | *  | 
            ||
| 56 | * @param string $code  | 
            ||
| 57 | * @param string $url  | 
            ||
| 58 | */  | 
            ||
| 59 | public function __construct($code, $url)  | 
            ||
| 60 |     { | 
            ||
| 61 | $magescanUrl = new Url;  | 
            ||
| 62 | $this->url = $magescanUrl->clean(urldecode($url));  | 
            ||
| 63 | $this->request = new Request($this->url, isset($_SERVER['ALLOW_INSECURE']));  | 
            ||
| 64 | call_user_func([$this, 'check' . ucwords($code)]);  | 
            ||
| 65 | }  | 
            ||
| 66 | |||
| 67 | /**  | 
            ||
| 68 | * Check for Magento version  | 
            ||
| 69 | *  | 
            ||
| 70 | * @return void  | 
            ||
| 71 | */  | 
            ||
| 72 | public function checkMagentoinfo()  | 
            ||
| 73 |     { | 
            ||
| 74 | $version = new Version;  | 
            ||
| 75 | $version->setRequest($this->request);  | 
            ||
| 76 | $version = $version->getInfo();  | 
            ||
| 77 | $rows = [  | 
            ||
| 78 | ['Edition', $version[0] ?: 'Unknown'],  | 
            ||
| 79 | ['Version', $version[1] ?: 'Unknown']  | 
            ||
| 80 | ];  | 
            ||
| 81 | $this->respond(['body' => $rows]);  | 
            ||
| 82 | }  | 
            ||
| 83 | |||
| 84 | /**  | 
            ||
| 85 | * Check for installed modules  | 
            ||
| 86 | *  | 
            ||
| 87 | * @return void  | 
            ||
| 88 | */  | 
            ||
| 89 | public function checkModules()  | 
            ||
| 90 |     { | 
            ||
| 91 | $module = new Module;  | 
            ||
| 92 | $module->setRequest($this->request);  | 
            ||
| 93 | $this->respond(array_keys($module->getFiles()));  | 
            ||
| 94 | }  | 
            ||
| 95 | |||
| 96 | /**  | 
            ||
| 97 | * Check for an installed module  | 
            ||
| 98 | *  | 
            ||
| 99 | * @return void  | 
            ||
| 100 | */  | 
            ||
| 101 | public function checkModulessingle()  | 
            ||
| 102 |     { | 
            ||
| 103 | $module = new Module;  | 
            ||
| 104 | $module->setRequest($this->request);  | 
            ||
| 105 | $file = $_GET['path'];  | 
            ||
| 106 | $files = $module->getFiles();  | 
            ||
| 107 | $result = $module->checkForModule($_GET['path']);  | 
            ||
| 108 |         if ($result) { | 
            ||
| 109 | $this->respond([  | 
            ||
| 110 | isset($files[$file]) ? $files[$file] : '<!-- how did this happen -->'  | 
            ||
| 111 | ]);  | 
            ||
| 112 | }  | 
            ||
| 113 | }  | 
            ||
| 114 | |||
| 115 | /**  | 
            ||
| 116 | * Check for install patches  | 
            ||
| 117 | *  | 
            ||
| 118 | * @return void  | 
            ||
| 119 | */  | 
            ||
| 120 | public function checkPatch()  | 
            ||
| 121 |     { | 
            ||
| 122 | $patch = new Patch;  | 
            ||
| 123 | $patch->setRequest($this->request);  | 
            ||
| 124 | $patches = $patch->checkAll($this->url);  | 
            ||
| 125 | $rows = [];  | 
            ||
| 126 | View Code Duplication |         foreach ($patches as $name => $result) { | 
            |
| 127 |             switch ($result) { | 
            ||
| 128 | case PATCH::PATCHED:  | 
            ||
| 129 | $status = '<span class="pass">Patched</span class="pass">';  | 
            ||
| 130 | break;  | 
            ||
| 131 | case PATCH::UNPATCHED:  | 
            ||
| 132 | $status = '<span class="fail">Unpatched</span class="fail">';  | 
            ||
| 133 | break;  | 
            ||
| 134 | default:  | 
            ||
| 135 | $status = 'Unknown';  | 
            ||
| 136 | }  | 
            ||
| 137 | $rows[] = [  | 
            ||
| 138 | $name,  | 
            ||
| 139 | $status  | 
            ||
| 140 | ];  | 
            ||
| 141 | }  | 
            ||
| 142 | $this->respond([  | 
            ||
| 143 | 'head' => ['Patch', 'Status'],  | 
            ||
| 144 | 'body' => $rows  | 
            ||
| 145 | ]);  | 
            ||
| 146 | }  | 
            ||
| 147 | |||
| 148 | /**  | 
            ||
| 149 | * Check for catalog information  | 
            ||
| 150 | *  | 
            ||
| 151 | * @return void  | 
            ||
| 152 | */  | 
            ||
| 153 | public function checkCatalog()  | 
            ||
| 154 |     { | 
            ||
| 155 | $rows = [];  | 
            ||
| 156 | $catalog = new Catalog;  | 
            ||
| 157 | $catalog->setRequest($this->request);  | 
            ||
| 158 | $categoryCount = $catalog->categoryCount();  | 
            ||
| 159 | $rows[] = [  | 
            ||
| 160 | '<a href="' . $this->url. 'catalog/seo_sitemap/category" target="_blank">Categories</a>',  | 
            ||
| 161 | $categoryCount !== false ? $categoryCount : 'Unknown'  | 
            ||
| 162 | ];  | 
            ||
| 163 | $productCount = $catalog->productCount();  | 
            ||
| 164 | $rows[] = [  | 
            ||
| 165 | '<a href="' . $this->url . 'catalog/seo_sitemap/product" target="_blank">Products</a>',  | 
            ||
| 166 | $productCount !== false ? $productCount : 'Unknown'  | 
            ||
| 167 | ];  | 
            ||
| 168 | $this->respond(['body' => $rows]);  | 
            ||
| 169 | }  | 
            ||
| 170 | |||
| 171 | /**  | 
            ||
| 172 | * Check for a valid sitemap  | 
            ||
| 173 | *  | 
            ||
| 174 | * @return void  | 
            ||
| 175 | */  | 
            ||
| 176 | public function checkSitemap()  | 
            ||
| 177 |     { | 
            ||
| 178 | $rows = [];  | 
            ||
| 179 |         $response   = $this->request->get('robots.txt'); | 
            ||
| 180 | $sitemap = new Sitemap;  | 
            ||
| 181 | $sitemap->setRequest($this->request);  | 
            ||
| 182 | $sitemapUrl = $sitemap->getSitemapFromRobotsTxt($response);  | 
            ||
| 183 |         if ($sitemapUrl === false) { | 
            ||
| 184 | $rows[] = ['<span class="fail">Sitemap is not declared in <a href="' . $this->url  | 
            ||
| 185 | . 'robots.txt" target="_blank">robots.txt</a></span>'];  | 
            ||
| 186 | $sitemapUrl = $this->url . 'sitemap.xml';  | 
            ||
| 187 |         } else { | 
            ||
| 188 | $rows[] = ['<span class="pass">Sitemap is declared in <a href="' . $this->url  | 
            ||
| 189 | . 'robots.txt" target="_blank">robots.txt</a></span></span>'];  | 
            ||
| 190 | }  | 
            ||
| 191 | $response = $this->request->get($sitemapUrl);  | 
            ||
| 
                                                                                                    
                         1 ignored issue 
                            –
                            show
                         | 
                |||
| 192 |         if ($response->getStatusCode() == 200) { | 
            ||
| 193 | $rows[] = ['<span class="pass"><a href="' . $sitemapUrl  | 
            ||
| 194 | . '" target="_blank">Sitemap</a> is accessible</span>'];  | 
            ||
| 195 |         } else { | 
            ||
| 196 | $rows[] = ['<span class="fail"><a href="' . $sitemapUrl  | 
            ||
| 197 | . '" target="_blank">Sitemap</a> is not accessible</span>'];  | 
            ||
| 198 | }  | 
            ||
| 199 | $this->respond(['body' => $rows]);  | 
            ||
| 200 | }  | 
            ||
| 201 | |||
| 202 | /**  | 
            ||
| 203 | * Check for server technologies  | 
            ||
| 204 | *  | 
            ||
| 205 | * @return void  | 
            ||
| 206 | */  | 
            ||
| 207 | public function checkServertech()  | 
            ||
| 208 |     { | 
            ||
| 209 | $rows = [];  | 
            ||
| 210 | $techHeader = new TechHeader;  | 
            ||
| 211 | $techHeader->setRequest($this->request);  | 
            ||
| 212 | $values = $techHeader->getHeaders();  | 
            ||
| 213 |         if (empty($values)) { | 
            ||
| 214 | $rows[] = ['No detectable technology was found'];  | 
            ||
| 215 | }  | 
            ||
| 216 |         foreach ($values as $key => $value) { | 
            ||
| 217 | $rows[] = [$key, $value];  | 
            ||
| 218 | }  | 
            ||
| 219 | $this->respond(['body' => $rows]);  | 
            ||
| 220 | }  | 
            ||
| 221 | |||
| 222 | /**  | 
            ||
| 223 | * Check for unreachable paths  | 
            ||
| 224 | *  | 
            ||
| 225 | * @return void  | 
            ||
| 226 | */  | 
            ||
| 227 | public function checkUnreachablepath()  | 
            ||
| 228 |     { | 
            ||
| 229 | $unreachablePath = new UnreachablePath;  | 
            ||
| 230 | $unreachablePath->setRequest($this->request);  | 
            ||
| 231 | $this->respond($unreachablePath->getPaths());  | 
            ||
| 232 | }  | 
            ||
| 233 | |||
| 234 | /**  | 
            ||
| 235 | * Check for unreachable paths  | 
            ||
| 236 | *  | 
            ||
| 237 | * @return void  | 
            ||
| 238 | */  | 
            ||
| 239 | public function checkUnreachablepathsingle()  | 
            ||
| 240 |     { | 
            ||
| 241 | $unreachablePath = new UnreachablePath;  | 
            ||
| 242 | $unreachablePath->setRequest($this->request);  | 
            ||
| 243 | $result = $unreachablePath->checkPath($_GET['path']);  | 
            ||
| 244 |         if ($result[2] === true) { | 
            ||
| 245 | return;  | 
            ||
| 246 | }  | 
            ||
| 247 |         if ($result[2] === false) { | 
            ||
| 248 | $result[0] = '<a target="_blank" href="' . $this->url . $result[0] . '">' . $result[0] . '</a>';  | 
            ||
| 249 | $result[2] = '<span class="fail">Reachable</span>';  | 
            ||
| 250 |         } elseif (substr($result[1], 0, 1) == 3) { | 
            ||
| 251 |             if (substr($result[2], 0, 4) == 'http') { | 
            ||
| 252 | $newUrl = $result[2];  | 
            ||
| 253 |             } else { | 
            ||
| 254 | $newUrl = $this->url . substr($result[2], 1);  | 
            ||
| 255 | }  | 
            ||
| 256 | $result[0] = '<a target="_blank" href="' . $newUrl . '">' . $result[0] . '</a>';  | 
            ||
| 257 | $result[2] = '<a target="_blank" href="' . $newUrl . '">Redirect</a>';  | 
            ||
| 258 | }  | 
            ||
| 259 | $this->respond($result);  | 
            ||
| 260 | }  | 
            ||
| 261 | |||
| 262 | /**  | 
            ||
| 263 | * Send JSON response  | 
            ||
| 264 | *  | 
            ||
| 265 | * @param array $data  | 
            ||
| 266 | *  | 
            ||
| 267 | * @return void  | 
            ||
| 268 | */  | 
            ||
| 269 | public function respond(array $data)  | 
            ||
| 273 | }  | 
            ||
| 274 | 
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:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.