Joomla Platform  13.1
Documentation des API du framework Joomla Platform
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Pages
collection.php
Aller à la documentation de ce fichier.
1 <?php
2 /**
3  * @package Joomla.Platform
4  * @subpackage Updater
5  *
6  * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
7  * @license GNU General Public License version 2 or later; see LICENSE
8  */
9 
10 defined('JPATH_PLATFORM') or die;
11 
12 jimport('joomla.updater.updateadapter');
13 
14 /**
15  * Collection Update Adapter Class
16  *
17  * @package Joomla.Platform
18  * @subpackage Updater
19  * @since 11.1
20  */
22 {
23  /**
24  * Root of the tree
25  *
26  * @var object
27  * @since 11.1
28  */
29  protected $base;
30 
31  /**
32  * Tree of objects
33  *
34  * @var array
35  * @since 11.1
36  */
37  protected $parent = array(0);
38 
39  /**
40  * Used to control if an item has a child or not
41  *
42  * @var boolean
43  * @since 11.1
44  */
45  protected $pop_parent = 0;
46 
47  /**
48  * @var array A list of discovered update sites
49  */
50  protected $update_sites;
51 
52  /**
53  * A list of discovered updates
54  *
55  * @var array
56  */
57  protected $updates;
58 
59  /**
60  * Gets the reference to the current direct parent
61  *
62  * @return object
63  *
64  * @since 11.1
65  */
66  protected function _getStackLocation()
67  {
68  return implode('->', $this->stack);
69  }
70 
71  /**
72  * Get the parent tag
73  *
74  * @return string parent
75  *
76  * @since 11.1
77  */
78  protected function _getParent()
79  {
80  return end($this->parent);
81  }
82 
83  /**
84  * Opening an XML element
85  *
86  * @param object $parser Parser object
87  * @param string $name Name of element that is opened
88  * @param array $attrs Array of attributes for the element
89  *
90  * @return void
91  *
92  * @since 11.1
93  */
94  public function _startElement($parser, $name, $attrs = array())
95  {
96  array_push($this->stack, $name);
97  $tag = $this->_getStackLocation();
98 
99  // Reset the data
100  if (isset($this->$tag))
101  {
102  $this->$tag->_data = "";
103  }
104 
105  switch ($name)
106  {
107  case 'CATEGORY':
108  if (isset($attrs['REF']))
109  {
110  $this->update_sites[] = array('type' => 'collection', 'location' => $attrs['REF'], 'update_site_id' => $this->updateSiteId);
111  }
112  else
113  {
114  // This item will have children, so prepare to attach them
115  $this->pop_parent = 1;
116  }
117  break;
118  case 'EXTENSION':
119  $update = JTable::getInstance('update');
120  $update->set('update_site_id', $this->updateSiteId);
121  foreach ($this->updatecols as $col)
122  {
123  // Reset the values if it doesn't exist
124  if (!array_key_exists($col, $attrs))
125  {
126  $attrs[$col] = '';
127  if ($col == 'CLIENT')
128  {
129  $attrs[$col] = 'site';
130  }
131  }
132  }
133  $client = JApplicationHelper::getClientInfo($attrs['CLIENT'], 1);
134  if (isset($client->id))
135  {
136  $attrs['CLIENT_ID'] = $client->id;
137  }
138 
139  // Lower case all of the fields
140  foreach ($attrs as $key => $attr)
141  {
142  $values[strtolower($key)] = $attr;
143  }
144 
145  // Only add the update if it is on the same platform and release as we are
146  $ver = new JVersion;
147 
148  // Lower case and remove the exclamation mark
149  $product = strtolower(JFilterInput::getInstance()->clean($ver->PRODUCT, 'cmd'));
150 
151  /*
152  * Set defaults, the extension file should clarify in case but it may be only available in one version
153  * This allows an update site to specify a targetplatform
154  * targetplatformversion can be a regexp, so 1.[56] would be valid for an extension that supports 1.5 and 1.6
155  * Note: Whilst the version is a regexp here, the targetplatform is not (new extension per platform)
156  * Additionally, the version is a regexp here and it may also be in an extension file if the extension is
157  * compatible against multiple versions of the same platform (e.g. a library)
158  */
159  if (!isset($values['targetplatform']))
160  {
161  $values['targetplatform'] = $product;
162  }
163  // Set this to ourself as a default
164  if (!isset($values['targetplatformversion']))
165  {
166  $values['targetplatformversion'] = $ver->RELEASE;
167  }
168  // Set this to ourself as a default
169  // validate that we can install the extension
170  if ($product == $values['targetplatform'] && preg_match('/' . $values['targetplatformversion'] . '/', $ver->RELEASE))
171  {
172  $update->bind($values);
173  $this->updates[] = $update;
174  }
175  break;
176  }
177  }
178 
179  /**
180  * Closing an XML element
181  * Note: This is a protected function though has to be exposed externally as a callback
182  *
183  * @param object $parser Parser object
184  * @param string $name Name of the element closing
185  *
186  * @return void
187  *
188  * @since 11.1
189  */
190  protected function _endElement($parser, $name)
191  {
192  array_pop($this->stack);
193  switch ($name)
194  {
195  case 'CATEGORY':
196  if ($this->pop_parent)
197  {
198  $this->pop_parent = 0;
199  array_pop($this->parent);
200  }
201  break;
202  }
203  }
204 
205  // Note: we don't care about char data in collection because there should be none
206 
207  /**
208  * Finds an update
209  *
210  * @param array $options Options to use: update_site_id: the unique ID of the update site to look at
211  *
212  * @return array Update_sites and updates discovered
213  *
214  * @since 11.1
215  */
216  public function findUpdate($options)
217  {
218  $url = $options['location'];
219  $this->updateSiteId = $options['update_site_id'];
220  if (substr($url, -4) != '.xml')
221  {
222  if (substr($url, -1) != '/')
223  {
224  $url .= '/';
225  }
226  $url .= 'update.xml';
227  }
228 
229  $this->base = new stdClass;
230  $this->update_sites = array();
231  $this->updates = array();
232  $db = $this->parent->getDBO();
233 
234  $http = JHttpFactory::getHttp();
235  $response = $http->get($url);
236 
237  // JHttp transport throws an exception when there's no reponse.
238  try
239  {
240  $response = $http->get($url);
241  }
242  catch (Exception $e)
243  {
244  $response = null;
245  }
246 
247  if (!isset($response) || 200 != $response->code)
248  {
249  $query = $db->getQuery(true)
250  ->update('#__update_sites')
251  ->set('enabled = 0')
252  ->where('update_site_id = ' . $this->updateSiteId);
253  $db->setQuery($query);
254  $db->execute();
255 
256  JLog::add("Error parsing url: " . $url, JLog::WARNING, 'updater');
257  $app = JFactory::getApplication();
258  $app->enqueueMessage(JText::sprintf('JLIB_UPDATER_ERROR_COLLECTION_OPEN_URL', $url), 'warning');
259  return false;
260  }
261 
262  $this->xmlParser = xml_parser_create('');
263  xml_set_object($this->xmlParser, $this);
264  xml_set_element_handler($this->xmlParser, '_startElement', '_endElement');
265  if (!xml_parse($this->xmlParser, $response->body))
266  {
267  JLog::add("Error parsing url: " . $url, JLog::WARNING, 'updater');
268  $app = JFactory::getApplication();
269  $app->enqueueMessage(JText::sprintf('JLIB_UPDATER_ERROR_COLLECTION_PARSE_URL', $url), 'warning');
270  return false;
271  }
272  // TODO: Decrement the bad counter if non-zero
273  return array('update_sites' => $this->update_sites, 'updates' => $this->updates);
274  }
275 }