Completed
Push — master ( de8bd8...d0433f )
by Dimas
08:48
created

cache::imageCache()   C

Complexity

Conditions 12
Paths 48

Size

Total Lines 59
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 12
eloc 44
c 1
b 0
f 1
nc 48
nop 2
dl 0
loc 59
rs 6.9666

How to fix   Long Method    Complexity   

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
namespace img;
4
5
class cache
6
{
7
  public static $saved;
8
  public static $url;
9
  public static $api;
10
  public static $cache;
11
  public static $cache_dir = ROOT . '/tmp/img/';
12
13
  public function __construct()
14
  {
15
    self::$api = new \Extender\request('https://unsplash.it');
16
  }
17
18
  public static function imageCache(string $url, bool $rewrite = false)
19
  {
20
    if (!self::$api) {
21
      self::$api = new \Extender\request('https://unsplash.it');
22
    }
23
    self::$url = $url;
24
    $saved = self::$cache_dir . '/img/saved.json';
25
    self::$saved = $saved;
26
    $res = read_file($saved, []);
27
    if (is_string($res)) {
28
      $res = json_decode($res, true);
29
    }
30
31
    self::$api->setUrl($url);
32
    $url = self::$api->url;
33
    $cache = self::$cache_dir . '/' . md5($url);
34
    self::$cache = $cache;
35
    if (file_exists($cache) && !headers_sent()) {
36
      header_remove('x-powered-by');
37
      header_remove('pragma');
38
      self::send_cache_header($cache);
39
      $lastModified = gmdate('D, d M Y H:i:s', filemtime($cache)) . ' GMT';
40
      header('Cache-Control: private');
41
      /*
42
       * Send fallback headers
43
       */
44
      //header('Content-type: image/jpeg');
45
      header('ETag: ' . md5_file($cache));
46
      header("Last-Modified: $lastModified");
47
      // 1 day expires
48
      header('Expires: ' . gmdate('D, d M Y H:i:s', ((60 * 60 * 24 * 1) + strtotime($lastModified))));
49
    }
50
51
    if (!isset($res[$url]) || (is_bool($rewrite) && $rewrite)) {
52
      self::$api->set_method('get');
53
      self::$api->exec();
54
      for ($i = 0; $i < 2; ++$i) {
55
        if (isset(self::$api->responseHeaders['Location'])) {
56
          self::$api->get(self::$api->responseHeaders['Location']);
57
        } else {
58
          break;
59
        }
60
      }
61
      $res[$url] = self::$api->url;
62
      write_file($saved, $res, true);
63
      write_file($cache, self::$api->response, true);
64
      header('Content-Type: ' . self::$api->responseHeaders['Content-Type'], true);
65
      echo self::$api->response;
66
    } elseif (file_exists($cache)) {
67
      header('Content-Type: ' . mime_content_type($cache), true);
68
      $read = read_file($cache);
69
      if (!empty($read)) {
70
        echo $read;
71
      } else {
72
        return self::{__FUNCTION__}($url, true);
73
      }
74
    } else {
75
      self::$api->set_url($res[$url])->set_method('get')->exec();
76
      self::writeCache();
77
    }
78
  }
79
80
  /**
81
   * Transform url image to cache
82
   * * `schema data cache`
83
   * ```json
84
   * { "md5": "realURL" }
85
   * ```.
86
   *
87
   * @author Dimas Lanjaka <[email protected]>
88
   */
89
  public static function url2cache(string $url)
90
  {
91
    if (!self::$api) {
92
      self::$api = new \Extender\request('https://unsplash.it');
93
    }
94
    /**
95
     * @var string Anonymize url into md5
96
     *
97
     * @todo Fix unecessary characters from url
98
     */
99
    $md5 = md5($url);
100
    /**
101
     * @var string Save cache name generator.
102
     *
103
     * @return string domain or default
104
     */
105
    $savedname = function () {
106
      global $url;
107
      $savedname = \MVC\helper::url2host($url);
108
      if (!$savedname) {
109
        $savedname = 'default';
110
      }
111
112
      return $savedname;
113
    };
114
    /**
115
     * @var string Save location schema image
116
     */
117
    $saved = __DIR__ . "/data/$savedname.json";
118
    self::$saved = $saved;
119
    $res = read_file($saved, []);
120
    if (is_string($res)) {
121
      $res = json_decode($res, true);
122
    }
123
    if (isset($res[$md5])) {
124
      self::$url = $res[$md5];
125
    } elseif (\MVC\helper::is_url($url)) {
126
      $res[$md5] = self::$url = $url;
127
      $saved = __DIR__ . "/data/$savedname.json";
128
    }
129
130
    self::$api->setUrl(self::$url);
131
    $url = self::$api->url;
132
    $cache = ROOT . '/tmp/img/' . md5($url);
133
    self::$cache = $cache;
134
135
    if (!file_exists($cache)) {
136
      self::$api->set_method('get');
137
      self::$api->exec();
138
      for ($i = 0; $i < 10; ++$i) {
139
        if (isset(self::$api->responseHeaders['Location'])) {
140
          self::$api->get(self::$api->responseHeaders['Location']);
141
        } else {
142
          break;
143
        }
144
      }
145
146
      write_file($saved, $res, true);
147
      write_file($cache, self::$api->response, true);
148
    }
149
150
    return '/img/cache?hash=' . md5($url);
151
  }
152
153
  /**
154
   * Write Cache.
155
   *
156
   * @return void
157
   */
158
  public static function writeCache()
159
  {
160
    $res[self::$url] = self::$api->url;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$res was never initialized. Although not strictly required by PHP, it is generally a good practice to add $res = array(); before regardless.
Loading history...
161
    write_file(self::$saved, $res, true);
162
    write_file(self::$cache, self::$api->response, true);
163
    header('Content-Type: ' . self::$api->responseHeaders['Content-Type'], true);
164
    echo self::$api->response;
165
  }
166
167
  /**
168
   * Send Cache Header for static content.
169
   *
170
   * @param [type] $cache_file_name
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
171
   * @param bool   $check_request
172
   *
173
   * @return void
174
   */
175
  public static function send_cache_header($cache_file_name, $check_request = false)
176
  {
177
    if (headers_sent()) {
178
      return;
179
    }
180
    $mtime = @filemtime($cache_file_name);
181
182
    if ($mtime > 0) {
183
      $gmt_mtime = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';
184
      $etag = sprintf('%08x-%08x', crc32($cache_file_name), $mtime);
185
186
      header('ETag: "' . $etag . '"', true);
187
      header('Last-Modified: ' . $gmt_mtime, true);
188
      header('Cache-Control: private', true);
189
      // we don't send an "Expires:" header to make clients/browsers use if-modified-since and/or if-none-match
190
191
      if ($check_request) {
192
        if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && !empty($_SERVER['HTTP_IF_NONE_MATCH'])) {
193
          $tmp = explode(';', $_SERVER['HTTP_IF_NONE_MATCH']); // IE fix!
194
          if (!empty($tmp[0]) && strtotime($tmp[0]) == strtotime($gmt_mtime)) {
195
            header('HTTP/1.1 304 Not Modified');
196
197
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type void.
Loading history...
198
          }
199
        }
200
201
        if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
202
          if (str_replace(['\"', '"'], '', $_SERVER['HTTP_IF_NONE_MATCH']) == $etag) {
203
            header('HTTP/1.1 304 Not Modified');
204
205
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type void.
Loading history...
206
          }
207
        }
208
      }
209
    }
210
211
    return true;
0 ignored issues
show
Bug Best Practice introduced by
The expression return true returns the type true which is incompatible with the documented return type void.
Loading history...
212
  }
213
}
214