Dotclear

source: inc/core/class.dc.store.reader.php @ 2319:abe2702e1585

Revision 2319:abe2702e1585, 6.0 KB checked in by Denis Jean-Chirstian <contact@…>, 12 years ago (diff)

Move ex-daInstaller settings to core and install and upgrade

Line 
1<?php
2# -- BEGIN LICENSE BLOCK ---------------------------------------
3#
4# This file is part of Dotclear 2.
5#
6# Copyright (c) 2003-2013 Olivier Meunier & Association Dotclear
7# Licensed under the GPL version 2.0 license.
8# See LICENSE file or
9# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10#
11# -- END LICENSE BLOCK -----------------------------------------
12if (!defined('DC_RC_PATH')) { return; }
13
14/**
15@ingroup DC_CORE
16@brief Repository modules XML feed reader
17@since 2.6
18
19Provides an object to parse XML feed of modules from repository.
20This class extends clearbricks netHttp class.
21*/
22class dcStoreReader extends netHttp
23{
24     /** @var  string    User agent used to query repository */
25     protected $user_agent = 'DotClear.org RepoBrowser/0.1';
26     /** @var  integer   User agent used to query repository */
27     protected $timeout = 5;
28     /** @var  array      HTTP Cache validators */
29     protected $validators = null;
30     /** @var  string    Cache temporary directory */
31     protected $cache_dir = null;
32     /** @var  string    Cache file prefix */
33     protected $cache_file_prefix = 'dcrepo';
34     /** @var  integer   Cache TTL */
35     protected $cache_ttl = '-30 minutes';
36     /** @var  boolean   'Cache' TTL on server failed */
37     protected $cache_touch_on_fail = true;
38     /** @var  boolean   Force query server */
39     protected $force = false;
40
41     /**
42      * Constructor.
43      *
44      * Bypass first argument of clearbricks netHttp constructor.
45      */
46     public function __construct()
47     {
48          parent::__construct('');
49          $this->setUserAgent(sprintf('Dotclear/%s)', DC_VERSION));
50     }
51
52     /**
53      * Parse modules feed.
54      *
55      * @param string    $url      XML feed URL
56      * @return     object    dcStore instance
57      */
58     public function parse($url)
59     {
60          $this->validators = array();
61
62          if ($this->cache_dir) {
63               return $this->withCache($url);
64          }
65          elseif (!$this->getModulesXML($url) || $this->getStatus() != '200') {
66               return false;
67          }
68
69          return new dcStoreParser($this->getContent());
70     }
71
72     /**
73      * Quick parse modules feed.
74      *
75      * @param string    $url      XML feed URL
76      * @param string    $cache_dir     Cache directoy or null for no cache
77      * @param boolean   $force         Force query repository
78      * @return     object    Self instance
79      */
80     public static function quickParse($url, $cache_dir=null, $force=false)
81     {
82          $parser = new self();
83          if ($cache_dir) {
84               $parser->setCacheDir($cache_dir);
85          }
86          if ($force) {
87               $parser->setForce($force);
88          }
89
90          return $parser->parse($url);
91     }
92
93     /**
94      * Set cache directory.
95      *
96      * @param string    $dir      Cache directory
97      * @return     boolean   True if cache dierctory is useable
98      */
99     public function setCacheDir($dir)
100     {
101          $this->cache_dir = null;
102
103          if (!empty($dir) && is_dir($dir) && is_writeable($dir)) {
104               $this->cache_dir = $dir;
105               return true;
106          }
107
108          return false;
109     }
110
111     /**
112      * Set cache TTL.
113      *
114      * @param string    $str      Cache TTL
115      */
116     public function setCacheTTL($str)
117     {
118          $str = trim($str);
119
120          if (!empty($str)) {
121               $this->cache_ttl = substr($str, 0, 1) == '-' ? $str : '-'.$str;
122          }
123     }
124
125     /**
126      * Set force query repository.
127      *
128      * @param boolean   $force    True to force query
129      */
130     public function setForce($force)
131     {
132          $this->force = $force;
133     }
134
135     /**
136      * Get repository XML feed URL content.
137      *
138      * @param string    $url      XML feed URL
139      * @return     string    Feed content
140      */
141     protected function getModulesXML($url)
142     {
143          if (!self::readURL($url, $ssl, $host, $port, $path, $user, $pass)) {
144               return false;
145          }
146          $this->setHost($host, $port);
147          $this->useSSL($ssl);
148          $this->setAuthorization($user, $pass);
149
150          try {
151               return $this->get($path);
152          }
153          catch(Exception $e) {
154               // @todo Log error when repository query fail
155               return false;
156          }
157     }
158
159     /**
160      * Get repository modules list using cache.
161      *
162      * @param string    $url      XML feed URL
163      * @return     array     Feed content or False on fail
164      */
165     protected function withCache($url)
166     {
167          $url_md5 = md5($url);
168          $cached_file = sprintf('%s/%s/%s/%s/%s.ser',
169               $this->cache_dir,
170               $this->cache_file_prefix,
171               substr($url_md5,0,2),
172               substr($url_md5,2,2),
173               $url_md5
174          );
175
176          $may_use_cached = false;
177
178          # Use cache file ?
179          if (@file_exists($cached_file) && !$this->force) {
180               $may_use_cached = true;
181               $ts = @filemtime($cached_file);
182               if ($ts > strtotime($this->cache_ttl)) {
183                    # Direct cache
184                    return unserialize(file_get_contents($cached_file));
185               }
186               $this->setValidator('IfModifiedSince', $ts);
187          }
188
189          # Query repository
190          if (!$this->getModulesXML($url)) {
191               if ($may_use_cached) {
192                    # Touch cache TTL even if query failed ?
193                    if ($this->cache_touch_on_fail) {
194                         @files::touch($cached_file);
195                    }
196                    # Connection failed - fetched from cache
197                    return unserialize(file_get_contents($cached_file));
198               }
199               return false;
200          }
201
202          # Parse response
203          switch ($this->getStatus())
204          {
205               # Not modified, use cache
206               case '304':
207                    @files::touch($cached_file);
208                    return unserialize(file_get_contents($cached_file));
209               # Ok, parse feed
210               case '200':
211                    if ($modules = new dcStoreParser($this->getContent())) {
212                         try {
213                              files::makeDir(dirname($cached_file), true);
214                         }
215                         catch (Exception $e) {
216                              return $modules;
217                         }
218
219                         if (($fp = @fopen($cached_file, 'wb'))) {
220                              fwrite($fp, serialize($modules));
221                              fclose($fp);
222                              files::inheritChmod($cached_file);
223                         }
224                         return $modules;
225                    }
226          }
227
228          return false;
229     }
230
231     /**
232      * Prepare query.
233      *
234      * @return     array     Query headers
235      */
236     protected function buildRequest()
237     {
238          $headers = parent::buildRequest();
239
240          # Cache validators
241          if (!empty($this->validators)) {
242               if (isset($this->validators['IfModifiedSince'])) {
243                    $headers[] = 'If-Modified-Since: '.$this->validators['IfModifiedSince'];
244               }
245               if (isset($this->validators['IfNoneMatch'])) {
246                    if (is_array($this->validators['IfNoneMatch'])) {
247                         $etags = implode(',', $this->validators['IfNoneMatch']);
248                    }
249                    else {
250                         $etags = $this->validators['IfNoneMatch'];
251                    }
252                    $headers[] = '';
253               }
254          }
255
256          return $headers;
257     }
258
259     /**
260      * Tweak query cache validator.
261      *
262      * @param string    $key      Validator key
263      * @param string    $value         Validator value
264      */
265     private function setValidator($key, $value)
266     {
267          if ($key == 'IfModifiedSince') {
268               $value = gmdate('D, d M Y H:i:s', $value).' GMT';
269          }
270
271          $this->validators[$key] = $value;
272     }
273}
Note: See TracBrowser for help on using the repository browser.

Sites map