RemoteFetcher   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 99
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
dl 0
loc 99
c 0
b 0
f 0
wmc 11
lcom 1
cbo 7
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B fetchPage() 0 29 3
C findPageInList() 0 34 7
1
<?php
2
declare(strict_types=1);
3
4
namespace GarethEllis\Tldr\Fetcher;
5
6
use GarethEllis\Tldr\Fetcher\Exception\PageNotFoundException;
7
use GarethEllis\Tldr\Page\TldrPage;
8
use GuzzleHttp\Client;
9
use GarethEllis\Tldr\Fetcher\Exception\RemoteFetcherException;
10
11
/**
12
 * Class RemoteFetcher
13
 *
14
 * Fetches a page from the remote repository and optionally caches the result
15
 *
16
 * @package GarethEllis\Tldr\Fetcher
17
 */
18
class RemoteFetcher implements PageFetcherInterface
19
{
20
    use OperatingSystemTrait;
21
22
    protected $http;
23
24
    /**
25
     * @var string The base URL of the JSON index containing a list of commands
26
     */
27
    protected $baseUrl = "https://api.github.com/repos/tldr-pages/tldr/contents/pages/index.json?ref=master";
28
29
    /**
30
     * @var string URL template for fetching an individual page
31
     */
32
    protected $pageInfoUrlTemplate =
33
        "https://api.github.com/repos/tldr-pages/tldr/contents/pages/{platform}/{command}.md?ref=master";
34
35
    /**
36
     * RemoteFetcher constructor.
37
     *
38
     * @param \GuzzleHttp\Client $http
39
     */
40
    public function __construct(Client $http)
41
    {
42
        $this->http = $http;
43
    }
44
45
    /**
46
     * Fetch a page from remote repository
47
     *
48
     * @param string $pageName
49
     * @return string
50
     * @throws PageNotFoundException
51
     */
52
    public function fetchPage(String $pageName, array $options = []): TldrPage
53
    {
54
        try {
55
            $response = $this->http->get($this->baseUrl);
56
        } catch (\Exception $e) {
57
            throw new RemoteFetcherException($e->getMessage());
58
        }
59
60
        $contents = json_decode($response->getBody()->getContents(), true);
61
        $pages = base64_decode($contents["content"]);
62
        $json = json_decode($pages, true);
63
        $pages = $json["commands"];
64
        $page = $this->findPageInList($pageName, $pages, $options);
65
66
        $url = str_replace("{platform}", $page["platform"], $this->pageInfoUrlTemplate);
67
        $url = str_replace("{command}", $page["name"], $url);
68
69
        try {
70
            $response = $this->http->get($url);
71
        } catch (\Exception $e) {
72
            throw new RemoteFetcherException($e->getMessage());
73
        }
74
75
        $contents = json_decode($response->getBody()->getContents(), true);
76
        $pageContent = base64_decode($contents["content"]);
77
        $page = new TldrPage($pageName, $page["platform"], $pageContent);
78
79
        return $page;
80
    }
81
82
    protected function findPageInList(String $page, array $list, array $options)
83
    {
84
        $filtered = array_filter($list, function ($foundPage) use ($page) {
85
            return $foundPage["name"] === $page;
86
        });
87
88
        if (empty($filtered)) {
89
            throw new PageNotFoundException;
90
        }
91
92
        $page = array_shift($filtered);
93
94
        foreach ($page["platform"] as $k => $platform) {
95
96
            if ($platform === $this->getOperatingSystem($options)) {
97
                $platformSpecificKey = $k;
98
                continue;
99
            }
100
101
            if ($platform === "common") {
102
                $commonKey = $k;
103
                continue;
104
            }
105
        }
106
107
        if (!isset($commonKey) && !isset($platformSpecificKey)) {
108
            throw new PageNotFoundException();
109
        }
110
111
        $key = $platformSpecificKey ?? $commonKey;
0 ignored issues
show
Bug introduced by
The variable $platformSpecificKey does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
112
        $page["platform"] = $page["platform"][$key];
113
114
        return $page;
115
    }
116
}
117