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

RevLine 
[2146]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
[2214]16@brief Repository modules XML feed reader
[2222]17@since 2.6
[2146]18
[2214]19Provides an object to parse XML feed of modules from repository.
20This class extends clearbricks netHttp class.
[2146]21*/
[2216]22class dcStoreReader extends netHttp
[2146]23{
[2214]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 */
[2146]37     protected $cache_touch_on_fail = true;
[2214]38     /** @var  boolean   Force query server */
39     protected $force = false;
[2146]40
[2214]41     /**
42      * Constructor.
43      *
44      * Bypass first argument of clearbricks netHttp constructor.
45      */
[2146]46     public function __construct()
47     {
48          parent::__construct('');
49          $this->setUserAgent(sprintf('Dotclear/%s)', DC_VERSION));
50     }
51
[2214]52     /**
53      * Parse modules feed.
54      *
55      * @param string    $url      XML feed URL
[2216]56      * @return     object    dcStore instance
[2214]57      */
[2146]58     public function parse($url)
59     {
60          $this->validators = array();
[2214]61
62          if ($this->cache_dir) {
[2146]63               return $this->withCache($url);
64          }
[2214]65          elseif (!$this->getModulesXML($url) || $this->getStatus() != '200') {
66               return false;
67          }
[2146]68
[2216]69          return new dcStoreParser($this->getContent());
[2146]70     }
71
[2214]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      */
[2146]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
[2214]93     /**
94      * Set cache directory.
95      *
96      * @param string    $dir      Cache directory
97      * @return     boolean   True if cache dierctory is useable
98      */
[2146]99     public function setCacheDir($dir)
100     {
101          $this->cache_dir = null;
102
[2214]103          if (!empty($dir) && is_dir($dir) && is_writeable($dir)) {
[2146]104               $this->cache_dir = $dir;
105               return true;
106          }
107
108          return false;
109     }
110
[2214]111     /**
112      * Set cache TTL.
113      *
114      * @param string    $str      Cache TTL
115      */
[2146]116     public function setCacheTTL($str)
117     {
118          $str = trim($str);
[2214]119
120          if (!empty($str)) {
121               $this->cache_ttl = substr($str, 0, 1) == '-' ? $str : '-'.$str;
[2146]122          }
123     }
124
[2214]125     /**
[2216]126      * Set force query repository.
[2214]127      *
128      * @param boolean   $force    True to force query
129      */
[2146]130     public function setForce($force)
131     {
132          $this->force = $force;
133     }
134
[2214]135     /**
136      * Get repository XML feed URL content.
137      *
138      * @param string    $url      XML feed URL
139      * @return     string    Feed content
140      */
[2146]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
[2319]150          try {
151               return $this->get($path);
152          }
153          catch(Exception $e) {
154               // @todo Log error when repository query fail
155               return false;
156          }
[2146]157     }
158
[2214]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      */
[2146]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
[2214]178          # Use cache file ?
179          if (@file_exists($cached_file) && !$this->force) {
[2146]180               $may_use_cached = true;
181               $ts = @filemtime($cached_file);
[2214]182               if ($ts > strtotime($this->cache_ttl)) {
[2146]183                    # Direct cache
184                    return unserialize(file_get_contents($cached_file));
185               }
186               $this->setValidator('IfModifiedSince', $ts);
187          }
188
[2214]189          # Query repository
190          if (!$this->getModulesXML($url)) {
191               if ($may_use_cached) {
192                    # Touch cache TTL even if query failed ?
[2146]193                    if ($this->cache_touch_on_fail) {
194                         @files::touch($cached_file);
195                    }
[2214]196                    # Connection failed - fetched from cache
[2146]197                    return unserialize(file_get_contents($cached_file));
198               }
199               return false;
200          }
201
[2214]202          # Parse response
[2146]203          switch ($this->getStatus())
204          {
[2214]205               # Not modified, use cache
[2146]206               case '304':
207                    @files::touch($cached_file);
208                    return unserialize(file_get_contents($cached_file));
[2214]209               # Ok, parse feed
[2146]210               case '200':
[2216]211                    if ($modules = new dcStoreParser($this->getContent())) {
[2146]212                         try {
213                              files::makeDir(dirname($cached_file), true);
[2214]214                         }
215                         catch (Exception $e) {
[2146]216                              return $modules;
217                         }
218
[2214]219                         if (($fp = @fopen($cached_file, 'wb'))) {
[2146]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
[2214]231     /**
232      * Prepare query.
233      *
234      * @return     array     Query headers
235      */
[2146]236     protected function buildRequest()
237     {
238          $headers = parent::buildRequest();
239
240          # Cache validators
[2214]241          if (!empty($this->validators)) {
[2146]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']);
[2214]248                    }
249                    else {
[2146]250                         $etags = $this->validators['IfNoneMatch'];
251                    }
252                    $headers[] = '';
253               }
254          }
255
256          return $headers;
257     }
258
[2214]259     /**
260      * Tweak query cache validator.
261      *
262      * @param string    $key      Validator key
263      * @param string    $value         Validator value
264      */
[2146]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