1<?php 2/** 3 * PEAR_Command_Pickle (pickle command) 4 * 5 * PHP versions 4 and 5 6 * 7 * @category pear 8 * @package PEAR 9 * @author Greg Beaver <cellog@php.net> 10 * @copyright 2005-2009 The Authors 11 * @license http://opensource.org/licenses/bsd-license.php New BSD License 12 * @link http://pear.php.net/package/PEAR 13 * @since File available since Release 1.4.1 14 */ 15 16/** 17 * base class 18 */ 19require_once 'PEAR/Command/Common.php'; 20 21/** 22 * PEAR commands for login/logout 23 * 24 * @category pear 25 * @package PEAR 26 * @author Greg Beaver <cellog@php.net> 27 * @copyright 2005-2009 The Authors 28 * @license http://opensource.org/licenses/bsd-license.php New BSD License 29 * @version Release: @package_version@ 30 * @link http://pear.php.net/package/PEAR 31 * @since Class available since Release 1.4.1 32 */ 33 34class PEAR_Command_Pickle extends PEAR_Command_Common 35{ 36 var $commands = array( 37 'pickle' => array( 38 'summary' => 'Build PECL Package', 39 'function' => 'doPackage', 40 'shortcut' => 'pi', 41 'options' => array( 42 'nocompress' => array( 43 'shortopt' => 'Z', 44 'doc' => 'Do not gzip the package file' 45 ), 46 'showname' => array( 47 'shortopt' => 'n', 48 'doc' => 'Print the name of the packaged file.', 49 ), 50 ), 51 'doc' => '[descfile] 52Creates a PECL package from its package2.xml file. 53 54An automatic conversion will be made to a package.xml 1.0 and written out to 55disk in the current directory as "package.xml". Note that 56only simple package.xml 2.0 will be converted. package.xml 2.0 with: 57 58 - dependency types other than required/optional PECL package/ext/php/pearinstaller 59 - more than one extsrcrelease or zendextsrcrelease 60 - zendextbinrelease, extbinrelease, phprelease, or bundle release type 61 - dependency groups 62 - ignore tags in release filelist 63 - tasks other than replace 64 - custom roles 65 66will cause pickle to fail, and output an error message. If your package2.xml 67uses any of these features, you are best off using PEAR_PackageFileManager to 68generate both package.xml. 69' 70 ), 71 ); 72 73 /** 74 * PEAR_Command_Package constructor. 75 * 76 * @access public 77 */ 78 function __construct(&$ui, &$config) 79 { 80 parent::__construct($ui, $config); 81 } 82 83 /** 84 * For unit-testing ease 85 * 86 * @return PEAR_Packager 87 */ 88 function &getPackager() 89 { 90 if (!class_exists('PEAR_Packager')) { 91 require_once 'PEAR/Packager.php'; 92 } 93 94 $a = new PEAR_Packager; 95 return $a; 96 } 97 98 /** 99 * For unit-testing ease 100 * 101 * @param PEAR_Config $config 102 * @param bool $debug 103 * @param string|null $tmpdir 104 * @return PEAR_PackageFile 105 */ 106 function &getPackageFile($config, $debug = false) 107 { 108 if (!class_exists('PEAR_Common')) { 109 require_once 'PEAR/Common.php'; 110 } 111 112 if (!class_exists('PEAR_PackageFile')) { 113 require_once 'PEAR/PackageFile.php'; 114 } 115 116 $a = new PEAR_PackageFile($config, $debug); 117 $common = new PEAR_Common; 118 $common->ui = $this->ui; 119 $a->setLogger($common); 120 return $a; 121 } 122 123 function doPackage($command, $options, $params) 124 { 125 $this->output = ''; 126 $pkginfofile = isset($params[0]) ? $params[0] : 'package2.xml'; 127 $packager = &$this->getPackager(); 128 if (PEAR::isError($err = $this->_convertPackage($pkginfofile))) { 129 return $err; 130 } 131 132 $compress = empty($options['nocompress']) ? true : false; 133 $result = $packager->package($pkginfofile, $compress, 'package.xml'); 134 if (PEAR::isError($result)) { 135 return $this->raiseError($result); 136 } 137 138 // Don't want output, only the package file name just created 139 if (isset($options['showname'])) { 140 $this->ui->outputData($result, $command); 141 } 142 143 return true; 144 } 145 146 function _convertPackage($packagexml) 147 { 148 $pkg = &$this->getPackageFile($this->config); 149 $pf2 = &$pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL); 150 if (!is_a($pf2, 'PEAR_PackageFile_v2')) { 151 return $this->raiseError('Cannot process "' . 152 $packagexml . '", is not a package.xml 2.0'); 153 } 154 155 require_once 'PEAR/PackageFile/v1.php'; 156 $pf = new PEAR_PackageFile_v1; 157 $pf->setConfig($this->config); 158 if ($pf2->getPackageType() != 'extsrc' && $pf2->getPackageType() != 'zendextsrc') { 159 return $this->raiseError('Cannot safely convert "' . $packagexml . 160 '", is not an extension source package. Using a PEAR_PackageFileManager-based ' . 161 'script is an option'); 162 } 163 164 if (is_array($pf2->getUsesRole())) { 165 return $this->raiseError('Cannot safely convert "' . $packagexml . 166 '", contains custom roles. Using a PEAR_PackageFileManager-based script or ' . 167 'the convert command is an option'); 168 } 169 170 if (is_array($pf2->getUsesTask())) { 171 return $this->raiseError('Cannot safely convert "' . $packagexml . 172 '", contains custom tasks. Using a PEAR_PackageFileManager-based script or ' . 173 'the convert command is an option'); 174 } 175 176 $deps = $pf2->getDependencies(); 177 if (isset($deps['group'])) { 178 return $this->raiseError('Cannot safely convert "' . $packagexml . 179 '", contains dependency groups. Using a PEAR_PackageFileManager-based script ' . 180 'or the convert command is an option'); 181 } 182 183 if (isset($deps['required']['subpackage']) || 184 isset($deps['optional']['subpackage'])) { 185 return $this->raiseError('Cannot safely convert "' . $packagexml . 186 '", contains subpackage dependencies. Using a PEAR_PackageFileManager-based '. 187 'script is an option'); 188 } 189 190 if (isset($deps['required']['os'])) { 191 return $this->raiseError('Cannot safely convert "' . $packagexml . 192 '", contains os dependencies. Using a PEAR_PackageFileManager-based '. 193 'script is an option'); 194 } 195 196 if (isset($deps['required']['arch'])) { 197 return $this->raiseError('Cannot safely convert "' . $packagexml . 198 '", contains arch dependencies. Using a PEAR_PackageFileManager-based '. 199 'script is an option'); 200 } 201 202 $pf->setPackage($pf2->getPackage()); 203 $pf->setSummary($pf2->getSummary()); 204 $pf->setDescription($pf2->getDescription()); 205 foreach ($pf2->getMaintainers() as $maintainer) { 206 $pf->addMaintainer($maintainer['role'], $maintainer['handle'], 207 $maintainer['name'], $maintainer['email']); 208 } 209 210 $pf->setVersion($pf2->getVersion()); 211 $pf->setDate($pf2->getDate()); 212 $pf->setLicense($pf2->getLicense()); 213 $pf->setState($pf2->getState()); 214 $pf->setNotes($pf2->getNotes()); 215 $pf->addPhpDep($deps['required']['php']['min'], 'ge'); 216 if (isset($deps['required']['php']['max'])) { 217 $pf->addPhpDep($deps['required']['php']['max'], 'le'); 218 } 219 220 if (isset($deps['required']['package'])) { 221 if (!isset($deps['required']['package'][0])) { 222 $deps['required']['package'] = array($deps['required']['package']); 223 } 224 225 foreach ($deps['required']['package'] as $dep) { 226 if (!isset($dep['channel'])) { 227 return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . 228 ' contains uri-based dependency on a package. Using a ' . 229 'PEAR_PackageFileManager-based script is an option'); 230 } 231 232 if ($dep['channel'] != 'pear.php.net' 233 && $dep['channel'] != 'pecl.php.net' 234 && $dep['channel'] != 'doc.php.net') { 235 return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . 236 ' contains dependency on a non-standard channel package. Using a ' . 237 'PEAR_PackageFileManager-based script is an option'); 238 } 239 240 if (isset($dep['conflicts'])) { 241 return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . 242 ' contains conflicts dependency. Using a ' . 243 'PEAR_PackageFileManager-based script is an option'); 244 } 245 246 if (isset($dep['exclude'])) { 247 $this->ui->outputData('WARNING: exclude tags are ignored in conversion'); 248 } 249 250 if (isset($dep['min'])) { 251 $pf->addPackageDep($dep['name'], $dep['min'], 'ge'); 252 } 253 254 if (isset($dep['max'])) { 255 $pf->addPackageDep($dep['name'], $dep['max'], 'le'); 256 } 257 } 258 } 259 260 if (isset($deps['required']['extension'])) { 261 if (!isset($deps['required']['extension'][0])) { 262 $deps['required']['extension'] = array($deps['required']['extension']); 263 } 264 265 foreach ($deps['required']['extension'] as $dep) { 266 if (isset($dep['conflicts'])) { 267 return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . 268 ' contains conflicts dependency. Using a ' . 269 'PEAR_PackageFileManager-based script is an option'); 270 } 271 272 if (isset($dep['exclude'])) { 273 $this->ui->outputData('WARNING: exclude tags are ignored in conversion'); 274 } 275 276 if (isset($dep['min'])) { 277 $pf->addExtensionDep($dep['name'], $dep['min'], 'ge'); 278 } 279 280 if (isset($dep['max'])) { 281 $pf->addExtensionDep($dep['name'], $dep['max'], 'le'); 282 } 283 } 284 } 285 286 if (isset($deps['optional']['package'])) { 287 if (!isset($deps['optional']['package'][0])) { 288 $deps['optional']['package'] = array($deps['optional']['package']); 289 } 290 291 foreach ($deps['optional']['package'] as $dep) { 292 if (!isset($dep['channel'])) { 293 return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . 294 ' contains uri-based dependency on a package. Using a ' . 295 'PEAR_PackageFileManager-based script is an option'); 296 } 297 298 if ($dep['channel'] != 'pear.php.net' 299 && $dep['channel'] != 'pecl.php.net' 300 && $dep['channel'] != 'doc.php.net') { 301 return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . 302 ' contains dependency on a non-standard channel package. Using a ' . 303 'PEAR_PackageFileManager-based script is an option'); 304 } 305 306 if (isset($dep['exclude'])) { 307 $this->ui->outputData('WARNING: exclude tags are ignored in conversion'); 308 } 309 310 if (isset($dep['min'])) { 311 $pf->addPackageDep($dep['name'], $dep['min'], 'ge', 'yes'); 312 } 313 314 if (isset($dep['max'])) { 315 $pf->addPackageDep($dep['name'], $dep['max'], 'le', 'yes'); 316 } 317 } 318 } 319 320 if (isset($deps['optional']['extension'])) { 321 if (!isset($deps['optional']['extension'][0])) { 322 $deps['optional']['extension'] = array($deps['optional']['extension']); 323 } 324 325 foreach ($deps['optional']['extension'] as $dep) { 326 if (isset($dep['exclude'])) { 327 $this->ui->outputData('WARNING: exclude tags are ignored in conversion'); 328 } 329 330 if (isset($dep['min'])) { 331 $pf->addExtensionDep($dep['name'], $dep['min'], 'ge', 'yes'); 332 } 333 334 if (isset($dep['max'])) { 335 $pf->addExtensionDep($dep['name'], $dep['max'], 'le', 'yes'); 336 } 337 } 338 } 339 340 $contents = $pf2->getContents(); 341 $release = $pf2->getReleases(); 342 if (isset($releases[0])) { 343 return $this->raiseError('Cannot safely process "' . $packagexml . '" contains ' 344 . 'multiple extsrcrelease/zendextsrcrelease tags. Using a PEAR_PackageFileManager-based script ' . 345 'or the convert command is an option'); 346 } 347 348 if ($configoptions = $pf2->getConfigureOptions()) { 349 foreach ($configoptions as $option) { 350 $default = isset($option['default']) ? $option['default'] : false; 351 $pf->addConfigureOption($option['name'], $option['prompt'], $default); 352 } 353 } 354 355 if (isset($release['filelist']['ignore'])) { 356 return $this->raiseError('Cannot safely process "' . $packagexml . '" contains ' 357 . 'ignore tags. Using a PEAR_PackageFileManager-based script or the convert' . 358 ' command is an option'); 359 } 360 361 if (isset($release['filelist']['install']) && 362 !isset($release['filelist']['install'][0])) { 363 $release['filelist']['install'] = array($release['filelist']['install']); 364 } 365 366 if (isset($contents['dir']['attribs']['baseinstalldir'])) { 367 $baseinstalldir = $contents['dir']['attribs']['baseinstalldir']; 368 } else { 369 $baseinstalldir = false; 370 } 371 372 if (!isset($contents['dir']['file'][0])) { 373 $contents['dir']['file'] = array($contents['dir']['file']); 374 } 375 376 foreach ($contents['dir']['file'] as $file) { 377 if ($baseinstalldir && !isset($file['attribs']['baseinstalldir'])) { 378 $file['attribs']['baseinstalldir'] = $baseinstalldir; 379 } 380 381 $processFile = $file; 382 unset($processFile['attribs']); 383 if (count($processFile)) { 384 foreach ($processFile as $name => $task) { 385 if ($name != $pf2->getTasksNs() . ':replace') { 386 return $this->raiseError('Cannot safely process "' . $packagexml . 387 '" contains tasks other than replace. Using a ' . 388 'PEAR_PackageFileManager-based script is an option.'); 389 } 390 $file['attribs']['replace'][] = $task; 391 } 392 } 393 394 if (!in_array($file['attribs']['role'], PEAR_Common::getFileRoles())) { 395 return $this->raiseError('Cannot safely convert "' . $packagexml . 396 '", contains custom roles. Using a PEAR_PackageFileManager-based script ' . 397 'or the convert command is an option'); 398 } 399 400 if (isset($release['filelist']['install'])) { 401 foreach ($release['filelist']['install'] as $installas) { 402 if ($installas['attribs']['name'] == $file['attribs']['name']) { 403 $file['attribs']['install-as'] = $installas['attribs']['as']; 404 } 405 } 406 } 407 408 $pf->addFile('/', $file['attribs']['name'], $file['attribs']); 409 } 410 411 if ($pf2->getChangeLog()) { 412 $this->ui->outputData('WARNING: changelog is not translated to package.xml ' . 413 '1.0, use PEAR_PackageFileManager-based script if you need changelog-' . 414 'translation for package.xml 1.0'); 415 } 416 417 $gen = &$pf->getDefaultGenerator(); 418 $gen->toPackageFile('.'); 419 } 420} 421