/trunk/bibliotheque/pear/PEAR/PackageFile/v2/Validator.php |
---|
New file |
0,0 → 1,2058 |
<?php |
// |
// +----------------------------------------------------------------------+ |
// | PHP Version 5 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2004 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 3.0 of the PHP license, | |
// | that is bundled with this package in the file LICENSE, and is | |
// | available through the world-wide-web at the following url: | |
// | http://www.php.net/license/3_0.txt. | |
// | If you did not receive a copy of the PHP license and are unable to | |
// | obtain it through the world-wide-web, please send a note to | |
// | license@php.net so we can mail you a copy immediately. | |
// +----------------------------------------------------------------------+ |
// | Author: Greg Beaver <cellog@php.net> | |
// | | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Validator.php,v 1.97 2007/02/10 05:56:18 cellog Exp $ |
/** |
* Private validation class used by PEAR_PackageFile_v2 - do not use directly, its |
* sole purpose is to split up the PEAR/PackageFile/v2.php file to make it smaller |
* @author Greg Beaver <cellog@php.net> |
* @access private |
*/ |
class PEAR_PackageFile_v2_Validator |
{ |
/** |
* @var array |
*/ |
var $_packageInfo; |
/** |
* @var PEAR_PackageFile_v2 |
*/ |
var $_pf; |
/** |
* @var PEAR_ErrorStack |
*/ |
var $_stack; |
/** |
* @var int |
*/ |
var $_isValid = 0; |
/** |
* @var int |
*/ |
var $_filesValid = 0; |
/** |
* @var int |
*/ |
var $_curState = 0; |
/** |
* @param PEAR_PackageFile_v2 |
* @param int |
*/ |
function validate(&$pf, $state = PEAR_VALIDATE_NORMAL) |
{ |
$this->_pf = &$pf; |
$this->_curState = $state; |
$this->_packageInfo = $this->_pf->getArray(); |
$this->_isValid = $this->_pf->_isValid; |
$this->_filesValid = $this->_pf->_filesValid; |
$this->_stack = &$pf->_stack; |
$this->_stack->getErrors(true); |
if (($this->_isValid & $state) == $state) { |
return true; |
} |
if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) { |
return false; |
} |
if (!isset($this->_packageInfo['attribs']['version']) || |
($this->_packageInfo['attribs']['version'] != '2.0' && |
$this->_packageInfo['attribs']['version'] != '2.1')) { |
$this->_noPackageVersion(); |
} |
$structure = |
array( |
'name', |
'channel|uri', |
'*extends', // can't be multiple, but this works fine |
'summary', |
'description', |
'+lead', // these all need content checks |
'*developer', |
'*contributor', |
'*helper', |
'date', |
'*time', |
'version', |
'stability', |
'license->?uri->?filesource', |
'notes', |
'contents', //special validation needed |
'*compatible', |
'dependencies', //special validation needed |
'*usesrole', |
'*usestask', // reserve these for 1.4.0a1 to implement |
// this will allow a package.xml to gracefully say it |
// needs a certain package installed in order to implement a role or task |
'*providesextension', |
'*srcpackage|*srcuri', |
'+phprelease|+extsrcrelease|+extbinrelease|' . |
'+zendextsrcrelease|+zendextbinrelease|bundle', //special validation needed |
'*changelog', |
); |
$test = $this->_packageInfo; |
if (isset($test['dependencies']) && |
isset($test['dependencies']['required']) && |
isset($test['dependencies']['required']['pearinstaller']) && |
isset($test['dependencies']['required']['pearinstaller']['min']) && |
version_compare('1.5.1', |
$test['dependencies']['required']['pearinstaller']['min'], '<')) { |
$this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']); |
return false; |
} |
// ignore post-installation array fields |
if (array_key_exists('filelist', $test)) { |
unset($test['filelist']); |
} |
if (array_key_exists('_lastmodified', $test)) { |
unset($test['_lastmodified']); |
} |
if (array_key_exists('#binarypackage', $test)) { |
unset($test['#binarypackage']); |
} |
if (array_key_exists('old', $test)) { |
unset($test['old']); |
} |
if (array_key_exists('_lastversion', $test)) { |
unset($test['_lastversion']); |
} |
if (!$this->_stupidSchemaValidate($structure, |
$test, '<package>')) { |
return false; |
} |
if (empty($this->_packageInfo['name'])) { |
$this->_tagCannotBeEmpty('name'); |
} |
if (isset($this->_packageInfo['uri'])) { |
$test = 'uri'; |
} else { |
$test = 'channel'; |
} |
if (empty($this->_packageInfo[$test])) { |
$this->_tagCannotBeEmpty($test); |
} |
if (is_array($this->_packageInfo['license']) && |
(!isset($this->_packageInfo['license']['_content']) || |
empty($this->_packageInfo['license']['_content']))) { |
$this->_tagCannotBeEmpty('license'); |
} elseif (empty($this->_packageInfo['license'])) { |
$this->_tagCannotBeEmpty('license'); |
} |
if (empty($this->_packageInfo['summary'])) { |
$this->_tagCannotBeEmpty('summary'); |
} |
if (empty($this->_packageInfo['description'])) { |
$this->_tagCannotBeEmpty('description'); |
} |
if (empty($this->_packageInfo['date'])) { |
$this->_tagCannotBeEmpty('date'); |
} |
if (empty($this->_packageInfo['notes'])) { |
$this->_tagCannotBeEmpty('notes'); |
} |
if (isset($this->_packageInfo['time']) && empty($this->_packageInfo['time'])) { |
$this->_tagCannotBeEmpty('time'); |
} |
if (isset($this->_packageInfo['dependencies'])) { |
$this->_validateDependencies(); |
} |
if (isset($this->_packageInfo['compatible'])) { |
$this->_validateCompatible(); |
} |
if (!isset($this->_packageInfo['bundle'])) { |
if (empty($this->_packageInfo['contents'])) { |
$this->_tagCannotBeEmpty('contents'); |
} |
if (!isset($this->_packageInfo['contents']['dir'])) { |
$this->_filelistMustContainDir('contents'); |
return false; |
} |
if (isset($this->_packageInfo['contents']['file'])) { |
$this->_filelistCannotContainFile('contents'); |
return false; |
} |
} |
$this->_validateMaintainers(); |
$this->_validateStabilityVersion(); |
$fail = false; |
if (array_key_exists('usesrole', $this->_packageInfo)) { |
$roles = $this->_packageInfo['usesrole']; |
if (!is_array($roles) || !isset($roles[0])) { |
$roles = array($roles); |
} |
foreach ($roles as $role) { |
if (!isset($role['role'])) { |
$this->_usesroletaskMustHaveRoleTask('usesrole', 'role'); |
$fail = true; |
} else { |
if (!isset($role['channel'])) { |
if (!isset($role['uri'])) { |
$this->_usesroletaskMustHaveChannelOrUri($role['role'], 'usesrole'); |
$fail = true; |
} |
} elseif (!isset($role['package'])) { |
$this->_usesroletaskMustHavePackage($role['role'], 'usesrole'); |
$fail = true; |
} |
} |
} |
} |
if (array_key_exists('usestask', $this->_packageInfo)) { |
$roles = $this->_packageInfo['usestask']; |
if (!is_array($roles) || !isset($roles[0])) { |
$roles = array($roles); |
} |
foreach ($roles as $role) { |
if (!isset($role['task'])) { |
$this->_usesroletaskMustHaveRoleTask('usestask', 'task'); |
$fail = true; |
} else { |
if (!isset($role['channel'])) { |
if (!isset($role['uri'])) { |
$this->_usesroletaskMustHaveChannelOrUri($role['task'], 'usestask'); |
$fail = true; |
} |
} elseif (!isset($role['package'])) { |
$this->_usesroletaskMustHavePackage($role['task'], 'usestask'); |
$fail = true; |
} |
} |
} |
} |
if ($fail) { |
return false; |
} |
$list = $this->_packageInfo['contents']; |
if (isset($list['dir']) && is_array($list['dir']) && isset($list['dir'][0])) { |
$this->_multipleToplevelDirNotAllowed(); |
return $this->_isValid = 0; |
} |
$this->_validateFilelist(); |
$this->_validateRelease(); |
if (!$this->_stack->hasErrors()) { |
$chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true); |
if (PEAR::isError($chan)) { |
$this->_unknownChannel($this->_pf->getChannel()); |
} else { |
$valpack = $chan->getValidationPackage(); |
// for channel validator packages, always use the default PEAR validator. |
// otherwise, they can't be installed or packaged |
$validator = $chan->getValidationObject($this->_pf->getPackage()); |
if (!$validator) { |
$this->_stack->push(__FUNCTION__, 'error', |
array_merge( |
array('channel' => $chan->getName(), |
'package' => $this->_pf->getPackage()), |
$valpack |
), |
'package "%channel%/%package%" cannot be properly validated without ' . |
'validation package "%channel%/%name%-%version%"'); |
return $this->_isValid = 0; |
} |
$validator->setPackageFile($this->_pf); |
$validator->validate($state); |
$failures = $validator->getFailures(); |
foreach ($failures['errors'] as $error) { |
$this->_stack->push(__FUNCTION__, 'error', $error, |
'Channel validator error: field "%field%" - %reason%'); |
} |
foreach ($failures['warnings'] as $warning) { |
$this->_stack->push(__FUNCTION__, 'warning', $warning, |
'Channel validator warning: field "%field%" - %reason%'); |
} |
} |
} |
$this->_pf->_isValid = $this->_isValid = !$this->_stack->hasErrors('error'); |
if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$this->_filesValid) { |
if ($this->_pf->getPackageType() == 'bundle') { |
if ($this->_analyzeBundledPackages()) { |
$this->_filesValid = $this->_pf->_filesValid = true; |
} else { |
$this->_pf->_isValid = $this->_isValid = 0; |
} |
} else { |
if (!$this->_analyzePhpFiles()) { |
$this->_pf->_isValid = $this->_isValid = 0; |
} else { |
$this->_filesValid = $this->_pf->_filesValid = true; |
} |
} |
} |
if ($this->_isValid) { |
return $this->_pf->_isValid = $this->_isValid = $state; |
} |
return $this->_pf->_isValid = $this->_isValid = 0; |
} |
function _stupidSchemaValidate($structure, $xml, $root) |
{ |
if (!is_array($xml)) { |
$xml = array(); |
} |
$keys = array_keys($xml); |
reset($keys); |
$key = current($keys); |
while ($key == 'attribs' || $key == '_contents') { |
$key = next($keys); |
} |
$unfoundtags = $optionaltags = array(); |
$ret = true; |
$mismatch = false; |
foreach ($structure as $struc) { |
if ($key) { |
$tag = $xml[$key]; |
} |
$test = $this->_processStructure($struc); |
if (isset($test['choices'])) { |
$loose = true; |
foreach ($test['choices'] as $choice) { |
if ($key == $choice['tag']) { |
$key = next($keys); |
while ($key == 'attribs' || $key == '_contents') { |
$key = next($keys); |
} |
$unfoundtags = $optionaltags = array(); |
$mismatch = false; |
if ($key && $key != $choice['tag'] && isset($choice['multiple'])) { |
$unfoundtags[] = $choice['tag']; |
$optionaltags[] = $choice['tag']; |
if ($key) { |
$mismatch = true; |
} |
} |
$ret &= $this->_processAttribs($choice, $tag, $root); |
continue 2; |
} else { |
$unfoundtags[] = $choice['tag']; |
$mismatch = true; |
} |
if (!isset($choice['multiple']) || $choice['multiple'] != '*') { |
$loose = false; |
} else { |
$optionaltags[] = $choice['tag']; |
} |
} |
if (!$loose) { |
$this->_invalidTagOrder($unfoundtags, $key, $root); |
return false; |
} |
} else { |
if ($key != $test['tag']) { |
if (isset($test['multiple']) && $test['multiple'] != '*') { |
$unfoundtags[] = $test['tag']; |
$this->_invalidTagOrder($unfoundtags, $key, $root); |
return false; |
} else { |
if ($key) { |
$mismatch = true; |
} |
$unfoundtags[] = $test['tag']; |
$optionaltags[] = $test['tag']; |
} |
if (!isset($test['multiple'])) { |
$this->_invalidTagOrder($unfoundtags, $key, $root); |
return false; |
} |
continue; |
} else { |
$unfoundtags = $optionaltags = array(); |
$mismatch = false; |
} |
$key = next($keys); |
while ($key == 'attribs' || $key == '_contents') { |
$key = next($keys); |
} |
if ($key && $key != $test['tag'] && isset($test['multiple'])) { |
$unfoundtags[] = $test['tag']; |
$optionaltags[] = $test['tag']; |
$mismatch = true; |
} |
$ret &= $this->_processAttribs($test, $tag, $root); |
continue; |
} |
} |
if (!$mismatch && count($optionaltags)) { |
// don't error out on any optional tags |
$unfoundtags = array_diff($unfoundtags, $optionaltags); |
} |
if (count($unfoundtags)) { |
$this->_invalidTagOrder($unfoundtags, $key, $root); |
} elseif ($key) { |
// unknown tags |
$this->_invalidTagOrder('*no tags allowed here*', $key, $root); |
while ($key = next($keys)) { |
$this->_invalidTagOrder('*no tags allowed here*', $key, $root); |
} |
} |
return $ret; |
} |
function _processAttribs($choice, $tag, $context) |
{ |
if (isset($choice['attribs'])) { |
if (!is_array($tag)) { |
$tag = array($tag); |
} |
$tags = $tag; |
if (!isset($tags[0])) { |
$tags = array($tags); |
} |
$ret = true; |
foreach ($tags as $i => $tag) { |
if (!is_array($tag) || !isset($tag['attribs'])) { |
foreach ($choice['attribs'] as $attrib) { |
if ($attrib{0} != '?') { |
$ret &= $this->_tagHasNoAttribs($choice['tag'], |
$context); |
continue 2; |
} |
} |
} |
foreach ($choice['attribs'] as $attrib) { |
if ($attrib{0} != '?') { |
if (!isset($tag['attribs'][$attrib])) { |
$ret &= $this->_tagMissingAttribute($choice['tag'], |
$attrib, $context); |
} |
} |
} |
} |
return $ret; |
} |
return true; |
} |
function _processStructure($key) |
{ |
$ret = array(); |
if (count($pieces = explode('|', $key)) > 1) { |
$ret['choices'] = array(); |
foreach ($pieces as $piece) { |
$ret['choices'][] = $this->_processStructure($piece); |
} |
return $ret; |
} |
$multi = $key{0}; |
if ($multi == '+' || $multi == '*') { |
$ret['multiple'] = $key{0}; |
$key = substr($key, 1); |
} |
if (count($attrs = explode('->', $key)) > 1) { |
$ret['tag'] = array_shift($attrs); |
$ret['attribs'] = $attrs; |
} else { |
$ret['tag'] = $key; |
} |
return $ret; |
} |
function _validateStabilityVersion() |
{ |
$structure = array('release', 'api'); |
$a = $this->_stupidSchemaValidate($structure, $this->_packageInfo['version'], '<version>'); |
$a &= $this->_stupidSchemaValidate($structure, $this->_packageInfo['stability'], '<stability>'); |
if ($a) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$this->_packageInfo['version']['release'])) { |
$this->_invalidVersion('release', $this->_packageInfo['version']['release']); |
} |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$this->_packageInfo['version']['api'])) { |
$this->_invalidVersion('api', $this->_packageInfo['version']['api']); |
} |
if (!in_array($this->_packageInfo['stability']['release'], |
array('snapshot', 'devel', 'alpha', 'beta', 'stable'))) { |
$this->_invalidState('release', $this->_packageinfo['stability']['release']); |
} |
if (!in_array($this->_packageInfo['stability']['api'], |
array('devel', 'alpha', 'beta', 'stable'))) { |
$this->_invalidState('api', $this->_packageinfo['stability']['api']); |
} |
} |
} |
function _validateMaintainers() |
{ |
$structure = |
array( |
'name', |
'user', |
'email', |
'active', |
); |
foreach (array('lead', 'developer', 'contributor', 'helper') as $type) { |
if (!isset($this->_packageInfo[$type])) { |
continue; |
} |
if (isset($this->_packageInfo[$type][0])) { |
foreach ($this->_packageInfo[$type] as $lead) { |
$this->_stupidSchemaValidate($structure, $lead, '<' . $type . '>'); |
} |
} else { |
$this->_stupidSchemaValidate($structure, $this->_packageInfo[$type], |
'<' . $type . '>'); |
} |
} |
} |
function _validatePhpDep($dep, $installcondition = false) |
{ |
$structure = array( |
'min', |
'*max', |
'*exclude', |
); |
$type = $installcondition ? '<installcondition><php>' : '<dependencies><required><php>'; |
$this->_stupidSchemaValidate($structure, $dep, $type); |
if (isset($dep['min'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?$/', |
$dep['min'])) { |
$this->_invalidVersion($type . '<min>', $dep['min']); |
} |
} |
if (isset($dep['max'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?$/', |
$dep['max'])) { |
$this->_invalidVersion($type . '<max>', $dep['max']); |
} |
} |
if (isset($dep['exclude'])) { |
if (!is_array($dep['exclude'])) { |
$dep['exclude'] = array($dep['exclude']); |
} |
foreach ($dep['exclude'] as $exclude) { |
if (!preg_match( |
'/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?$/', |
$exclude)) { |
$this->_invalidVersion($type . '<exclude>', $exclude); |
} |
} |
} |
} |
function _validatePearinstallerDep($dep) |
{ |
$structure = array( |
'min', |
'*max', |
'*recommended', |
'*exclude', |
); |
$this->_stupidSchemaValidate($structure, $dep, '<dependencies><required><pearinstaller>'); |
if (isset($dep['min'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$dep['min'])) { |
$this->_invalidVersion('<dependencies><required><pearinstaller><min>', |
$dep['min']); |
} |
} |
if (isset($dep['max'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$dep['max'])) { |
$this->_invalidVersion('<dependencies><required><pearinstaller><max>', |
$dep['max']); |
} |
} |
if (isset($dep['recommended'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$dep['recommended'])) { |
$this->_invalidVersion('<dependencies><required><pearinstaller><recommended>', |
$dep['recommended']); |
} |
} |
if (isset($dep['exclude'])) { |
if (!is_array($dep['exclude'])) { |
$dep['exclude'] = array($dep['exclude']); |
} |
foreach ($dep['exclude'] as $exclude) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$exclude)) { |
$this->_invalidVersion('<dependencies><required><pearinstaller><exclude>', |
$exclude); |
} |
} |
} |
} |
function _validatePackageDep($dep, $group, $type = '<package>') |
{ |
if (isset($dep['uri'])) { |
if (isset($dep['conflicts'])) { |
$structure = array( |
'name', |
'uri', |
'conflicts', |
'*providesextension', |
); |
} else { |
$structure = array( |
'name', |
'uri', |
'*providesextension', |
); |
} |
} else { |
if (isset($dep['conflicts'])) { |
$structure = array( |
'name', |
'channel', |
'*min', |
'*max', |
'*exclude', |
'conflicts', |
'*providesextension', |
); |
} else { |
$structure = array( |
'name', |
'channel', |
'*min', |
'*max', |
'*recommended', |
'*exclude', |
'*nodefault', |
'*providesextension', |
); |
} |
} |
if (isset($dep['name'])) { |
$type .= '<name>' . $dep['name'] . '</name>'; |
} |
$this->_stupidSchemaValidate($structure, $dep, '<dependencies>' . $group . $type); |
if (isset($dep['uri']) && (isset($dep['min']) || isset($dep['max']) || |
isset($dep['recommended']) || isset($dep['exclude']))) { |
$this->_uriDepsCannotHaveVersioning('<dependencies>' . $group . $type); |
} |
if (isset($dep['channel']) && strtolower($dep['channel']) == '__uri') { |
$this->_DepchannelCannotBeUri('<dependencies>' . $group . $type); |
} |
if (isset($dep['min'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$dep['min'])) { |
$this->_invalidVersion('<dependencies>' . $group . $type . '<min>', $dep['min']); |
} |
} |
if (isset($dep['max'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$dep['max'])) { |
$this->_invalidVersion('<dependencies>' . $group . $type . '<max>', $dep['max']); |
} |
} |
if (isset($dep['recommended'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$dep['recommended'])) { |
$this->_invalidVersion('<dependencies>' . $group . $type . '<recommended>', |
$dep['recommended']); |
} |
} |
if (isset($dep['exclude'])) { |
if (!is_array($dep['exclude'])) { |
$dep['exclude'] = array($dep['exclude']); |
} |
foreach ($dep['exclude'] as $exclude) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$exclude)) { |
$this->_invalidVersion('<dependencies>' . $group . $type . '<exclude>', |
$exclude); |
} |
} |
} |
} |
function _validateSubpackageDep($dep, $group) |
{ |
$this->_validatePackageDep($dep, $group, '<subpackage>'); |
if (isset($dep['providesextension'])) { |
$this->_subpackageCannotProvideExtension(isset($dep['name']) ? $dep['name'] : ''); |
} |
if (isset($dep['conflicts'])) { |
$this->_subpackagesCannotConflict(isset($dep['name']) ? $dep['name'] : ''); |
} |
} |
function _validateExtensionDep($dep, $group = false, $installcondition = false) |
{ |
if (isset($dep['conflicts'])) { |
$structure = array( |
'name', |
'*min', |
'*max', |
'*exclude', |
'conflicts', |
); |
} else { |
$structure = array( |
'name', |
'*min', |
'*max', |
'*recommended', |
'*exclude', |
); |
} |
if ($installcondition) { |
$type = '<installcondition><extension>'; |
} else { |
$type = '<dependencies>' . $group . '<extension>'; |
} |
if (isset($dep['name'])) { |
$type .= '<name>' . $dep['name'] . '</name>'; |
} |
$this->_stupidSchemaValidate($structure, $dep, $type); |
if (isset($dep['min'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$dep['min'])) { |
$this->_invalidVersion(substr($type, 1) . '<min', $dep['min']); |
} |
} |
if (isset($dep['max'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$dep['max'])) { |
$this->_invalidVersion(substr($type, 1) . '<max', $dep['max']); |
} |
} |
if (isset($dep['recommended'])) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$dep['recommended'])) { |
$this->_invalidVersion(substr($type, 1) . '<recommended', $dep['recommended']); |
} |
} |
if (isset($dep['exclude'])) { |
if (!is_array($dep['exclude'])) { |
$dep['exclude'] = array($dep['exclude']); |
} |
foreach ($dep['exclude'] as $exclude) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$exclude)) { |
$this->_invalidVersion(substr($type, 1) . '<exclude', $exclude); |
} |
} |
} |
} |
function _validateOsDep($dep, $installcondition = false) |
{ |
$structure = array( |
'name', |
'*conflicts', |
); |
$type = $installcondition ? '<installcondition><os>' : '<dependencies><required><os>'; |
if ($this->_stupidSchemaValidate($structure, $dep, $type)) { |
if ($dep['name'] == '*') { |
if (array_key_exists('conflicts', $dep)) { |
$this->_cannotConflictWithAllOs($type); |
} |
} |
} |
} |
function _validateArchDep($dep, $installcondition = false) |
{ |
$structure = array( |
'pattern', |
'*conflicts', |
); |
$type = $installcondition ? '<installcondition><arch>' : '<dependencies><required><arch>'; |
$this->_stupidSchemaValidate($structure, $dep, $type); |
} |
function _validateInstallConditions($cond, $release) |
{ |
$structure = array( |
'*php', |
'*extension', |
'*os', |
'*arch', |
); |
if (!$this->_stupidSchemaValidate($structure, |
$cond, $release)) { |
return false; |
} |
foreach (array('php', 'extension', 'os', 'arch') as $type) { |
if (isset($cond[$type])) { |
$iter = $cond[$type]; |
if (!is_array($iter) || !isset($iter[0])) { |
$iter = array($iter); |
} |
foreach ($iter as $package) { |
if ($type == 'extension') { |
$this->{"_validate{$type}Dep"}($package, false, true); |
} else { |
$this->{"_validate{$type}Dep"}($package, true); |
} |
} |
} |
} |
} |
function _validateDependencies() |
{ |
$structure = array( |
'required', |
'*optional', |
'*group->name->hint' |
); |
if (!$this->_stupidSchemaValidate($structure, |
$this->_packageInfo['dependencies'], '<dependencies>')) { |
return false; |
} |
foreach (array('required', 'optional') as $simpledep) { |
if (isset($this->_packageInfo['dependencies'][$simpledep])) { |
if ($simpledep == 'optional') { |
$structure = array( |
'*package', |
'*subpackage', |
'*extension', |
); |
} else { |
$structure = array( |
'php', |
'pearinstaller', |
'*package', |
'*subpackage', |
'*extension', |
'*os', |
'*arch', |
); |
} |
if ($this->_stupidSchemaValidate($structure, |
$this->_packageInfo['dependencies'][$simpledep], |
"<dependencies><$simpledep>")) { |
foreach (array('package', 'subpackage', 'extension') as $type) { |
if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) { |
$iter = $this->_packageInfo['dependencies'][$simpledep][$type]; |
if (!isset($iter[0])) { |
$iter = array($iter); |
} |
foreach ($iter as $package) { |
if ($type != 'extension') { |
if (isset($package['uri'])) { |
if (isset($package['channel'])) { |
$this->_UrlOrChannel($type, |
$package['name']); |
} |
} else { |
if (!isset($package['channel'])) { |
$this->_NoChannel($type, $package['name']); |
} |
} |
} |
$this->{"_validate{$type}Dep"}($package, "<$simpledep>"); |
} |
} |
} |
if ($simpledep == 'optional') { |
continue; |
} |
foreach (array('php', 'pearinstaller', 'os', 'arch') as $type) { |
if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) { |
$iter = $this->_packageInfo['dependencies'][$simpledep][$type]; |
if (!isset($iter[0])) { |
$iter = array($iter); |
} |
foreach ($iter as $package) { |
$this->{"_validate{$type}Dep"}($package); |
} |
} |
} |
} |
} |
} |
if (isset($this->_packageInfo['dependencies']['group'])) { |
$groups = $this->_packageInfo['dependencies']['group']; |
if (!isset($groups[0])) { |
$groups = array($groups); |
} |
$structure = array( |
'*package', |
'*subpackage', |
'*extension', |
); |
foreach ($groups as $group) { |
if ($this->_stupidSchemaValidate($structure, $group, '<group>')) { |
if (!PEAR_Validate::validGroupName($group['attribs']['name'])) { |
$this->_invalidDepGroupName($group['attribs']['name']); |
} |
foreach (array('package', 'subpackage', 'extension') as $type) { |
if (isset($group[$type])) { |
$iter = $group[$type]; |
if (!isset($iter[0])) { |
$iter = array($iter); |
} |
foreach ($iter as $package) { |
if ($type != 'extension') { |
if (isset($package['uri'])) { |
if (isset($package['channel'])) { |
$this->_UrlOrChannelGroup($type, |
$package['name'], |
$group['name']); |
} |
} else { |
if (!isset($package['channel'])) { |
$this->_NoChannelGroup($type, |
$package['name'], |
$group['name']); |
} |
} |
} |
$this->{"_validate{$type}Dep"}($package, '<group name="' . |
$group['attribs']['name'] . '">'); |
} |
} |
} |
} |
} |
} |
} |
function _validateCompatible() |
{ |
$compat = $this->_packageInfo['compatible']; |
if (!isset($compat[0])) { |
$compat = array($compat); |
} |
$required = array('name', 'channel', 'min', 'max', '*exclude'); |
foreach ($compat as $package) { |
$type = '<compatible>'; |
if (is_array($package) && array_key_exists('name', $package)) { |
$type .= '<name>' . $package['name'] . '</name>'; |
} |
$this->_stupidSchemaValidate($required, $package, $type); |
if (is_array($package) && array_key_exists('min', $package)) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$package['min'])) { |
$this->_invalidVersion(substr($type, 1) . '<min', $package['min']); |
} |
} |
if (is_array($package) && array_key_exists('max', $package)) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$package['max'])) { |
$this->_invalidVersion(substr($type, 1) . '<max', $package['max']); |
} |
} |
if (is_array($package) && array_key_exists('exclude', $package)) { |
if (!is_array($package['exclude'])) { |
$package['exclude'] = array($package['exclude']); |
} |
foreach ($package['exclude'] as $exclude) { |
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/', |
$exclude)) { |
$this->_invalidVersion(substr($type, 1) . '<exclude', $exclude); |
} |
} |
} |
} |
} |
function _validateBundle($list) |
{ |
if (!is_array($list) || !isset($list['bundledpackage'])) { |
return $this->_NoBundledPackages(); |
} |
if (!is_array($list['bundledpackage']) || !isset($list['bundledpackage'][0])) { |
return $this->_AtLeast2BundledPackages(); |
} |
foreach ($list['bundledpackage'] as $package) { |
if (!is_string($package)) { |
$this->_bundledPackagesMustBeFilename(); |
} |
} |
} |
function _validateFilelist($list = false, $allowignore = false, $dirs = '') |
{ |
$iscontents = false; |
if (!$list) { |
$iscontents = true; |
$list = $this->_packageInfo['contents']; |
if (isset($this->_packageInfo['bundle'])) { |
return $this->_validateBundle($list); |
} |
} |
if ($allowignore) { |
$struc = array( |
'*install->name->as', |
'*ignore->name' |
); |
} else { |
$struc = array( |
'*dir->name->?baseinstalldir', |
'*file->name->role->?baseinstalldir->?md5sum' |
); |
if (isset($list['dir']) && isset($list['file'])) { |
// stave off validation errors without requiring a set order. |
$_old = $list; |
if (isset($list['attribs'])) { |
$list = array('attribs' => $_old['attribs']); |
} |
$list['dir'] = $_old['dir']; |
$list['file'] = $_old['file']; |
} |
} |
if (!isset($list['attribs']) || !isset($list['attribs']['name'])) { |
$unknown = $allowignore ? '<filelist>' : '<dir name="*unknown*">'; |
$dirname = $iscontents ? '<contents>' : $unknown; |
} else { |
$dirname = '<dir name="' . $list['attribs']['name'] . '">'; |
} |
$res = $this->_stupidSchemaValidate($struc, $list, $dirname); |
if ($allowignore && $res) { |
$ignored_or_installed = array(); |
$this->_pf->getFilelist(); |
$fcontents = $this->_pf->getContents(); |
$filelist = array(); |
if (!isset($fcontents['dir']['file'][0])) { |
$fcontents['dir']['file'] = array($fcontents['dir']['file']); |
} |
foreach ($fcontents['dir']['file'] as $file) { |
$filelist[$file['attribs']['name']] = true; |
} |
if (isset($list['install'])) { |
if (!isset($list['install'][0])) { |
$list['install'] = array($list['install']); |
} |
foreach ($list['install'] as $file) { |
if (!isset($filelist[$file['attribs']['name']])) { |
$this->_notInContents($file['attribs']['name'], 'install'); |
continue; |
} |
if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) { |
$this->_multipleInstallAs($file['attribs']['name']); |
} |
if (!isset($ignored_or_installed[$file['attribs']['name']])) { |
$ignored_or_installed[$file['attribs']['name']] = array(); |
} |
$ignored_or_installed[$file['attribs']['name']][] = 1; |
} |
} |
if (isset($list['ignore'])) { |
if (!isset($list['ignore'][0])) { |
$list['ignore'] = array($list['ignore']); |
} |
foreach ($list['ignore'] as $file) { |
if (!isset($filelist[$file['attribs']['name']])) { |
$this->_notInContents($file['attribs']['name'], 'ignore'); |
continue; |
} |
if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) { |
$this->_ignoreAndInstallAs($file['attribs']['name']); |
} |
} |
} |
} |
if (!$allowignore && isset($list['file'])) { |
if (!isset($list['file'][0])) { |
// single file |
$list['file'] = array($list['file']); |
} |
foreach ($list['file'] as $i => $file) |
{ |
if (isset($file['attribs']) && isset($file['attribs']['name']) && |
$file['attribs']['name']{0} == '.' && |
$file['attribs']['name']{1} == '/') { |
// name is something like "./doc/whatever.txt" |
$this->_invalidFileName($file['attribs']['name']); |
} |
if (isset($file['attribs']) && isset($file['attribs']['role'])) { |
if (!$this->_validateRole($file['attribs']['role'])) { |
if (isset($this->_packageInfo['usesrole'])) { |
$roles = $this->_packageInfo['usesrole']; |
if (!isset($roles[0])) { |
$roles = array($roles); |
} |
foreach ($roles as $role) { |
if ($role['role'] = $file['attribs']['role']) { |
$msg = 'This package contains role "%role%" and requires ' . |
'package "%package%" to be used'; |
if (isset($role['uri'])) { |
$params = array('role' => $role['role'], |
'package' => $role['uri']); |
} else { |
$params = array('role' => $role['role'], |
'package' => $this->_pf->_registry-> |
parsedPackageNameToString(array('package' => |
$role['package'], 'channel' => $role['channel']), |
true)); |
} |
$this->_stack->push('_mustInstallRole', 'error', $params, $msg); |
} |
} |
} |
$this->_invalidFileRole($file['attribs']['name'], |
$dirname, $file['attribs']['role']); |
} |
} |
if (!isset($file['attribs'])) { |
continue; |
} |
$save = $file['attribs']; |
if ($dirs) { |
$save['name'] = $dirs . '/' . $save['name']; |
} |
unset($file['attribs']); |
if (count($file) && $this->_curState != PEAR_VALIDATE_DOWNLOADING) { // has tasks |
foreach ($file as $task => $value) { |
if ($tagClass = $this->_pf->getTask($task)) { |
if (!is_array($value) || !isset($value[0])) { |
$value = array($value); |
} |
foreach ($value as $v) { |
$ret = call_user_func(array($tagClass, 'validateXml'), |
$this->_pf, $v, $this->_pf->_config, $save); |
if (is_array($ret)) { |
$this->_invalidTask($task, $ret, isset($save['name']) ? |
$save['name'] : ''); |
} |
} |
} else { |
if (isset($this->_packageInfo['usestask'])) { |
$roles = $this->_packageInfo['usestask']; |
if (!isset($roles[0])) { |
$roles = array($roles); |
} |
foreach ($roles as $role) { |
if ($role['task'] = $task) { |
$msg = 'This package contains task "%task%" and requires ' . |
'package "%package%" to be used'; |
if (isset($role['uri'])) { |
$params = array('task' => $role['task'], |
'package' => $role['uri']); |
} else { |
$params = array('task' => $role['task'], |
'package' => $this->_pf->_registry-> |
parsedPackageNameToString(array('package' => |
$role['package'], 'channel' => $role['channel']), |
true)); |
} |
$this->_stack->push('_mustInstallTask', 'error', |
$params, $msg); |
} |
} |
} |
$this->_unknownTask($task, $save['name']); |
} |
} |
} |
} |
} |
if (isset($list['ignore'])) { |
if (!$allowignore) { |
$this->_ignoreNotAllowed('ignore'); |
} |
} |
if (isset($list['install'])) { |
if (!$allowignore) { |
$this->_ignoreNotAllowed('install'); |
} |
} |
if (isset($list['file'])) { |
if ($allowignore) { |
$this->_fileNotAllowed('file'); |
} |
} |
if (isset($list['dir'])) { |
if ($allowignore) { |
$this->_fileNotAllowed('dir'); |
} else { |
if (!isset($list['dir'][0])) { |
$list['dir'] = array($list['dir']); |
} |
foreach ($list['dir'] as $dir) { |
if (isset($dir['attribs']) && isset($dir['attribs']['name'])) { |
if ($dir['attribs']['name'] == '/' || |
!isset($this->_packageInfo['contents']['dir']['dir'])) { |
// always use nothing if the filelist has already been flattened |
$newdirs = ''; |
} elseif ($dirs == '') { |
$newdirs = $dir['attribs']['name']; |
} else { |
$newdirs = $dirs . '/' . $dir['attribs']['name']; |
} |
} else { |
$newdirs = $dirs; |
} |
$this->_validateFilelist($dir, $allowignore, $newdirs); |
} |
} |
} |
} |
function _validateRelease() |
{ |
if (isset($this->_packageInfo['phprelease'])) { |
$release = 'phprelease'; |
if (isset($this->_packageInfo['providesextension'])) { |
$this->_cannotProvideExtension($release); |
} |
if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) { |
$this->_cannotHaveSrcpackage($release); |
} |
$releases = $this->_packageInfo['phprelease']; |
if (!is_array($releases)) { |
return true; |
} |
if (!isset($releases[0])) { |
$releases = array($releases); |
} |
foreach ($releases as $rel) { |
$this->_stupidSchemaValidate(array( |
'*installconditions', |
'*filelist', |
), $rel, '<phprelease>'); |
} |
} |
foreach (array('', 'zend') as $prefix) { |
$releasetype = $prefix . 'extsrcrelease'; |
if (isset($this->_packageInfo[$releasetype])) { |
$release = $releasetype; |
if (!isset($this->_packageInfo['providesextension'])) { |
$this->_mustProvideExtension($release); |
} |
if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) { |
$this->_cannotHaveSrcpackage($release); |
} |
$releases = $this->_packageInfo[$releasetype]; |
if (!is_array($releases)) { |
return true; |
} |
if (!isset($releases[0])) { |
$releases = array($releases); |
} |
foreach ($releases as $rel) { |
$this->_stupidSchemaValidate(array( |
'*installconditions', |
'*configureoption->name->prompt->?default', |
'*binarypackage', |
'*filelist', |
), $rel, '<' . $releasetype . '>'); |
if (isset($rel['binarypackage'])) { |
if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) { |
$rel['binarypackage'] = array($rel['binarypackage']); |
} |
foreach ($rel['binarypackage'] as $bin) { |
if (!is_string($bin)) { |
$this->_binaryPackageMustBePackagename(); |
} |
} |
} |
} |
} |
$releasetype = 'extbinrelease'; |
if (isset($this->_packageInfo[$releasetype])) { |
$release = $releasetype; |
if (!isset($this->_packageInfo['providesextension'])) { |
$this->_mustProvideExtension($release); |
} |
if (isset($this->_packageInfo['channel']) && |
!isset($this->_packageInfo['srcpackage'])) { |
$this->_mustSrcPackage($release); |
} |
if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) { |
$this->_mustSrcuri($release); |
} |
$releases = $this->_packageInfo[$releasetype]; |
if (!is_array($releases)) { |
return true; |
} |
if (!isset($releases[0])) { |
$releases = array($releases); |
} |
foreach ($releases as $rel) { |
$this->_stupidSchemaValidate(array( |
'*installconditions', |
'*filelist', |
), $rel, '<' . $releasetype . '>'); |
} |
} |
} |
if (isset($this->_packageInfo['bundle'])) { |
$release = 'bundle'; |
if (isset($this->_packageInfo['providesextension'])) { |
$this->_cannotProvideExtension($release); |
} |
if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) { |
$this->_cannotHaveSrcpackage($release); |
} |
$releases = $this->_packageInfo['bundle']; |
if (!is_array($releases) || !isset($releases[0])) { |
$releases = array($releases); |
} |
foreach ($releases as $rel) { |
$this->_stupidSchemaValidate(array( |
'*installconditions', |
'*filelist', |
), $rel, '<bundle>'); |
} |
} |
foreach ($releases as $rel) { |
if (is_array($rel) && array_key_exists('installconditions', $rel)) { |
$this->_validateInstallConditions($rel['installconditions'], |
"<$release><installconditions>"); |
} |
if (is_array($rel) && array_key_exists('filelist', $rel)) { |
if ($rel['filelist']) { |
$this->_validateFilelist($rel['filelist'], true); |
} |
} |
} |
} |
/** |
* This is here to allow role extension through plugins |
* @param string |
*/ |
function _validateRole($role) |
{ |
return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())); |
} |
function _pearVersionTooLow($version) |
{ |
$this->_stack->push(__FUNCTION__, 'error', |
array('version' => $version), |
'This package.xml requires PEAR version %version% to parse properly, we are ' . |
'version 1.5.1'); |
} |
function _invalidTagOrder($oktags, $actual, $root) |
{ |
$this->_stack->push(__FUNCTION__, 'error', |
array('oktags' => $oktags, 'actual' => $actual, 'root' => $root), |
'Invalid tag order in %root%, found <%actual%> expected one of "%oktags%"'); |
} |
function _ignoreNotAllowed($type) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type), |
'<%type%> is not allowed inside global <contents>, only inside ' . |
'<phprelease>/<extbinrelease>/<zendextbinrelease>, use <dir> and <file> only'); |
} |
function _fileNotAllowed($type) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type), |
'<%type%> is not allowed inside release <filelist>, only inside ' . |
'<contents>, use <ignore> and <install> only'); |
} |
function _tagMissingAttribute($tag, $attr, $context) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, |
'attribute' => $attr, 'context' => $context), |
'tag <%tag%> in context "%context%" has no attribute "%attribute%"'); |
} |
function _tagHasNoAttribs($tag, $context) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, |
'context' => $context), |
'tag <%tag%> has no attributes in context "%context%"'); |
} |
function _invalidInternalStructure() |
{ |
$this->_stack->push(__FUNCTION__, 'exception', array(), |
'internal array was not generated by compatible parser, or extreme parser error, cannot continue'); |
} |
function _invalidFileRole($file, $dir, $role) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array( |
'file' => $file, 'dir' => $dir, 'role' => $role, |
'roles' => PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())), |
'File "%file%" in directory "%dir%" has invalid role "%role%", should be one of %roles%'); |
} |
function _invalidFileName($file, $dir) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array( |
'file' => $file), |
'File "%file%" cannot begin with "."'); |
} |
function _filelistCannotContainFile($filelist) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist), |
'<%tag%> can only contain <dir>, contains <file>. Use ' . |
'<dir name="/"> as the first dir element'); |
} |
function _filelistMustContainDir($filelist) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist), |
'<%tag%> must contain <dir>. Use <dir name="/"> as the ' . |
'first dir element'); |
} |
function _tagCannotBeEmpty($tag) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag), |
'<%tag%> cannot be empty (<%tag%/>)'); |
} |
function _UrlOrChannel($type, $name) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type, |
'name' => $name), |
'Required dependency <%type%> "%name%" can have either url OR ' . |
'channel attributes, and not both'); |
} |
function _NoChannel($type, $name) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type, |
'name' => $name), |
'Required dependency <%type%> "%name%" must have either url OR ' . |
'channel attributes'); |
} |
function _UrlOrChannelGroup($type, $name, $group) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type, |
'name' => $name, 'group' => $group), |
'Group "%group%" dependency <%type%> "%name%" can have either url OR ' . |
'channel attributes, and not both'); |
} |
function _NoChannelGroup($type, $name, $group) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type, |
'name' => $name, 'group' => $group), |
'Group "%group%" dependency <%type%> "%name%" must have either url OR ' . |
'channel attributes'); |
} |
function _unknownChannel($channel) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('channel' => $channel), |
'Unknown channel "%channel%"'); |
} |
function _noPackageVersion() |
{ |
$this->_stack->push(__FUNCTION__, 'error', array(), |
'package.xml <package> tag has no version attribute, or version is not 2.0'); |
} |
function _NoBundledPackages() |
{ |
$this->_stack->push(__FUNCTION__, 'error', array(), |
'No <bundledpackage> tag was found in <contents>, required for bundle packages'); |
} |
function _AtLeast2BundledPackages() |
{ |
$this->_stack->push(__FUNCTION__, 'error', array(), |
'At least 2 packages must be bundled in a bundle package'); |
} |
function _ChannelOrUri($name) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('name' => $name), |
'Bundled package "%name%" can have either a uri or a channel, not both'); |
} |
function _noChildTag($child, $tag) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('child' => $child, 'tag' => $tag), |
'Tag <%tag%> is missing child tag <%child%>'); |
} |
function _invalidVersion($type, $value) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value), |
'Version type <%type%> is not a valid version (%value%)'); |
} |
function _invalidState($type, $value) |
{ |
$states = array('stable', 'beta', 'alpha', 'devel'); |
if ($type != 'api') { |
$states[] = 'snapshot'; |
} |
if (strtolower($value) == 'rc') { |
$this->_stack->push(__FUNCTION__, 'error', |
array('version' => $this->_packageInfo['version']['release']), |
'RC is not a state, it is a version postfix, try %version%RC1, stability beta'); |
} |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value, |
'types' => $states), |
'Stability type <%type%> is not a valid stability (%value%), must be one of ' . |
'%types%'); |
} |
function _invalidTask($task, $ret, $file) |
{ |
switch ($ret[0]) { |
case PEAR_TASK_ERROR_MISSING_ATTRIB : |
$info = array('attrib' => $ret[1], 'task' => $task, 'file' => $file); |
$msg = 'task <%task%> is missing attribute "%attrib%" in file %file%'; |
break; |
case PEAR_TASK_ERROR_NOATTRIBS : |
$info = array('task' => $task, 'file' => $file); |
$msg = 'task <%task%> has no attributes in file %file%'; |
break; |
case PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE : |
$info = array('attrib' => $ret[1], 'values' => $ret[3], |
'was' => $ret[2], 'task' => $task, 'file' => $file); |
$msg = 'task <%task%> attribute "%attrib%" has the wrong value "%was%" '. |
'in file %file%, expecting one of "%values%"'; |
break; |
case PEAR_TASK_ERROR_INVALID : |
$info = array('reason' => $ret[1], 'task' => $task, 'file' => $file); |
$msg = 'task <%task%> in file %file% is invalid because of "%reason%"'; |
break; |
} |
$this->_stack->push(__FUNCTION__, 'error', $info, $msg); |
} |
function _unknownTask($task, $file) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('task' => $task, 'file' => $file), |
'Unknown task "%task%" passed in file <file name="%file%">'); |
} |
function _subpackageCannotProvideExtension($name) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('name' => $name), |
'Subpackage dependency "%name%" cannot use <providesextension>, ' . |
'only package dependencies can use this tag'); |
} |
function _subpackagesCannotConflict($name) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('name' => $name), |
'Subpackage dependency "%name%" cannot use <conflicts/>, ' . |
'only package dependencies can use this tag'); |
} |
function _cannotProvideExtension($release) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release), |
'<%release%> packages cannot use <providesextension>, only extbinrelease, extsrcrelease, zendextsrcrelease, and zendextbinrelease can provide a PHP extension'); |
} |
function _mustProvideExtension($release) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release), |
'<%release%> packages must use <providesextension> to indicate which PHP extension is provided'); |
} |
function _cannotHaveSrcpackage($release) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release), |
'<%release%> packages cannot specify a source code package, only extension binaries may use the <srcpackage> tag'); |
} |
function _mustSrcPackage($release) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release), |
'<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcpackage>'); |
} |
function _mustSrcuri($release) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release), |
'<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcuri>'); |
} |
function _uriDepsCannotHaveVersioning($type) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type), |
'%type%: dependencies with a <uri> tag cannot have any versioning information'); |
} |
function _conflictingDepsCannotHaveVersioning($type) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type), |
'%type%: conflicting dependencies cannot have versioning info, use <exclude> to ' . |
'exclude specific versions of a dependency'); |
} |
function _DepchannelCannotBeUri($type) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type), |
'%type%: channel cannot be __uri, this is a pseudo-channel reserved for uri ' . |
'dependencies only'); |
} |
function _bundledPackagesMustBeFilename() |
{ |
$this->_stack->push(__FUNCTION__, 'error', array(), |
'<bundledpackage> tags must contain only the filename of a package release ' . |
'in the bundle'); |
} |
function _binaryPackageMustBePackagename() |
{ |
$this->_stack->push(__FUNCTION__, 'error', array(), |
'<binarypackage> tags must contain the name of a package that is ' . |
'a compiled version of this extsrc/zendextsrc package'); |
} |
function _fileNotFound($file) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file), |
'File "%file%" in package.xml does not exist'); |
} |
function _notInContents($file, $tag) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file, 'tag' => $tag), |
'<%tag% name="%file%"> is invalid, file is not in <contents>'); |
} |
function _cannotValidateNoPathSet() |
{ |
$this->_stack->push(__FUNCTION__, 'error', array(), |
'Cannot validate files, no path to package file is set (use setPackageFile())'); |
} |
function _usesroletaskMustHaveChannelOrUri($role, $tag) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag), |
'<%tag%> must contain either <uri>, or <channel> and <package>'); |
} |
function _usesroletaskMustHavePackage($role, $tag) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag), |
'<%tag%> must contain <package>'); |
} |
function _usesroletaskMustHaveRoleTask($tag, $type) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'type' => $type), |
'<%tag%> must contain <%type%> defining the %type% to be used'); |
} |
function _cannotConflictWithAllOs($type) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag), |
'%tag% cannot conflict with all OSes'); |
} |
function _invalidDepGroupName($name) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('group' => $name), |
'Invalid dependency group name "%name%"'); |
} |
function _multipleToplevelDirNotAllowed() |
{ |
$this->_stack->push(__FUNCTION__, 'error', array(), |
'Multiple top-level <dir> tags are not allowed. Enclose them ' . |
'in a <dir name="/">'); |
} |
function _multipleInstallAs($file) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file), |
'Only one <install> tag is allowed for file "%file%"'); |
} |
function _ignoreAndInstallAs($file) |
{ |
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file), |
'Cannot have both <ignore> and <install> tags for file "%file%"'); |
} |
function _analyzeBundledPackages() |
{ |
if (!$this->_isValid) { |
return false; |
} |
if (!$this->_pf->getPackageType() == 'bundle') { |
return false; |
} |
if (!isset($this->_pf->_packageFile)) { |
return false; |
} |
$dir_prefix = dirname($this->_pf->_packageFile); |
$log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') : |
array('PEAR_Common', 'log'); |
$info = $this->_pf->getContents(); |
$info = $info['bundledpackage']; |
if (!is_array($info)) { |
$info = array($info); |
} |
$pkg = &new PEAR_PackageFile($this->_pf->_config); |
foreach ($info as $package) { |
if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $package)) { |
$this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $package); |
$this->_isValid = 0; |
continue; |
} |
call_user_func_array($log, array(1, "Analyzing bundled package $package")); |
PEAR::pushErrorHandling(PEAR_ERROR_RETURN); |
$ret = $pkg->fromAnyFile($dir_prefix . DIRECTORY_SEPARATOR . $package, |
PEAR_VALIDATE_NORMAL); |
PEAR::popErrorHandling(); |
if (PEAR::isError($ret)) { |
call_user_func_array($log, array(0, "ERROR: package $package is not a valid " . |
'package')); |
$inf = $ret->getUserInfo(); |
if (is_array($inf)) { |
foreach ($inf as $err) { |
call_user_func_array($log, array(1, $err['message'])); |
} |
} |
return false; |
} |
} |
return true; |
} |
function _analyzePhpFiles() |
{ |
if (!$this->_isValid) { |
return false; |
} |
if (!isset($this->_pf->_packageFile)) { |
$this->_cannotValidateNoPathSet(); |
return false; |
} |
$dir_prefix = dirname($this->_pf->_packageFile); |
$common = new PEAR_Common; |
$log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') : |
array(&$common, 'log'); |
$info = $this->_pf->getContents(); |
if (!$info || !isset($info['dir']['file'])) { |
$this->_tagCannotBeEmpty('contents><dir'); |
return false; |
} |
$info = $info['dir']['file']; |
if (isset($info['attribs'])) { |
$info = array($info); |
} |
$provides = array(); |
foreach ($info as $fa) { |
$fa = $fa['attribs']; |
$file = $fa['name']; |
if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) { |
$this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $file); |
$this->_isValid = 0; |
continue; |
} |
if (in_array($fa['role'], PEAR_Installer_Role::getPhpRoles()) && $dir_prefix) { |
call_user_func_array($log, array(1, "Analyzing $file")); |
$srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file); |
if ($srcinfo) { |
$provides = array_merge($provides, $this->_buildProvidesArray($srcinfo)); |
} |
} |
} |
$this->_packageName = $pn = $this->_pf->getPackage(); |
$pnl = strlen($pn); |
foreach ($provides as $key => $what) { |
if (isset($what['explicit']) || !$what) { |
// skip conformance checks if the provides entry is |
// specified in the package.xml file |
continue; |
} |
extract($what); |
if ($type == 'class') { |
if (!strncasecmp($name, $pn, $pnl)) { |
continue; |
} |
$this->_stack->push(__FUNCTION__, 'warning', |
array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn), |
'in %file%: %type% "%name%" not prefixed with package name "%package%"'); |
} elseif ($type == 'function') { |
if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) { |
continue; |
} |
$this->_stack->push(__FUNCTION__, 'warning', |
array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn), |
'in %file%: %type% "%name%" not prefixed with package name "%package%"'); |
} |
} |
return $this->_isValid; |
} |
/** |
* Analyze the source code of the given PHP file |
* |
* @param string Filename of the PHP file |
* @param boolean whether to analyze $file as the file contents |
* @return mixed |
*/ |
function analyzeSourceCode($file, $string = false) |
{ |
if (!function_exists("token_get_all")) { |
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file), |
'Parser error: token_get_all() function must exist to analyze source code, PHP may have been compiled with --disable-tokenizer'); |
return false; |
} |
if (!defined('T_DOC_COMMENT')) { |
define('T_DOC_COMMENT', T_COMMENT); |
} |
if (!defined('T_INTERFACE')) { |
define('T_INTERFACE', -1); |
} |
if (!defined('T_IMPLEMENTS')) { |
define('T_IMPLEMENTS', -1); |
} |
if ($string) { |
$contents = $file; |
} else { |
if (!$fp = @fopen($file, "r")) { |
return false; |
} |
fclose($fp); |
$contents = file_get_contents($file); |
} |
$tokens = token_get_all($contents); |
/* |
for ($i = 0; $i < sizeof($tokens); $i++) { |
@list($token, $data) = $tokens[$i]; |
if (is_string($token)) { |
var_dump($token); |
} else { |
print token_name($token) . ' '; |
var_dump(rtrim($data)); |
} |
} |
*/ |
$look_for = 0; |
$paren_level = 0; |
$bracket_level = 0; |
$brace_level = 0; |
$lastphpdoc = ''; |
$current_class = ''; |
$current_interface = ''; |
$current_class_level = -1; |
$current_function = ''; |
$current_function_level = -1; |
$declared_classes = array(); |
$declared_interfaces = array(); |
$declared_functions = array(); |
$declared_methods = array(); |
$used_classes = array(); |
$used_functions = array(); |
$extends = array(); |
$implements = array(); |
$nodeps = array(); |
$inquote = false; |
$interface = false; |
for ($i = 0; $i < sizeof($tokens); $i++) { |
if (is_array($tokens[$i])) { |
list($token, $data) = $tokens[$i]; |
} else { |
$token = $tokens[$i]; |
$data = ''; |
} |
if ($inquote) { |
if ($token != '"' && $token != T_END_HEREDOC) { |
continue; |
} else { |
$inquote = false; |
continue; |
} |
} |
switch ($token) { |
case T_WHITESPACE : |
continue; |
case ';': |
if ($interface) { |
$current_function = ''; |
$current_function_level = -1; |
} |
break; |
case '"': |
case T_START_HEREDOC: |
$inquote = true; |
break; |
case T_CURLY_OPEN: |
case T_DOLLAR_OPEN_CURLY_BRACES: |
case '{': $brace_level++; continue 2; |
case '}': |
$brace_level--; |
if ($current_class_level == $brace_level) { |
$current_class = ''; |
$current_class_level = -1; |
} |
if ($current_function_level == $brace_level) { |
$current_function = ''; |
$current_function_level = -1; |
} |
continue 2; |
case '[': $bracket_level++; continue 2; |
case ']': $bracket_level--; continue 2; |
case '(': $paren_level++; continue 2; |
case ')': $paren_level--; continue 2; |
case T_INTERFACE: |
$interface = true; |
case T_CLASS: |
if (($current_class_level != -1) || ($current_function_level != -1)) { |
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file), |
'Parser error: invalid PHP found in file "%file%"'); |
return false; |
} |
case T_FUNCTION: |
case T_NEW: |
case T_EXTENDS: |
case T_IMPLEMENTS: |
$look_for = $token; |
continue 2; |
case T_STRING: |
if (version_compare(zend_version(), '2.0', '<')) { |
if (in_array(strtolower($data), |
array('public', 'private', 'protected', 'abstract', |
'interface', 'implements', 'throw') |
)) { |
$this->_stack->push(__FUNCTION__, 'warning', array( |
'file' => $file), |
'Error, PHP5 token encountered in %file%,' . |
' analysis should be in PHP5'); |
} |
} |
if ($look_for == T_CLASS) { |
$current_class = $data; |
$current_class_level = $brace_level; |
$declared_classes[] = $current_class; |
} elseif ($look_for == T_INTERFACE) { |
$current_interface = $data; |
$current_class_level = $brace_level; |
$declared_interfaces[] = $current_interface; |
} elseif ($look_for == T_IMPLEMENTS) { |
$implements[$current_class] = $data; |
} elseif ($look_for == T_EXTENDS) { |
$extends[$current_class] = $data; |
} elseif ($look_for == T_FUNCTION) { |
if ($current_class) { |
$current_function = "$current_class::$data"; |
$declared_methods[$current_class][] = $data; |
} elseif ($current_interface) { |
$current_function = "$current_interface::$data"; |
$declared_methods[$current_interface][] = $data; |
} else { |
$current_function = $data; |
$declared_functions[] = $current_function; |
} |
$current_function_level = $brace_level; |
$m = array(); |
} elseif ($look_for == T_NEW) { |
$used_classes[$data] = true; |
} |
$look_for = 0; |
continue 2; |
case T_VARIABLE: |
$look_for = 0; |
continue 2; |
case T_DOC_COMMENT: |
case T_COMMENT: |
if (preg_match('!^/\*\*\s!', $data)) { |
$lastphpdoc = $data; |
if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) { |
$nodeps = array_merge($nodeps, $m[1]); |
} |
} |
continue 2; |
case T_DOUBLE_COLON: |
if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) { |
$this->_stack->push(__FUNCTION__, 'warning', array('file' => $file), |
'Parser error: invalid PHP found in file "%file%"'); |
return false; |
} |
$class = $tokens[$i - 1][1]; |
if (strtolower($class) != 'parent') { |
$used_classes[$class] = true; |
} |
continue 2; |
} |
} |
return array( |
"source_file" => $file, |
"declared_classes" => $declared_classes, |
"declared_interfaces" => $declared_interfaces, |
"declared_methods" => $declared_methods, |
"declared_functions" => $declared_functions, |
"used_classes" => array_diff(array_keys($used_classes), $nodeps), |
"inheritance" => $extends, |
"implements" => $implements, |
); |
} |
/** |
* Build a "provides" array from data returned by |
* analyzeSourceCode(). The format of the built array is like |
* this: |
* |
* array( |
* 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'), |
* ... |
* ) |
* |
* |
* @param array $srcinfo array with information about a source file |
* as returned by the analyzeSourceCode() method. |
* |
* @return void |
* |
* @access private |
* |
*/ |
function _buildProvidesArray($srcinfo) |
{ |
if (!$this->_isValid) { |
return array(); |
} |
$providesret = array(); |
$file = basename($srcinfo['source_file']); |
$pn = $this->_pf->getPackage(); |
$pnl = strlen($pn); |
foreach ($srcinfo['declared_classes'] as $class) { |
$key = "class;$class"; |
if (isset($providesret[$key])) { |
continue; |
} |
$providesret[$key] = |
array('file'=> $file, 'type' => 'class', 'name' => $class); |
if (isset($srcinfo['inheritance'][$class])) { |
$providesret[$key]['extends'] = |
$srcinfo['inheritance'][$class]; |
} |
} |
foreach ($srcinfo['declared_methods'] as $class => $methods) { |
foreach ($methods as $method) { |
$function = "$class::$method"; |
$key = "function;$function"; |
if ($method{0} == '_' || !strcasecmp($method, $class) || |
isset($providesret[$key])) { |
continue; |
} |
$providesret[$key] = |
array('file'=> $file, 'type' => 'function', 'name' => $function); |
} |
} |
foreach ($srcinfo['declared_functions'] as $function) { |
$key = "function;$function"; |
if ($function{0} == '_' || isset($providesret[$key])) { |
continue; |
} |
if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) { |
$warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\""; |
} |
$providesret[$key] = |
array('file'=> $file, 'type' => 'function', 'name' => $function); |
} |
return $providesret; |
} |
} |
?> |
/trunk/bibliotheque/pear/PEAR/PackageFile/v2/rw.php |
---|
New file |
0,0 → 1,1601 |
<?php |
/** |
* PEAR_PackageFile_v2, package.xml version 2.0, read/write version |
* |
* PHP versions 4 and 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2006 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version CVS: $Id: rw.php,v 1.19 2006/10/30 04:12:02 cellog Exp $ |
* @link http://pear.php.net/package/PEAR |
* @since File available since Release 1.4.0a8 |
*/ |
/** |
* For base class |
*/ |
require_once 'PEAR/PackageFile/v2.php'; |
/** |
* @category pear |
* @package PEAR |
* @author Greg Beaver <cellog@php.net> |
* @copyright 1997-2006 The PHP Group |
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
* @version Release: 1.5.1 |
* @link http://pear.php.net/package/PEAR |
* @since Class available since Release 1.4.0a8 |
*/ |
class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2 |
{ |
/** |
* @param string Extension name |
* @return bool success of operation |
*/ |
function setProvidesExtension($extension) |
{ |
if (in_array($this->getPackageType(), |
array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) { |
if (!isset($this->_packageInfo['providesextension'])) { |
// ensure that the channel tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', |
'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'bundle', 'changelog'), |
$extension, 'providesextension'); |
} |
$this->_packageInfo['providesextension'] = $extension; |
return true; |
} |
return false; |
} |
function setPackage($package) |
{ |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['attribs'])) { |
$this->_packageInfo = array_merge(array('attribs' => array( |
'version' => '2.0', |
'xmlns' => 'http://pear.php.net/dtd/package-2.0', |
'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', |
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', |
'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0 |
http://pear.php.net/dtd/tasks-1.0.xsd |
http://pear.php.net/dtd/package-2.0 |
http://pear.php.net/dtd/package-2.0.xsd', |
)), $this->_packageInfo); |
} |
if (!isset($this->_packageInfo['name'])) { |
return $this->_packageInfo = array_merge(array('name' => $package), |
$this->_packageInfo); |
} |
$this->_packageInfo['name'] = $package; |
} |
/** |
* set this as a package.xml version 2.1 |
* @access private |
*/ |
function _setPackageVersion2_1() |
{ |
$info = array( |
'version' => '2.1', |
'xmlns' => 'http://pear.php.net/dtd/package-2.1', |
'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', |
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', |
'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0 |
http://pear.php.net/dtd/tasks-1.0.xsd |
http://pear.php.net/dtd/package-2.1 |
http://pear.php.net/dtd/package-2.1.xsd', |
); |
if (!isset($this->_packageInfo['attribs'])) { |
$this->_packageInfo = array_merge(array('attribs' => $info), $this->_packageInfo); |
} else { |
$this->_packageInfo['attribs'] = $info; |
} |
} |
function setUri($uri) |
{ |
unset($this->_packageInfo['channel']); |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['uri'])) { |
// ensure that the uri tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('extends', 'summary', 'description', 'lead', |
'developer', 'contributor', 'helper', 'date', 'time', 'version', |
'stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), $uri, 'uri'); |
} |
$this->_packageInfo['uri'] = $uri; |
} |
function setChannel($channel) |
{ |
unset($this->_packageInfo['uri']); |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['channel'])) { |
// ensure that the channel tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('extends', 'summary', 'description', 'lead', |
'developer', 'contributor', 'helper', 'date', 'time', 'version', |
'stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), $channel, 'channel'); |
} |
$this->_packageInfo['channel'] = $channel; |
} |
function setExtends($extends) |
{ |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['extends'])) { |
// ensure that the extends tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('summary', 'description', 'lead', |
'developer', 'contributor', 'helper', 'date', 'time', 'version', |
'stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), $extends, 'extends'); |
} |
$this->_packageInfo['extends'] = $extends; |
} |
function setSummary($summary) |
{ |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['summary'])) { |
// ensure that the summary tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('description', 'lead', |
'developer', 'contributor', 'helper', 'date', 'time', 'version', |
'stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), $summary, 'summary'); |
} |
$this->_packageInfo['summary'] = $summary; |
} |
function setDescription($desc) |
{ |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['description'])) { |
// ensure that the description tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('lead', |
'developer', 'contributor', 'helper', 'date', 'time', 'version', |
'stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), $desc, 'description'); |
} |
$this->_packageInfo['description'] = $desc; |
} |
/** |
* Adds a new maintainer - no checking of duplicates is performed, use |
* updatemaintainer for that purpose. |
*/ |
function addMaintainer($role, $handle, $name, $email, $active = 'yes') |
{ |
if (!in_array($role, array('lead', 'developer', 'contributor', 'helper'))) { |
return false; |
} |
if (isset($this->_packageInfo[$role])) { |
if (!isset($this->_packageInfo[$role][0])) { |
$this->_packageInfo[$role] = array($this->_packageInfo[$role]); |
} |
$this->_packageInfo[$role][] = |
array( |
'name' => $name, |
'user' => $handle, |
'email' => $email, |
'active' => $active, |
); |
} else { |
$testarr = array('lead', |
'developer', 'contributor', 'helper', 'date', 'time', 'version', |
'stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', |
'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'); |
foreach (array('lead', 'developer', 'contributor', 'helper') as $testrole) { |
array_shift($testarr); |
if ($role == $testrole) { |
break; |
} |
} |
if (!isset($this->_packageInfo[$role])) { |
// ensure that the extends tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, $testarr, |
array(), $role); |
} |
$this->_packageInfo[$role] = |
array( |
'name' => $name, |
'user' => $handle, |
'email' => $email, |
'active' => $active, |
); |
} |
$this->_isValid = 0; |
} |
function updateMaintainer($newrole, $handle, $name, $email, $active = 'yes') |
{ |
$found = false; |
foreach (array('lead', 'developer', 'contributor', 'helper') as $role) { |
if (!isset($this->_packageInfo[$role])) { |
continue; |
} |
$info = $this->_packageInfo[$role]; |
if (!isset($info[0])) { |
if ($info['user'] == $handle) { |
$found = true; |
break; |
} |
} |
foreach ($info as $i => $maintainer) { |
if ($maintainer['user'] == $handle) { |
$found = $i; |
break 2; |
} |
} |
} |
if ($found === false) { |
return $this->addMaintainer($newrole, $handle, $name, $email, $active); |
} |
if ($found !== false) { |
if ($found === true) { |
unset($this->_packageInfo[$role]); |
} else { |
unset($this->_packageInfo[$role][$found]); |
$this->_packageInfo[$role] = array_values($this->_packageInfo[$role]); |
} |
} |
$this->addMaintainer($newrole, $handle, $name, $email, $active); |
$this->_isValid = 0; |
} |
function deleteMaintainer($handle) |
{ |
$found = false; |
foreach (array('lead', 'developer', 'contributor', 'helper') as $role) { |
if (!isset($this->_packageInfo[$role])) { |
continue; |
} |
if (!isset($this->_packageInfo[$role][0])) { |
$this->_packageInfo[$role] = array($this->_packageInfo[$role]); |
} |
foreach ($this->_packageInfo[$role] as $i => $maintainer) { |
if ($maintainer['user'] == $handle) { |
$found = $i; |
break; |
} |
} |
if ($found !== false) { |
unset($this->_packageInfo[$role][$found]); |
if (!count($this->_packageInfo[$role]) && $role == 'lead') { |
$this->_isValid = 0; |
} |
if (!count($this->_packageInfo[$role])) { |
unset($this->_packageInfo[$role]); |
return true; |
} |
$this->_packageInfo[$role] = |
array_values($this->_packageInfo[$role]); |
if (count($this->_packageInfo[$role]) == 1) { |
$this->_packageInfo[$role] = $this->_packageInfo[$role][0]; |
} |
return true; |
} |
if (count($this->_packageInfo[$role]) == 1) { |
$this->_packageInfo[$role] = $this->_packageInfo[$role][0]; |
} |
} |
return false; |
} |
function setReleaseVersion($version) |
{ |
if (isset($this->_packageInfo['version']) && |
isset($this->_packageInfo['version']['release'])) { |
unset($this->_packageInfo['version']['release']); |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array( |
'version' => array('stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), |
'release' => array('api'))); |
$this->_isValid = 0; |
} |
function setAPIVersion($version) |
{ |
if (isset($this->_packageInfo['version']) && |
isset($this->_packageInfo['version']['api'])) { |
unset($this->_packageInfo['version']['api']); |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array( |
'version' => array('stability', 'license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), |
'api' => array())); |
$this->_isValid = 0; |
} |
/** |
* snapshot|devel|alpha|beta|stable |
*/ |
function setReleaseStability($state) |
{ |
if (isset($this->_packageInfo['stability']) && |
isset($this->_packageInfo['stability']['release'])) { |
unset($this->_packageInfo['stability']['release']); |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array( |
'stability' => array('license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), |
'release' => array('api'))); |
$this->_isValid = 0; |
} |
/** |
* @param devel|alpha|beta|stable |
*/ |
function setAPIStability($state) |
{ |
if (isset($this->_packageInfo['stability']) && |
isset($this->_packageInfo['stability']['api'])) { |
unset($this->_packageInfo['stability']['api']); |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array( |
'stability' => array('license', 'notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), |
'api' => array())); |
$this->_isValid = 0; |
} |
function setLicense($license, $uri = false, $filesource = false) |
{ |
if (!isset($this->_packageInfo['license'])) { |
// ensure that the license tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('notes', 'contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), 0, 'license'); |
} |
if ($uri || $filesource) { |
$attribs = array(); |
if ($uri) { |
$attribs['uri'] = $uri; |
} |
$uri = true; // for test below |
if ($filesource) { |
$attribs['filesource'] = $filesource; |
} |
} |
$license = $uri ? array('attribs' => $attribs, '_content' => $license) : $license; |
$this->_packageInfo['license'] = $license; |
$this->_isValid = 0; |
} |
function setNotes($notes) |
{ |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['notes'])) { |
// ensure that the notes tag is set up in the right location |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('contents', 'compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'extbinrelease', 'bundle', 'changelog'), $notes, 'notes'); |
} |
$this->_packageInfo['notes'] = $notes; |
} |
/** |
* This is only used at install-time, after all serialization |
* is over. |
* @param string file name |
* @param string installed path |
*/ |
function setInstalledAs($file, $path) |
{ |
if ($path) { |
return $this->_packageInfo['filelist'][$file]['installed_as'] = $path; |
} |
unset($this->_packageInfo['filelist'][$file]['installed_as']); |
} |
/** |
* This is only used at install-time, after all serialization |
* is over. |
*/ |
function installedFile($file, $atts) |
{ |
if (isset($this->_packageInfo['filelist'][$file])) { |
$this->_packageInfo['filelist'][$file] = |
array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']); |
} else { |
$this->_packageInfo['filelist'][$file] = $atts['attribs']; |
} |
} |
/** |
* Reset the listing of package contents |
* @param string base installation dir for the whole package, if any |
*/ |
function clearContents($baseinstall = false) |
{ |
$this->_filesValid = false; |
$this->_isValid = 0; |
if (!isset($this->_packageInfo['contents'])) { |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('compatible', |
'dependencies', 'providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', |
'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'bundle', 'changelog'), array(), 'contents'); |
} |
if ($this->getPackageType() != 'bundle') { |
$this->_packageInfo['contents'] = |
array('dir' => array('attribs' => array('name' => '/'))); |
if ($baseinstall) { |
$this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'] = $baseinstall; |
} |
} |
} |
/** |
* @param string relative path of the bundled package. |
*/ |
function addBundledPackage($path) |
{ |
if ($this->getPackageType() != 'bundle') { |
return false; |
} |
$this->_filesValid = false; |
$this->_isValid = 0; |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $path, array( |
'contents' => array('compatible', 'dependencies', 'providesextension', |
'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', |
'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'bundle', 'changelog'), |
'bundledpackage' => array())); |
} |
/** |
* @param string file name |
* @param PEAR_Task_Common a read/write task |
*/ |
function addTaskToFile($filename, $task) |
{ |
if (!method_exists($task, 'getXml')) { |
return false; |
} |
if (!method_exists($task, 'getName')) { |
return false; |
} |
if (!method_exists($task, 'validate')) { |
return false; |
} |
if (!$task->validate()) { |
return false; |
} |
if (!isset($this->_packageInfo['contents']['dir']['file'])) { |
return false; |
} |
$this->getTasksNs(); // discover the tasks namespace if not done already |
$files = $this->_packageInfo['contents']['dir']['file']; |
if (!isset($files[0])) { |
$files = array($files); |
$ind = false; |
} else { |
$ind = true; |
} |
foreach ($files as $i => $file) { |
if (isset($file['attribs'])) { |
if ($file['attribs']['name'] == $filename) { |
if ($ind) { |
$t = isset($this->_packageInfo['contents']['dir']['file'][$i] |
['attribs'][$this->_tasksNs . |
':' . $task->getName()]) ? |
$this->_packageInfo['contents']['dir']['file'][$i] |
['attribs'][$this->_tasksNs . |
':' . $task->getName()] : false; |
if ($t && !isset($t[0])) { |
$this->_packageInfo['contents']['dir']['file'][$i] |
[$this->_tasksNs . ':' . $task->getName()] = array($t); |
} |
$this->_packageInfo['contents']['dir']['file'][$i][$this->_tasksNs . |
':' . $task->getName()][] = $task->getXml(); |
} else { |
$t = isset($this->_packageInfo['contents']['dir']['file'] |
['attribs'][$this->_tasksNs . |
':' . $task->getName()]) ? $this->_packageInfo['contents']['dir']['file'] |
['attribs'][$this->_tasksNs . |
':' . $task->getName()] : false; |
if ($t && !isset($t[0])) { |
$this->_packageInfo['contents']['dir']['file'] |
[$this->_tasksNs . ':' . $task->getName()] = array($t); |
} |
$this->_packageInfo['contents']['dir']['file'][$this->_tasksNs . |
':' . $task->getName()][] = $task->getXml(); |
} |
return true; |
} |
} |
} |
return false; |
} |
/** |
* @param string path to the file |
* @param string filename |
* @param array extra attributes |
*/ |
function addFile($dir, $file, $attrs) |
{ |
if ($this->getPackageType() == 'bundle') { |
return false; |
} |
$this->_filesValid = false; |
$this->_isValid = 0; |
$dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir); |
if ($dir == '/' || $dir == '') { |
$dir = ''; |
} else { |
$dir .= '/'; |
} |
$attrs['name'] = $dir . $file; |
if (!isset($this->_packageInfo['contents'])) { |
// ensure that the contents tag is set up |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, |
array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', |
'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'bundle', 'changelog'), array(), 'contents'); |
} |
if (isset($this->_packageInfo['contents']['dir']['file'])) { |
if (!isset($this->_packageInfo['contents']['dir']['file'][0])) { |
$this->_packageInfo['contents']['dir']['file'] = |
array($this->_packageInfo['contents']['dir']['file']); |
} |
$this->_packageInfo['contents']['dir']['file'][]['attribs'] = $attrs; |
} else { |
$this->_packageInfo['contents']['dir']['file']['attribs'] = $attrs; |
} |
} |
/** |
* @param string Dependent package name |
* @param string Dependent package's channel name |
* @param string minimum version of specified package that this release is guaranteed to be |
* compatible with |
* @param string maximum version of specified package that this release is guaranteed to be |
* compatible with |
* @param string versions of specified package that this release is not compatible with |
*/ |
function addCompatiblePackage($name, $channel, $min, $max, $exclude = false) |
{ |
$this->_isValid = 0; |
$set = array( |
'name' => $name, |
'channel' => $channel, |
'min' => $min, |
'max' => $max, |
); |
if ($exclude) { |
$set['exclude'] = $exclude; |
} |
$this->_isValid = 0; |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array( |
'compatible' => array('dependencies', 'providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog') |
)); |
} |
/** |
* Removes the <usesrole> tag entirely |
*/ |
function resetUsesrole() |
{ |
if (isset($this->_packageInfo['usesrole'])) { |
unset($this->_packageInfo['usesrole']); |
} |
} |
/** |
* @param string |
* @param string package name or uri |
* @param string channel name if non-uri |
*/ |
function addUsesrole($role, $packageOrUri, $channel = false) { |
$set = array('role' => $role); |
if ($channel) { |
$set['package'] = $packageOrUri; |
$set['channel'] = $channel; |
} else { |
$set['uri'] = $packageOrUri; |
} |
$this->_isValid = 0; |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array( |
'usesrole' => array('usestask', 'srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog') |
)); |
} |
/** |
* Removes the <usestask> tag entirely |
*/ |
function resetUsestask() |
{ |
if (isset($this->_packageInfo['usestask'])) { |
unset($this->_packageInfo['usestask']); |
} |
} |
/** |
* @param string |
* @param string package name or uri |
* @param string channel name if non-uri |
*/ |
function addUsestask($task, $packageOrUri, $channel = false) { |
$set = array('task' => $task); |
if ($channel) { |
$set['package'] = $packageOrUri; |
$set['channel'] = $channel; |
} else { |
$set['uri'] = $packageOrUri; |
} |
$this->_isValid = 0; |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array( |
'usestask' => array('srcpackage', 'srcuri', |
'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog') |
)); |
} |
/** |
* Remove all compatible tags |
*/ |
function clearCompatible() |
{ |
unset($this->_packageInfo['compatible']); |
} |
/** |
* Reset dependencies prior to adding new ones |
*/ |
function clearDeps() |
{ |
if (!isset($this->_packageInfo['dependencies'])) { |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(), |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'))); |
} |
$this->_packageInfo['dependencies'] = array(); |
} |
/** |
* @param string minimum PHP version allowed |
* @param string maximum PHP version allowed |
* @param array $exclude incompatible PHP versions |
*/ |
function setPhpDep($min, $max = false, $exclude = false) |
{ |
$this->_isValid = 0; |
$dep = |
array( |
'min' => $min, |
); |
if ($max) { |
$dep['max'] = $max; |
} |
if ($exclude) { |
if (count($exclude) == 1) { |
$exclude = $exclude[0]; |
} |
$dep['exclude'] = $exclude; |
} |
if (isset($this->_packageInfo['dependencies']['required']['php'])) { |
$this->_stack->push(__FUNCTION__, 'warning', array('dep' => |
$this->_packageInfo['dependencies']['required']['php']), |
'warning: PHP dependency already exists, overwriting'); |
unset($this->_packageInfo['dependencies']['required']['php']); |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
'required' => array('optional', 'group'), |
'php' => array('pearinstaller', 'package', 'subpackage', 'extension', 'os', 'arch') |
)); |
return true; |
} |
/** |
* @param string minimum allowed PEAR installer version |
* @param string maximum allowed PEAR installer version |
* @param string recommended PEAR installer version |
* @param array incompatible version of the PEAR installer |
*/ |
function setPearinstallerDep($min, $max = false, $recommended = false, $exclude = false) |
{ |
$this->_isValid = 0; |
$dep = |
array( |
'min' => $min, |
); |
if ($max) { |
$dep['max'] = $max; |
} |
if ($recommended) { |
$dep['recommended'] = $recommended; |
} |
if ($exclude) { |
if (count($exclude) == 1) { |
$exclude = $exclude[0]; |
} |
$dep['exclude'] = $exclude; |
} |
if (isset($this->_packageInfo['dependencies']['required']['pearinstaller'])) { |
$this->_stack->push(__FUNCTION__, 'warning', array('dep' => |
$this->_packageInfo['dependencies']['required']['pearinstaller']), |
'warning: PEAR Installer dependency already exists, overwriting'); |
unset($this->_packageInfo['dependencies']['required']['pearinstaller']); |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
'required' => array('optional', 'group'), |
'pearinstaller' => array('package', 'subpackage', 'extension', 'os', 'arch') |
)); |
} |
/** |
* Mark a package as conflicting with this package |
* @param string package name |
* @param string package channel |
* @param string extension this package provides, if any |
* @param string|false minimum version required |
* @param string|false maximum version allowed |
* @param array|false versions to exclude from installation |
*/ |
function addConflictingPackageDepWithChannel($name, $channel, |
$providesextension = false, $min = false, $max = false, $exclude = false) |
{ |
$this->_isValid = 0; |
$dep = $this->_constructDep($name, $channel, false, $min, $max, false, |
$exclude, $providesextension, false, true); |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
'required' => array('optional', 'group'), |
'package' => array('subpackage', 'extension', 'os', 'arch') |
)); |
} |
/** |
* Mark a package as conflicting with this package |
* @param string package name |
* @param string package channel |
* @param string extension this package provides, if any |
*/ |
function addConflictingPackageDepWithUri($name, $uri, $providesextension = false) |
{ |
$this->_isValid = 0; |
$dep = |
array( |
'name' => $name, |
'uri' => $uri, |
'conflicts' => '', |
); |
if ($providesextension) { |
$dep['providesextension'] = $providesextension; |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
'required' => array('optional', 'group'), |
'package' => array('subpackage', 'extension', 'os', 'arch') |
)); |
} |
function addDependencyGroup($name, $hint) |
{ |
$this->_isValid = 0; |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, |
array('attribs' => array('name' => $name, 'hint' => $hint)), |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
'group' => array(), |
)); |
} |
/** |
* @param string package name |
* @param string|false channel name, false if this is a uri |
* @param string|false uri name, false if this is a channel |
* @param string|false minimum version required |
* @param string|false maximum version allowed |
* @param string|false recommended installation version |
* @param array|false versions to exclude from installation |
* @param string extension this package provides, if any |
* @param bool if true, tells the installer to ignore the default optional dependency group |
* when installing this package |
* @param bool if true, tells the installer to negate this dependency (conflicts) |
* @return array |
* @access private |
*/ |
function _constructDep($name, $channel, $uri, $min, $max, $recommended, $exclude, |
$providesextension = false, $nodefault = false, |
$conflicts = false) |
{ |
$dep = |
array( |
'name' => $name, |
); |
if ($channel) { |
$dep['channel'] = $channel; |
} elseif ($uri) { |
$dep['uri'] = $uri; |
} |
if ($min) { |
$dep['min'] = $min; |
} |
if ($max) { |
$dep['max'] = $max; |
} |
if ($recommended) { |
$dep['recommended'] = $recommended; |
} |
if ($exclude) { |
if (is_array($exclude) && count($exclude) == 1) { |
$exclude = $exclude[0]; |
} |
$dep['exclude'] = $exclude; |
} |
if ($conflicts) { |
$dep['conflicts'] = ''; |
} |
if ($nodefault) { |
$dep['nodefault'] = ''; |
} |
if ($providesextension) { |
$dep['providesextension'] = $providesextension; |
} |
return $dep; |
} |
/** |
* @param package|subpackage |
* @param string group name |
* @param string package name |
* @param string package channel |
* @param string minimum version |
* @param string maximum version |
* @param string recommended version |
* @param array|false optional excluded versions |
* @param string extension this package provides, if any |
* @param bool if true, tells the installer to ignore the default optional dependency group |
* when installing this package |
* @return bool false if the dependency group has not been initialized with |
* {@link addDependencyGroup()}, or a subpackage is added with |
* a providesextension |
*/ |
function addGroupPackageDepWithChannel($type, $groupname, $name, $channel, $min = false, |
$max = false, $recommended = false, $exclude = false, |
$providesextension = false, $nodefault = false) |
{ |
if ($type == 'subpackage' && $providesextension) { |
return false; // subpackages must be php packages |
} |
$dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude, |
$providesextension, $nodefault); |
return $this->_addGroupDependency($type, $dep, $groupname); |
} |
/** |
* @param package|subpackage |
* @param string group name |
* @param string package name |
* @param string package uri |
* @param string extension this package provides, if any |
* @param bool if true, tells the installer to ignore the default optional dependency group |
* when installing this package |
* @return bool false if the dependency group has not been initialized with |
* {@link addDependencyGroup()} |
*/ |
function addGroupPackageDepWithURI($type, $groupname, $name, $uri, $providesextension = false, |
$nodefault = false) |
{ |
if ($type == 'subpackage' && $providesextension) { |
return false; // subpackages must be php packages |
} |
$dep = $this->_constructDep($name, false, $uri, false, false, false, false, |
$providesextension, $nodefault); |
return $this->_addGroupDependency($type, $dep, $groupname); |
} |
/** |
* @param string group name (must be pre-existing) |
* @param string extension name |
* @param string minimum version allowed |
* @param string maximum version allowed |
* @param string recommended version |
* @param array incompatible versions |
*/ |
function addGroupExtensionDep($groupname, $name, $min = false, $max = false, |
$recommended = false, $exclude = false) |
{ |
$this->_isValid = 0; |
$dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude); |
return $this->_addGroupDependency('extension', $dep, $groupname); |
} |
/** |
* @param package|subpackage|extension |
* @param array dependency contents |
* @param string name of the dependency group to add this to |
* @return boolean |
* @access private |
*/ |
function _addGroupDependency($type, $dep, $groupname) |
{ |
$arr = array('subpackage', 'extension'); |
if ($type != 'package') { |
array_shift($arr); |
} |
if ($type == 'extension') { |
array_shift($arr); |
} |
if (!isset($this->_packageInfo['dependencies']['group'])) { |
return false; |
} else { |
if (!isset($this->_packageInfo['dependencies']['group'][0])) { |
if ($this->_packageInfo['dependencies']['group']['attribs']['name'] == $groupname) { |
$this->_packageInfo['dependencies']['group'] = $this->_mergeTag( |
$this->_packageInfo['dependencies']['group'], $dep, |
array( |
$type => $arr |
)); |
$this->_isValid = 0; |
return true; |
} else { |
return false; |
} |
} else { |
foreach ($this->_packageInfo['dependencies']['group'] as $i => $group) { |
if ($group['attribs']['name'] == $groupname) { |
$this->_packageInfo['dependencies']['group'][$i] = $this->_mergeTag( |
$this->_packageInfo['dependencies']['group'][$i], $dep, |
array( |
$type => $arr |
)); |
$this->_isValid = 0; |
return true; |
} |
} |
return false; |
} |
} |
} |
/** |
* @param optional|required |
* @param string package name |
* @param string package channel |
* @param string minimum version |
* @param string maximum version |
* @param string recommended version |
* @param string extension this package provides, if any |
* @param bool if true, tells the installer to ignore the default optional dependency group |
* when installing this package |
* @param array|false optional excluded versions |
*/ |
function addPackageDepWithChannel($type, $name, $channel, $min = false, $max = false, |
$recommended = false, $exclude = false, |
$providesextension = false, $nodefault = false) |
{ |
if (!in_array($type, array('optional', 'required'), true)) { |
$type = 'required'; |
} |
$this->_isValid = 0; |
$arr = array('optional', 'group'); |
if ($type != 'required') { |
array_shift($arr); |
} |
$dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude, |
$providesextension, $nodefault); |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
$type => $arr, |
'package' => array('subpackage', 'extension', 'os', 'arch') |
)); |
} |
/** |
* @param optional|required |
* @param string name of the package |
* @param string uri of the package |
* @param string extension this package provides, if any |
* @param bool if true, tells the installer to ignore the default optional dependency group |
* when installing this package |
*/ |
function addPackageDepWithUri($type, $name, $uri, $providesextension = false, |
$nodefault = false) |
{ |
$this->_isValid = 0; |
$arr = array('optional', 'group'); |
if ($type != 'required') { |
array_shift($arr); |
} |
$dep = $this->_constructDep($name, false, $uri, false, false, false, false, |
$providesextension, $nodefault); |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
$type => $arr, |
'package' => array('subpackage', 'extension', 'os', 'arch') |
)); |
} |
/** |
* @param optional|required optional, required |
* @param string package name |
* @param string package channel |
* @param string minimum version |
* @param string maximum version |
* @param string recommended version |
* @param array incompatible versions |
* @param bool if true, tells the installer to ignore the default optional dependency group |
* when installing this package |
*/ |
function addSubpackageDepWithChannel($type, $name, $channel, $min = false, $max = false, |
$recommended = false, $exclude = false, |
$nodefault = false) |
{ |
$this->_isValid = 0; |
$arr = array('optional', 'group'); |
if ($type != 'required') { |
array_shift($arr); |
} |
$dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude, |
$nodefault); |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
$type => $arr, |
'subpackage' => array('extension', 'os', 'arch') |
)); |
} |
/** |
* @param optional|required optional, required |
* @param string package name |
* @param string package uri for download |
* @param bool if true, tells the installer to ignore the default optional dependency group |
* when installing this package |
*/ |
function addSubpackageDepWithUri($type, $name, $uri, $nodefault = false) |
{ |
$this->_isValid = 0; |
$arr = array('optional', 'group'); |
if ($type != 'required') { |
array_shift($arr); |
} |
$dep = $this->_constructDep($name, false, $uri, false, false, false, false, $nodefault); |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
$type => $arr, |
'subpackage' => array('extension', 'os', 'arch') |
)); |
} |
/** |
* @param optional|required optional, required |
* @param string extension name |
* @param string minimum version |
* @param string maximum version |
* @param string recommended version |
* @param array incompatible versions |
*/ |
function addExtensionDep($type, $name, $min = false, $max = false, $recommended = false, |
$exclude = false) |
{ |
$this->_isValid = 0; |
$arr = array('optional', 'group'); |
if ($type != 'required') { |
array_shift($arr); |
} |
$dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude); |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
$type => $arr, |
'extension' => array('os', 'arch') |
)); |
} |
/** |
* @param string Operating system name |
* @param boolean true if this package cannot be installed on this OS |
*/ |
function addOsDep($name, $conflicts = false) |
{ |
$this->_isValid = 0; |
$dep = array('name' => $name); |
if ($conflicts) { |
$dep['conflicts'] = ''; |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
'required' => array('optional', 'group'), |
'os' => array('arch') |
)); |
} |
/** |
* @param string Architecture matching pattern |
* @param boolean true if this package cannot be installed on this architecture |
*/ |
function addArchDep($pattern, $conflicts = false) |
{ |
$this->_isValid = 0; |
$dep = array('pattern' => $pattern); |
if ($conflicts) { |
$dep['conflicts'] = ''; |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, |
array( |
'dependencies' => array('providesextension', 'usesrole', 'usestask', |
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), |
'required' => array('optional', 'group'), |
'arch' => array() |
)); |
} |
/** |
* Set the kind of package, and erase all release tags |
* |
* - a php package is a PEAR-style package |
* - an extbin package is a PECL-style extension binary |
* - an extsrc package is a PECL-style source for a binary |
* - an zendextbin package is a PECL-style zend extension binary |
* - an zendextsrc package is a PECL-style source for a zend extension binary |
* - a bundle package is a collection of other pre-packaged packages |
* @param php|extbin|extsrc|zendextsrc|zendextbin|bundle |
* @return bool success |
*/ |
function setPackageType($type) |
{ |
$this->_isValid = 0; |
if (!in_array($type, array('php', 'extbin', 'extsrc', 'zendextsrc', |
'zendextbin', 'bundle'))) { |
return false; |
} |
if (in_array($type, array('zendextsrc', 'zendextbin'))) { |
$this->_setPackageVersion2_1(); |
} |
if ($type != 'bundle') { |
$type .= 'release'; |
} |
foreach (array('phprelease', 'extbinrelease', 'extsrcrelease', |
'zendextsrcrelease', 'zendextbinrelease', 'bundle') as $test) { |
unset($this->_packageInfo[$test]); |
} |
if (!isset($this->_packageInfo[$type])) { |
// ensure that the release tag is set up |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('changelog'), |
array(), $type); |
} |
$this->_packageInfo[$type] = array(); |
return true; |
} |
/** |
* @return bool true if package type is set up |
*/ |
function addRelease() |
{ |
if ($type = $this->getPackageType()) { |
if ($type != 'bundle') { |
$type .= 'release'; |
} |
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(), |
array($type => array('changelog'))); |
return true; |
} |
return false; |
} |
/** |
* Get the current release tag in order to add to it |
* @param bool returns only releases that have installcondition if true |
* @return array|null |
*/ |
function &_getCurrentRelease($strict = true) |
{ |
if ($p = $this->getPackageType()) { |
if ($strict) { |
if ($p == 'extsrc' || $p == 'zendextsrc') { |
$a = null; |
return $a; |
} |
} |
if ($p != 'bundle') { |
$p .= 'release'; |
} |
if (isset($this->_packageInfo[$p][0])) { |
return $this->_packageInfo[$p][count($this->_packageInfo[$p]) - 1]; |
} else { |
return $this->_packageInfo[$p]; |
} |
} else { |
$a = null; |
return $a; |
} |
} |
/** |
* Add a file to the current release that should be installed under a different name |
* @param string <contents> path to file |
* @param string name the file should be installed as |
*/ |
function addInstallAs($path, $as) |
{ |
$r = &$this->_getCurrentRelease(); |
if ($r === null) { |
return false; |
} |
$this->_isValid = 0; |
$r = $this->_mergeTag($r, array('attribs' => array('name' => $path, 'as' => $as)), |
array( |
'filelist' => array(), |
'install' => array('ignore') |
)); |
} |
/** |
* Add a file to the current release that should be ignored |
* @param string <contents> path to file |
* @return bool success of operation |
*/ |
function addIgnore($path) |
{ |
$r = &$this->_getCurrentRelease(); |
if ($r === null) { |
return false; |
} |
$this->_isValid = 0; |
$r = $this->_mergeTag($r, array('attribs' => array('name' => $path)), |
array( |
'filelist' => array(), |
'ignore' => array() |
)); |
} |
/** |
* Add an extension binary package for this extension source code release |
* |
* Note that the package must be from the same channel as the extension source package |
* @param string |
*/ |
function addBinarypackage($package) |
{ |
if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') { |
return false; |
} |
$r = &$this->_getCurrentRelease(false); |
if ($r === null) { |
return false; |
} |
$this->_isValid = 0; |
$r = $this->_mergeTag($r, $package, |
array( |
'binarypackage' => array('filelist'), |
)); |
} |
/** |
* Add a configureoption to an extension source package |
* @param string |
* @param string |
* @param string |
*/ |
function addConfigureOption($name, $prompt, $default = null) |
{ |
if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') { |
return false; |
} |
$r = &$this->_getCurrentRelease(false); |
if ($r === null) { |
return false; |
} |
$opt = array('attribs' => array('name' => $name, 'prompt' => $prompt)); |
if ($default !== null) { |
$opt['default'] = $default; |
} |
$this->_isValid = 0; |
$r = $this->_mergeTag($r, $opt, |
array( |
'configureoption' => array('binarypackage', 'filelist'), |
)); |
} |
/** |
* Set an installation condition based on php version for the current release set |
* @param string minimum version |
* @param string maximum version |
* @param false|array incompatible versions of PHP |
*/ |
function setPhpInstallCondition($min, $max, $exclude = false) |
{ |
$r = &$this->_getCurrentRelease(); |
if ($r === null) { |
return false; |
} |
$this->_isValid = 0; |
if (isset($r['installconditions']['php'])) { |
unset($r['installconditions']['php']); |
} |
$dep = array('min' => $min, 'max' => $max); |
if ($exclude) { |
if (is_array($exclude) && count($exclude) == 1) { |
$exclude = $exclude[0]; |
} |
$dep['exclude'] = $exclude; |
} |
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { |
$r = $this->_mergeTag($r, $dep, |
array( |
'installconditions' => array('configureoption', 'binarypackage', |
'filelist'), |
'php' => array('extension', 'os', 'arch') |
)); |
} else { |
$r = $this->_mergeTag($r, $dep, |
array( |
'installconditions' => array('filelist'), |
'php' => array('extension', 'os', 'arch') |
)); |
} |
} |
/** |
* @param optional|required optional, required |
* @param string extension name |
* @param string minimum version |
* @param string maximum version |
* @param string recommended version |
* @param array incompatible versions |
*/ |
function addExtensionInstallCondition($name, $min = false, $max = false, $recommended = false, |
$exclude = false) |
{ |
$r = &$this->_getCurrentRelease(); |
if ($r === null) { |
return false; |
} |
$this->_isValid = 0; |
$dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude); |
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { |
$r = $this->_mergeTag($r, $dep, |
array( |
'installconditions' => array('configureoption', 'binarypackage', |
'filelist'), |
'extension' => array('os', 'arch') |
)); |
} else { |
$r = $this->_mergeTag($r, $dep, |
array( |
'installconditions' => array('filelist'), |
'extension' => array('os', 'arch') |
)); |
} |
} |
/** |
* Set an installation condition based on operating system for the current release set |
* @param string OS name |
* @param bool whether this OS is incompatible with the current release |
*/ |
function setOsInstallCondition($name, $conflicts = false) |
{ |
$r = &$this->_getCurrentRelease(); |
if ($r === null) { |
return false; |
} |
$this->_isValid = 0; |
if (isset($r['installconditions']['os'])) { |
unset($r['installconditions']['os']); |
} |
$dep = array('name' => $name); |
if ($conflicts) { |
$dep['conflicts'] = ''; |
} |
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { |
$r = $this->_mergeTag($r, $dep, |
array( |
'installconditions' => array('configureoption', 'binarypackage', |
'filelist'), |
'os' => array('arch') |
)); |
} else { |
$r = $this->_mergeTag($r, $dep, |
array( |
'installconditions' => array('filelist'), |
'os' => array('arch') |
)); |
} |
} |
/** |
* Set an installation condition based on architecture for the current release set |
* @param string architecture pattern |
* @param bool whether this arch is incompatible with the current release |
*/ |
function setArchInstallCondition($pattern, $conflicts = false) |
{ |
$r = &$this->_getCurrentRelease(); |
if ($r === null) { |
return false; |
} |
$this->_isValid = 0; |
if (isset($r['installconditions']['arch'])) { |
unset($r['installconditions']['arch']); |
} |
$dep = array('pattern' => $pattern); |
if ($conflicts) { |
$dep['conflicts'] = ''; |
} |
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { |
$r = $this->_mergeTag($r, $dep, |
array( |
'installconditions' => array('configureoption', 'binarypackage', |
'filelist'), |
'arch' => array() |
)); |
} else { |
$r = $this->_mergeTag($r, $dep, |
array( |
'installconditions' => array('filelist'), |
'arch' => array() |
)); |
} |
} |
/** |
* For extension binary releases, this is used to specify either the |
* static URI to a source package, or the package name and channel of the extsrc/zendextsrc |
* package it is based on. |
* @param string Package name, or full URI to source package (extsrc/zendextsrc type) |
*/ |
function setSourcePackage($packageOrUri) |
{ |
$this->_isValid = 0; |
if (isset($this->_packageInfo['channel'])) { |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease', |
'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'bundle', 'changelog'), |
$packageOrUri, 'srcpackage'); |
} else { |
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease', |
'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', |
'bundle', 'changelog'), $packageOrUri, 'srcuri'); |
} |
} |
/** |
* Generate a valid change log entry from the current package.xml |
* @param string|false |
*/ |
function generateChangeLogEntry($notes = false) |
{ |
return array( |
'version' => |
array( |
'release' => $this->getVersion('release'), |
'api' => $this->getVersion('api'), |
), |
'stability' => |
$this->getStability(), |
'date' => $this->getDate(), |
'license' => $this->getLicense(true), |
'notes' => $notes ? $notes : $this->getNotes() |
); |
} |
/** |
* @param string release version to set change log notes for |
* @param array output of {@link generateChangeLogEntry()} |
*/ |
function setChangelogEntry($releaseversion, $contents) |
{ |
if (!isset($this->_packageInfo['changelog'])) { |
$this->_packageInfo['changelog']['release'] = $contents; |
return; |
} |
if (!isset($this->_packageInfo['changelog']['release'][0])) { |
if ($this->_packageInfo['changelog']['release']['version']['release'] == $releaseversion) { |
$this->_packageInfo['changelog']['release'] = array( |
$this->_packageInfo['changelog']['release']); |
} else { |
$this->_packageInfo['changelog']['release'] = array( |
$this->_packageInfo['changelog']['release']); |
return $this->_packageInfo['changelog']['release'][] = $contents; |
} |
} |
foreach($this->_packageInfo['changelog']['release'] as $index => $changelog) { |
if (isset($changelog['version']) && |
strnatcasecmp($changelog['version']['release'], $releaseversion) == 0) { |
$curlog = $index; |
} |
} |
if (isset($curlog)) { |
$this->_packageInfo['changelog']['release'][$curlog] = $contents; |
} else { |
$this->_packageInfo['changelog']['release'][] = $contents; |
} |
} |
/** |
* Remove the changelog entirely |
*/ |
function clearChangeLog() |
{ |
unset($this->_packageInfo['changelog']); |
} |
} |
?> |