265 lines
6.3 KiB
PHP
265 lines
6.3 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* @package Joomla.Platform
|
||
|
* @subpackage Updater
|
||
|
*
|
||
|
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||
|
* @license GNU General Public License version 2 or later; see LICENSE
|
||
|
*/
|
||
|
|
||
|
defined('JPATH_PLATFORM') or die;
|
||
|
|
||
|
jimport('joomla.updater.updateadapter');
|
||
|
|
||
|
/**
|
||
|
* Collection Update Adapter Class
|
||
|
*
|
||
|
* @package Joomla.Platform
|
||
|
* @subpackage Updater
|
||
|
* @since 11.1
|
||
|
*/
|
||
|
class JUpdaterCollection extends JUpdateAdapter
|
||
|
{
|
||
|
/**
|
||
|
* Root of the tree
|
||
|
*
|
||
|
* @var object
|
||
|
* @since 11.1
|
||
|
*/
|
||
|
protected $base;
|
||
|
|
||
|
/**
|
||
|
* Tree of objects
|
||
|
*
|
||
|
* @var array
|
||
|
* @since 11.1
|
||
|
*/
|
||
|
protected $parent = array(0);
|
||
|
|
||
|
/**
|
||
|
* Used to control if an item has a child or not
|
||
|
*
|
||
|
* @var boolean
|
||
|
* @since 11.1
|
||
|
*/
|
||
|
protected $pop_parent = 0;
|
||
|
|
||
|
/**
|
||
|
* @var array A list of discovered update sites
|
||
|
*/
|
||
|
protected $update_sites;
|
||
|
|
||
|
/**
|
||
|
* A list of discovered updates
|
||
|
*
|
||
|
* @var array
|
||
|
*/
|
||
|
protected $updates;
|
||
|
|
||
|
/**
|
||
|
* Gets the reference to the current direct parent
|
||
|
*
|
||
|
* @return object
|
||
|
*
|
||
|
* @since 11.1
|
||
|
*/
|
||
|
protected function _getStackLocation()
|
||
|
{
|
||
|
return implode('->', $this->stack);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the parent tag
|
||
|
*
|
||
|
* @return string parent
|
||
|
*
|
||
|
* @since 11.1
|
||
|
*/
|
||
|
protected function _getParent()
|
||
|
{
|
||
|
return end($this->parent);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Opening an XML element
|
||
|
*
|
||
|
* @param object $parser Parser object
|
||
|
* @param string $name Name of element that is opened
|
||
|
* @param array $attrs Array of attributes for the element
|
||
|
*
|
||
|
* @return void
|
||
|
*
|
||
|
* @since 11.1
|
||
|
*/
|
||
|
public function _startElement($parser, $name, $attrs = array())
|
||
|
{
|
||
|
array_push($this->stack, $name);
|
||
|
$tag = $this->_getStackLocation();
|
||
|
|
||
|
// Reset the data
|
||
|
if (isset($this->$tag))
|
||
|
{
|
||
|
$this->$tag->_data = "";
|
||
|
}
|
||
|
|
||
|
switch ($name)
|
||
|
{
|
||
|
case 'CATEGORY':
|
||
|
if (isset($attrs['REF']))
|
||
|
{
|
||
|
$this->update_sites[] = array('type' => 'collection', 'location' => $attrs['REF'], 'update_site_id' => $this->updateSiteId);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// This item will have children, so prepare to attach them
|
||
|
$this->pop_parent = 1;
|
||
|
}
|
||
|
break;
|
||
|
case 'EXTENSION':
|
||
|
$update = JTable::getInstance('update');
|
||
|
$update->set('update_site_id', $this->updateSiteId);
|
||
|
foreach ($this->updatecols as $col)
|
||
|
{
|
||
|
// Reset the values if it doesn't exist
|
||
|
if (!array_key_exists($col, $attrs))
|
||
|
{
|
||
|
$attrs[$col] = '';
|
||
|
if ($col == 'CLIENT')
|
||
|
{
|
||
|
$attrs[$col] = 'site';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
$client = JApplicationHelper::getClientInfo($attrs['CLIENT'], 1);
|
||
|
if (isset($client->id))
|
||
|
{
|
||
|
$attrs['CLIENT_ID'] = $client->id;
|
||
|
}
|
||
|
|
||
|
// Lower case all of the fields
|
||
|
foreach ($attrs as $key => $attr)
|
||
|
{
|
||
|
$values[strtolower($key)] = $attr;
|
||
|
}
|
||
|
|
||
|
// Only add the update if it is on the same platform and release as we are
|
||
|
$ver = new JVersion;
|
||
|
|
||
|
// Lower case and remove the exclamation mark
|
||
|
$product = strtolower(JFilterInput::getInstance()->clean($ver->PRODUCT, 'cmd'));
|
||
|
|
||
|
/*
|
||
|
* Set defaults, the extension file should clarify in case but it may be only available in one version
|
||
|
* This allows an update site to specify a targetplatform
|
||
|
* targetplatformversion can be a regexp, so 1.[56] would be valid for an extension that supports 1.5 and 1.6
|
||
|
* Note: Whilst the version is a regexp here, the targetplatform is not (new extension per platform)
|
||
|
* Additionally, the version is a regexp here and it may also be in an extension file if the extension is
|
||
|
* compatible against multiple versions of the same platform (e.g. a library)
|
||
|
*/
|
||
|
if (!isset($values['targetplatform']))
|
||
|
{
|
||
|
$values['targetplatform'] = $product;
|
||
|
}
|
||
|
// Set this to ourself as a default
|
||
|
if (!isset($values['targetplatformversion']))
|
||
|
{
|
||
|
$values['targetplatformversion'] = $ver->RELEASE;
|
||
|
}
|
||
|
// Set this to ourself as a default
|
||
|
// validate that we can install the extension
|
||
|
if ($product == $values['targetplatform'] && preg_match('/' . $values['targetplatformversion'] . '/', $ver->RELEASE))
|
||
|
{
|
||
|
$update->bind($values);
|
||
|
$this->updates[] = $update;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Closing an XML element
|
||
|
* Note: This is a protected function though has to be exposed externally as a callback
|
||
|
*
|
||
|
* @param object $parser Parser object
|
||
|
* @param string $name Name of the element closing
|
||
|
*
|
||
|
* @return void
|
||
|
*
|
||
|
* @since 11.1
|
||
|
*/
|
||
|
protected function _endElement($parser, $name)
|
||
|
{
|
||
|
array_pop($this->stack);
|
||
|
switch ($name)
|
||
|
{
|
||
|
case 'CATEGORY':
|
||
|
if ($this->pop_parent)
|
||
|
{
|
||
|
$this->pop_parent = 0;
|
||
|
array_pop($this->parent);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Note: we don't care about char data in collection because there should be none
|
||
|
|
||
|
/**
|
||
|
* Finds an update
|
||
|
*
|
||
|
* @param array $options Options to use: update_site_id: the unique ID of the update site to look at
|
||
|
*
|
||
|
* @return array Update_sites and updates discovered
|
||
|
*
|
||
|
* @since 11.1
|
||
|
*/
|
||
|
public function findUpdate($options)
|
||
|
{
|
||
|
$url = $options['location'];
|
||
|
$this->updateSiteId = $options['update_site_id'];
|
||
|
if (substr($url, -4) != '.xml')
|
||
|
{
|
||
|
if (substr($url, -1) != '/')
|
||
|
{
|
||
|
$url .= '/';
|
||
|
}
|
||
|
$url .= 'update.xml';
|
||
|
}
|
||
|
|
||
|
$this->base = new stdClass;
|
||
|
$this->update_sites = array();
|
||
|
$this->updates = array();
|
||
|
$db = $this->parent->getDBO();
|
||
|
|
||
|
$http = JHttpFactory::getHttp();
|
||
|
$response = $http->get($url);
|
||
|
if (200 != $response->code)
|
||
|
{
|
||
|
$query = $db->getQuery(true)
|
||
|
->update('#__update_sites')
|
||
|
->set('enabled = 0')
|
||
|
->where('update_site_id = ' . $this->updateSiteId);
|
||
|
$db->setQuery($query);
|
||
|
$db->execute();
|
||
|
|
||
|
JLog::add("Error parsing url: " . $url, JLog::WARNING, 'updater');
|
||
|
$app = JFactory::getApplication();
|
||
|
$app->enqueueMessage(JText::sprintf('JLIB_UPDATER_ERROR_COLLECTION_OPEN_URL', $url), 'warning');
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$this->xmlParser = xml_parser_create('');
|
||
|
xml_set_object($this->xmlParser, $this);
|
||
|
xml_set_element_handler($this->xmlParser, '_startElement', '_endElement');
|
||
|
if (!xml_parse($this->xmlParser, $response->body))
|
||
|
{
|
||
|
JLog::add("Error parsing url: " . $url, JLog::WARNING, 'updater');
|
||
|
$app = JFactory::getApplication();
|
||
|
$app->enqueueMessage(JText::sprintf('JLIB_UPDATER_ERROR_COLLECTION_PARSE_URL', $url), 'warning');
|
||
|
return false;
|
||
|
}
|
||
|
// TODO: Decrement the bad counter if non-zero
|
||
|
return array('update_sites' => $this->update_sites, 'updates' => $this->updates);
|
||
|
}
|
||
|
}
|