Jacek Kowalski
2012-08-29 10ce8b71d56dfb2843af99624867fc3f13cfb3b3
commit | author | age
80ddb4 1 <?php
JK 2 class DownloadHelper {
3     protected $url;
4     protected $curl;
5     protected $headers = array();
9b2b4a 6     protected $return = NULL;
80ddb4 7     
JK 8     protected $cacheDir = './cache/';
9     protected $cacheFile;
10     protected $cacheInfo = array();
11     
12     function build_url($components) {
48c64f 13         return $components['scheme'].'://'.(isset($components['user']) && !empty($components['user']) ? $components['user'].(isset($components['pass']) && !empty($components['pass']) ? ':'.$components['pass'] : '').'@' : '').$components['host'].($components['path'] ? $components['path'] : '/').($components['query'] ? '?'.$components['query'] : '');
80ddb4 14     }
JK 15     
16     function __construct($url) {
17         $this->url = parse_url($url);
18         if(!$this->url) {
19             throw new Exception('Parametr przekazywany do DownloadHelper::__construct() musi być poprawnym adresem URL.');
20         }
21         
22         if($this->url['scheme'] != 'http' && $this->url['scheme'] != 'https') {
23             throw new Exception('Klasa DownloadHelper obsługuje tylko i wyłącznie protokoły HTTP i HTTPS.');
24         }
25         
26         if(strlen($this->url['host']) == 0) {
27             throw new Exception('URL przekazany klasie DownloadHelper jest nieprawidłowy - brak nazwy hosta.');
28         }
29         
30         $url = $this->build_url($this->url);
31         $this->cacheFile = $this->url['host'].'/'.$this->url['scheme'].'-'.sha1($url);
32         
33         $this->curl = curl_init($url);
34     }
35     
36     function setopt($option, $value) {
37         if($option == CURLOPT_HTTPHEADER) {
38             if(is_string($value)) {
39                 $value = array($value);
40             }
41             
42             if(!is_array($value)) {
43                 throw new Exception('Parametr przekazywany jako CURLOPT_HTTPHEADER musi być tablicą.');
44             }
45             
46             $this->headers = array_merge($this->headers, $value);
47         }
48         
49         curl_setopt($this->curl, $option, $value);
50     }
51     
52     function setopt_array($options) {
53         if(!is_array($options)) {
54             throw new Exception('Parametr przekazywany do DownloadHelper::setopt_array() musi być tablicą.');
55         }
56         
57         foreach($options as $option => $value) {
58             $this->setopt($option, $value);
59         }
60     }
61     
62     function cacheDir($directory) {
63         $this->cacheDir = $directory;
64     }
65     
66     function exec() {
67         if(!is_dir($this->cacheDir)) {
68             mkdir($this->cacheDir);
69         }
70         
71         if(!is_dir($this->cacheDir.$this->url['host'])) {
72             mkdir($this->cacheDir.$this->url['host']);
73         }
74         
75         // Sprawdź, czy są dane na temat pliku w cache...
76         if(is_file($this->cacheDir.$this->cacheFile.'-info')) {
77             $this->cacheInfo = unserialize(file_get_contents($this->cacheDir.$this->cacheFile.'-info'));
78             if(!$this->cacheInfo) {
79                 $this->cacheInfo = array();
80             }
81         }
82         else
83         {
84             if(is_file($this->cacheDir.$this->cacheFile)) {
85                 unlink($this->cacheDir.$this->cacheFile);
86             }
87         }
88         
89         // Czy można wykorzystać cache...
90         if(isset($this->cacheInfo['cache']) && $this->cacheInfo['cache'] >= time()) {
91             if(is_file($this->cacheDir.$this->cacheFile)) {
92                 return file_get_contents($this->cacheDir.$this->cacheFile);
93             }
94             else
95             {
96                 return FALSE;
97             }
98         }
99         
100         // Nie można wykorzystać cache, sprawdź czy plik się zmienił...
101         if(isset($this->cacheInfo['last_seen'])) {
102             $this->headers[] = 'If-Modified-Since: '.date(DATE_RFC1123, $this->cacheInfo['last_seen']);
103         }
104         
105         if(count($this->headers) > 0) {
106             curl_setopt($this->curl, CURLOPT_HTTPHEADER, $this->headers);
107         }
108         curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, TRUE);
109         
110         $this->return = curl_exec($this->curl);
111         
112         $this->cacheInfo['last_updated'] = time();
113         $info = $this->getinfo();
114         
115         if($info['http_code'] == '304') {
116             // Plik się nie zmienił...
117             $this->cacheInfo['last_seen'] = time();
118             
119             if(is_file($this->cacheDir.$this->cacheFile)) {
120                 $this->return = file_get_contents($this->cacheDir.$this->cacheFile);
121             }
122             else
123             {
124                 $this->return = FALSE;
125             }
126         }
127         
128         return $this->return;
129     }
130     
131     function cacheFor($seconds) {
132         $this->cacheUntil(time() + $seconds);
133     }
134     
135     function cacheUntil($timestamp) {
136         if($timestamp >= time()) {
137             // Można cache'ować
138             $this->cacheInfo['cache'] = $timestamp;
139         }
140         else
141         {
142             if(isset($this->cacheInfo['cache'])) {
143                 unset($this->cacheInfo['cache']);
144             }
145         }
146         
147         file_put_contents($this->cacheDir.$this->cacheFile.'-info', serialize($this->cacheInfo));
148         
149         if($this->return === FALSE) {
150             // Usuń stary plik z cache - zapytanie nie powiodło się
151             if(is_file($this->cacheDir.$this->cacheFile)) {
152                 unlink($this->cacheDir.$this->cacheFile);
153             }
154         }
155         elseif($this->return !== NULL) {
156             // Umieść w cache nowy plik...
157             $this->cacheInfo['last_seen'] = $this->cacheInfo['downloaded'] = time();
158             file_put_contents($this->cacheDir.$this->cacheFile, $this->return);
159         }
160     }
161     
162     function invalidate() {
163         if(is_file($this->cacheDir.$this->cacheFile)) {
164             unlink($this->cacheDir.$this->cacheFile);
165         }
166         
167         if(is_file($this->cacheDir.$this->cacheFile.'-info')) {
168             unlink($this->cacheDir.$this->cacheFile.'-info');
169         }
170     }
171     
172     function getinfo() {
173         return curl_getinfo($this->curl);
174     }
175     
176     function __destruct() {
177         curl_close($this->curl);
178     }
179 }
180 ?>